diff --git a/resources/report/html/plugin-card.html b/resources/report/html/plugin-card.html
index 7931f2e7..8961449f 100644
--- a/resources/report/html/plugin-card.html
+++ b/resources/report/html/plugin-card.html
@@ -1,4 +1,7 @@
-
+
@@ -477,39 +517,40 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
},
showEditor: {
- value: function() {
+ value: function(evt) {
+ var pluginCard = evt.target.parentElement.parentElement.parentElement.parentElement.parentNode.host;
/* Fill editor controls with values from the plugin this card corresponds to. */
/* First find the corresponding plugin. */
for (var i = 0; i < loot.game.plugins.length; ++i) {
- if (loot.game.plugins[i].id == this.id) {
+ if (loot.game.plugins[i].id == pluginCard.id) {
- this.shadowRoot.getElementById('editor').getElementsByTagName('h1')[0].textContent = loot.game.plugins[i].name;
- this.shadowRoot.getElementById('editor').getElementsByClassName('version')[0].textContent = loot.game.plugins[i].version;
+ pluginCard.shadowRoot.getElementById('editor').getElementsByTagName('h1')[0].textContent = loot.game.plugins[i].name;
+ pluginCard.shadowRoot.getElementById('editor').getElementsByClassName('version')[0].textContent = loot.game.plugins[i].version;
if (loot.game.plugins[i].crc != '0') {
- this.shadowRoot.getElementById('editor').getElementsByClassName('crc')[0].textContent = loot.game.plugins[i].crc.toString(16).toUpperCase();
+ pluginCard.shadowRoot.getElementById('editor').getElementsByClassName('crc')[0].textContent = loot.game.plugins[i].crc.toString(16).toUpperCase();
}
/* Fill in the editor input values. */
if (loot.game.plugins[i].userlist && !loot.game.plugins[i].userlist.enabled) {
- this.shadowRoot.getElementById('enableEdits').checked = false;
+ pluginCard.shadowRoot.getElementById('enableEdits').checked = false;
} else {
- this.shadowRoot.getElementById('enableEdits').checked = true;
+ pluginCard.shadowRoot.getElementById('enableEdits').checked = true;
}
- this.shadowRoot.getElementById('globalPriority').checked = loot.game.plugins[i].isGlobalPriority;
- this.shadowRoot.getElementById('priorityValue').value = loot.game.plugins[i].modPriority;
+ pluginCard.shadowRoot.getElementById('globalPriority').checked = loot.game.plugins[i].isGlobalPriority;
+ pluginCard.shadowRoot.getElementById('priorityValue').value = loot.game.plugins[i].modPriority;
/* Clear any existing editor table data. Don't remove the last row though,
that's the "add new row" one. */
- var tables = this.shadowRoot.getElementsByTagName('table');
+ var tables = pluginCard.shadowRoot.getElementsByTagName('table');
for (var j = 0; j < tables.length; ++j) {
tables[j].clear();
}
/* Fill in editor table data. Masterlist-originated rows should have
their contents made read-only, and be unremovable. */
- var tables = this.shadowRoot.getElementsByTagName('table');
+ var tables = pluginCard.shadowRoot.getElementsByTagName('table');
for (var j = 0; j < tables.length; ++j) {
if (tables[j].id == 'loadAfter') {
@@ -641,16 +682,16 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
}
/* Set up table tab event handlers. */
- var elements = this.shadowRoot.getElementById('tableTabs').children;
+ var elements = pluginCard.shadowRoot.getElementById('tableTabs').children;
for (var i = 0; i < elements.length; ++i) {
if (elements[i].hasAttribute('data-for')) {
- elements[i].addEventListener('click', this.showEditorTable, false);
+ elements[i].addEventListener('click', pluginCard.showEditorTable, false);
}
}
/* Set up button event handlers. */
- this.shadowRoot.getElementById('accept').addEventListener('click', this.hideEditor, false);
- this.shadowRoot.getElementById('cancel').addEventListener('click', this.hideEditor, false);
+ pluginCard.shadowRoot.getElementById('accept').addEventListener('click', pluginCard.hideEditor, false);
+ pluginCard.shadowRoot.getElementById('cancel').addEventListener('click', pluginCard.hideEditor, false);
/* Set up drag 'n' drop event handlers. */
elements = document.getElementById('pluginsNav').children;
@@ -673,42 +714,98 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
document.body.setAttribute('data-editors', numEditors);
/* Now show editor. */
- this.classList.toggle('flip');
+ pluginCard.classList.toggle('flip');
+ }
+ },
+
+ onShowOnlyConflicts: {
+ value: function(evt) {
+ /* Depending on what was clicked, this function may be run before
+ the checkbox state has updated. Handle both cases. */
+ var activateFilter, card;
+ if (evt.currentTarget == evt.target) {
+ /* Clicked on the label, checkbox state isn't updated yet. */
+ activateFilter = !evt.target.firstElementChild.checked;
+ card = evt.target.parentElement.parentElement.parentElement.parentElement.parentNode.host;
+ } else {
+ /* Clicked on the checkbox. */
+ activateFilter = evt.target.checked;
+ card = evt.target.parentElement.parentElement.parentElement.parentElement.parentElement.parentNode.host;
+ }
+ if (activateFilter) {
+ /* Un-highlight any existing filter plugin. */
+ var cards = document.getElementsByTagName('main')[0].getElementsByTagName('plugin-card');
+ for (var i = 0; i < cards.length; ++i) {
+ cards[i].classList.toggle('highlight', false);
+ }
+ card.classList.toggle('highlight', true);
+ document.body.setAttribute('data-conflicts', card.getName());
+ } else {
+ card.classList.toggle('highlight', false);
+ document.body.removeAttribute('data-conflicts');
+ }
+ applyFilters(evt);
+ }
+ },
+
+ onCopyMetadata: {
+ value: function(evt) {
+ var card = evt.target.parentElement.parentElement.parentElement.parentElement.parentNode.host;
+ var request = JSON.stringify({
+ name: 'copyMetadata',
+ args: [
+ card.getName()
+ ]
+ });
+
+ loot.query(request).catch(processCefError);
+ }
+ },
+
+ onClearMetadata: {
+ value: function(evt) {
+ var pluginCard = evt.target.parentElement.parentElement.parentElement.parentElement.parentNode.host;
+
+ showMessageDialog('Clear Plugin Metadata', 'Are you sure you want to clear all existing user-added metadata from "' + pluginCard.getName() + '"?', function(result){
+ if (result) {
+ var request = JSON.stringify({
+ name: 'clearPluginMetadata',
+ args: [
+ pluginCard.getName()
+ ]
+ });
+
+ loot.query(request).then(JSON.parse).then(function(result){
+ if (result) {
+ /* Need to empty the UI-side user metadata. */
+ for (var i = 0; i < loot.game.plugins.length; ++i) {
+ if (loot.game.plugins[i].id == pluginCard.id) {
+ loot.game.plugins[i].userlist = undefined;
+
+ loot.game.plugins[i].modPriority = result.modPriority;
+ loot.game.plugins[i].isGlobalPriority = result.isGlobalPriority;
+ loot.game.plugins[i].messages = result.messages;
+ loot.game.plugins[i].tags = result.tags;
+ loot.game.plugins[i].isDirty = result.isDirty;
+
+ break;
+ }
+ }
+ }
+ }).catch(processCefError);
+ }
+ });
}
},
onMenuButtonClick: {
value: function(evt) {
-
- /* Open a new plugin menu. */
- var menu = new PluginMenu();
- var card = evt.currentTarget.parentElement.parentElement.parentNode.host;
-
- menu.setAttribute('data-for', card.id);
- var main = document.getElementsByTagName('main')[0];
-
- /* Set page position of menu. */
- var rect = evt.target.getBoundingClientRect();
- menu.style.right = (main.offsetWidth - (rect.right - main.offsetLeft) - 15) + 'px';
- menu.style.top = (rect.bottom - document.getElementById('container').offsetTop + main.scrollTop + 5) + 'px';
-
- main.appendChild(menu);
-
- evt.stopPropagation();
-
- /* To prevent the click event closing this menu just after it was
- opened, stop the current event and send off a new one. */
- document.body.dispatchEvent(new CustomEvent('click', {
- bubbles: true,
- detail: {
- newMenu: menu
- }
- }));
+ /* Open the plugin menu. */
+ evt.currentTarget.firstElementChild.classList.toggle('hidden');
}
},
createdCallback: {
-
value: function() {
var template = pluginCardImportDoc.getElementById('pluginCard');
@@ -746,6 +843,33 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
hoverTargets[i].addEventListener('mouseenter', showHoverText, false);
hoverTargets[i].addEventListener('mouseleave', hideHoverText, false);
}
+
+ /* Add event listeners for the menu items. */
+ /* For some reason clicking on the label is processed slower
+ than the checkbox state, and in the time difference the menu
+ gets closed, so that the conflicts filter never gets applied.
+ To get around this, listen for a click on the label rather
+ than for checkbox state change. */
+ if (document.body.getAttribute('data-conflicts') == this.getName()) {
+ this.shadowRoot.getElementById('showOnlyConflicts').checked = true;
+ }
+ this.shadowRoot.getElementById('showOnlyConflicts').parentElement.addEventListener('click', this.onShowOnlyConflicts, false);
+ this.shadowRoot.getElementById('editMetadata').addEventListener('click', this.showEditor, false);
+ this.shadowRoot.getElementById('copyMetadata').addEventListener('click', this.onCopyMetadata, false);
+ this.shadowRoot.getElementById('clearMetadata').addEventListener('click', this.onClearMetadata, false);
+
+ /* Because of the 3D flip effect used when accessing the editor,
+ plugin menus get hidden underneath later plugin cards unless
+ those cards have a lower z-index than the card the menu is part
+ of. Therefore, set this card's z-index to the negative of its
+ position in the plugin list.
+ */
+ var cards = this.parentElement.getElementsByTagName('plugin-card');
+ for (var i = 0; i < cards.length; ++i) {
+ if (cards[i] == this) {
+ this.style.zIndex = -1 * i;
+ }
+ }
}
},
@@ -758,6 +882,14 @@ var pluginCardProto = Object.create(HTMLElement.prototype, {
hoverTargets[i].removeEventListener('mouseenter', showHoverText, false);
hoverTargets[i].removeEventListener('mouseleave', hideHoverText, false);
}
+
+ /* Remove event listeners for the menu items. */
+ /* Nothing happens if we try to remove a listener that doesn't exist,
+ so don't bother checking first. */
+ this.shadowRoot.getElementById('showOnlyConflicts').parentElement.removeEventListener('click', this.onShowOnlyConflicts, false);
+ this.shadowRoot.getElementById('editMetadata').removeEventListener('click', this.showEditor, false);
+ this.shadowRoot.getElementById('copyMetadata').removeEventListener('click', this.onCopyMetadata, false);
+ this.shadowRoot.getElementById('clearMetadata').removeEventListener('click', this.onClearMetadata, false);
}
}
diff --git a/resources/report/html/plugin-menu.html b/resources/report/html/plugin-menu.html
deleted file mode 100644
index 770697aa..00000000
--- a/resources/report/html/plugin-menu.html
+++ /dev/null
@@ -1,195 +0,0 @@
-
-
-
-
diff --git a/resources/report/js/l10n.js b/resources/report/js/l10n.js
index c60ed5a7..b899d96b 100644
--- a/resources/report/js/l10n.js
+++ b/resources/report/js/l10n.js
@@ -95,6 +95,11 @@
pluginCard.getElementById('accept').textContent = l10n.translate("Apply").fetch();
pluginCard.getElementById('cancel').textContent = l10n.translate("Cancel").fetch();
+ pluginCard.getElementById('showOnlyConflicts').nextSibling.textContent = l10n.translate("Show Only Conflicts").fetch();
+ pluginCard.getElementById('editMetadata').firstChild.nextSibling.textContent = l10n.translate("Edit Metadata").fetch();
+ pluginCard.getElementById('copyMetadata').firstChild.nextSibling.textContent = l10n.translate("Copy Metadata As Text").fetch();
+ pluginCard.getElementById('clearMetadata').firstChild.nextSibling.textContent = l10n.translate("Clear User Metadata").fetch();
+
/* Plugin List Item Template */
var pluginLI = pluginLiImportDoc.querySelector('#pluginLI').content;
pluginLI.querySelector('.dummyPlugin').title = l10n.translate("Dummy Plugin").fetch();
@@ -102,13 +107,6 @@
pluginLI.querySelector('.hasUserEdits').title = l10n.translate("Has User Metadata").fetch();
pluginLI.querySelector('.hasGlobalPriority').title = l10n.translate("Priority Is Global").fetch();
- /* Plugin menu template */
- var pluginMenu = pluginMenuImportDoc.querySelector('#pluginMenu').content;
- pluginMenu.getElementById('showOnlyConflicts').nextSibling.textContent = l10n.translate("Show Only Conflicts").fetch();
- pluginMenu.getElementById('editMetadata').firstChild.nextSibling.textContent = l10n.translate("Edit Metadata").fetch();
- pluginMenu.getElementById('copyMetadata').firstChild.nextSibling.textContent = l10n.translate("Copy Metadata As Text").fetch();
- pluginMenu.getElementById('clearMetadata').firstChild.nextSibling.textContent = l10n.translate("Clear User Metadata").fetch();
-
/* Message row template */
var messageRow = editableTableImportDoc.querySelector('#messageRow').content;
messageRow.querySelector('.type').children[0].textContent = l10n.translate("Note").fetch();
diff --git a/resources/report/report.html b/resources/report/report.html
index cd1a8842..b161fa0f 100644
--- a/resources/report/report.html
+++ b/resources/report/report.html
@@ -7,7 +7,6 @@
-