///////////////////////// Text /////////////////////////
/**
* A text field
* <pre><strong>options:</strong> {
* element : «Element | ID»,
* name : «String»,
* key : «String»,
* maxHeight : «<strong>100</strong> | integer»,
* animateUserChange : «<strong>true</strong> | false»
* }
*
* <strong>Events:</strong>
* $valueChanged(value) - When the value of the field is changed by the user
* @constructor
*/
hui.ui.TextInput = function(options) {
this.options = hui.override({key:null,lines:1,maxHeight:100,animateUserChange:true,submitOnEnter:null},options);
this.element = hui.get(options.element);
this.name = options.name;
hui.ui.extend(this);
this.input = this.element;
this.multiline = this.input.tagName.toLowerCase() == 'textarea';
this.placeholder = hui.get.firstByClass(this.element,'hui_field_placeholder');
this.value = this.input.value;
this.modified = false;
this._attach();
};
/**
* Creates a new text field
* <pre><strong>options:</strong> {
* value : «String»,
* multiline : «true | <strong>false</strong>»,
* lines : «<strong>1</strong> | integer»,
*
* name : «String»,
* key : «String»,
* maxHeight : «<strong>100</strong> | integer»,
* animateUserChange : «<strong>true</strong> | false»
* }
* </pre>
*/
hui.ui.TextInput.create = function(options) {
options = hui.override({lines:1},options);
var node,input;
if (options.lines>1 || options.multiline) {
input = hui.build('textarea',
{'class':'hui_textinput','rows':options.lines}
);
} else {
input = hui.build('input',{'class':'hui_textinput'});
if (options.secret) {
input.setAttribute('type','password');
}
}
if (options.testName) {
input.setAttribute('data-test', options.testName);
}
if (options.value!==undefined) {
input.value=options.value;
}
options.element = input;
return new hui.ui.TextInput(options);
};
hui.ui.TextInput.prototype = {
_attach : function() {
if (this.placeholder || this.input.type=='password') {
var self = this;
hui.ui.onReady(function() {
window.setTimeout(function() {
self.value = self.input.value;
self._updateClass();
}, 500);
});
}
hui.ui.addFocusClass({
element: this.input,
classElement: this.element,
'class': 'hui_field_focused',
widget: this
});
hui.listen(this.input, 'keyup', this._onKeyUp.bind(this));
hui.listen(this.input, 'keydown', this._onKeyDown.bind(this));
hui.listen(this.input, 'input', this._onKeyUp.bind(this));
hui.listen(this.input, 'change', this._onChange.bind(this));
var p = this.element.getElementsByTagName('em')[0];
if (p) {
this._updateClass();
hui.listen(p, 'mousedown', function() {
window.setTimeout(function() {
this.input.focus();
this.input.select();
}.bind(this));
}.bind(this));
hui.listen(p, 'mouseup', function() {
this.input.focus();
this.input.select();
}.bind(this));
}
},
_updateClass : function() {
hui.cls.set(this.element,'hui_field_dirty',this.value.length>0);
},
_onKeyDown : function(e) {
if (e.keyCode === 13) {
if (this.multiline && !(e.ctrlKey || e.metaKey)) {
return;
}
hui.stop(e);
this.fire('submit');
var form = hui.ui.getAncestor(this,'hui_form');
if (form) {form.submit();}
}
},
_onChange : function(e) {
this._onKeyUp(e);
},
_onKeyUp : function(e) {
if (this.input.value==this.value) {return;}
this.value=this.input.value;
this._updateClass();
this._expand(this.options.animateUserChange);
hui.ui.callAncestors(this,'childValueChanged',this.input.value);
this.fire('valueChanged',this.input.value);
this.modified = true;
},
/** Focus the text field */
focus : function() {
try {
this.input.focus();
} catch (e) {}
},
/** Select the text in the text field */
select : function() {
try {
this.input.focus();
this.input.select();
} catch (e) {}
},
/** Clear the value of the text field */
reset : function() {
this.setValue('');
},
isModified : function() {
return this.modified;
},
/** Draw attention to the field */
stress : function() {
hui.ui.stress(this);
},
/** Set the value of the field
* @value {String} The value
*/
setValue : function(value) {
if (value===undefined || value===null) {
value='';
}
this.value = value;
this.input.value = value;
this._expand(this.options.animateValueChange);
this.modified = false;
},
/** Get the value
* @returns {String} The value
*/
getValue : function() {
return this.input.value;
},
/** Check if the value is empty ('' / the empty string)
* @returns {Boolean} True if the value the empty string
*/
isEmpty : function() {
return this.input.value === '';
},
/** Check if the value has any non-white-space characters
* @returns {Boolean} True if the value is blank
*/
isBlank : function() {
return hui.isBlank(this.input.value);
},
/** Mark the field with error
* @value {String | Boolean} The error message or true to mark the field
*/
setError : function(error) {
var isError = error ? true : false;
hui.cls.set(this.element,'hui_field_error',isError);
if (typeof(error) == 'string') {
hui.ui.showToolTip({text:error,element:this.element,key:this.name});
}
if (!isError) {
hui.ui.hideToolTip({key:this.name});
}
},
// Expanding...
/** @private */
$visibilityChanged : function() {
if (hui.dom.isVisible(this.element)) {
window.setTimeout(this._expand.bind(this));
}
},
_expand : function(animate) {
if (!this.multiline || !hui.dom.isVisible(this.element)) {
return;
}
var textHeight = this._getTextAreaHeight(this.input);
textHeight = Math.min(textHeight,this.options.maxHeight);
if (animate) {
hui.animate({
node : this.input,
duration : 300,
css : {height:textHeight+'px'},
ease : hui.ease.slowFastSlow
});
} else {
this.input.style.height = textHeight+'px';
}
},
_getTextAreaHeight : function(input) {
var t = this.textAreaDummy;
if (!t) {
t = this.textAreaDummy = hui.build('div.hui_textinput_dummy', {parent: document.body});
}
var html = input.value;
if (html[html.length-1]==='\n') {
html+='x';
}
html = hui.string.escape(html).replace(/\n/g,'<br/>');
t.innerHTML = html;
t.style.width = input.clientWidth + 'px';
return t.clientHeight + 2;
}
};