<commit_before>// -------------------------------------------------------------------------- \\
// File: TextView.js                                                          \\
// Module: View                                                               \\
// Requires: Core, Foundation, DOM, Validate, AbstractControlView.js          \\
// Author: <NAME>                                                       \\
// License: © 2010–2012 Opera Software ASA. All rights reserved.              \\
// -------------------------------------------------------------------------- \\

/*global document */

"use strict";

( function ( NS, undefined ) {

var isOperaMini = !!NS.UA.operaMini;
var nativePlaceholder = !isOperaMini &&
        'placeholder' in document.createElement( 'input' );

var TextView = NS.Class({

    Extends: NS.AbstractControlView,

    Mixin: NS.Validate,

    init: function () {
        TextView.parent.init.apply( this, arguments );
        this._settingFromInput = false;
        this.initValidate();
    },

    isMasked: false,
    isMultiline: false,
    isExpanding: false,
    isHighlighted: false,
    isFocussed: false,

    maxLength: undefined,

    placeholder: '',
    value: '',

    selection: function ( selection ) {
        var control = this._domControl,
            isNumber = ( typeof selection === 'number' ),
            start = selection ? isNumber ?
                    selection : selection.start : 0,
            end = selection ? isNumber ?
                    selection : selection.end || start : start;
        if ( selection !== undefined ) {
            // Ensure any value changes have been drawn.
            this.redraw();
            // Firefox will throw an error if the control is not actually in the
            // document when trying to set the selection. There might be other
            // situations where it does so as well, so just using a try/catch to
            // guard against all.
            try {
                control.setSelectionRange( start, end );
            } catch ( error ) {}
        } else {
            // Firefox sometimes throws an error if you try to read the
            // selection. Again, probably if the control is not actually in the
            // document.
            try {
                start = control.selectionStart;
                end = control.selectionEnd;
            } catch ( error ) {}
        }
        return selection || {
            start: start,
            end: end
        };
    }.property().nocache(),

    blurOnEscape: true,

    // --- Render ---

    allowTextSelection: true,

    type: function () {
        return this.get( 'isMultiline' ) ?
            this.get( 'isExpanding' ) ? 'expanding' : 'multiline' : 'text';
    }.property(),

    className: function () {
        return 'TextView ' + this.get( 'type' ) +
            ( this.get( 'isHighlighted' ) ? ' highlight' : '' ) +
            ( this.get( 'isFocussed' ) ? ' focussed' : '' ) +
            ( this.get( 'isValid' ) ? '' : ' invalid' ) +
            ( this.get( 'isDisabled' ) ? ' disabled' : '' );
    }.property( 'type', 'isHighlighted',
        'isFocussed', 'isValid', 'isDisabled' ),

    draw: function ( layer ) {
        var Element = NS.Element,
            el = NS.Element.create,
            value = this.get( 'value' ),
            placeholder = this.get( 'placeholder' ),
            control = this._domControl = el(
                this.get( 'isMultiline' ) ? 'textarea' : 'input', {
                    type: this.get( 'isMasked' ) ? 'password' : 'text',
                    autocomplete: 'off',
                    disabled: this.get( 'isDisabled' ),
                    tabIndex: this.get( 'tabIndex' ),
                    maxLength: this.get( 'maxLength' ),
                    value: value
                });

        // Need to add explicit handlers, or Opera Mini won't fire the events
        if ( isOperaMini ) {
            control.onfocus = function () {};
            control.onblur = function () {};
        }

        if ( placeholder ) {
            if ( nativePlaceholder ) {
                control.placeholder = placeholder;
            } else if ( !value ) {
                control.className = 'placeholder';
                control.value = placeholder;
                this._placeholderShowing = true;
            }
        }

        layer.title = this.get( 'tooltip' );
        Element.appendChildren( layer, [
            this._domLabel = el( 'span', [ this.get( 'label' ) ] ),
            this.get( 'isExpanding' ) ? el( 'pre', [
                this._mirror = el( 'span', {
                    text: NS.bind( 'value', this )
                }),
                el( 'br' )
            ]) : null,
            control
        ]);
    },

    // --- Keep render in sync with state ---

    propertyNeedsRedraw: function ( _, property ) {
        var isValue = ( property === 'value' );
        if ( !isValue || !this._settingFromInput ) {
            TextView.parent.propertyNeedsRedraw.apply( this, arguments );
        }
        if ( isValue && this.get( 'isExpanding' ) ) {
            NS.RunLoop.queueFn( 'after', this.didResize, this );
        }
    }.observes( 'className', 'layerStyles',
        'isDisabled', 'label', 'tooltip', 'tabIndex',
        'value', 'placeholder', 'maxLength' ),

    redrawValue: function () {
        var value = this.get( 'value' );
        this._domControl.value = value;
        // Ensure placeholder is updated.
        if ( !this.get( 'isFocussed' ) ) {
            this._onBlur();
        }
    },

    redrawPlaceholder: function () {
        var placeholder = this.get( 'placeholder' ),
            control = this._domControl;
        if ( nativePlaceholder ) {
            control.placeholder = placeholder;
        } else if ( this._placeholderShowing ) {
            control.value = placeholder;<commit_msg>Fix reference after destroy bug in TextView.<commit_after>// -------------------------------------------------------------------------- \\
// File: TextView.js                                                          \\
// Module: View                                                               \\
// Requires: Core, Foundation, DOM, Validate, AbstractControlView.js          \\
// Author: <NAME>                                                       \\
// License: © 2010–2012 Opera Software ASA. All rights reserved.              \\
// -------------------------------------------------------------------------- \\

/*global document */

"use strict";

( function ( NS, undefined ) {

var isOperaMini = !!NS.UA.operaMini;
var nativePlaceholder = !isOperaMini &&
        'placeholder' in document.createElement( 'input' );

var TextView = NS.Class({

    Extends: NS.AbstractControlView,

    Mixin: NS.Validate,

    init: function () {
        TextView.parent.init.apply( this, arguments );
        this._settingFromInput = false;
        this.initValidate();
    },

    isMasked: false,
    isMultiline: false,
    isExpanding: false,
    isHighlighted: false,
    isFocussed: false,

    maxLength: undefined,

    placeholder: '',
    value: '',

    selection: function ( selection ) {
        var control = this._domControl,
            isNumber = ( typeof selection === 'number' ),
            start = selection ? isNumber ?
                    selection : selection.start : 0,
            end = selection ? isNumber ?
                    selection : selection.end || start : start;
        if ( selection !== undefined ) {
            // Ensure any value changes have been drawn.
            this.redraw();
            // Firefox will throw an error if the control is not actually in the
            // document when trying to set the selection. There might be other
            // situations where it does so as well, so just using a try/catch to
            // guard against all.
            try {
                control.setSelectionRange( start, end );
            } catch ( error ) {}
        } else {
            // Firefox sometimes throws an error if you try to read the
            // selection. Again, probably if the control is not actually in the
            // document.
            try {
                start = control.selectionStart;
                end = control.selectionEnd;
            } catch ( error ) {}
        }
        return selection || {
            start: start,
            end: end
        };
    }.property().nocache(),

    blurOnEscape: true,

    // --- Render ---

    allowTextSelection: true,

    type: function () {
        return this.get( 'isMultiline' ) ?
            this.get( 'isExpanding' ) ? 'expanding' : 'multiline' : 'text';
    }.property(),

    className: function () {
        return 'TextView ' + this.get( 'type' ) +
            ( this.get( 'isHighlighted' ) ? ' highlight' : '' ) +
            ( this.get( 'isFocussed' ) ? ' focussed' : '' ) +
            ( this.get( 'isValid' ) ? '' : ' invalid' ) +
            ( this.get( 'isDisabled' ) ? ' disabled' : '' );
    }.property( 'type', 'isHighlighted',
        'isFocussed', 'isValid', 'isDisabled' ),

    draw: function ( layer ) {
        var Element = NS.Element,
            el = NS.Element.create,
            value = this.get( 'value' ),
            placeholder = this.get( 'placeholder' ),
            control = this._domControl = el(
                this.get( 'isMultiline' ) ? 'textarea' : 'input', {
                    type: this.get( 'isMasked' ) ? 'password' : 'text',
                    autocomplete: 'off',
                    disabled: this.get( 'isDisabled' ),
                    tabIndex: this.get( 'tabIndex' ),
                    maxLength: this.get( 'maxLength' ),
                    value: value
                });

        // Need to add explicit handlers, or Opera Mini won't fire the events
        if ( isOperaMini ) {
            control.onfocus = function () {};
            control.onblur = function () {};
        }

        if ( placeholder ) {
            if ( nativePlaceholder ) {
                control.placeholder = placeholder;
            } else if ( !value ) {
                control.className = 'placeholder';
                control.value = placeholder;
                this._placeholderShowing = true;
            }
        }

        layer.title = this.get( 'tooltip' );
        Element.appendChildren( layer, [
            this._domLabel = el( 'span', [ this.get( 'label' ) ] ),
            this.get( 'isExpanding' ) ? el( 'pre', [
                this._mirror = el( 'span', {
                    text: NS.bind( 'value', this )
                }),
                el( 'br' )
            ]) : null,
            control
        ]);
    },

    // --- Keep render in sync with state ---

    propertyNeedsRedraw: function ( _, property ) {
        var isValue = ( property === 'value' );
        if ( !isValue || !this._settingFromInput ) {
            TextView.parent.propertyNeedsRedraw.apply( this, arguments );
        }
        if ( isValue && this.get( 'isExpanding' ) ) {
            NS.RunLoop.queueFn( 'after', this.parentViewDidResize, this );
        }
    }.observes( 'className', 'layerStyles',
        'isDisabled', 'label', 'tooltip', 'tabIndex',
        'value', 'placeholder', 'maxLength' ),

    redrawValue: function () {
        var value = this.get( 'value' );
        this._domControl.value = value;
        // Ensure placeholder is updated.
        if ( !this.get( 'isFocussed' ) ) {
            this._onBlur();
        }
    },

    redrawPlaceholder: function () {
        var placeholder = this.get( 'placeholder' ),
            control = this._domControl;
        if ( nativePlaceholder ) {
            control.placeholder = placeholder;
        } else if ( this._placeholderShowing ) {
            control.value = placeholder;
{'fraction_non_alphanumeric': 0.14692183927512914, 'fraction_numerical': 0.0015242611567448557, 'mean_word_length': 1.4072564207093354, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4542749', 'n_tokens_mistral': 3098, 'n_tokens_neox': 2960, 'n_words': 791}