overte/examples/html/entityList.html
2015-09-21 09:59:00 -07:00

266 lines
12 KiB
HTML

<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="list.min.js"></script>
<script>
var entities = {};
var selectedEntities = [];
var currentSortColumn = 'type';
var currentSortOrder = 'asc';
var entityList = null;
var refreshEntityListTimer = null;
const ASCENDING_STRING = '&nbsp;&#x25BE;';
const DESCENDING_STRING = '&nbsp;&#x25B4;';
const DELETE = 46; // Key code for the delete key.
const MAX_ITEMS = Number.MAX_VALUE; // Used to set the max length of the list of discovered entities.
function loaded() {
entityList = new List('entity-list', { valueNames: ['name', 'type', 'url'], page: MAX_ITEMS});
entityList.clear();
elEntityTable = document.getElementById("entity-table");
elEntityTableBody = document.getElementById("entity-table-body");
elRefresh = document.getElementById("refresh");
elDelete = document.getElementById("delete");
elTeleport = document.getElementById("teleport");
elRadius = document.getElementById("radius");
elNoEntitiesMessage = document.getElementById("no-entities");
elNoEntitiesRadius = document.getElementById("no-entities-radius");
document.getElementById("entity-name").onclick = function() {
setSortColumn('name');
};
document.getElementById("entity-type").onclick = function() {
setSortColumn('type');
};
document.getElementById("entity-url").onclick = function() {
setSortColumn('url');
};
function onRowClicked(clickEvent) {
var id = this.dataset.entityId;
var selection = [this.dataset.entityId];
if (clickEvent.ctrlKey) {
selection = selection.concat(selectedEntities);
} else if (clickEvent.shiftKey && selectedEntities.length > 0) {
var previousItemFound = -1;
var clickedItemFound = -1;
for (var entity in entityList.visibleItems) {
if (clickedItemFound === -1 && this.dataset.entityId == entityList.visibleItems[entity].values().id) {
clickedItemFound = entity;
} else if(previousItemFound === -1 && selectedEntities[0] == entityList.visibleItems[entity].values().id) {
previousItemFound = entity;
}
}
if (previousItemFound !== -1 && clickedItemFound !== -1) {
var betweenItems = [];
var toItem = Math.max(previousItemFound, clickedItemFound);
// skip first and last item in this loop, we add them to selection after the loop
for (var i = (Math.min(previousItemFound, clickedItemFound) + 1); i < toItem; i++) {
entityList.visibleItems[i].elm.className = 'selected';
betweenItems.push(entityList.visibleItems[i].values().id);
}
if (previousItemFound > clickedItemFound) {
// always make sure that we add the items in the right order
betweenItems.reverse();
}
selection = selection.concat(betweenItems, selectedEntities);
}
}
selectedEntities = selection;
this.className = 'selected';
EventBridge.emitWebEvent(JSON.stringify({
type: "selectionUpdate",
focus: false,
entityIds: selection,
}));
}
function onRowDoubleClicked() {
EventBridge.emitWebEvent(JSON.stringify({
type: "selectionUpdate",
focus: true,
entityIds: [this.dataset.entityId],
}));
}
function addEntity(id, name, type, url) {
if (entities[id] === undefined) {
var urlParts = url.split('/');
var filename = urlParts[urlParts.length - 1];
entityList.add([{ id: id, name: name, type: type, url: filename }], function(items) {
var currentElement = items[0].elm;
var id = items[0]._values.id;
entities[id] = {
id: id,
name: name,
el: currentElement,
item: items[0],
};
currentElement.setAttribute('id', 'entity_' + id);
currentElement.setAttribute('title', url);
currentElement.dataset.entityId = id;
currentElement.onclick = onRowClicked;
currentElement.ondblclick = onRowDoubleClicked;
});
if (refreshEntityListTimer) {
clearTimeout(refreshEntityListTimer);
}
refreshEntityListTimer = setTimeout(refreshEntityListObject, 50);
} else {
var item = entities[id].item;
item.values({ name: name, url: url });
}
}
function clearEntities() {
entities = {};
entityList.clear();
}
var elSortOrder = {
name: document.querySelector('#entity-name .sort-order'),
type: document.querySelector('#entity-type .sort-order'),
url: document.querySelector('#entity-url .sort-order'),
}
function setSortColumn(column) {
if (currentSortColumn == column) {
currentSortOrder = currentSortOrder == "asc" ? "desc" : "asc";
} else {
elSortOrder[currentSortColumn].style.display = 'none';
elSortOrder[column].style.display = 'inline';
currentSortColumn = column;
currentSortOrder = "asc";
}
elSortOrder[column].innerHTML = currentSortOrder == "asc" ? ASCENDING_STRING : DESCENDING_STRING;
entityList.sort(currentSortColumn, { order: currentSortOrder });
}
function refreshEntities() {
clearEntities();
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
}
function refreshEntityListObject() {
refreshEntityListTimer = null;
entityList.sort(currentSortColumn, { order: currentSortOrder });
entityList.search(document.getElementById("filter").value);
}
function updateSelectedEntities(selectedEntities) {
var notFound = false;
for (var id in entities) {
entities[id].el.className = '';
}
for (var i = 0; i < selectedEntities.length; i++) {
var id = selectedEntities[i];
if (id in entities) {
var entity = entities[id];
entity.el.className = 'selected';
} else {
notFound = true;
}
}
return notFound;
}
elRefresh.onclick = function() {
refreshEntities();
}
elTeleport.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'teleport' }));
}
elDelete.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
refreshEntities();
}
document.addEventListener("keydown", function (keyDownEvent) {
if (keyDownEvent.target.nodeName === "INPUT") {
return;
}
var keyCode = keyDownEvent.keyCode;
if (keyCode === DELETE) {
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
refreshEntities();
}
}, false);
elRadius.onchange = function () {
elRadius.value = Math.max(elRadius.value, 0);
EventBridge.emitWebEvent(JSON.stringify({ type: 'radius', radius: elRadius.value }));
refreshEntities();
elNoEntitiesRadius.firstChild.nodeValue = elRadius.value;
}
if (window.EventBridge !== undefined) {
EventBridge.scriptEventReceived.connect(function(data) {
data = JSON.parse(data);
if (data.type === "clearEntityList") {
clearEntities();
} else if (data.type == "selectionUpdate") {
var notFound = updateSelectedEntities(data.selectedIDs);
if (notFound) {
refreshEntities();
}
} else if (data.type == "update") {
var newEntities = data.entities;
if (newEntities.length == 0) {
elEntityTable.style.display = "none";
elNoEntitiesMessage.style.display = "block";
} else {
elEntityTable.style.display = "table";
elNoEntitiesMessage.style.display = "none";
for (var i = 0; i < newEntities.length; i++) {
var id = newEntities[i].id;
addEntity(id, newEntities[i].name, newEntities[i].type, newEntities[i].url);
}
updateSelectedEntities(data.selectedIDs);
}
}
});
setTimeout(refreshEntities, 1000);
}
}
</script>
</head>
<body onload='loaded();'>
<div id="entity-list-header">
<input type="button" id="refresh" value="Refresh" />
<input type="button" id="teleport" value="Teleport" />
<input type="button" id="delete" style="background-color: rgb(244, 64, 64); float: right" value="Delete" />
</div>
<div id="entity-list">
<div id="search-area">
<input type="text" class="search" id="filter" placeholder="Filter" />
<span id="radius-and-unit"><input type="number" id="radius" value="100" />&nbsp;m</span>
</div>
<table id="entity-table">
<thead>
<tr>
<th id="entity-type" data-sort="type">Type <span class="sort-order" style="display: inline">&nbsp;&#x25BE;</span></th>
<th id="entity-name" data-sort="type">Name <span class="sort-order" style="display: inline">&nbsp;&#x25BE;</span></th>
<th id="entity-url" data-sort="url">URL <span class="sort-order" style="display: none">&nbsp;&#x25BE;</span></th>
</tr>
</thead>
<tbody class="list" id="entity-table-body">
<tr>
<td class="id" style="display: none">Type</td>
<td class="type">Type</td>
<td class="name">Name</td>
<td class="url"><div class='outer'><div class='inner'>URL</div></div></td>
</tr>
</tbody>
</table>
</div>
<div id="no-entities">
No entities found within a <span id="no-entities-radius">100</span> meter radius. Try moving to a different location and refreshing.
</div>
</body>
</html>