toloframework
Version:
Javascript/HTML/CSS compiler for Firefox OS or nodewebkit apps using modules in the nodejs style.
234 lines (213 loc) • 6.62 kB
JavaScript
/** @module wdg.combo */require( 'wdg.combo', function(exports, module) { var $ = require("dom");
var DB = require("tfw.data-binding");
var LaterAction = require("tfw.timer").laterAction;
/**
* @class tfw.edit.text
* @description HTML5 text input with many options.
*
* __Attributes__:
* * {string} `value`:
* * {string} `value`:
* * {string} `value`:
* * {string} `value`:
* * {string} `value`:
* * {string} `value`:
* * {string} `value`:
*/
var Text = function(opts) {
var that = this;
var dataListHasFocus = false;
var label = $.div( 'label' );
var input = $.tag( 'input' );
var datalist = $.div( 'datalist' );
this._input = input;
var elem = $.elem( this, 'div', 'wdg-text', [label, input, datalist] );
DB.propString(this, 'value')(function(v) {
input.value = v;
that.validate();
});
DB.propEnum(['text', 'button', 'checkbox', 'color', 'date', 'datetime', 'email', 'file',
'hidden', 'image', 'month', 'password', 'radio', 'range', 'reset',
'search', 'submit', 'tel', 'time', 'url', 'week'])(this, 'type')
(function(v) {
$.att(input, {type: v});
});
DB.propStringArray(this, 'list')(function(v) {
$.clear( datalist );
$.removeClass( elem, "list" );
if (!Array.isArray( v )) return;
v.forEach(function ( item ) {
$.add( datalist, $.div( [item] ) );
});
$.att( elem, "list" );
});
DB.propValidator(this, 'validator')(this.validate.bind( this ));
DB.propBoolean(this, 'valid')(function(v) {
if (v === null || !that.validator) {
$.removeClass( elem, "valid", "no-valid" );
} else {
if (v) {
$.addClass( elem, "valid" );
$.removeClass( elem, "no-valid" );
} else {
$.removeClass( elem, "valid" );
$.addClass( elem, "no-valid" );
}
}
});
DB.propBoolean(this, 'enabled')(function(v) {
if (v) {
$.removeAtt(input, 'disabled');
} else {
$.att(input, {disabled: v});
}
});
DB.propInteger(this, 'size')(function(v) {
if (v < 1) {
$.removeAtt(input, 'size');
} else {
$.att(input, {size: v});
}
});
DB.propString(this, 'label')(function(v) {
if (v === null || (typeof v === 'string' && v.trim() == '')) {
$.addClass(elem, 'no-label');
} else {
$.removeClass(elem, 'no-label');
$.textOrHtml(label, v);
if (v.substr(0, 6) == '<html>') {
$.att(label, {title: ''});
} else {
$.att(label, {title: v});
}
}
});
DB.propString(this, 'placeholder')(function(v) {
$.att(input, {placeholder: v});
});
DB.propString(this, 'width')(function(v) {
elem.style.width = v;
});
DB.propInteger(this, 'action', '');
opts = DB.extend({
value: '',
type: 'text',
placeholder: '',
enabled: true,
validator: null,
valid: true,
list: null,
label: null,
placeholder: '',
size: 10,
width: 'auto',
wide: false,
visible: true
}, opts, this);
var complete = function() {
$.removeClass( elem, "list" );
if (!that.list || that.list.length == 0) return;
$.clear( datalist );
var list = that.list.map(String.toLowerCase);
var needle = input.value.trim().toLowerCase();
if (needle.length > 0) {
list = list.map(function(itm, idx) {
return [idx, itm.indexOf( needle )];
}).filter(function(itm) {
return itm[1] > -1;
}).sort(function(a, b) {
var d = a[1] - b[1];
if (d != 0) return d;
var sa = that.list[a[0]];
var sb = that.list[b[0]];
if (sa < sb) return -1;
if (sa > sb) return 1;
return 0;
}).map(function(itm) {
var t = that.list[itm[0]];
var i = itm[1];
return t.substr(0, i)
+ "<b>" + t.substr(i, needle.length) + "</b>"
+ t.substr(i + needle.length);
});
} else {
list = list.sort();
}
list.forEach(function (item) {
var div = $.div();
div.innerHTML = item;
$.add( datalist, div );
$.on( div, {
down: function() {
dataListHasFocus = true;
},
up: function() {
dataListHasFocus = false;
input.focus();
},
tap: function() {
that.value = div.textContent.trim();
$.removeClass( elem, 'list' );
}
});
});
$.addClass( elem, "list" );
};
var actionUpdateValue = LaterAction(function() {
that.value = input.value;
}, 300);
input.addEventListener('keyup', function() {
complete();
actionUpdateValue.fire();
});
input.addEventListener('blur', function() {
that.value = input.value;
if (!dataListHasFocus) {
$.removeClass( elem, "list" );
}
});
input.addEventListener('focus', that.selectAll.bind(that));
input.addEventListener('keydown', function(evt) {
if (evt.keyCode == 13) {
evt.preventDefault();
evt.stopPropagation();
if (that.valid !== false) {
DB.fire( that, 'value', input.value );
DB.fire( that, 'action', input.value );
}
}
});
this.validate();
};
/**
* Force value validation.
*/
Text.prototype.validate = function() {
var validator = this.validator;
if (!validator) return;
try {
this.valid = validator( this.value );
}
catch (ex) {
console.error("[wdg.text:validate] Exception = ", ex);
console.error("[wdg.text:validate] Validator = ", validator);
}
};
/**
* Select whole text.
* @return {this}
*/
Text.prototype.selectAll = function() {
var e = this._input;
e.setSelectionRange(0, e.value.length);
return true;
};
module.exports = Text;
/**
* @module wdg.combo
* @see module:dom
* @see module:tfw.data-binding
* @see module:tfw.timer
* @see module:wdg.combo
*/
});