contacts-pane
Version:
Contacts Pane: Contacts manager for Address Book, Groups, and Individuals.
239 lines • 11.4 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderAutoComplete = renderAutoComplete;
const solid_logic_1 = require("solid-logic");
const solid_ui_1 = require("solid-ui");
const publicData_1 = require("./publicData");
const AUTOCOMPLETE_THRESHOLD = 4; // don't check until this many characters typed
const AUTOCOMPLETE_ROWS = 20; // 20?
const AUTOCOMPLETE_ROWS_STRETCH = 40;
const AUTOCOMPLETE_DEBOUNCE_MS = 300;
const autocompleteRowStyle = 'border: 0.2em solid straw;'; // @@ white
// The core of the autocomplete UI
function renderAutoComplete(dom, options, // subject:NamedNode, predicate:NamedNode,
callback) {
return __awaiter(this, void 0, void 0, function* () {
function complain(message) {
const errorRow = table.appendChild(dom.createElement('tr'));
console.log(message);
errorRow.appendChild(solid_ui_1.widgets.errorMessageBlock(dom, message, 'pink'));
solid_ui_1.style.setStyle(errorRow, 'autocompleteRowStyle');
errorRow.style.padding = '1em';
}
function remove(ele) {
if (ele) {
ele.parentNode.removeChild(ele);
}
}
function finish(object, name) {
console.log('Auto complete: finish! ' + object);
// remove(options.cancelButton)
// remove(options.acceptButton)
// remove(div)
callback(object, name);
}
function gotIt(object, name) {
return __awaiter(this, void 0, void 0, function* () {
if (options.acceptButton) {
options.acceptButton.disabled = false;
searchInput.value = name; // complete it
foundName = name;
foundObject = object;
console.log('Auto complete: name: ' + name);
console.log('Auto complete: waiting for accept ' + object);
return;
}
finish(object, name);
});
}
function acceptButtonHandler(_event) {
return __awaiter(this, void 0, void 0, function* () {
if (searchInput.value === foundName) { // still
finish(foundObject, foundName);
}
else {
options.acceptButton.disabled = true;
}
});
}
function cancelButtonHandler(_event) {
return __awaiter(this, void 0, void 0, function* () {
console.log('Auto complete: Canceled by user! ');
div.innerHTML = ''; // Clear out the table
});
}
function nameMatch(filter, candidate) {
const parts = filter.split(' '); // Each name part must be somewhere
for (let j = 0; j < parts.length; j++) {
const word = parts[j];
if (candidate.toLowerCase().indexOf(word) < 0)
return false;
}
return true;
}
function cancelText(_event) {
searchInput.value = '';
if (options.acceptButton) {
options.acceptButton.disabled == true; // start again
}
candidatesLoaded = false;
}
function thinOut(filter) {
var hits = 0;
var pick = null, pickedName = '';
for (let j = table.children.length - 1; j > 0; j--) { // backwards as we are removing rows
let row = table.children[j];
if (nameMatch(filter, row.textContent)) {
hits += 1;
pick = row.getAttribute('subject');
pickedName = row.textContent;
row.style.display = '';
row.style.color = 'blue'; // @@ chose color
}
else {
;
row.style.display = 'none';
}
}
if (hits == 1) { // Maybe require green confirmation button be clicked?
console.log(` auto complete elimination: "${filter}" -> "${pickedName}"`);
gotIt(solid_logic_1.store.sym(pick), pickedName); // uri, name
}
}
function clearList() {
while (table.children.length > 1) {
table.removeChild(table.lastChild);
}
}
function inputEventHHandler(_event) {
return __awaiter(this, void 0, void 0, function* () {
if (runningTimeout) {
clearTimeout(runningTimeout);
}
setTimeout(refreshList, AUTOCOMPLETE_DEBOUNCE_MS);
});
}
function refreshList() {
return __awaiter(this, void 0, void 0, function* () {
if (inputEventHandlerLock) {
console.log(`Ignoring "${searchInput.value}" because of lock `);
return;
}
inputEventHandlerLock = true;
var languagePrefs = yield (0, publicData_1.getPreferredLanguages)();
const filter = searchInput.value.trim().toLowerCase();
if (filter.length < AUTOCOMPLETE_THRESHOLD) { // too small
clearList();
candidatesLoaded = false;
numberOfRows = AUTOCOMPLETE_ROWS;
}
else {
if (allDisplayed && lastFilter && filter.startsWith(lastFilter)) {
thinOut(filter); // reversible?
inputEventHandlerLock = false;
return;
}
var bindings;
try {
bindings = yield (0, publicData_1.queryPublicDataByName)(filter, OrgClass, options.queryParams);
// bindings = await queryDbpedia(sparql)
}
catch (err) {
complain('Error querying db of organizations: ' + err);
inputEventHandlerLock = false;
return;
}
candidatesLoaded = true;
const loadedEnough = bindings.length < publicData_1.AUTOCOMPLETE_LIMIT;
if (loadedEnough) {
lastFilter = filter;
}
else {
lastFilter = null;
}
clearList();
const slimmed = (0, publicData_1.filterByLanguage)(bindings, languagePrefs);
if (loadedEnough && slimmed.length <= AUTOCOMPLETE_ROWS_STRETCH) {
numberOfRows = slimmed.length; // stretch if it means we get all items
}
allDisplayed = loadedEnough && slimmed.length <= numberOfRows;
console.log(` Filter:"${filter}" bindings: ${bindings.length}, slimmed to ${slimmed.length}; rows: ${numberOfRows}, Enough? ${loadedEnough}, All displayed? ${allDisplayed}`);
slimmed.slice(0, numberOfRows).forEach(binding => {
const row = table.appendChild(dom.createElement('tr'));
solid_ui_1.style.setStyle(row, 'autocompleteRowStyle');
var uri = binding.subject.value;
var name = binding.name.value;
row.setAttribute('style', 'padding: 0.3em;');
row.setAttribute('subject', uri);
row.style.color = allDisplayed ? '#080' : '#000'; // green means 'you should find it here'
row.textContent = name;
row.addEventListener('click', (_event) => __awaiter(this, void 0, void 0, function* () {
console.log(' click row textContent: ' + row.textContent);
console.log(' click name: ' + name);
gotIt(solid_logic_1.store.sym(uri), name);
}));
});
}
inputEventHandlerLock = false;
});
} // refreshList
/* sparqlForSearch
*
* name -- e.g., "mass"
* theType -- e.g., <http://umbel.org/umbel/rc/EducationalOrganization>
*/
function sparqlForSearch(name, theType) {
let clean = name.replace(/\W/g, ''); // Remove non alphanum so as to protect regexp
const sparql = `select distinct ?subject, ?name where {
?subject a <${theType.uri}>; rdfs:label ?name
FILTER regex(?name, "${clean}", "i")
} LIMIT ${publicData_1.AUTOCOMPLETE_LIMIT}`;
return sparql;
}
const queryParams = options.queryParams;
const OrgClass = options.class; // kb.sym('http://umbel.org/umbel/rc/EducationalOrganization') // @@@ other
if (options.acceptButton) {
options.acceptButton.addEventListener('click', acceptButtonHandler, false);
}
if (options.cancelButton) {
// options.cancelButton.addEventListener('click', cancelButtonHandler, false)
}
let candidatesLoaded = false;
let runningTimeout = null;
let inputEventHandlerLock = false;
let allDisplayed = false;
var lastFilter = null;
var numberOfRows = AUTOCOMPLETE_ROWS;
var div = dom.createElement('div');
var foundName = null; // once found accepted string must match this
var foundObject = null;
var table = div.appendChild(dom.createElement('table'));
table.setAttribute('style', 'max-width: 30em; margin: 0.5em;');
const head = table.appendChild(dom.createElement('tr'));
solid_ui_1.style.setStyle(head, 'autocompleteRowStyle');
const cell = head.appendChild(dom.createElement('td'));
const searchInput = cell.appendChild(dom.createElement('input'));
searchInput.setAttribute('type', 'text');
const searchInputStyle = solid_ui_1.style.searchInputStyle ||
'border: 0.1em solid #444; border-radius: 0.5em; width: 100%; font-size: 100%; padding: 0.1em 0.6em'; // @
searchInput.setAttribute('style', searchInputStyle);
searchInput.addEventListener('keyup', function (event) {
if (event.keyCode === 13) {
acceptButtonHandler(event);
}
}, false);
searchInput.addEventListener('input', inputEventHHandler);
return div;
});
} // renderAutoComplete
const ends = 'ENDS';
//# sourceMappingURL=autocompletePicker.js.map