Combo v3
This commit is contained in:
parent
c4afb057aa
commit
8061d58ad8
|
@ -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));
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue