Add support for teleport, delete, and filtering in entity list

This commit is contained in:
Ryan Huffman 2015-01-13 15:35:19 -08:00
parent ce60a410cf
commit 9e8458edd9
3 changed files with 171 additions and 44 deletions

View file

@ -2,13 +2,30 @@
<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;
var ASC_STRING = '&nbsp;&#x25BE;';
var DESC_STRING = '&nbsp;&#x25B4;';
function loaded() {
elEntityTable = document.getElementById("entity-table");
elEntityTableBody = document.getElementById("entity-table-body");
elRefresh = document.getElementById("refresh");
elDelete = document.getElementById("delete");
elTeleport = document.getElementById("teleport");
document.getElementById("entity-type").onclick = function() {
setSortColumn('type');
};
document.getElementById("entity-url").onclick = function() {
setSortColumn('url');
};
function onRowClicked(e) {
var id = this.dataset.entityId;
@ -40,14 +57,17 @@
function addEntity(id, type, url) {
if (entities[id] === undefined) {
var urlParts = url.split('/');
var filename = urlParts[urlParts.length - 1];
var el = document.createElement('tr');
el.setAttribute('id', 'entity_' + id);
el.innerHTML += "<td>" + type + "</td>";
el.innerHTML += "<td>" + url + "</td>";
el.innerHTML += "<td class='type'>" + type + "</td>";
el.innerHTML += "<td class='url' title='" + url + "'><div class='outer'><div class='inner'>" + filename + "</div></div></td>";
el.dataset.entityId = id;
el.onclick = onRowClicked;
el.ondblclick = onRowDoubleClicked;
elEntityTable.appendChild(el);
elEntityTableBody.appendChild(el);
// Add element to local dict
entities[id] = {
@ -55,43 +75,94 @@
name: id,
el: el,
};
if (refreshEntityListTimer) {
clearTimeout(refreshEntityListTimer);
}
refreshEntityListTimer = setTimeout(refreshEntityListObject, 50);
}
}
function removeEntity(id) {
if (entities[id] !== undefined) {
elEntityTable.removeChild(entities[id].el);
elEntityTableBody.removeChild(entities[id].el);
delete entities[id];
}
}
function clearEntities() {
for (id in entities) {
elEntityTable.removeChild(entities[id].el);
elEntityTableBody.removeChild(entities[id].el);
}
entities = {};
}
elRefresh.onclick = function() {
var elSortOrder = {
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";
}
console.log(currentSortColumn, currentSortOrder);
elSortOrder[column].innerHTML = currentSortOrder == "asc" ? ASC_STRING : DESC_STRING;
entityList.sort(currentSortColumn, { order: currentSortOrder });
}
function refreshEntities() {
clearEntities();
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
}
function refreshEntityListObject() {
refreshEntityListTimer = null;
entityList = new List('entity-list', { valueNames: ['type', 'url']});
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();
}
if (window.EventBridge !== undefined) {
EventBridge.scriptEventReceived.connect(function(data) {
data = JSON.parse(data);
if (data.type == "selectionUpdate") {
selectedEntities = data.selectedIDs;
for (var id in entities) {
entities[id].el.className = '';
}
for (var i = 0; i < data.selectedIDs.length; i++) {
var id = data.selectedIDs[i];
if (id in entities) {
var entity = entities[id];
entity.el.className = 'selected';
}
var notFound = updateSelectedEntities(data.selectedIDs);
if (notFound) {
refreshEntities();
}
} else if (data.type == "update") {
var newEntities = data.entities;
@ -99,27 +170,42 @@
var id = newEntities[i].id;
addEntity(id, newEntities[i].type, newEntities[i].url);
}
updateSelectedEntities(data.selectedIDs);
}
});
}
// var _id = 0;
// setInterval(function() {
// for(var i = 0; i < 2; i++) {
// addEntity(_id, ['Model', 'Light'][i], 'http' + _id);
// _id++;
// }
// }, 5000);
setTimeout(refreshEntities, 1);
}
</script>
</head>
<body onload='loaded();'>
<div>
<button id="refresh">Refresh</button>
<input type="button" id="refresh" value="Refresh"></button>
<input type="button" id="teleport" value="Teleport"></button>
<input type="button" id="delete" style="background-color: rgb(244, 64, 64); float: right" value="Delete"></button>
</div>
<table id="entity-table">
<thead>
<tr>
<th id="entity-type">Type</th>
<th id="entity-url">URL</th>
</tr>
</thead>
<tbody id="entity-table-body">
</tbody>
</table>
<div id="entity-list">
<input type="text" class="search" id="filter" placeholder="Filter" />
<table id="entity-table">
<thead>
<tr>
<th id="entity-type">Type <span class="sort-order" style="display: inline">&nbsp;&#x25BE;</span></th>
<th id="entity-url">URL <span class="sort-order" style="display: none">&nbsp;&#x25BE;</span></th>
</tr>
</thead>
<tbody class="list" id="entity-table-body">
</tbody>
</table>
</div>
</body>
</html>

View file

@ -114,6 +114,7 @@ table#entity-table {
#entity-table tr {
cursor: pointer;
border-bottom: 1px solid #e5e5e5;
}
#entity-table tr.selected {
@ -133,14 +134,18 @@ table#entity-table {
border: 0px black solid;
word-wrap: nowrap;
white-space: nowrap;
text-overflow: ellipsis;
}
#entity-table td.url {
white-space: nowrap;
overflow: hidden;
}
th#entity-type {
width: 60px;
}
th#entity-url {
}
div.input-area {
@ -186,3 +191,20 @@ table#properties-table {
col#col-label {
width: 130px;
}
div.outer {
position: relative;
}
div.inner {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
position: absolute;
width: 100%;
}
td {
vertical-align: top;
}

View file

@ -24,10 +24,38 @@ EntityListTool = function(opts) {
type: 'selectionUpdate',
selectedIDs: selectedIDs,
};
print("Sending: " + JSON.stringify(data));
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
});
function sendUpdate() {
var entities = [];
var ids = Entities.findEntities(MyAvatar.position, 100);
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
var properties = Entities.getEntityProperties(id);
entities.push({
id: id.id,
type: properties.type,
url: properties.type == "Model" ? properties.modelURL : "",
});
}
var selectedIDs = [];
for (var i = 0; i < selectionManager.selections.length; i++) {
selectedIDs.push(selectionManager.selections[i].id);
}
var data = {
type: "update",
entities: entities,
selectedIDs: selectedIDs,
};
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
}
webView.eventBridge.webEventReceived.connect(function(data) {
print("Got: " + data);
data = JSON.parse(data);
if (data.type == "selectionUpdate") {
var ids = data.entityIds;
@ -46,22 +74,13 @@ EntityListTool = function(opts) {
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
}
} else if (data.type == "refresh") {
var entities = [];
var ids = Entities.findEntities(MyAvatar.position, 100);
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
var properties = Entities.getEntityProperties(id);
entities.push({
id: id.id,
type: properties.type,
url: properties.type == "Model" ? properties.modelURL : "",
});
sendUpdate();
} else if (data.type == "teleport") {
if (selectionManager.hasSelection()) {
MyAvatar.position = selectionManager.worldPosition;
}
var data = {
type: "update",
entities: entities,
};
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
} else if (data.type == "delete") {
deleteSelectedEntities();
}
});