foam-framework
Version:
MVC metaprogramming framework
190 lines (178 loc) • 5.46 kB
JavaScript
/**
* @license
* Copyright 2014 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
CLASS({
package: 'foam.ui',
name: 'ListInputView',
extends: 'foam.ui.AbstractDAOView',
properties: [
{
name: 'name'
},
{
name: 'dao',
help: 'The DAO to fetch autocomplete objects from.',
},
{
name: 'property',
help: 'The property model to map autocomplete objecst to values with.'
},
{
model_: 'ArrayProperty',
name: 'searchProperties',
help: 'The properties with which to construct the autocomplete query with.'
},
{
name: 'autocompleteView',
postSet: function(oldValue, newValue) {
oldValue && oldValue.unsubscribe('selected', this.selected);
newValue.subscribe('selected', this.selected);
}
},
{
name: 'placeholder',
postSet: function(oldValue, newValue) {
if ( this.$ && this.usePlaceholer ) this.$.placeholder = newValue;
}
},
{
model_: 'BooleanProperty',
name: 'usePlaceholder',
defaultValue: true,
postSet: function(_, newValue) {
if ( this.$ ) this.$.placeholder = newValue ?
this.placeholder : '';
}
},
{
name: 'data',
help: 'The array value we are editing.',
factory: function() { return []; }
},
{
name: 'domInputValue'
}
],
methods: {
toHTML: function() {
this.on('keydown', this.onKeyDown, this.id);
this.on('keypress', this.onKeyPress, this.id);
this.on('blur', this.framed(this.delay(200, this.framed(this.framed(this.onBlur)))), this.id);
this.on('focus', this.onInput, this.id);
return '<input name="' + this.name + '" type="text" id="' + this.id + '" class="listInputView">' + this.autocompleteView.toHTML();
},
initHTML: function() {
this.SUPER();
if ( this.usePlaceholder && this.placeholder )
this.$.placeholder = this.placeholder;
this.autocompleteView.initHTML();
this.domInputValue = DomValue.create(this.$, 'input');
this.domInputValue.addListener(this.onInput);
},
pushValue: function(v) {
this.data = this.data.concat(v);
this.domInputValue.set('');
// Previous line doesn't trigger listeners.
this.onInput();
},
popValue: function() {
var a = this.data.slice();
a.pop();
this.data = a;
}
},
listeners: [
{
name: 'selected',
code: function() {
if ( this.autocompleteView.data ) {
this.pushValue(
this.property.f(this.autocompleteView.data));
}
this.scrollContainer = e || window;
this.scrollContainer.addEventListener('scroll', this.onScroll, false);
}
},
{
name: 'onInput',
code: function() {
var value = this.domInputValue.get();
if ( value.charAt(value.length - 1) === ',' ) {
if ( value.length > 1 ) this.pushValue(value.substring(0, value.length - 1));
else this.domInputValue.set('');
return;
}
if ( value === '' ) {
this.autocompleteView.dao = [];
return;
}
var predicate = OR();
value = this.domInputValue.get();
for ( var i = 0; i < this.searchProperties.length; i++ ) {
predicate.args.push(STARTS_WITH(this.searchProperties[i], value));
}
value = this.data;
if ( value.length > 0 ) {
predicate = AND(NOT(IN(this.property, value)), predicate);
}
this.autocompleteView.dao = this.dao.where(predicate);
}
},
{
name: 'onKeyDown',
code: function(e) {
if ( e.keyCode === 40 /* down */) {
this.autocompleteView.nextSelection();
e.preventDefault();
} else if ( e.keyCode === 38 /* up */ ) {
this.autocompleteView.prevSelection();
e.preventDefault();
} else if ( e.keyCode === 13 /* RET */ || e.keyCode === 9 /* TAB */ ) {
if ( this.autocompleteView.data ) {
this.pushValue(
this.property.f(this.autocompleteView.data));
e.preventDefault();
}
} else if ( e.keyCode === 8 && this.domInputValue.get() === '' ) {
this.popValue();
}
}
},
{
name: 'onKeyPress',
documentation: 'Prevent shortcut keys from firing on <input> element',
code: function(e) { e.stopPropagation(); }
},
{
name: 'onBlur',
code: function(e) {
var value = this.domInputValue.get();
if ( value.length > 0 ) {
this.pushValue(value);
} else {
this.domInputValue.set('');
}
this.autocompleteView.dao = [];
}
},
{
name: 'onValueChange',
code: function() {
this.usePlaceholder = this.data.length == 0;
}
}
]
});