This commit is contained in:
Juan Ferrer Toribio 2017-01-19 18:11:30 +01:00
parent c4afb057aa
commit 8061d58ad8
3 changed files with 168 additions and 115 deletions

View File

@ -29,6 +29,7 @@ function controller($http, $element, $attrs, $scope, $parse, $document, popover)
let data = [];
let locked = false;
let timeoutId = null;
let activeOption = -1;
$scope.$watch($attrs.model, (newValue) => {
if(!locked) {
@ -43,125 +44,167 @@ function controller($http, $element, $attrs, $scope, $parse, $document, popover)
});
componentHandler.upgradeElement($element[0].firstChild);
this.loadData = function(where, callback) {
if(!where) where = {};
let fields = {};
fields[this.valueField] = true;
fields[this.showField] = true;
Object.assign(this, {
loadData: function(where, callback) {
if(!where) where = {};
let fields = {};
fields[this.valueField] = true;
fields[this.showField] = true;
let filter = {
fields: fields,
where: where,
order: `${this.showField} ASC`,
limit: 5
};
let filter = {
fields: fields,
where: where,
order: `${this.showField} ASC`,
limit: 5
};
let json = JSON.stringify(filter);
let json = JSON.stringify(filter);
$http.get(`${this.url}?filter=${json}`).then(
json => {
data = json.data;
if (callback) callback();
},
json => {
data = [];
$http.get(`${this.url}?filter=${json}`).then(
json => {
data = json.data;
if (callback) callback();
},
json => {
data = [];
}
);
},
showPopover: function() {
//FIXME
this.hidePopover();
dropdown = $document[0].createElement('ul');
dropdown.addEventListener('click',
(e) => this.onPopoverClick(e));
dropdown.addEventListener('mousedown',
(e) => this.onPopoverMousedown(e));
dropdown.className = 'vn-dropdown';
for(let i = 0; i < data.length; i++) {
let li = $document[0].createElement('li');
li.appendChild($document[0].createTextNode(data[i][this.showField]));
dropdown.appendChild(li);
}
);
};
this.onClick = function() {
input[0].select();
this.showDropdown();
};
popover.show(dropdown, input);
},
hidePopover: function() {
activeOption = -1;
popover.hide();
dropdown = null;
},
onPopoverClick: function(event) {
let childs = dropdown.childNodes;
for(let i = 0; i < childs.length; i++)
if(childs[i] === event.target) {
this.selectOptionByIndex(i);
break;
}
this.showDropdown = function() {
//FIXME
popover.hide();
dropdown = $document[0].createElement('ul');
dropdown.addEventListener('click',
(e) => this.onOptionClick(e));
dropdown.className = 'vn-dropdown';
for(let i = 0; i < data.length; i++) {
let li = $document[0].createElement('li');
li.tabIndex = 0;
li.appendChild($document[0].createTextNode(data[i][this.showField]));
dropdown.appendChild(li);
}
popover.show(dropdown, input);
}
this.onOptionClick = function(event) {
popover.hide();
let childs = dropdown.childNodes;
for(let i = 0; i < childs.length; i++)
if(childs[i] === event.target) {
this.selectOptionByIndex(i);
break;
}
}
this.onTimeout = function() {
let value = input.val();
let filter = {};
filter[this.showField] = {ilike: value};
this.loadData(filter, () => this.showDropdown());
clearTimeout(timeoutId);
timeoutId = null;
}
this.onKeyup = function(event) {
if(timeoutId) clearTimeout(timeoutId);
switch(event.keyCode) {
case 13: // Enter
this.selectOptionByIndex(0);
this.hidePopover();
},
onPopoverMousedown: function(event) {
// Prevents input from loosing focus
event.preventDefault();
},
onFocus: function() {
input[0].select();
this.showPopover();
},
onBlur: function() {
this.hidePopover();
},
onKeypress: function(event) {
if(dropdown)
switch(event.keyCode) {
case 13: // Enter
this.selectOptionByIndex(activeOption);
return;
case 38: // Arrow up
this.activateOption(activeOption-1);
return;
case 40: // Arrow down
this.activateOption(activeOption+1);
return;
}
},
onClick: function(event) {
if(!dropdown)
this.showPopover();
},
onKeyup: function(event) {
if(!this.isKeycodePrintable(event.keyCode))
return;
case 40: // Arrow down
dropdown.firstChild.focus();
if(timeoutId) clearTimeout(timeoutId);
timeoutId = setTimeout(() => this.onTimeout(), 300);
},
onTimeout: function() {
let value = input.val();
let filter = {};
filter[this.showField] = {ilike: value};
this.loadData(filter, () => this.showPopover());
timeoutId = null;
},
isKeycodePrintable: function(keycode) {
return keycode == 32 // Spacebar
|| (keycode > 47 && keycode < 58) // Numbers
|| (keycode > 64 && keycode < 91) // Letters
|| (keycode > 95 && keycode < 112) // Numpad
|| (keycode > 185 && keycode < 193) // ;=,-./`
|| (keycode > 218 && keycode < 223); // [\]'
},
activateOption: function(index) {
let childs = dropdown.childNodes;
if(activeOption >= 0)
childs[activeOption].className = '';
if(index >= childs.length)
index = 0;
else if (index < 0)
index = childs.length - 1;
if (index >= 0)
childs[index].className = 'active';
activeOption = index;
},
setValue: function(value) {
let index = -1;
if(value && data)
for(let i = 0; i < data.length; i++)
if(data[i][this.valueField] == value) {
this.selectOptionByIndex(i);
return;
}
this.selectOptionByIndex(-1);
},
selectOptionByIndex: function(index) {
let value;
if(index >= 0 && index < data.length) {
let item = data[index];
input.val(item[this.showField]);
value = item[this.valueField];
}
else {
input.val('');
value = undefined;
}
if(!locked) {
$scope.$apply(function () {
locked = true;
$parse($attrs.model).assign($scope, value);
locked = false;
});
}
}
timeoutId = setTimeout(() => this.onTimeout(), 300);
};
this.setValue = function(value) {
let index = -1;
if(value && data)
for(let i = 0; i < data.length; i++)
if(data[i][this.valueField] == value) {
this.selectOptionByIndex(i);
return;
}
this.selectOptionByIndex(-1);
}
this.selectOptionByIndex = function(index) {
let value;
if(index >= 0 && index < data.length) {
let item = data[index];
input.val(item[this.showField]);
value = item[this.valueField];
}
else {
input.val('');
value = undefined;
}
if(!locked) {
$scope.$apply(function () {
locked = true;
$parse($attrs.model).assign($scope, value);
locked = false;
});
}
}
});
this.loadData(null, () => {
setTimeout(() => this.setValue(this.model));

View File

@ -1,4 +1,14 @@
<div class="mdl-textfield mdl-js-textfield *[className]*" ng-click="$ctrl.onClick($event)">
<input class="mdl-textfield__input" type="text" rule="*[rule]*" ng-keyup="$ctrl.onKeyup($event)" *[enabled]* *[focus]*/>
<div class="mdl-textfield mdl-js-textfield *[className]*">
<input
class="mdl-textfield__input"
type="text"
rule="*[rule]*"
*[enabled]*
*[focus]*
ng-keypress="$ctrl.onKeypress($event)"
ng-click="$ctrl.onClick($event)"
ng-keyup="$ctrl.onKeyup($event)"
ng-focus="$ctrl.onFocus($event)"
ng-blur="$ctrl.onBlur($event)"/>
<label class="mdl-textfield__label" translate>*[label]*</label>
</div>

View File

@ -9,10 +9,10 @@
padding: .8em;
margin: 0;
}
.vn-dropdown > li.active {
background-color: rgba(1,1,1,.1);
}
.vn-dropdown > li:hover {
background-color: rgba(1,1,1,.1);
cursor: pointer;
}
.vn-dropdown > li:active {
background-color: rgba(1,1,1,.2);
}