| /** | |
| * @file Text input and textarea input. | |
| * @author sushuang(sushuang@baidu.com) | |
| */ | |
| define(function (require) { | |
| var $ = require('jquery'); | |
| var lib = require('../lib'); | |
| var Component = require('./Component'); | |
| /** | |
| * 模板中的声明方法举例: | |
| * <div data-cpt=" | |
| * type: 'dt/ui/TextInput', | |
| * name: 'myTextInput', | |
| * viewModel: { | |
| * value: viewModel.valueOb, | |
| * css: 'dtm-text-input', | |
| * type: 'textarea', // 默认为'text' | |
| * disabled: viewModel.disabled, // lib.ob(boolean) | |
| * alert: viewModel.alert, // lib.ob(boolean|string) | |
| * placeholder: lib.ob('asdf') | |
| * }"> | |
| * </div> | |
| * | |
| * @class | |
| * @extends dt/ui/Component | |
| */ | |
| var TextInput = Component.extend({ | |
| _define: { | |
| css: 'dtui-txipt', | |
| viewModel: function () { | |
| return { | |
| // 如果需要对数据进行验证,验证不通过时改变当前输入框中的值, | |
| // 或者需要对输入进行parse, | |
| // 则使用ob.extendWriter,把验证逻辑扩展进ob即可。 | |
| value: lib.ob(''), | |
| mouseEnterSelect: false, // 也可以是lib.ob(true),这样可以动态更改。 | |
| type: 'text', // 可选值:'text'(默认), 'textarea' | |
| placeholder: lib.ob(''), // 可以是lib.ob('asdf') | |
| alert: lib.ob(false), // 如果为true则只显示alert css,如果为string则还显示错误信息 | |
| confirmPoint: { | |
| pressEnter: true, | |
| blur: true | |
| } | |
| }; | |
| }, | |
| viewModelPublic: ['value', 'placeholder', 'text', 'mouseEnterSelect', 'type', 'alert'] | |
| }, | |
| /** | |
| * @override | |
| */ | |
| _init: function () { | |
| var viewModel = this._viewModel(); | |
| var type = viewModel.type = viewModel.type || 'text'; | |
| var $mainEl = this.$el(); | |
| $mainEl.addClass(this.getFullCss( | |
| type === 'textarea' ? '-type-textarea' : '-type-text' | |
| ).join(' ')); | |
| var html = '' | |
| + (type === 'textarea' | |
| ? '<textarea></textarea>' | |
| : '<input type="text"/>' | |
| ) | |
| + '<span class="' | |
| + this.getFullCss('-alert-mark').join(' ') | |
| + '" style="display:none"></span>' | |
| + '<span class="' | |
| + this.getFullCss('-alert-text').join(' ') | |
| + '" style="display:none"></span>'; | |
| this._$input = $($mainEl.html(html)[0].firstChild); | |
| this._$input.on( | |
| this._event('mouseenter'), | |
| function () { | |
| if (lib.peek(viewModel.mouseEnterSelect)) { | |
| this.select && this.select(); | |
| } | |
| } | |
| ); | |
| this._initAlert(); | |
| this._initPlaceHolder(); | |
| this._initViewUpdater(); | |
| this._initModelUpdater(); | |
| }, | |
| /** | |
| * @public | |
| */ | |
| focus: function () { | |
| this._$input.focus(); | |
| }, | |
| /** | |
| * @public | |
| */ | |
| select: function () { | |
| this._$input.select(); | |
| }, | |
| /** | |
| * @private | |
| */ | |
| _initAlert: function () { | |
| var $mainEl = this.$el(); | |
| var cssAlertMark = this.getFullCss('-alert-mark'); | |
| var cssAlertText = this.getFullCss('-alert-text'); | |
| var $alertMark = this.$el( | |
| 'alertMark', $mainEl.find('.' + cssAlertMark[cssAlertMark.length - 1]) | |
| ); | |
| var $alertText = this.$el( | |
| 'alertText', $mainEl.find('.' + cssAlertText[cssAlertText.length - 1]) | |
| ); | |
| $alertMark.on(this._event('mouseenter'), showAlert); | |
| $alertMark.on(this._event('mouseleave'), hideAlert); | |
| this._disposable(this._viewModel().alert.subscribe(updateAlert, this)); | |
| function updateAlert(alert) { | |
| var $el = this.$el(); | |
| var alertCss = this.getFullCss('-alert').join(' '); | |
| if (alert) { | |
| $el.addClass(alertCss); | |
| if ($.type(alert) === 'string') { | |
| $alertText[0].innerHTML = lib.encodeHTML(alert); | |
| $alertMark.show(); | |
| } | |
| } | |
| else { | |
| $el.removeClass(alertCss); | |
| $alertMark.hide(); | |
| } | |
| } | |
| function showAlert() { | |
| $alertText.show(); | |
| } | |
| function hideAlert() { | |
| $alertText.hide(); | |
| } | |
| }, | |
| /** | |
| * @private | |
| */ | |
| _initPlaceHolder: function () { | |
| var placeholderOb = this._viewModel().placeholder; | |
| if (lib.obTypeOf(placeholderOb) === 'ob') { | |
| placeholderOb.subscribe(onChange, this); | |
| onChange.call(this, placeholderOb()); | |
| } | |
| else if (placeholderOb != null) { | |
| onChange.call(this, placeholderOb); | |
| } | |
| function onChange(text) { | |
| this._$input.attr('placeholder', text); | |
| } | |
| }, | |
| /** | |
| * @private | |
| */ | |
| _initViewUpdater: function () { | |
| var viewModel = this._viewModel(); | |
| var $input = this._$input; | |
| // disabled | |
| this._disposable(viewModel.disabled.subscribe( | |
| function (dis) { | |
| $input[0].disabled = !!dis; | |
| }, | |
| this | |
| )); | |
| // 建立文本输入和value的依赖 | |
| this._disposable(viewModel.value.subscribe(updateText, this)); | |
| // 第一次调用 | |
| updateText(viewModel.value()); | |
| function updateText(nextValue) { | |
| // 此更新由文本输入触发时,也会重新写入。因为value可能会在decorator中被改变。 | |
| $input.val(nextValue); | |
| } | |
| }, | |
| /** | |
| * @private | |
| */ | |
| _initModelUpdater: function () { | |
| var viewModel = this._viewModel(); | |
| var insUID = this.uid(); | |
| var $input = this._$input; | |
| var that = this; | |
| // 现在是失焦触发更新,并未做随着输入实时更新。暂无此需求。 | |
| // 监听value对文本输入的依赖 | |
| var confirmPoint = viewModel.confirmPoint || {}; | |
| if (confirmPoint.blur) { | |
| $input.on(this._event('blur'), confirmInput); | |
| } | |
| if (confirmPoint.pressEnter) { | |
| $input.on(this._event('keypress'), onKeyPress); | |
| } | |
| function onKeyPress(event) { | |
| if (that.isDisabled()) { | |
| return; | |
| } | |
| if (viewModel.type === 'text' && event.which === 13) { // Enter键 | |
| confirmInput(); | |
| event.preventDefault(); | |
| } | |
| } | |
| function confirmInput() { | |
| if (that.isDisabled()) { | |
| return; | |
| } | |
| viewModel.value( | |
| $input.val(), lib.valueInfoForConfirmed(insUID), {force: true} | |
| ); | |
| // 因为 value 写入时会负责校验,所以写入完后,还应把当前状态回显到屏幕上 | |
| $input.val(viewModel.value()); | |
| } | |
| }, | |
| /** | |
| * @override | |
| */ | |
| _dispose: function () { | |
| this._$input.off(this._event()); | |
| this._$input = null; | |
| this.$el().html(''); | |
| } | |
| }); | |
| return TextInput; | |
| }); |