Some tidying of editable-table implementation.

No more global JS vars, and the row templates no longer contain <tr>
wrappers. Also some use of <table>'s API.
This commit is contained in:
Oliver Hamlet
2014-11-11 17:16:30 +00:00
parent 2e5a0d0eb4
commit ac32501b26
4 changed files with 192 additions and 206 deletions
+187 -201
View File
@@ -4,15 +4,12 @@
<link rel="import" href="../bower_components/core-icons/core-icons.html">
<template id="fileRow">
<tr>
<td><input class="name" type="text" required></td>
<td><input class="display" type="text"></td>
<td><input class="condition" type="text"></td>
<td><paper-icon-button class="delete" icon="delete"></paper-icon-button></td>
</tr>
</template>
<template id="messageRow">
<tr>
<td><select class="type">
<option value="say">Note</option>
<option value="warn">Warning</option>
@@ -26,10 +23,8 @@
</select>
</td>
<td><paper-icon-button class="delete" icon="delete"></paper-icon-button></td>
</tr>
</template>
<template id="tagRow">
<tr>
<td><select class="type">
<option value="add">Add</option>
<option value="remove">Remove</option>
@@ -38,27 +33,21 @@
<td><input class="name" type="text" required></td>
<td><input class="condition" type="text"></td>
<td><paper-icon-button class="delete" icon="delete"></paper-icon-button></td>
</tr>
</template>
<template id="dirtyInfoRow">
<tr>
<td><input class="crc" type="text" maxlength="8" minlength="8" pattern="[0-9A-Fa-f]{8}" required></td>
<td><input class="itm" type="number" min="0" step="1" value="0"></td>
<td><input class="udr" type="number" min="0" step="1" value="0"></td>
<td><input class="nav" type="number" min="0" step="1" value="0"></td>
<td><input class="util" type="text" required></td>
<td><paper-icon-button class="delete" icon="delete"></paper-icon-button></td>
</tr>
</template>
<template id="locationRow">
<tr>
<td><input class="link" type="text" required></td>
<td><input class="ver" type="text"></td>
<td><paper-icon-button class="delete" icon="delete"></paper-icon-button></td>
</tr>
</template>
<template id="gameRow">
<tr>
<td><input class="name" type="text" required></td>
<td>
<select class="type">
@@ -72,7 +61,6 @@
<td><input class="path" type="text"></td>
<td><input class="registry" type="text"></td>
<td><paper-icon-button class="delete" icon="delete"></paper-icon-button></td>
</tr>
</template>
<style>
table[is=editable-table] td:last-child {
@@ -107,221 +95,219 @@ td paper-icon-button.hidden {
</style>
<script>
'use strict';
// Record this document.
var editableTableImportDoc = document.currentScript.ownerDocument;
(function(){
/* Create a <editable-table> element type that extends from <table>. */
var EditableTableProto = Object.create(HTMLTableElement.prototype, {
/* Create a <editable-table> element type that extends from <table>. */
var EditableTableProto = Object.create(HTMLTableElement.prototype, {
handleDrop: {
value: function(evt) {
evt.stopPropagation();
handleDrop: {
value: function(evt) {
evt.stopPropagation();
if (evt.currentTarget.tagName == 'TABLE' && (evt.currentTarget.id == 'req' || evt.currentTarget.id == 'inc' || evt.currentTarget.id == 'loadAfter')) {
var data = {
name: evt.dataTransfer.getData('text/plain')
};
evt.currentTarget.addRow(data);
}
return false;
}
},
handleDragOver: {
value: function(evt) {
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
}
},
getRowsData: {
value: function(writableOnly) {
var writableRows = [];
var rows = this.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
for (var i = 0; i < rows.length; ++i) {
var trash = rows[i].getElementsByClassName('delete');
if (trash.length > 0 && (!writableOnly || !trash[0].classList.contains('hidden'))) {
var rowData = {};
var inputs = rows[i].querySelectorAll('input, paper-input');
for (var j = 0; j < inputs.length; ++j) {
rowData[inputs[j].className] = inputs[j].value;
}
var selects = rows[i].getElementsByTagName('select');
for (var j = 0; j < selects.length; ++j) {
rowData[selects[j].className] = selects[j].value;
}
writableRows.push(rowData);
if (evt.currentTarget.tagName == 'TABLE' && (evt.currentTarget.id == 'req' || evt.currentTarget.id == 'inc' || evt.currentTarget.id == 'loadAfter')) {
var data = {
name: evt.dataTransfer.getData('text/plain')
};
evt.currentTarget.addRow(data);
}
return false;
}
},
return writableRows;
}
},
setReadOnly: {
value: function(row, classMask, readOnly) {
if (readOnly == undefined) {
readOnly = true;
handleDragOver: {
value: function(evt) {
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
}
},
var trash = row.getElementsByClassName('delete')[0];
if (classMask) {
if (classMask.indexOf('delete') != -1) {
getRowsData: {
value: function(writableOnly) {
var writableRows = [];
var rows = this.tBodies[0].rows[0];
for (var i = 0; i < rows.length; ++i) {
var trash = rows[i].getElementsByClassName('delete');
if (trash.length > 0 && (!writableOnly || !trash[0].classList.contains('hidden'))) {
var rowData = {};
var inputs = rows[i].querySelectorAll('input, paper-input');
for (var j = 0; j < inputs.length; ++j) {
rowData[inputs[j].className] = inputs[j].value;
}
var selects = rows[i].getElementsByTagName('select');
for (var j = 0; j < selects.length; ++j) {
rowData[selects[j].className] = selects[j].value;
}
writableRows.push(rowData);
}
}
return writableRows;
}
},
setReadOnly: {
value: function(row, classMask, readOnly) {
if (readOnly == undefined) {
readOnly = true;
}
var trash = row.getElementsByClassName('delete')[0];
if (classMask) {
if (classMask.indexOf('delete') != -1) {
trash.classList.toggle('hidden', readOnly);
}
} else {
trash.classList.toggle('hidden', readOnly);
}
} else {
trash.classList.toggle('hidden', readOnly);
}
var inputs = row.querySelectorAll('input, paper-input');
for (var i = 0; i < inputs.length; ++i) {
if (classMask) {
for (var j = 0; j < classMask.length; ++j) {
if (inputs[i].classList.contains(classMask[j])) {
if (inputs[i].tagName == 'PAPER-INPUT') {
inputs[i].readonly = readOnly;
} else {
inputs[i].readOnly = readOnly;
var inputs = row.querySelectorAll('input, paper-input');
for (var i = 0; i < inputs.length; ++i) {
if (classMask) {
for (var j = 0; j < classMask.length; ++j) {
if (inputs[i].classList.contains(classMask[j])) {
if (inputs[i].tagName == 'PAPER-INPUT') {
inputs[i].readonly = readOnly;
} else {
inputs[i].readOnly = readOnly;
}
break;
}
break;
}
} else {
if (inputs[i].tagName == 'PAPER-INPUT') {
inputs[i].disabled = readOnly;
} else {
inputs[i].readOnly = readOnly;
}
}
} else {
if (inputs[i].tagName == 'PAPER-INPUT') {
inputs[i].disabled = readOnly;
} else {
inputs[i].readOnly = readOnly;
}
}
}
var selects = row.getElementsByTagName('select');
for (var i = 0; i < selects.length; ++i) {
if (classMask) {
for (var j = 0; j < classMask.length; ++j) {
if (selects[i].classList.contains(classMask[j])) {
selects[i].disabled = readOnly;
break;
var selects = row.getElementsByTagName('select');
for (var i = 0; i < selects.length; ++i) {
if (classMask) {
for (var j = 0; j < classMask.length; ++j) {
if (selects[i].classList.contains(classMask[j])) {
selects[i].disabled = readOnly;
break;
}
}
}
} else {
selects[i].disabled = readOnly;
}
}
}
},
clear: {
value: function() {
var rowDeletes = this.getElementsByTagName('tbody')[0].getElementsByClassName('delete');
while (rowDeletes.length > 0) {
rowDeletes[0].click();
}
}
},
removeRow: {
value: function(evt) {
var tr = evt.target.parentElement.parentElement;
var tbody = tr.parentElement;
var table = tbody.parentElement;
/* Remove deletion listener. */
evt.target.removeEventListener('click', table.removeRow, false);
/* Now remove row. */
tbody.removeChild(tr);
}
},
addEmptyRow: {
value: function(evt) {
/* Create new row. */
var table = evt.currentTarget.parentElement.parentElement;
var rowTemplateId = table.getAttribute('data-template');
var content = editableTableImportDoc.getElementById(rowTemplateId).content;
var row = document.importNode(content, true);
table.getElementsByTagName('tbody')[0].insertBefore(row, evt.currentTarget);
row = evt.currentTarget.previousElementSibling;
/* Add deletion listener. */
row.getElementsByClassName('delete')[0].addEventListener('click', table.removeRow, false);
}
},
addRow: {
value: function(tableData) {
var rowTemplateId = this.getAttribute('data-template');
var content = editableTableImportDoc.getElementById(rowTemplateId).content;
var row = document.importNode(content, true);
var tbody = this.getElementsByTagName('tbody')[0];
tbody.insertBefore(row, tbody.lastElementChild);
row = tbody.lastElementChild.previousElementSibling;
/* Data is an object with keys that match element class names. */
for (var key in tableData) {
var elems = row.getElementsByClassName(key);
if (tableData[key] != undefined && elems.length == 1) {
/*if (elems[0].tagName == 'PAPER-INPUT') {
elems[0].inputValue = tableData[key];
elems[0].commit();
} else {
*/ elems[0].value = tableData[key];
//}
selects[i].disabled = readOnly;
}
}
}
},
/* Add deletion listener. */
row.getElementsByClassName('delete')[0].addEventListener('click', this.removeRow, false);
clear: {
value: function() {
var rowDeletes = this.tBodies[0].getElementsByClassName('delete');
return row;
}
},
attachedCallback: {
value: function() {
/* Add new row listener. */
this.querySelector('tbody tr:last-child').addEventListener('click', this.addEmptyRow, false);
/* Add drag 'n' drop listeners.
Drag 'n' drop should only be enabled for file-row tables.
*/
if (this.getAttribute('data-template') == 'fileRow') {
this.addEventListener('drop', this.handleDrop, false);
this.addEventListener('dragover', this.handleDragOver, false);
while (rowDeletes.length > 0) {
rowDeletes[0].click();
}
}
}
},
},
detachedCallback: {
value: function() {
/* Remove event listeners. */
var tbody = this.getElementsByTagName('tbody')[0];
removeRow: {
value: function(evt) {
var tr = evt.target.parentElement.parentElement;
var tbody = tr.parentElement;
var table = tbody.parentElement;
/* Remove deletion listener. */
var icons = tbody.getElementsByClassName('delete');
for (var i = 0; i < icons.length; ++i) {
icons[i].removeEventListener('click', this.removeRow, false);
/* Remove deletion listener. */
evt.target.removeEventListener('click', table.removeRow, false);
/* Now remove row. */
tbody.removeChild(tr);
}
},
/* Remove new row listener. */
this.querySelector('tbody tr:last-child').removeEventListener('click', this.addEmptyRow, false);
addEmptyRow: {
value: function(evt) {
/* Create new row. */
var table = evt.currentTarget.parentElement.parentElement;
var rowTemplateId = table.getAttribute('data-template');
var content = document.querySelector('link[rel="import"][href$="editable-table.html"]').import.getElementById(rowTemplateId).content;
var rowContent = document.importNode(content, true);
/* Remove drag 'n' drop listeners. */
this.removeEventListener('drop', this.handleDrop, false);
this.removeEventListener('dragover', this.handleDragOver, false);
}
},
var row = document.createElement('tr');
row.appendChild(rowContent);
table.tBodies[0].insertBefore(row, evt.currentTarget);
row = evt.currentTarget.previousElementSibling;
});
var EditableTable = document.registerElement('editable-table', {
prototype: EditableTableProto,
extends: 'table'
});
/* Add deletion listener. */
row.getElementsByClassName('delete')[0].addEventListener('click', table.removeRow, false);
}
},
addRow: {
value: function(tableData) {
var rowTemplateId = this.getAttribute('data-template');
var content = document.querySelector('link[rel="import"][href$="editable-table.html"]').import.getElementById(rowTemplateId).content;
var rowContent = document.importNode(content, true);
var row = document.createElement('tr');
row.appendChild(rowContent);
var tbody = this.tBodies[0];
tbody.insertBefore(row, tbody.lastElementChild);
row = tbody.lastElementChild.previousElementSibling;
/* Data is an object with keys that match element class names. */
for (var key in tableData) {
var elems = row.getElementsByClassName(key);
if (tableData[key] != undefined && elems.length == 1) {
elems[0].value = tableData[key];
}
}
/* Add deletion listener. */
row.getElementsByClassName('delete')[0].addEventListener('click', this.removeRow, false);
return row;
}
},
attachedCallback: {
value: function() {
/* Add new row listener. */
this.querySelector('tbody tr:last-child').addEventListener('click', this.addEmptyRow, false);
/* Add drag 'n' drop listeners.
Drag 'n' drop should only be enabled for file-row tables.
*/
if (this.getAttribute('data-template') == 'fileRow') {
this.addEventListener('drop', this.handleDrop, false);
this.addEventListener('dragover', this.handleDragOver, false);
}
}
},
detachedCallback: {
value: function() {
/* Remove deletion listener. */
var icons = this.tBodies[0].getElementsByClassName('delete');
for (var i = 0; i < icons.length; ++i) {
icons[i].removeEventListener('click', this.removeRow, false);
}
/* Remove new row listener. */
this.querySelector('tbody tr:last-child').removeEventListener('click', this.addEmptyRow, false);
/* Remove drag 'n' drop listeners. */
this.removeEventListener('drop', this.handleDrop, false);
this.removeEventListener('dragover', this.handleDragOver, false);
}
},
});
document.registerElement('editable-table', {
prototype: EditableTableProto,
extends: 'table'
});
})();
</script>
+2 -2
View File
@@ -126,13 +126,13 @@
pluginItem.querySelector('#hasGlobalPriority').label = l10n.translate("Priority Is Global").fetch();
/* Message row template */
var messageRow = editableTableImportDoc.querySelector('#messageRow').content;
var messageRow = document.querySelector('link[rel="import"][href$="editable-table.html"]').import.querySelector('#messageRow').content;
messageRow.querySelector('.type').children[0].textContent = l10n.translate("Note").fetch();
messageRow.querySelector('.type').children[1].textContent = l10n.translate("Warning").fetch();
messageRow.querySelector('.type').children[2].textContent = l10n.translate("Error").fetch();
/* Tag row template */
var tagRow = editableTableImportDoc.querySelector('#tagRow').content;
var tagRow = document.querySelector('link[rel="import"][href$="editable-table.html"]').import.querySelector('#tagRow').content;
tagRow.querySelector('.type').children[0].textContent = l10n.translate("Add").fetch();
tagRow.querySelector('.type').children[1].textContent = l10n.translate("Remove").fetch();
+2 -2
View File
@@ -1239,7 +1239,7 @@ function initVars() {
/* Now fill in language options. */
var settingsLangSelect = document.getElementById('languageSelect');
var messageLangSelect = editableTableImportDoc.querySelector('#messageRow').content.querySelector('.language');
var messageLangSelect = document.querySelector('link[rel="import"][href$="editable-table.html"]').import.querySelector('#messageRow').content.querySelector('.language');
for (var i = 0; i < loot.languages.length; ++i) {
var settingsItem = document.createElement('paper-item');
settingsItem.setAttribute('value', loot.languages[i].locale);
@@ -1290,7 +1290,7 @@ function initVars() {
}
/* Fill in game row template's game type options. */
var select = editableTableImportDoc.querySelector('#gameRow').content.querySelector('select');
var select = document.querySelector('link[rel="import"][href$="editable-table.html"]').import.querySelector('#gameRow').content.querySelector('select');
for (var j = 0; j < loot.gameTypes.length; ++j) {
var option = document.createElement('option');
option.value = loot.gameTypes[j];
+1 -1
View File
@@ -217,7 +217,7 @@ along with LOOT. If not, see &lt;http://www.gnu.org/licenses/&gt;.
<tbody>
<!-- Game rows go here. -->
<tr>
<td colspan="4">Add new row...</td>
<td colspan="8">Add new row...</td>
<td></td>
</tr>
</tbody>