# Source: ui/text-input.js

    /**
        @module montage/ui/text-input
    */
    var Control = require("ui/control").Control,
        deprecate = require("core/deprecate");

    /**
        The base class for all text-based input components. You typically won't create instances of this prototype.
        @class module:montage/ui/text-input.TextInput
        @extends module:montage/ui/component.Component
        @see {module:"montage/ui/input-date.reel".DateInput}
        @see module:"montage/ui/input-text.reel".InputText
        @see module:"montage/ui/input-number.reel".InputNumber
        @see module:"montage/ui/input-range.reel".RangeInput
        @see module:"montage/ui/textarea.reel".TextArea

    */

    /*

    To-DO: Move value logic with converter to Control

    */

    var TextInput = exports.TextInput =  Control.specialize(/** @lends module:montage/ui/text-input.TextInput# */ {
        select: {
            value: function() {
                this._element.select();
            }
        },

        _hasStandardElement: {
            value: true
        },

        /**
            Hard to imagine a text-input that is not using a input nor textarea
            @type {boolean}
            @default true
        */
        _updateOnInput: {
            value: true
        },

    /**
        When this property and the converter's <code>allowPartialConversion</code> are both true, as the user enters text in the input element each new character is added to the component's <code>value</code> property, which triggers the conversion. Depending on the type of input element being used, this behavior may not be desirable. For instance, you likely would not want to convert a date string as a user is entering it, only when they've completed their input.
        Specifies whether
        @type {boolean}
        @default true
    */
        updateOnInput: {
            get: function() {
                return !!this._updateOnInput;
            },
            set: function(v) {
                this._updateOnInput = v;
            }
        },

        // HTMLInputElement methods

        // select() defined where it's allowed
        // click() deliberately omitted, use focus() instead

        // Callbacks

        enterDocument: {
            value: function(firstTime) {
                if (firstTime) {

                    if (this._value === this.constructor.prototype._value) {
                        this.value = this.originalElement ? this.originalElement.textContent : this._element.textContent;
                    }

                    if(this.hasStandardElement || this.element.contentEditable === "true") {
                        this.element.addEventListener('input', this);
                        this.element.addEventListener('change', this);
                    }

                }
            }
        },

        _setElementValue: {
            value: function(value) {
                var drawValue;
                if (value === null ||  typeof value === "undefined") {
                    drawValue = "";
                } else {
                    drawValue = String((value === null || value === undefined ? '' : value));
                }

                if (drawValue !== this.element.value) {
                    this.element.value = drawValue;
                }
            }
        },

        drawsFocusOnPointerActivation : {
            value: true
        },

        draw: {
            enumerable: false,
            value: function() {
                Control.prototype.draw.call(this);

                var el = this.element;

                //if (!this._valueSyncedWithElement) {
                    this._setElementValue(this.converter ? this.converter.convert(this._value) : this._value);
                //}

                if (this.error) {
                    el.classList.add('montage--invalidText');
                    el.title = this.error.message || '';
                } else {
                    el.classList.remove("montage--invalidText");
                    el.title = '';
                }
            }
        },

        didDraw: {
            enumerable: false,
            value: function() {
                if (this._hasFocus && this._value !== null && this._value !== undefined) {
                    var length = this._value.toString().length;
                    this.element.setSelectionRange(length, length);
                }
                // The value might have been changed during the draw if bindings
                // were reified, and another draw will be needed.
                if (!this.needsDraw) {
                    this._valueSyncedWithElement = true;
                }
            }
        },

        // Event handlers

        handleInput: {
            enumerable: false,
            value: function() {
                if (this.converter) {
                    if (this.converter.allowPartialConversion === true && this.updateOnInput === true) {
                        this.takeValueFromElement();
                    }
                } else if(this.updateOnInput === true){
                    this.takeValueFromElement();
                }
            }
        },
        handleChange: {
            enumerable: false,
            value: function(event) {
                this.takeValueFromElement();
                this.dispatchActionEvent();
                this._hasFocus = false;
            }
        },
        handleBlur: {
            enumerable: false,
            value: function(event) {
                this.super(event) ;
                this.takeValueFromElement();
                this.dispatchActionEvent();
            }
        },

        placeholderValue: {
            set: function (value) {
                deprecate.deprecationWarning("placeholderValue", "placeholder");
                this.placeholder = value;
            },
            get: function () {
                return this.placeholder;
            }
        },

    });

    // Standard <input> tag attributes - http://www.w3.org/TR/html5/the-input-element.html#the-input-element

    TextInput.addAttributes({
        accept: null,
        alt: null,
        autocomplete: null,
        checked: {dataType: "boolean"},
        dirname: null,
        formaction: null,
        formenctype: null,
        formmethod: null,
        formnovalidate: {dataType: 'boolean'},
        formtarget: null,
        height: null,
        list: null,
        maxlength: null,
        multiple: {dataType: 'boolean'},
        pattern: null,
        placeholder: null,
        readonly: {dataType: 'boolean'},
        required: {dataType: 'boolean'},
        size: null,
        src: null,
        width: null
        // "type" is not bindable and "value" is handled as a special attribute
    });