fx-compat: Initial fix for Scaffold

Not working:
- Web tests (hidden browser is broken)
- Test Updated status text
- Various platform menu things (code copied from ZP and will use whichever
  approach we settle on there)
This commit is contained in:
Abe Jellinek 2022-06-08 17:16:50 -05:00
parent 1b324f9bd1
commit e537018e71
11 changed files with 504 additions and 325 deletions

View file

@ -0,0 +1,15 @@
addMessageListener('Scaffold:GetDocument', {
receiveMessage() {
dump('received document request\n')
sendAsyncMessage('Scaffold:Document', {
html: new XMLSerializer().serializeToString(content.document),
url: content.location.href
});
}
});
function onLoad() {
sendAsyncMessage('Scaffold:Load', { url: content.location.href });
}
addEventListener('load', onLoad, true);

View file

@ -24,12 +24,14 @@
*/ */
var Scaffold_Load = new function() { var Scaffold_Load = new function() {
this.onLoad = Zotero.Promise.coroutine(function* () { this.onLoad = async function () {
document.addEventListener('dialogaccept', () => this.accept());
var listitem, translator, listcell, set; var listitem, translator, listcell, set;
var listbox = document.getElementById("listbox"); var listbox = document.getElementById("listbox");
listbox.addEventListener('dblclick', () => { listbox.addEventListener('dblclick', () => {
var translatorID = document.getElementById("listbox").selectedItem.getUserData("zotero-id"); var translatorID = document.getElementById("listbox").selectedItem.dataset.zoteroID;
if (!translatorID) return; if (!translatorID) return;
this.accept(); this.accept();
window.close(); window.close();
@ -42,44 +44,48 @@ var Scaffold_Load = new function() {
var url = window.arguments[0].url; var url = window.arguments[0].url;
var rootUrl = window.arguments[0].rootUrl var rootUrl = window.arguments[0].rootUrl
url = Zotero.Proxies.proxyToProper(url); url = Zotero.Proxies.proxyToProper(url);
translators["Matching Translators"] = (yield translatorProvider.getWebTranslatorsForLocation(url, rootUrl))[0]; translators["Matching Translators"] = (await translatorProvider.getWebTranslatorsForLocation(url, rootUrl))[0];
translators["Web Translators"] = (yield translatorProvider.getAllForType("web")) translators["Web Translators"] = (await translatorProvider.getAllForType("web"))
.sort((a, b) => a.label.localeCompare(b.label)); .sort((a, b) => a.label.localeCompare(b.label));
translators["Import Translators"] = (yield translatorProvider.getAllForType("import")) translators["Import Translators"] = (await translatorProvider.getAllForType("import"))
.sort((a, b) => a.label.localeCompare(b.label)); .sort((a, b) => a.label.localeCompare(b.label));
translators["Export Translators"] = (yield translatorProvider.getAllForType("export")) translators["Export Translators"] = (await translatorProvider.getAllForType("export"))
.sort((a, b) => a.label.localeCompare(b.label)); .sort((a, b) => a.label.localeCompare(b.label));
translators["Search Translators"] = (yield translatorProvider.getAllForType("search")) translators["Search Translators"] = (await translatorProvider.getAllForType("search"))
.sort((a, b) => a.label.localeCompare(b.label)); .sort((a, b) => a.label.localeCompare(b.label));
for (set in translators) { for (set in translators) {
// Make a separator // Make a separator
listitem = document.createElement("listitem"); listitem = document.createXULElement("richlistitem");
listitem.setAttribute("disabled", true); listitem.setAttribute("disabled", true);
listitem.setAttribute("label", set); // Need to set this to disable up/down keys selecting:
listitem.style.MozUserInput = 'none';
listitem.append(set);
listbox.appendChild(listitem); listbox.appendChild(listitem);
for (var j=0; j<translators[set].length; j++) { for (var j=0; j<translators[set].length; j++) {
var translator = translators[set][j]; var translator = translators[set][j];
listitem = document.createElement("listitem"); listitem = document.createXULElement("richlistitem");
// set label for type-to-find functionality. This is not displayed. // set search label for type-to-find functionality. This is not displayed.
listitem.setAttribute("label", translator.label); listitem.searchLabel = translator.label;
// And the ID goes in DOM user data // And the ID goes in DOM user data
listitem.setUserData("zotero-id", translator.translatorID, null); listitem.dataset.zoteroID = translator.translatorID;
listcell = document.createElement("listcell"); listcell = document.createXULElement("hbox");
listcell.setAttribute("label", translator.label); listcell.setAttribute('flex', '1');
listcell.append(translator.label);
listitem.appendChild(listcell); listitem.appendChild(listcell);
listcell = document.createElement("listcell"); listcell = document.createXULElement("hbox");
listcell.setAttribute("label", translator.creator); listcell.setAttribute('width', '130');
listcell.append(translator.creator);
listitem.appendChild(listcell); listitem.appendChild(listcell);
listbox.appendChild(listitem); listbox.appendChild(listitem);
} }
} }
}); };
this.accept = function () { this.accept = function () {
var translatorID = document.getElementById("listbox").selectedItem.getUserData("zotero-id"); var translatorID = document.getElementById("listbox").selectedItem.dataset.zoteroID;
var translator = window.arguments[0].translatorProvider.get(translatorID); var translator = window.arguments[0].translatorProvider.get(translatorID);
Zotero.debug(translatorID); Zotero.debug(translatorID);

View file

@ -25,24 +25,23 @@
--> -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://scaffold/skin/scaffold.css" type="text/css"?> <?xml-stylesheet href="chrome://scaffold/skin/scaffold.css" type="text/css"?>
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://scaffold/locale/scaffold.dtd"> <!DOCTYPE window SYSTEM "chrome://scaffold/locale/scaffold.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" <window
title="&scaffold.load.title;" width="400" height="330" buttons="cancel,accept" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
ondialogaccept="Scaffold_Load.accept()" onload="Scaffold_Load.onLoad()" title="&scaffold.load.title;" width="400" height="330"
onload="Scaffold_Load.onLoad()">
<dialog buttons="cancel,accept"
id="scaffold-load"> id="scaffold-load">
<script src="chrome://zotero/content/include.js"/> <script src="chrome://zotero/content/include.js"/>
<script src="load.js"/> <script src="load.js"/>
<listbox id="listbox" flex="1"> <listheader>
<listhead> <treecol flex="1" label="&scaffold.load.label.label;"/>
<listheader label="&scaffold.load.label.label;"/> <treecol width="130" label="&scaffold.load.creator.label;"/>
<listheader label="&scaffold.load.creator.label;"/> </listheader>
</listhead> <richlistbox id="listbox" flex="1"/>
<listcols>
<listcol flex="1"/>
<listcol width="130"/>
</listcols>
</listbox>
</dialog> </dialog>
</window>

View file

@ -23,7 +23,9 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
*/ */
Components.utils.import("resource://gre/modules/Services.jsm"); var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
var { E10SUtils } = ChromeUtils.import("resource://gre/modules/E10SUtils.jsm");
import FilePicker from 'zotero/modules/filePicker'; import FilePicker from 'zotero/modules/filePicker';
var Zotero = Components.classes["@zotero.org/Zotero;1"] var Zotero = Components.classes["@zotero.org/Zotero;1"]
@ -53,10 +55,12 @@ function fix2028(str) {
} }
var Scaffold = new function () { var Scaffold = new function () {
var _browser, _frames, _document; var _browser, _frames = [], _document;
var _translatorsLoadedPromise; var _translatorsLoadedPromise;
var _translatorProvider = null; var _translatorProvider = null;
var _lastModifiedTime = 0; var _lastModifiedTime = 0;
this.browser = () => _browser;
var _editors = {}; var _editors = {};
@ -85,17 +89,19 @@ var Scaffold = new function () {
_browser = document.getElementById('browser'); _browser = document.getElementById('browser');
_browser.addEventListener("pageshow", window.messageManager.addMessageListener('Scaffold:Load', ({ data }) => {
_updateFrames, true); document.getElementById("browser-url").value = data.url;
_updateFrames(); });
window.messageManager.loadFrameScript('chrome://scaffold/content/content.js', true);
let browserUrl = document.getElementById("browser-url"); let browserUrl = document.getElementById("browser-url");
browserUrl.addEventListener('keypress', function (e) { browserUrl.addEventListener('keydown', function (e) {
if (e.keyCode == e.DOM_VK_RETURN) { if (e.key == 'Enter') {
_browser.loadURIWithFlags( Zotero.debug('Scaffold: Loading URL in browser: ' + browserUrl.value);
browserUrl.value, _browser.loadURI(browserUrl.value, {
Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
); });
} }
}); });
@ -107,6 +113,8 @@ var Scaffold = new function () {
if (size) { if (size) {
this.setFontSize(size); this.setFontSize(size);
} }
document.getElementById('tabpanels').addEventListener('select', event => Scaffold.handleTabSelect(event));
this.generateTranslatorID(); this.generateTranslatorID();
@ -570,9 +578,8 @@ var Scaffold = new function () {
if (translatorID === undefined) { if (translatorID === undefined) {
var io = {}; var io = {};
io.translatorProvider = _translatorProvider; io.translatorProvider = _translatorProvider;
io.url = _getDocument()?.location.href || 'about:blank'; io.url = io.rootUrl = _browser.currentURI.spec;
io.rootUrl = _browser.contentDocument.location.href; window.openDialog("chrome://scaffold/content/load.xhtml",
window.openDialog("chrome://scaffold/content/load.xul",
"_blank", "chrome,modal", io); "_blank", "chrome,modal", io);
translator = io.dataOut; translator = io.dataOut;
} }
@ -752,8 +759,12 @@ var Scaffold = new function () {
}; };
this.handleTabSelect = function (event) { this.handleTabSelect = function (event) {
if (event.target.tagName != 'tabpanels') {
return;
}
// Focus editor when switching to tab // Focus editor when switching to tab
var tab = event.target.selectedItem.id.match(/^tab-(.+)$/)[1]; var tab = document.getElementById('tabs').selectedItem.id.match(/^tab-(.+)$/)[1];
switch (tab) { switch (tab) {
case 'import': case 'import':
case 'code': case 'code':
@ -785,7 +796,7 @@ var Scaffold = new function () {
let editImport = document.getElementById('testing_editImport'); let editImport = document.getElementById('testing_editImport');
let openURL = document.getElementById('testing_openURL'); let openURL = document.getElementById('testing_openURL');
if (selected.getUserData('test-type') == 'web') { if (selected.dataset.testType == 'web') {
editImport.setAttribute('disabled', true); editImport.setAttribute('disabled', true);
openURL.removeAttribute('disabled'); openURL.removeAttribute('disabled');
} }
@ -864,7 +875,7 @@ var Scaffold = new function () {
// Handle generic call run('detect'), run('do') // Handle generic call run('detect'), run('do')
if (functionToRun == "detect" || functionToRun == "do") { if (functionToRun == "detect" || functionToRun == "do") {
if (document.getElementById('checkbox-web').checked if (document.getElementById('checkbox-web').checked
&& _browser.contentWindow.location.href != 'about:blank') { && _browser.currentURI.spec != 'about:blank') {
functionToRun += 'Web'; functionToRun += 'Web';
} }
else if (document.getElementById('checkbox-import').checked else if (document.getElementById('checkbox-import').checked
@ -887,7 +898,9 @@ var Scaffold = new function () {
_logOutput(`Running ${functionToRun}`); _logOutput(`Running ${functionToRun}`);
let input = _getInput(functionToRun); let input = await _getInput(functionToRun);
Zotero.debug('got input')
Zotero.debug(input)
if (functionToRun.endsWith('Export')) { if (functionToRun.endsWith('Export')) {
let numItems = Zotero.getActiveZoteroPane().getSelectedItems().length; let numItems = Zotero.getActiveZoteroPane().getSelectedItems().length;
@ -991,8 +1004,8 @@ var Scaffold = new function () {
/** /**
* Test target regular expression against document URL and log the result * Test target regular expression against document URL and log the result
*/ */
this.logTargetRegex = function () { this.logTargetRegex = async function () {
_logOutput(_testTargetRegex(_getDocument())); _logOutput(_testTargetRegex(await _getDocument()));
}; };
/** /**
@ -1016,7 +1029,7 @@ var Scaffold = new function () {
*/ */
function _selectItems(obj, itemList) { function _selectItems(obj, itemList) {
var io = { dataIn: itemList, dataOut: null }; var io = { dataIn: itemList, dataOut: null };
window.openDialog("chrome://zotero/content/ingester/selectitems.xul", window.openDialog("chrome://zotero/content/ingester/selectitems.xhtml",
"_blank", "chrome,modal,centerscreen,resizable=yes", io); "_blank", "chrome,modal,centerscreen,resizable=yes", io);
return io.dataOut; return io.dataOut;
@ -1103,7 +1116,7 @@ var Scaffold = new function () {
+ ":" + Zotero.Utilities.lpad(date.getSeconds(), '0', 2) + ":" + Zotero.Utilities.lpad(date.getSeconds(), '0', 2)
+ " " + string.replace(/\n/g, "\n "); + " " + string.replace(/\n/g, "\n ");
// move to end // move to end
output.inputField.scrollTop = output.inputField.scrollHeight; output.scrollTop = output.scrollHeight;
} }
/* /*
@ -1131,7 +1144,7 @@ var Scaffold = new function () {
/* /*
* gets appropriate input for the given type/method * gets appropriate input for the given type/method
*/ */
function _getInput(typeOrMethod) { async function _getInput(typeOrMethod) {
typeOrMethod = typeOrMethod.toLowerCase(); typeOrMethod = typeOrMethod.toLowerCase();
if (typeOrMethod.endsWith('web')) { if (typeOrMethod.endsWith('web')) {
return _getDocument(); return _getDocument();
@ -1572,7 +1585,7 @@ var Scaffold = new function () {
return Promise.reject(new Error(`Test of type export cannot be created`)); return Promise.reject(new Error(`Test of type export cannot be created`));
} }
let input = _getInput(type); let input = await _getInput(type);
if (type == "web") { if (type == "web") {
let tester = new Zotero_TranslatorTester( let tester = new Zotero_TranslatorTester(
@ -1614,6 +1627,14 @@ var Scaffold = new function () {
* populate tests pane and url options in browser pane * populate tests pane and url options in browser pane
*/ */
this.populateTests = function () { this.populateTests = function () {
function wrapWithHBox(elem, { flex = undefined, width = undefined } = {}) {
let hbox = document.createXULElement('hbox');
hbox.append(elem);
hbox.setAttribute('flex', flex);
hbox.setAttribute('width', width);
return hbox;
}
let tests = _loadTestsFromPane(); let tests = _loadTestsFromPane();
let validateTestsBroadcaster = document.getElementById('validate-tests'); let validateTestsBroadcaster = document.getElementById('validate-tests');
if (tests === null) { if (tests === null) {
@ -1626,7 +1647,7 @@ var Scaffold = new function () {
let browserURL = document.getElementById("browser-url"); let browserURL = document.getElementById("browser-url");
let currentURL = browserURL.value; let currentURL = browserURL.value;
browserURL.removeAllItems(); // browserURL.removeAllItems();
browserURL.value = currentURL; browserURL.value = currentURL;
let listBox = document.getElementById("testing-listbox"); let listBox = document.getElementById("testing-listbox");
@ -1634,8 +1655,8 @@ var Scaffold = new function () {
let oldStatuses = {}; let oldStatuses = {};
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
let item = listBox.getItemAtIndex(i); let item = listBox.getItemAtIndex(i);
let [, statusCell] = item.getElementsByTagName('listcell'); let [, statusCell] = item.firstElementChild.children;
oldStatuses[item.getUserData('test-string')] = statusCell.getAttribute('label'); oldStatuses[item.dataset.testString] = statusCell.getAttribute('value');
} }
let testIndex = 0; let testIndex = 0;
@ -1645,40 +1666,46 @@ var Scaffold = new function () {
// try to reuse old rows // try to reuse old rows
let item = testIndex < count let item = testIndex < count
? listBox.getItemAtIndex(testIndex) ? listBox.getItemAtIndex(testIndex)
: document.createElement('listitem'); : document.createXULElement('richlistitem');
item.innerHTML = ''; // clear children/content if reusing item.innerHTML = ''; // clear children/content if reusing
let input = document.createElement('listcell'); let hbox = document.createXULElement('hbox');
input.setAttribute('label', getTestLabel(test)); hbox.setAttribute('flex', 1);
item.appendChild(input); hbox.setAttribute('align', 'center');
let status = document.createElement('listcell'); let input = document.createXULElement('label');
status.setAttribute('label', oldStatuses[testString] || 'Not run'); input.value = getTestLabel(test);
item.appendChild(status); hbox.appendChild(wrapWithHBox(input, { flex: 1 }));
let defer = document.createElement('listcell'); let status = document.createXULElement('label');
defer.setAttribute('type', 'checkbox'); status.value = oldStatuses[testString] || 'Not run';
defer.setAttribute('checked', test.defer); hbox.appendChild(wrapWithHBox(status, { width: 150 }));
item.appendChild(defer);
item.setUserData('test-string', testString, null); let defer = document.createXULElement('checkbox');
item.setUserData('test-type', test.type); defer.checked = test.defer;
defer.disabled = true;
hbox.appendChild(wrapWithHBox(defer));
item.appendChild(hbox);
item.dataset.testString = testString;
item.dataset.testType = test.type;
if (testIndex >= count) { if (testIndex >= count) {
listBox.appendChild(item); listBox.appendChild(item);
} }
if (test.type == 'web') { // if (test.type == 'web') {
browserURL.appendItem(test.url); // browserURL.appendItem(test.url);
} // }
testIndex++; testIndex++;
} }
// remove old rows that we didn't reuse // remove old rows that we didn't reuse
while (listBox.getItemAtIndex(testIndex)) { while (listBox.getItemAtIndex(testIndex)) {
listBox.removeItemAt(testIndex); listBox.getItemAtIndex(testIndex).remove();
} }
}; };
@ -1703,7 +1730,7 @@ var Scaffold = new function () {
this.editImportFromTest = function () { this.editImportFromTest = function () {
var listbox = document.getElementById("testing-listbox"); var listbox = document.getElementById("testing-listbox");
var item = listbox.selectedItems[0]; var item = listbox.selectedItems[0];
var test = JSON.parse(item.getUserData("test-string")); var test = JSON.parse(item.dataset.testString);
if (test.input === undefined) { if (test.input === undefined) {
_logOutput("Can't edit input of a non-import/search test."); _logOutput("Can't edit input of a non-import/search test.");
} }
@ -1726,8 +1753,8 @@ var Scaffold = new function () {
this.copyToClipboard = function () { this.copyToClipboard = function () {
var listbox = document.getElementById("testing-listbox"); var listbox = document.getElementById("testing-listbox");
var item = listbox.selectedItems[0]; var item = listbox.selectedItems[0];
var url = item.getElementsByTagName("listcell")[0].getAttribute("label"); var url = item.getElementsByTagName("label")[0].getAttribute("value");
var test = JSON.parse(item.getUserData("test-string")); var test = JSON.parse(item.dataset.testString);
var urlOrData = (test.input !== undefined) ? test.input : url; var urlOrData = (test.input !== undefined) ? test.input : url;
Zotero.Utilities.Internal.copyTextToClipboard(urlOrData); Zotero.Utilities.Internal.copyTextToClipboard(urlOrData);
}; };
@ -1740,15 +1767,14 @@ var Scaffold = new function () {
this.openURL = function (openExternally) { this.openURL = function (openExternally) {
var listbox = document.getElementById("testing-listbox"); var listbox = document.getElementById("testing-listbox");
var item = listbox.selectedItems[0]; var item = listbox.selectedItems[0];
var url = item.getElementsByTagName("listcell")[0].getAttribute("label"); var url = item.getElementsByTagName("label")[0].getAttribute("value");
if (openExternally) { if (openExternally) {
Zotero.launchURL(url); Zotero.launchURL(url);
} }
else { else {
_browser.loadURIWithFlags( _browser.loadURI(url, {
url, triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE });
);
_showTab('browser'); _showTab('browser');
} }
}; };
@ -1792,14 +1818,14 @@ var Scaffold = new function () {
if (!items || items.length == 0) return; // No action if nothing selected if (!items || items.length == 0) return; // No action if nothing selected
var tests = []; var tests = [];
for (let item of items) { for (let item of items) {
item.getElementsByTagName("listcell")[1].setAttribute("label", "Running"); item.getElementsByTagName("label")[1].setAttribute("value", "Running");
var test = JSON.parse(item.getUserData("test-string")); var test = JSON.parse(item.dataset.testString);
test["ui-item"] = item; test["ui-item"] = item;
tests.push(test); tests.push(test);
} }
this.runTests(tests, (obj, test, status, message) => { this.runTests(tests, (obj, test, status, message) => {
test["ui-item"].getElementsByTagName("listcell")[1].setAttribute("label", message); test["ui-item"].getElementsByTagName("label")[1].setAttribute("value", message);
}); });
}; };
@ -1823,8 +1849,8 @@ var Scaffold = new function () {
var itemIndices = items.map(item => listbox.getIndexOfItem(item)); var itemIndices = items.map(item => listbox.getIndexOfItem(item));
var tests = []; var tests = [];
for (let item of items) { for (let item of items) {
item.getElementsByTagName("listcell")[1].setAttribute("label", "Updating"); item.getElementsByTagName("label")[1].setAttribute("value", "Updating");
var test = JSON.parse(item.getUserData("test-string")); var test = JSON.parse(item.dataset.testString);
tests.push(test); tests.push(test);
} }
@ -1835,13 +1861,13 @@ var Scaffold = new function () {
// Assume sequential. TODO: handle this properly via test ID of some sort // Assume sequential. TODO: handle this properly via test ID of some sort
if (newTest) { if (newTest) {
message = "Test updated"; message = "Test updated";
items[testsDone].setUserData("test-string", _stringifyTests(newTest, 1)); items[testsDone].dataset.testString = _stringifyTests(newTest, 1);
tests[testsDone] = newTest; tests[testsDone] = newTest;
} }
else { else {
message = "Update failed"; message = "Update failed";
} }
items[testsDone].getElementsByTagName("listcell")[1].setAttribute("label", message); items[testsDone].getElementsByTagName("label")[1].setAttribute("value", message);
testsDone++; testsDone++;
}); });
@ -2011,77 +2037,19 @@ var Scaffold = new function () {
return guid; return guid;
} }
/*
* updates list of available frames and show URL of active tab
*/
function _updateFrames() {
var doc = _browser.contentDocument;
// Show URL of active tab
document.getElementById("browser-url").value = doc.location.href;
// No need to run if Scaffold isn't open
var menulist = _document.getElementById("menulist-testFrame");
if (!_document || !menulist) return;
menulist.removeAllItems();
var popup = _document.createElement("menupopup");
menulist.appendChild(popup);
_frames = [];
var frames = doc.getElementsByTagName("frame");
if (frames.length) {
_getFrames(frames, popup);
}
else {
var item = _document.createElement("menuitem");
item.setAttribute("label", "Default");
popup.appendChild(item);
_frames = [doc];
}
menulist.selectedIndex = 0;
}
/*
* recursively searches for frames
*/
function _getFrames(frames, popup) {
for (var i = 0; i < frames.length; i++) {
var frame = frames[i];
if (frame.contentDocument) {
// get a good name
var frameName;
if (frame.title) {
frameName = frame.title;
}
else if (frame.name) {
frameName = frame.name;
}
else {
frameName = frame.contentDocument.location.href;
}
// add frame
var item = _document.createElement("menuitem");
item.setAttribute("label", frameName);
popup.appendChild(item);
_frames.push(frame.contentDocument);
// see if frame has its own frames
var subframes = frame.contentDocument.getElementsByTagName("frame");
if (subframes.length) _getFrames(subframes, popup);
}
}
}
/* /*
* gets selected frame/document * gets selected frame/document
*/ */
function _getDocument() { function _getDocument() {
return _frames[_document.getElementById("menulist-testFrame").selectedIndex]; return new Promise((resolve) => {
window.messageManager.addMessageListener('Scaffold:Document', function onDocument({ data }) {
window.messageManager.removeMessageListener('Scaffold:Document', onDocument);
let doc = new DOMParser().parseFromString(data.html, 'text/html');
doc = Zotero.HTTP.wrapDocument(doc, data.url);
resolve(doc);
});
window.messageManager.broadcastAsyncMessage('Scaffold:GetDocument');
});
} }
function _getDocumentURL(doc) { function _getDocumentURL(doc) {

View file

@ -30,10 +30,6 @@
<?xml-stylesheet href="chrome://zotero-platform-version/content/style.css"?> <?xml-stylesheet href="chrome://zotero-platform-version/content/style.css"?>
<?xml-stylesheet href="chrome://zotero-platform/content/zotero-react-client.css"?> <?xml-stylesheet href="chrome://zotero-platform/content/zotero-react-client.css"?>
<?xul-overlay href="chrome://zotero/content/containers/containers.xul"?>
<?xul-overlay href="chrome://zotero/content/standalone/editMenuOverlay.xul"?>
<?xul-overlay href="chrome://zotero-platform/content/standalone/menuOverlay.xul"?>
<!DOCTYPE window [ <!DOCTYPE window [
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> %globalDTD; <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> %globalDTD;
<!ENTITY % standaloneDTD SYSTEM "chrome://zotero/locale/standalone.dtd" > %standaloneDTD; <!ENTITY % standaloneDTD SYSTEM "chrome://zotero/locale/standalone.dtd" > %standaloneDTD;
@ -44,15 +40,35 @@
]> ]>
<window id="scaffold" width="800" height="600" minheight="600" persist="screenX screenY width height" <window id="scaffold" width="800" height="600" minheight="600" persist="screenX screenY width height"
title="Scaffold" title="Scaffold"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
<script src="chrome://zotero/content/include.js"/> xmlns:html="http://www.w3.org/1999/xhtml"
<script src="chrome://zotero/content/xpcom/translate/testTranslators/translatorTester.js"/> style="display: flex;">
<script src="translators.js"/>
<script src="scaffold.js"/>
<script src="chrome://global/content/globalOverlay.js"/> <html:link rel="localization" href="zotero/menubar.ftl"/>
<script src="chrome://global/content/contentAreaUtils.js"/> <html:link rel="localization" href="zotero/textActions.ftl"/>
<script>
var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.scriptloader.loadSubScript("chrome://zotero/content/include.js", this);
Services.scriptloader.loadSubScript("resource://zotero/require.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/xpcom/translate/testTranslators/translatorTester.js", this);
Services.scriptloader.loadSubScript("chrome://scaffold/content/translators.js", this);
Services.scriptloader.loadSubScript("chrome://scaffold/content/scaffold.js", this);
// Mozilla scripts
Services.scriptloader.loadSubScript("chrome://global/content/globalOverlay.js", this);
Services.scriptloader.loadSubScript("chrome://global/content/editMenuOverlay.js", this);
Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", this);
if (Zotero.isMac) {
Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
}
// Custom elements
Services.scriptloader.loadSubScript("chrome://global/content/customElements.js", this);
</script>
<commandset id="mainCommandSet"> <commandset id="mainCommandSet">
<command id="cmd_quitApplication" oncommand="goQuitApplication(event);"/> <command id="cmd_quitApplication" oncommand="goQuitApplication(event);"/>
@ -100,10 +116,38 @@
<key modifiers="accel" key="9" oncommand="Scaffold.showTabNumbered(9)"/> <key modifiers="accel" key="9" oncommand="Scaffold.showTabNumbered(9)"/>
</keyset> </keyset>
<keyset id="editMenuKeys"/> <!--
TODO: Customize per platform without ifdef?
<keyset id="editMenuKeys">
<key id="key_undo" data-l10n-id="text-action-undo-shortcut" modifiers="accel" command="cmd_undo"/>
<key id="key_redo"
#ifdef XP_UNIX
data-l10n-id="text-action-undo-shortcut"
modifiers="accel,shift"
#else
data-l10n-id="text-action-redo-shortcut"
modifiers="accel"
#endif
command="cmd_redo"/>
<key id="key_cut" data-l10n-id="text-action-cut-shortcut" modifiers="accel" command="cmd_cut"/>
<key id="key_copy" data-l10n-id="text-action-copy-shortcut" modifiers="accel" command="cmd_copy"/>
<key id="key_paste" data-l10n-id="text-action-paste-shortcut" modifiers="accel" command="cmd_paste"/>
<key id="key_delete" keycode="VK_DELETE" command="cmd_delete"/>
<key id="key_selectAll" data-l10n-id="text-action-select-all-shortcut" modifiers="accel" command="cmd_selectAll"/>
<key id="key_find" key="&findCmd.key;" modifiers="accel" command="cmd_find"/>
<key id="key_findAgain" key="&findAgainCmd.key;" modifiers="accel" command="cmd_findAgain"/>
<key id="key_findPrevious" key="&findAgainCmd.key;" modifiers="shift,accel" command="cmd_findPrevious"/>
<key id="key_findAgain2" keycode="&findAgainCmd.key2;" command="cmd_findAgain"/>
<key id="key_findPrevious2" keycode="&findAgainCmd.key2;" modifiers="shift" command="cmd_findPrevious"/>
</keyset>
-->
<popupset> <popupset>
<menupopup id="testing-context-menue"> <menupopup id="testing-context-menu">
<menuitem label="&scaffold.testing.copyToClipboard;" tooltiptext="Copy the URL or data for the current test to the clipboard" oncommand="Scaffold.copyToClipboard()"/> <menuitem label="&scaffold.testing.copyToClipboard;" tooltiptext="Copy the URL or data for the current test to the clipboard" oncommand="Scaffold.copyToClipboard()"/>
<menuitem id="testing_editImport" label="&scaffold.testing.edit;" tooltiptext="Edit the input data for the current test" oncommand="Scaffold.editImportFromTest()"/> <menuitem id="testing_editImport" label="&scaffold.testing.edit;" tooltiptext="Edit the input data for the current test" oncommand="Scaffold.editImportFromTest()"/>
<menu id="testing_openURL" label="&scaffold.testing.openUrl;"> <menu id="testing_openURL" label="&scaffold.testing.openUrl;">
@ -139,19 +183,44 @@
</menupopup> </menupopup>
</menu> </menu>
<menu id="menu_edit"> <menu id="menu_edit" data-l10n-id="menu-edit">
<menupopup id="menu_EditPopup"> <menupopup id="menu_EditPopup">
<menuitem id="menu_undo" command="cmd_undo"/> <menuitem id="menu_undo"
<menuitem id="menu_redo" command="cmd_redo"/> key="key_undo"
command="cmd_undo" data-l10n-id="text-action-undo"/>
<menuitem id="menu_redo"
key="key_redo"
command="cmd_redo" data-l10n-id="text-action-redo"/>
<menuseparator/> <menuseparator/>
<menuitem id="menu_cut"/> <menuitem id="menu_cut"
<menuitem id="menu_copy"/> key="key_cut"
<menuitem id="menu_paste"/> command="cmd_cut" data-l10n-id="text-action-cut"/>
<menuitem id="menu_delete"/> <menuitem id="menu_copy"
<menuseparator class="menu-type-library"/> key="key_copy"
<menuitem id="menu_selectAll" class="menu-type-library" command="cmd_selectAll"/> command="cmd_copy" data-l10n-id="text-action-copy"/>
<menuseparator class="menu-type-library"/> <menuitem id="menu_paste"
<menuitem id="menu_find" class="menu-type-library" command="cmd_find"/> key="key_paste"
command="cmd_paste" data-l10n-id="text-action-paste"/>
<menuitem id="menu_delete"
key="key_delete"
command="cmd_delete" data-l10n-id="text-action-delete"/>
<menuseparator/>
<menuitem id="menu_selectAll"
key="key_selectAll"
command="cmd_selectAll" data-l10n-id="text-action-select-all"/>
<menuseparator/>
<menuitem id="menu_find" label="&findCmd.label;"
key="key_find" accesskey="&findCmd.accesskey;"
command="cmd_find"/>
<!--
#ifdef XP_UNIX
#ifndef XP_MACOSX
<menuseparator/>
<menuitem id="menu_preferences"
oncommand="Zotero.Utilities.Internal.openPreferences()" data-l10n-id="menu-preferences"/>
#endif
#endif
-->
</menupopup> </menupopup>
</menu> </menu>
@ -197,11 +266,87 @@
</menupopup> </menupopup>
</menu> </menu>
<!-- ifdef mac -->
<commandset id="macCommandSet"> <!-- was mainCommandSet -->
<command id="minimizeWindow"
label="&minimizeWindow.label;"
oncommand="window.minimize();" />
<command id="zoomWindow"
label="&zoomWindow.label;"
oncommand="zoomWindow();" />
</commandset>
<keyset id="macKeyset"> <!-- was mainKeySet -->
<key id="key_minimizeWindow"
command="minimizeWindow"
key="&minimizeWindow.key;"
modifiers="accel"/>
<!-- These are used to build the Application menu under Cocoa widgets -->
<key id="key_preferencesCmdMac"
key="&preferencesCmdMac.commandkey;"
modifiers="accel"/>
<key id="key_hideThisAppCmdMac"
key="&hideThisAppCmdMac.commandkey;"
modifiers="accel"/>
<key id="key_hideOtherAppsCmdMac"
key="&hideOtherAppsCmdMac.commandkey;"
modifiers="accel,alt"/>
<key id="key_quitApplication"
key="&quitApplicationCmdMac.key;"
command="cmd_quitApplication"
modifiers="accel"/>
</keyset>
<!-- nsMenuBarX hides these and uses them to build the Application menu. -->
<menupopup id="menu_FilePopup">
<menuitem id="menu_preferences"
label="&preferencesCmdMac.label;"
key="key_preferencesCmdMac"
oncommand="Zotero.Utilities.Internal.openPreferences()"/>
<menuitem id="menu_mac_services"
label="&servicesMenuMac.label;"/>
<menuitem id="menu_mac_hide_app"
label="&hideThisAppCmdMac.label;"
key="key_hideThisAppCmdMac"/>
<menuitem id="menu_mac_hide_others"
label="&hideOtherAppsCmdMac.label;"
key="key_hideOtherAppsCmdMac"/>
<menuitem id="menu_mac_show_all"
label="&showAllAppsCmdMac.label;"/>
<menuitem id="menu_FileQuitItem"
label="&quitApplicationCmdMac.label;"
key="key_quitApplication"
command="cmd_quitApplication"/>
</menupopup>
<menu id="windowMenu" <menu id="windowMenu"
label="&windowMenu.label;" label="&windowMenu.label;"
onpopupshowing="macWindowMenuDidShow();" datasources="rdf:window-mediator" ref="NC:WindowMediatorRoot"
onpopuphidden="macWindowMenuDidHide();"> onpopupshowing="macWindowMenuDidShow();"
onpopuphidden="macWindowMenuDidHide();"
hidden="false">
<template>
<rule>
<menupopup>
<menuitem uri="rdf:*"
label="rdf:http://home.netscape.com/NC-rdf#Name"
type="radio"
name="windowList"
oncommand="ShowWindowFromResource(event.target)"/>
</menupopup>
</rule>
</template>
<menupopup id="windowPopup">
<menuitem command="minimizeWindow" label="&minimizeWindow.label;" key="key_minimizeWindow"/>
<menuitem command="zoomWindow" label="&zoomWindow.label;"/>
<!-- decomment when "BringAllToFront" is implemented
<menuseparator/>
<menuitem label="&bringAllToFront.label;" disabled="true"/> -->
<menuseparator id="sep-window-list"/>
</menupopup>
</menu> </menu>
<!-- endif -->
<menu id="helpMenu" label="&helpMenu.label;" accesskey="&helpMenu.accesskey;"> <menu id="helpMenu" label="&helpMenu.label;" accesskey="&helpMenu.accesskey;">
<menupopup id="mb-help-popup"> <menupopup id="mb-help-popup">
@ -251,88 +396,61 @@
</toolbar> </toolbar>
<hbox flex="1"> <hbox flex="1">
<tabbox id="left-tabbox" flex="2" width="300"> <tabbox id="left-tabbox" flex="2" width="300">
<tabs id="tabs" onselect="Scaffold.handleTabSelect(event)"> <tabs id="tabs">
<tab id="tab-metadata" label="&scaffold.tabs.metadata.label;"/> <tab id="tab-metadata" label="&scaffold.tabs.metadata.label;"/>
<tab id="tab-code" label="&scaffold.tabs.code.label;"/> <tab id="tab-code" label="&scaffold.tabs.code.label;"/>
<tab id="tab-tests" label="&scaffold.tabs.tests.label;"/> <tab id="tab-tests" label="&scaffold.tabs.tests.label;"/>
<tab id="tab-browser" label="Browser"/> <tab id="tab-browser" label="Browser"/>
<tab id="tab-import" label="&scaffold.tabs.import.label;"/> <tab id="tab-import" label="&scaffold.tabs.import.label;"/>
</tabs> </tabs>
<tabpanels flex="1"> <tabpanels flex="1" id="tabpanels">
<tabpanel flex="1" id="tabpanel-metadata"> <tabpanel flex="1" id="tabpanel-metadata">
<grid flex="1"> <html:div id="metadata-grid">
<columns> <label class="label-metadata" value="&scaffold.metadata.translatorID.label;" control="textbox-translatorID"/>
<column/> <html:div class="button-row">
<column flex="1"/> <html:input type="text" id="textbox-translatorID"/>
</columns> <button label="&scaffold.metadata.translatorID.generate;" oncommand="Scaffold.generateTranslatorID()"/>
</html:div>
<rows> <label class="label-metadata" value="&scaffold.metadata.label.label;" control="textbox-label"/>
<row align="center"> <html:input type="text" id="textbox-label" flex="1" value="&scaffold.metadata.label.default;"/>
<label class="label-metadata" value="&scaffold.metadata.translatorID.label;" control="textbox-translatorID"/>
<hbox>
<textbox id="textbox-translatorID" flex="1"/>
<button label="&scaffold.metadata.translatorID.generate;" oncommand="Scaffold.generateTranslatorID()"/>
</hbox>
</row>
<row align="center"> <label class="label-metadata" value="&scaffold.metadata.creator.label;" control="textbox-creator"/>
<label class="label-metadata" value="&scaffold.metadata.label.label;" control="textbox-label"/> <html:input type="text" id="textbox-creator" flex="1"/>
<textbox id="textbox-label" flex="1" value="&scaffold.metadata.label.default;"/>
</row>
<row align="center"> <label class="label-metadata" value="&scaffold.metadata.target.label;" control="textbox-target"/>
<label class="label-metadata" value="&scaffold.metadata.creator.label;" control="textbox-creator"/> <html:div class="button-row">
<textbox id="textbox-creator" flex="1"/> <html:input type="text" id="textbox-target" flex="1"/>
</row> <button label="&scaffold.metadata.target.testRegex;" oncommand="Scaffold.logTargetRegex()"/>
</html:div>
<row align="center"> <label class="label-metadata" value="&scaffold.metadata.targetAll.label;" control="textbox-target-all" style="display: none"/>
<label class="label-metadata" value="&scaffold.metadata.target.label;" control="textbox-target"/> <html:input type="text" id="textbox-target-all" flex="1" style="display: none"/>
<hbox>
<textbox id="textbox-target" flex="1"/>
<button label="&scaffold.metadata.target.testRegex;" oncommand="Scaffold.logTargetRegex()"/>
</hbox>
</row>
<row align="center"> <label class="label-metadata" value="&scaffold.metadata.configOptions.label;" control="textbox-configOptions"/>
<label class="label-metadata" value="&scaffold.metadata.targetAll.label;" control="textbox-target-all" style="display: none"/> <html:input type="text" id="textbox-configOptions" flex="1"/>
<textbox id="textbox-target-all" flex="1" style="display: none"/>
</row>
<row align="center"> <label class="label-metadata" value="&scaffold.metadata.displayOptions.label;" control="textbox-displayOptions"/>
<label class="label-metadata" value="&scaffold.metadata.configOptions.label;" control="textbox-configOptions"/> <html:input type="text" id="textbox-displayOptions" flex="1"/>
<textbox id="textbox-configOptions" flex="1"/>
</row>
<row align="center"> <label class="label-metadata" value="&scaffold.metadata.minVersion.label;" control="textbox-minVersion"/>
<label class="label-metadata" value="&scaffold.metadata.displayOptions.label;" control="textbox-displayOptions"/> <html:div>
<textbox id="textbox-displayOptions" flex="1"/> <html:input type="text" id="textbox-minVersion" flex="1" value="5.0"/>
</row> <label class="label-metadata" value="&scaffold.metadata.priority.label;" control="textbox-priority"/>
<html:input type="text" id="textbox-priority" flex="1" value="&scaffold.metadata.priority.default;"/>
</html:div>
<row align="center"> <label class="label-metadata" value="&scaffold.metadata.hiddenPrefs.label;" control="textbox-hidden-prefs" style="display: none"/>
<label class="label-metadata" value="&scaffold.metadata.minVersion.label;" control="textbox-minVersion"/> <html:input type="text" id="textbox-hidden-prefs" flex="1" style="display: none"/>
<hbox>
<textbox id="textbox-minVersion" flex="1" value="5.0"/>
<label class="label-metadata" value="&scaffold.metadata.priority.label;" control="textbox-priority"/>
<textbox id="textbox-priority" flex="1" value="&scaffold.metadata.priority.default;"/>
</hbox>
</row>
<row align="center"> <label class="label-metadata" value="&scaffold.metadata.translatorType.label;"/>
<label class="label-metadata" value="&scaffold.metadata.hiddenPrefs.label;" control="textbox-hidden-prefs" style="display: none"/> <html:div id="checkboxes-translatorType">
<textbox id="textbox-hidden-prefs" flex="1" style="display: none"/> <checkbox id="checkbox-import" label="&scaffold.metadata.translatorType.import;"/>
</row> <checkbox id="checkbox-export" label="&scaffold.metadata.translatorType.export;"/>
<checkbox id="checkbox-web" label="&scaffold.metadata.translatorType.web;" checked="true"/>
<row align="center"> <checkbox id="checkbox-search" label="&scaffold.metadata.translatorType.search;"/>
<label class="label-metadata" value="&scaffold.metadata.translatorType.label;"/> </html:div>
<hbox id="checkboxes-translatorType"> </html:div>
<checkbox id="checkbox-import" label="&scaffold.metadata.translatorType.import;"/>
<checkbox id="checkbox-export" label="&scaffold.metadata.translatorType.export;"/>
<checkbox id="checkbox-web" label="&scaffold.metadata.translatorType.web;" checked="true"/>
<checkbox id="checkbox-search" label="&scaffold.metadata.translatorType.search;"/>
</hbox>
</row>
</rows>
</grid>
</tabpanel> </tabpanel>
<tabpanel flex="1" id="tabpanel-code"> <tabpanel flex="1" id="tabpanel-code">
<vbox flex="1"> <vbox flex="1">
@ -342,24 +460,24 @@
<tabpanel flex="1" id="tabpanel-tests"> <tabpanel flex="1" id="tabpanel-tests">
<vbox flex="1"> <vbox flex="1">
<vbox flex="1"> <vbox flex="1">
<hbox flex="1" context="testing-context-menue"> <keyset>
<keyset> <key id="key-delete-tests" observes="validate-tests" keycode="VK_BACK" oncommand="Scaffold.deleteSelectedTests()"/>
<key id="key-delete-tests" observes="validate-tests" keycode="VK_BACK" oncommand="Scaffold.deleteSelectedTests()"/> </keyset>
</keyset>
<listbox id="testing-listbox" observes="validate-tests" flex="1" seltype="multiple" onselect="Scaffold.handleTestSelect(event)"> <listheader>
<listhead> <treecol label="&scaffold.testing.input.label;" flex="1"/>
<listheader label="&scaffold.testing.input.label;"/> <treecol label="&scaffold.testing.status.label;" width="150"/>
<listheader label="&scaffold.testing.status.label;"/> <treecol label="&scaffold.testing.defer.label;"/>
<listheader label="&scaffold.testing.defer.label;"/> </listheader>
</listhead> <richlistbox
<listcols> id="testing-listbox"
<listcol flex="1"/> class="theme-listbox"
<listcol class="listcol-testMessage"/> observes="validate-tests"
<listcol/> flex="1"
</listcols> seltype="multiple"
</listbox> onselect="Scaffold.handleTestSelect(event)"
</hbox> context="testing-context-menu"
/>
<hbox> <hbox>
<button observes="validate-tests" label="&scaffold.testing.delete;" tooltiptext="Delete the selected tests" oncommand="Scaffold.deleteSelectedTests()"/> <button observes="validate-tests" label="&scaffold.testing.delete;" tooltiptext="Delete the selected tests" oncommand="Scaffold.deleteSelectedTests()"/>
<button observes="validate-tests" label="&scaffold.testing.run;" tooltiptext="Run the selected tests" oncommand="Scaffold.runSelectedTests()"/> <button observes="validate-tests" label="&scaffold.testing.run;" tooltiptext="Run the selected tests" oncommand="Scaffold.runSelectedTests()"/>
@ -374,13 +492,18 @@
<vbox flex="1"> <vbox flex="1">
<hbox align="center"> <hbox align="center">
<label control="textbox-tabUrl" value="&scaffold.tabUrl.label;"/> <label control="textbox-tabUrl" value="&scaffold.tabUrl.label;"/>
<menulist id="browser-url" editable="true" flex="1"> <html:input id="browser-url" style="-moz-box-flex: 1;"/>
<menupopup></menupopup>
</menulist>
<button observes="validate-tests" label="&scaffold.testing.create.web;" tooltiptext="Create a new test from the current page" oncommand="Scaffold.saveTestFromCurrent('web')"/> <button observes="validate-tests" label="&scaffold.testing.create.web;" tooltiptext="Create a new test from the current page" oncommand="Scaffold.saveTestFromCurrent('web')"/>
</hbox> </hbox>
<browser id="browser" src="about:blank" type="content" flex="1"></browser> <browser
id="browser"
type="content"
remote="false"
disablehistory="true"
src="about:blank"
maychangeremoteness="true"
flex="1"/>
</vbox> </vbox>
</tabpanel> </tabpanel>
<tabpanel flex="1" id="tabpanel-import"> <tabpanel flex="1" id="tabpanel-import">
@ -397,13 +520,7 @@
<splitter resizeafter="farthest" /> <splitter resizeafter="farthest" />
<vbox id="right-pane" flex="1"> <vbox id="right-pane" flex="1">
<html:textarea style="-moz-box-flex: 1" id="output" readonly="true"/>
<hbox id="hbox-testFrame" width="300">
<label control="menulist-testFrame" id="label-testFrame" value="&scaffold.testFrame.label;"/>
<menulist id="menulist-testFrame"/>
</hbox>
<textbox flex="1" id="output" multiline="true" readonly="true"/>
</vbox> </vbox>
</hbox> </hbox>

View file

@ -26,7 +26,7 @@
/** /**
* @namespace Singleton to interface with the browser when ingesting data * @namespace Singleton to interface with the browser when ingesting data
*/ */
var Zotero_Ingester_Interface_SelectItems = function() {} var Zotero_Ingester_Interface_SelectItems = function () {};
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@ -38,7 +38,10 @@ var Zotero_Ingester_Interface_SelectItems = function() {}
* Presents items to select in the select box. Assumes window.arguments[0].dataIn is an object with * Presents items to select in the select box. Assumes window.arguments[0].dataIn is an object with
* URLs as keys and descriptions as values * URLs as keys and descriptions as values
*/ */
Zotero_Ingester_Interface_SelectItems.init = function() { Zotero_Ingester_Interface_SelectItems.init = function () {
document.addEventListener('dialogaccept',
() => Zotero_Ingester_Interface_SelectItems.acceptSelection());
// Set font size from pref // Set font size from pref
var sbc = document.getElementById('zotero-select-items-container'); var sbc = document.getElementById('zotero-select-items-container');
Zotero.setFontSize(sbc); Zotero.setFontSize(sbc);
@ -46,59 +49,66 @@ Zotero_Ingester_Interface_SelectItems.init = function() {
this.io = window.arguments[0]; this.io = window.arguments[0];
var listbox = document.getElementById("zotero-selectitems-links"); var listbox = document.getElementById("zotero-selectitems-links");
for(var i in this.io.dataIn) { // we could use a tree for this if we wanted to for (var i in this.io.dataIn) { // we could use a tree for this if we wanted to
var item = this.io.dataIn[i]; var item = this.io.dataIn[i];
var title, checked = false; var title, checked = false;
if(item && typeof(item) == "object" && item.title !== undefined) { if (item && typeof item == "object" && item.title !== undefined) {
title = item.title; title = item.title;
checked = !!item.checked; checked = !!item.checked;
} else { }
else {
title = item; title = item;
} }
var itemNode = document.createElement("listitem"); let itemNode = document.createXULElement("richlistitem");
itemNode.setAttribute("type", "checkbox"); let checkbox = document.createXULElement("checkbox");
checkbox.checked = checked;
checkbox.label = title;
itemNode.setAttribute("value", i); itemNode.setAttribute("value", i);
itemNode.setAttribute("label", title); itemNode.append(checkbox);
itemNode.setAttribute("checked", checked); itemNode.addEventListener('click', (event) => {
listbox.appendChild(itemNode); if (event.target == itemNode) {
checkbox.checked = !checkbox.checked;
}
});
listbox.append(itemNode);
} }
// Check item if there is only one // Check item if there is only one
if (listbox.itemCount === 1) { if (listbox.itemCount === 1) {
listbox.getItemAtIndex(0).setAttribute("checked", true); listbox.getItemAtIndex(0).firstElementChild.checked = true;
} }
} };
/** /**
* Selects or deselects all items * Selects or deselects all items
* @param {Boolean} deselect If true, deselect all items instead of selecting all items * @param {Boolean} deselect If true, deselect all items instead of selecting all items
*/ */
Zotero_Ingester_Interface_SelectItems.selectAll = function(deselect) { Zotero_Ingester_Interface_SelectItems.selectAll = function (deselect) {
var listbox = document.getElementById("zotero-selectitems-links"); var listbox = document.getElementById("zotero-selectitems-links");
for (var i=0; i<listbox.childNodes.length; i++){ for (var i = 0; i < listbox.childNodes.length; i++) {
listbox.childNodes[i].setAttribute('checked', !deselect); listbox.childNodes[i].firstElementChild.checked = !deselect;
} }
} };
/** /**
* Called when "OK" button is pressed to populate window.arguments[0].dataOut with selected items * Called when "OK" button is pressed to populate window.arguments[0].dataOut with selected items
*/ */
Zotero_Ingester_Interface_SelectItems.acceptSelection = function() { Zotero_Ingester_Interface_SelectItems.acceptSelection = function () {
var listbox = document.getElementById("zotero-selectitems-links"); var listbox = document.getElementById("zotero-selectitems-links");
var returnObject = false; var returnObject = false;
this.io.dataOut = new Object(); this.io.dataOut = {};
// collect scrapeURLList from listbox // collect scrapeURLList from listbox
for(var i=0; i<listbox.childNodes.length; i++) { for (var i = 0; i < listbox.childNodes.length; i++) {
var itemNode = listbox.childNodes[i]; var itemNode = listbox.childNodes[i];
if(itemNode.getAttribute("checked") == "true") { if (itemNode.firstElementChild.checked) {
this.io.dataOut[itemNode.getAttribute("value")] = itemNode.getAttribute("label"); this.io.dataOut[itemNode.getAttribute("value")] = itemNode.firstElementChild.getAttribute("label");
returnObject = true; returnObject = true;
} }
} }
if(!returnObject) this.io.dataOut = null; if (!returnObject) this.io.dataOut = null;
} };

View file

@ -25,27 +25,33 @@
--> -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd"> <!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
<dialog xmlns:html="http://www.w3.org/1999/xhtml" <window xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&zotero.selectitems.title;" width="400" height="330" title="&zotero.selectitems.title;" width="400" height="330"
persist="width height screenX screenY" persist="width height screenX screenY"
buttons="cancel,accept"
ondialogaccept="Zotero_Ingester_Interface_SelectItems.acceptSelection()"
id="zotero-selectitems"
onload="Zotero_Ingester_Interface_SelectItems.init()"> onload="Zotero_Ingester_Interface_SelectItems.init()">
<dialog
<script src="../include.js"/> buttons="cancel,accept"
<script src="selectitems.js"/> id="zotero-selectitems">
<script>
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
Services.scriptloader.loadSubScript("chrome://zotero/content/include.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/ingester/selectitems.js", this);
Services.scriptloader.loadSubScript("chrome://global/content/customElements.js", this);
</script>
<vbox id="zotero-select-items-container" flex="1"> <vbox id="zotero-select-items-container" flex="1">
<caption label="&zotero.selectitems.intro.label;" id="zotero-selectitems-intro"/> <caption label="&zotero.selectitems.intro.label;" id="zotero-selectitems-intro"/>
<box flex="1"> <box flex="1">
<listbox id="zotero-selectitems-links" flex="1" context="zoteroSelectContext"></listbox> <richlistbox id="zotero-selectitems-links" flex="1"></richlistbox>
</box> </box>
<hbox> <hbox>
<button label="Select All" oncommand="Zotero_Ingester_Interface_SelectItems.selectAll()"/> <button label="Select All" oncommand="Zotero_Ingester_Interface_SelectItems.selectAll()"/>
<button label="Deselect All" oncommand="Zotero_Ingester_Interface_SelectItems.selectAll(true)"/> <button label="Deselect All" oncommand="Zotero_Ingester_Interface_SelectItems.selectAll(true)"/>
</hbox> </hbox>
</vbox> </vbox>
</dialog> </dialog>
</window>

View file

@ -912,7 +912,7 @@ function openStyleEditor() {
function openScaffold() { function openScaffold() {
openWindowByType( openWindowByType(
'chrome://scaffold/content/scaffold.xul', 'chrome://scaffold/content/scaffold.xhtml',
'zotero:scaffold', 'zotero:scaffold',
'chrome,resizable' 'chrome,resizable'
); );

View file

@ -164,7 +164,7 @@ Zotero.CookieSandbox.prototype = {
* @param {nsIInterfaceRequestor} ir * @param {nsIInterfaceRequestor} ir
*/ */
"attachToInterfaceRequestor": function(ir) { "attachToInterfaceRequestor": function(ir) {
Zotero.CookieSandbox.Observer.trackedInterfaceRequestors.push(Components.utils.getWeakReference(ir.QueryInterface(Components.interfaces.nsIInterfaceRequestor))); Zotero.CookieSandbox.Observer.trackedInterfaceRequestors.push(Cu.getWeakReference(ir.getInterface(Ci.nsIInterfaceRequestor)));
Zotero.CookieSandbox.Observer.trackedInterfaceRequestorSandboxes.push(this); Zotero.CookieSandbox.Observer.trackedInterfaceRequestorSandboxes.push(this);
}, },

View file

@ -1,6 +1,3 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
#tb-new { #tb-new {
list-style-image: url('chrome://scaffold/skin/new.png'); list-style-image: url('chrome://scaffold/skin/new.png');
} }
@ -53,11 +50,28 @@
list-style-image: url('chrome://scaffold/skin/add.png'); list-style-image: url('chrome://scaffold/skin/add.png');
} }
#tabpanel-metadata textbox { #metadata-grid {
height:2em; -moz-box-flex: 1;
display: grid;
align-content: start;
align-items: center;
grid-template-columns: max-content 1fr;
} }
#tabpanel-metadata hbox, #hbox-testFrame { #metadata-grid > label:nth-child(2n + 1) {
justify-self: right;
}
.button-row {
display: grid;
grid-template-columns: 1fr max-content;
}
#tabpanel-metadata input {
height: 1.5em;
}
#hbox-testFrame {
-moz-box-align: center; -moz-box-align: center;
} }
@ -65,7 +79,7 @@
height:200px; height:200px;
} }
listbox { richlistbox {
min-width:200px; min-width:200px;
} }
@ -95,12 +109,50 @@ vbox > splitter {
cursor: row-resize; cursor: row-resize;
} }
listbox[disabled], toolbarbutton[disabled] { /* Adapted from Mozilla common-shared.css */
/* https://searchfox.org/mozilla-central/rev/2f5ed7b7244172d46f538051250b14fb4d8f1a5f/toolkit/themes/shared/in-content/common-shared.css */
select[size][multiple],
listheader,
richlistbox {
appearance: none;
margin-inline: 0;
background-color: #fff;
border: 1px solid #ccc;
}
listheader {
padding-bottom: 1px;
}
treecol {
appearance: none;
border: none;
}
listheader + richlistbox {
margin-top: 0;
border-top: none;
}
select[size][multiple] > option,
treechildren::-moz-tree-row {
padding: 0.3em;
margin: 0;
border: none;
background-image: none;
}
richlistitem[selected] menulist:focus-visible {
outline-offset: -2px;
}
richlistbox[disabled], toolbarbutton[disabled] {
opacity: 0.6; opacity: 0.6;
pointer-events: none; pointer-events: none;
} }
dialog listbox > listitem[disabled] { dialog richlistbox > richlistitem[disabled] {
font-weight: 600; font-weight: 600;
} }
@ -110,12 +162,14 @@ dialog listbox > listitem[disabled] {
#checkboxes-translatorType checkbox { #checkboxes-translatorType checkbox {
margin-right: 10px; margin-right: 10px;
display: inline-block;
} }
#tabpanel-metadata label:first-child { #tabpanel-metadata label:first-child {
text-align: right; text-align: right;
} }
.listcol-testMessage { #right-pane textarea {
width: 200px; margin-right: 5px;
margin-bottom: 5px;
} }

View file

@ -111,7 +111,11 @@ zoterofilesyncstatus {
richlistitem { richlistitem {
padding: 0.2em 0.4em; padding: 0.2em 0.4em;
}
richlistitem, richlistitem > * {
overflow-x: hidden; overflow-x: hidden;
white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }