Merge branch 'master' of ssh://git.verdnatura.es:/var/lib/git/salix

This commit is contained in:
Javi Gallego 2017-01-20 12:43:44 +01:00
commit b953d7fa4f
2 changed files with 115 additions and 55 deletions

View File

@ -24,12 +24,7 @@ function template($element, $attrs, normalizer, resolve) {
controller.$inject = ['$http', '$element', '$attrs', '$scope', '$parse', '$document', 'vnPopover'];
function controller($http, $element, $attrs, $scope, $parse, $document, popoverProvider) {
let input = $element.find('input')[0];
let popover = null;
let data = [];
let locked = false;
let timeoutId = null;
let activeOption = -1;
$scope.$watch($attrs.model, (newValue) => {
if(!locked) {
@ -45,8 +40,43 @@ function controller($http, $element, $attrs, $scope, $parse, $document, popoverP
componentHandler.upgradeElement($element[0].firstChild);
Object.assign(this, {
loadData: function(where, callback) {
if(!where) where = {};
init: function() {
this.input = $element.find('input')[0];
this.popover = null;
this.data = null;
this.showData = null;
this.timeoutId = null;
this.activeOption = -1;
this.lastSearch = null;
this.lastRequest = null;
this.maxRows = 10;
this.filterDelay = 350;
this.loadData();
},
loadData: function(value) {
// Optimiza la petición
let lastSearch = this.lastSearch;
if(lastSearch === value) return;
this.lastSearch = value;
let lastRequest = this.lastRequest;
let requestWillSame = (
this.data && value && lastRequest
&& this.data.length < this.maxRows
&& value.substr(0, lastRequest.length) == lastRequest
);
if(requestWillSame) {
this.localFilter(value);
return;
}
// Genera el filtro
let where = {};
if(value) where[this.showField] = {ilike: value};
let fields = {};
fields[this.valueField] = true;
fields[this.showField] = true;
@ -55,48 +85,68 @@ function controller($http, $element, $attrs, $scope, $parse, $document, popoverP
fields: fields,
where: where,
order: `${this.showField} ASC`,
limit: 10
limit: this.maxRows
};
// Envia la petición
this.lastRequest = value;
let json = JSON.stringify(filter);
$http.get(`${this.url}?filter=${json}`).then(
json => {
data = json.data;
if (callback) callback();
},
json => {
data = [];
}
json => this.setData(json.data),
json => this.setData([])
);
},
setData: function(data) {
this.data = data;
this.setShowData(this.data);
},
localFilter: function(value) {
let regex = new RegExp(value, 'i');
let data = this.data.filter((item) => {
return regex.test(item[this.showField]);
});
this.setShowData(data);
},
setShowData: function(data) {
this.showData = data;
if(this.hasFocus)
this.showPopover();
else
this.setValue(this.model);
},
showPopover: function() {
//FIXME
this.hidePopover();
popover = $document[0].createElement('ul');
let popover = $document[0].createElement('ul');
popover.addEventListener('click',
(e) => this.onPopoverClick(e));
popover.addEventListener('mousedown',
(e) => this.onPopoverMousedown(e));
popover.className = 'vn-autocomplete-popover';
let data = this.showData;
for(let i = 0; i < data.length; i++) {
let li = $document[0].createElement('li');
li.appendChild($document[0].createTextNode(data[i][this.showField]));
popover.appendChild(li);
}
popoverProvider.show(popover, input);
popoverProvider.show(popover, this.input);
this.popover = popover;
},
hidePopover: function() {
if(!popover) return;
activeOption = -1;
if(!this.popover) return;
this.activeOption = -1;
popoverProvider.hide();
popover = null;
this.popover = null;
},
onPopoverClick: function(event) {
let childs = popover.childNodes;
let childs = this.popover.childNodes;
for(let i = 0; i < childs.length; i++)
if(childs[i] === event.target) {
this.selectOptionByIndex(i);
@ -110,45 +160,48 @@ function controller($http, $element, $attrs, $scope, $parse, $document, popoverP
event.preventDefault();
},
onFocus: function() {
input.select();
this.hasFocus = true;
this.input.select();
this.showPopover();
},
onBlur: function() {
this.hasFocus = false;
this.hidePopover();
},
onKeypress: function(event) {
onKeydown: function(event) {
switch(event.keyCode) {
case 13: // Enter
if(popover && activeOption != -1) {
this.selectOptionByIndex(activeOption);
if(this.popover && this.activeOption != -1) {
this.putValue(this.showData[this.activeOption]);
this.hidePopover();
}
return;
break;
case 27: // Escape
this.hidePopover();
break;
case 38: // Arrow up
this.activateOption(activeOption-1);
return;
this.activateOption(this.activeOption-1);
break;
case 40: // Arrow down
this.activateOption(activeOption+1);
this.activateOption(this.activeOption+1);
break;
default:
return;
}
event.preventDefault();
},
onClick: function(event) {
if(!popover)
this.showPopover();
if(!this.popover) this.showPopover();
},
onKeyup: function(event) {
if(!this.isKeycodePrintable(event.keyCode))
return;
if(timeoutId) clearTimeout(timeoutId);
timeoutId = setTimeout(() => this.onTimeout(), 300);
if(!this.isKeycodePrintable(event.keyCode)) return;
if(this.timeoutId) clearTimeout(this.timeoutId);
this.timeoutId = setTimeout(() => this.onTimeout(), this.filterDelay);
},
onTimeout: function() {
let value = input.value;
let filter = {};
filter[this.showField] = {ilike: value};
this.loadData(filter, () => this.showPopover());
timeoutId = null;
this.loadData(this.input.value);
this.timeoutId = null;
},
isKeycodePrintable: function(keyCode) {
return keyCode == 32 // Spacebar
@ -160,13 +213,13 @@ function controller($http, $element, $attrs, $scope, $parse, $document, popoverP
|| (keyCode > 218 && keyCode < 223); // [\]'
},
activateOption: function(index) {
if(!popover)
if(!this.popover)
this.showPopover();
let childs = popover.childNodes;
let childs = this.popover.childNodes;
if(activeOption >= 0)
childs[activeOption].className = '';
if(this.activeOption >= 0)
childs[this.activeOption].className = '';
if(index >= childs.length)
index = 0;
@ -176,30 +229,37 @@ function controller($http, $element, $attrs, $scope, $parse, $document, popoverP
if (index >= 0)
childs[index].className = 'active';
activeOption = index;
this.activeOption = index;
},
setValue: function(value) {
let index = -1;
let data = this.data;
if(value && data)
for(let i = 0; i < data.length; i++)
if(data[i][this.valueField] == value) {
this.selectOptionByIndex(i);
this.putValue(data[i]);
return;
}
this.selectOptionByIndex(-1);
this.putValue(null);
},
selectOptionByIndex: function(index) {
let data = this.data;
if(data && index >= 0 && index < data.length)
this.putValue(data[index]);
else
this.putValue(null);
},
putValue: function(item) {
let value;
if(index >= 0 && index < data.length) {
let item = data[index];
input.value = item[this.showField];
if(item) {
this.input.value = item[this.showField];
value = item[this.valueField];
}
else {
input.value = '';
this.input.value = '';
value = undefined;
}
@ -215,5 +275,5 @@ function controller($http, $element, $attrs, $scope, $parse, $document, popoverP
}
});
this.loadData(null, () => this.setValue(this.model));
this.init();
}

View File

@ -5,7 +5,7 @@
rule="*[rule]*"
*[enabled]*
*[focus]*
ng-keypress="$ctrl.onKeypress($event)"
ng-keydown="$ctrl.onKeydown($event)"
ng-click="$ctrl.onClick($event)"
ng-keyup="$ctrl.onKeyup($event)"
ng-focus="$ctrl.onFocus($event)"