diff --git a/chrome/content/zotero/elements/publicationsLicenseInfo.js b/chrome/content/zotero/elements/publicationsLicenseInfo.js new file mode 100644 index 0000000000..2a325ab871 --- /dev/null +++ b/chrome/content/zotero/elements/publicationsLicenseInfo.js @@ -0,0 +1,153 @@ +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2022 Corporation for Digital Scholarship + Vienna, Virginia, USA + https://www.zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see . + + ***** END LICENSE BLOCK ***** +*/ + +/* global XULElementBase: false */ + +{ + const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + Services.scriptloader.loadSubScript("chrome://zotero/content/elements/base.js", this); + + const links = { + cc: 'https://wiki.creativecommons.org/Considerations_for_licensors_and_licensees', + cc0: 'https://wiki.creativecommons.org/CC0_FAQ' + }; + + const getLicenseData = (license) => { + var name, img, url, id; + + switch (license) { + case 'reserved': + url = null; + name = 'All rights reserved'; + img = 'chrome://zotero/skin/licenses/reserved.png'; + id = null; + break; + case 'cc': + url = 'https://creativecommons.org/'; + name = 'Creative Commons'; + img = 'chrome://zotero/skin/licenses/cc-srr.png'; + id = null; + break; + + case 'cc0': + url = "https://creativecommons.org/publicdomain/zero/1.0/"; + name = null; + img = 'chrome://zotero/skin/licenses/' + license + ".svg"; + id = 'licenses-cc-0'; + break; + + default: + url = 'https://creativecommons.org/licenses/' + license.replace(/^cc-/, '') + '/4.0/'; + name = null; + img = 'chrome://zotero/skin/licenses/' + license + ".svg"; + id = `licenses-${license}`; + break; + } + + return { url, name, img, id }; + }; + + const makeLicenseInfo = (url, name, img, id) => { + const licenseInfo = `
` + + (id ? `
` : `
${name}
`); + + return MozXULElement.parseXULToFragment( + url + ? `${licenseInfo}` + : `
${licenseInfo}
` + ); + }; + + const makeLicenseMoreInfo = (license) => { + const needsMoreInfo = license.startsWith('cc') && license !== 'cc'; + const ccType = license === 'cc0' ? 'cc0' : 'cc'; + + return MozXULElement.parseXULToFragment(needsMoreInfo + ? `
+ +
` + : '' + ); + }; + + class PublicationsLicenseInfo extends XULElementBase { + get stylesheets() { + return [ + 'chrome://global/skin/global.css', + 'chrome://zotero/skin/elements/license-info.css' + ]; + } + + content = MozXULElement.parseXULToFragment(` +
+
+ `); + + validLicenses = new Set(['cc', 'cc-by', 'cc-by-sa', 'cc-by-nd', 'cc-by-nc', 'cc-by-nc-sa', 'cc-by-nc-nd', 'cc0', 'reserved']); + + get license() { + return this._license; + } + + set license(val) { + if (!this.validLicenses.has(val)) { + throw new Zotero.Error(`"${val}" is invalid value for attribute "license" in `); + } + this._license = val; + this.update(); + } + + get licenseName() { + return this.shadowRoot.querySelector('.license-name').getAttribute('label') + ? this.shadowRoot.querySelector('.license-name').getAttribute('label') + : this.shadowRoot.querySelector('.license-name').textContent; + } + + async init() { + this.license = this.getAttribute('license'); + this.shadowRoot.getElementById('license-info').addEventListener('click', this.onURLInteract.bind(this)); + this.shadowRoot.getElementById('license-info').addEventListener('keydown', this.onURLInteract.bind(this)); + } + + update() { + const { url, name, img, id } = getLicenseData(this.license); + const licenseInfoEl = makeLicenseInfo(url, name, img, id); + const licenseMoreEl = makeLicenseMoreInfo(this.license); + this.shadowRoot.getElementById('license-info').replaceChildren(licenseInfoEl, licenseMoreEl); + } + + onURLInteract(ev) { + const aEl = ev.target.closest('[href]'); + if (aEl && (ev.type === 'click' || (ev.type === 'keydown' && ev.key === ' '))) { + ev.preventDefault(); + Zotero.launchURL(aEl.getAttribute('href')); + } + } + } + customElements.define('publications-license-info', PublicationsLicenseInfo); +} diff --git a/chrome/content/zotero/publicationsDialog.js b/chrome/content/zotero/publicationsDialog.js index 5e02838659..35d83177dc 100644 --- a/chrome/content/zotero/publicationsDialog.js +++ b/chrome/content/zotero/publicationsDialog.js @@ -1,234 +1,29 @@ /* - ***** BEGIN LICENSE BLOCK ***** - - Copyright © 2015 Center for History and New Media - George Mason University, Fairfax, Virginia, USA - https://www.zotero.org - - This file is part of Zotero. - - Zotero is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Zotero is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with Zotero. If not, see . - - ***** END LICENSE BLOCK ***** + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2015 Center for History and New Media + George Mason University, Fairfax, Virginia, USA + https://www.zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see . + + ***** END LICENSE BLOCK ***** */ -var Zotero_Publications_Dialog = new function () { - var _initialized = false; - var _io; - var _hasFiles = false; - var _hasNotes = false; - var _hasRights = null; - var _includeFiles = true; - var _includeNotes = true; - var _keepRights = true; - var _shareSettings = { - sharing: 'reserved', // 'reserved', 'cc', 'cc0' - adaptations: 'no', - commercial: 'no' - }; - var _license = null; - - function _init() { - try { - var wizard = document.getElementById('zotero-publications-wizard'); - wizard.getButton('finish').label = - Zotero.getString('publications.buttons.addToMyPublications'); - - if (window.arguments && window.arguments.length) { - _io = window.arguments[0]; - _hasFiles = _io.hasFiles; - _hasNotes = _io.hasNotes; - _hasRights = _io.hasRights; - if (_hasRights == 'none') _keepRights = false; - delete _io.hasFiles; - delete _io.hasNotes; - delete _io.hasRights; - } - _initialized = true; - } - catch (e) { - window.close(); - throw e; - } - } - - - this.updatePage = function () { - if (!_initialized) { - _init(); - this.updateInclude(); - } - - var wizard = document.getElementById('zotero-publications-wizard'); - var currentPage = wizard.currentPage; - var pageid = currentPage.pageid; - - if (pageid == 'intro') { - let str = 'publications.authorship.checkbox'; - let filesCheckbox = document.getElementById('include-files'); - let notesCheckbox = document.getElementById('include-notes') - - // Enable the checkboxes only when relevant - filesCheckbox.disabled = !_hasFiles; - filesCheckbox.checked = _hasFiles && _includeFiles; - notesCheckbox.disabled = !_hasNotes; - notesCheckbox.checked = _hasNotes && _includeNotes; - - // Adjust the checkbox text based on whether there are files or notes - if (filesCheckbox.checked || notesCheckbox.checked) { - if (filesCheckbox.checked && notesCheckbox.checked) { - str += '.filesNotes'; - } - else if (filesCheckbox.checked) { - str += '.files'; - } - else { - str += '.notes'; - } - } - } - else if (pageid == 'choose-sharing') { - let keepRightsBox = document.getElementById('keep-rights'); - let keepRightsCheckbox = document.getElementById('keep-rights-checkbox'); - if (_hasRights == 'none') { - keepRightsBox.hidden = true; - document.getElementById('sharing-radiogroup').focus(); - } - else { - let str = 'publications.sharing.keepRightsField'; - if (_hasRights == 'some') { - str += 'WhereAvailable'; - } - keepRightsCheckbox.label = Zotero.getString(str); - keepRightsCheckbox.checked = _keepRights; - this.updateKeepRights(keepRightsCheckbox.checked); - } - } - // Select appropriate radio button from current license - else if (pageid == 'choose-license') { - document.getElementById('adaptations-' + _shareSettings.adaptations).selected = true; - document.getElementById('commercial-' + _shareSettings.commercial).selected = true; - } - - _updateLicense(); - this.updateNextButton(); - }; - - - this.updateNextButton = function () { - var wizard = document.getElementById('zotero-publications-wizard'); - var currentPage = wizard.currentPage; - var nextPage = wizard.wizardPages[wizard.pageIndex + 1]; - var nextButton = wizard.getButton('next'); - - // Require authorship checkbox on first page to be checked to advance - wizard.canAdvance = document.getElementById('confirm-authorship-checkbox').checked; - - if (!nextPage) { - return; - } - - if (_hasFiles - && _includeFiles - && (currentPage.pageid == 'intro' || - // If CC selected on sharing page and we're not using existing rights for all - // items, go to license chooser next - (currentPage.pageid == 'choose-sharing' - && _shareSettings.sharing == 'cc' - && !(_hasRights == 'all' && _keepRights)))) { - this.lastPage = false; - nextButton.label = Zotero.getString( - 'publications.buttons.next', - Zotero.getString('publications.buttons.' + nextPage.pageid) - ); - } - // Otherwise this is the last page - else { - this.lastPage = true; - // Due to issues with linux not handling finish button hiding correctly - // we just set the next button label to be the one for the finish button - // and leave visibility handling up to mr wizard - nextButton.label = Zotero.getString('publications.buttons.addToMyPublications'); - } - } - - - /** - * Update files/notes settings from checkboxes - */ - this.updateInclude = function () { - var filesCheckbox = document.getElementById('include-files'); - var notesCheckbox = document.getElementById('include-notes') - var authorshipCheckbox = document.getElementById('confirm-authorship-checkbox'); - _includeFiles = filesCheckbox.checked; - _includeNotes = notesCheckbox.checked; - authorshipCheckbox.label = Zotero.getString( - 'publications.intro.authorship' + (_includeFiles ? '.files' : '') - ); - this.updateNextButton(); - } - - - /** - * Update rights setting from checkbox and hide sharing setting if necessary - */ - this.updateKeepRights = function (keepRights) { - _keepRights = keepRights; - - // If all items have rights and we're using them, the sharing page is the last page - document.getElementById('choose-sharing-options').hidden = _hasRights == 'all' && keepRights; - this.updateNextButton(); - } - - - /** - * Update sharing and license settings - */ - this.updateSharing = function (id) { - var matches = id.match(/^(sharing|adaptations|commercial)-(.+)$/); - var setting = matches[1]; - var value = matches[2]; - _shareSettings[setting] = value; - _updateLicense(); - this.updateNextButton(); - } - - - this.onAdvance = function () { - if (this.lastPage) { - this.finish(); - return false; - } - return true; - } - - - this.onFinish = function () { - _io.includeFiles = document.getElementById('include-files').checked; - _io.includeNotes = document.getElementById('include-notes').checked; - _io.keepRights = _keepRights; - _io.license = _license; - _io.licenseName = _getLicenseName(_license); - } - - this.finish = function () { - this.onFinish(); - window.close(); - } - - - /** +/** * Update the calculated license and image * * Possible licenses: @@ -242,185 +37,180 @@ var Zotero_Publications_Dialog = new function () { * 'cc0' * 'reserved' */ - function _updateLicense() { - var s = _shareSettings.sharing; - var a = _shareSettings.adaptations; - var c = _shareSettings.commercial; - - if (s == 'cc0' || s == 'reserved') { - _license = s; - } - else { - _license = 'cc-by'; - if (c == 'no') { - _license += '-nc'; - } - if (a == 'no') { - _license += '-nd'; - } - else if (a == 'sharealike') { - _license += '-sa'; - } - } - _updateLicenseSummary(); +const getLicense = (sharing, adaptations, commercial, currentPage) => { + if (sharing === 'cc0' || sharing === 'reserved') { + return sharing; } - - - /** - * - */ - function _updateLicenseSummary() { - var wizard = document.getElementById('zotero-publications-wizard'); - var currentPage = wizard.currentPage; - var groupbox = currentPage.getElementsByAttribute('class', 'license-info')[0]; - if (!groupbox) return; - if (groupbox.hasChildNodes()) { - let hbox = groupbox.lastChild; - var icon = currentPage.getElementsByAttribute('class', 'license-icon')[0]; - var div = currentPage.getElementsByAttribute('class', 'license-description')[0]; - } - else { - let hbox = document.createXULElement('hbox'); - hbox.align = "center"; - groupbox.appendChild(hbox); - - var icon = document.createXULElement('image'); - icon.className = 'license-icon'; - icon.setAttribute('style', 'width: 88px'); - hbox.appendChild(icon); - - let sep = document.createXULElement('separator'); - sep.orient = 'vertical'; - sep.setAttribute('style', 'width: 10px'); - hbox.appendChild(sep); - - var div = document.createElement('div'); - div.className = 'license-description'; - div.setAttribute('style', 'width: 400px'); - hbox.appendChild(div); - } - - // Show generic CC icon on sharing page - if (currentPage.pageid == 'choose-sharing' && _shareSettings.sharing == 'cc') { - var license = 'cc'; - } - else { - var license = _license; - } - - icon.src = _getLicenseImage(license); - var url = _getLicenseURL(license); - if (url) { - icon.setAttribute('tooltiptext', url); - icon.style.cursor = 'pointer'; - icon.onclick = function () { - try { - let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] - .getService(Components.interfaces.nsIWindowMediator); - let win = wm.getMostRecentWindow("navigator:browser"); - win.ZoteroPane_Local.loadURI(url, { shiftKey: true }) - } - catch (e) { - Zotero.logError(e); - } - return false; - }; - } - else { - icon.removeAttribute('tooltiptext'); - icon.style.cursor = 'auto'; - } - - div.innerHTML = _getLicenseHTML(license); - Zotero.Utilities.Internal.updateHTMLInXUL(div, { linkEvent: { shiftKey: true } }); - - _updateLicenseMoreInfo(); + if (currentPage !== 'choose-license') { + return 'cc'; } - - - function _getLicenseImage(license) { - // Use generic "Some Rights Reserved" image - if (license == 'cc') { - return "chrome://zotero/skin/licenses/cc-srr.png"; - } - else if (license == 'reserved') { - return "chrome://zotero/skin/licenses/reserved.png"; - } - return "chrome://zotero/skin/licenses/" + license + ".svg"; + + let license = 'cc-by'; + if (commercial === 'no') { + license += '-nc'; } - - - function _getLicenseHTML(license) { - switch (license) { - case 'cc': - return '
Creative Commons'; - - case 'reserved': - return "All rights reserved"; - - case 'cc0': - return 'CC0 1.0 Universal Public Domain Dedication'; - - default: - return '' - + Zotero.getString('licenses.' + license) + ""; - } + if (adaptations === 'no') { + license += '-nd'; } - - - function _getLicenseName(license) { - switch (license) { - case 'reserved': - return "All rights reserved"; - - case 'cc0': - return 'CC0 1.0 Universal Public Domain Dedication'; - - default: - return Zotero.getString('licenses.' + license) + " (" + license.toUpperCase() + ")"; - } + else if (adaptations === 'sharealike') { + license += '-sa'; } - - - function _getLicenseURL(license) { - switch (license) { - case 'reserved': - return ""; + return license; +}; + +const id = document.getElementById.bind(document); + +const Zotero_Publications_Dialog = { // eslint-disable-line no-unused-vars, camelcase + async init() { + this.io = window.arguments?.[0] ?? {}; + this.wizard = id('publications-dialog-wizard'); + + id('include-files') + .addEventListener('CheckboxStateChange', this.onIntroPageCheckboxChange.bind(this)); + id('confirm-authorship-checkbox') + .addEventListener('CheckboxStateChange', this.onIntroPageCheckboxChange.bind(this)); + id('sharing-radiogroup') + .addEventListener('select', this.onLicenseAspectRadioChange.bind(this)); + id('choose-adaptations') + .addEventListener('select', this.onLicenseAspectRadioChange.bind(this)); + id('choose-commercial') + .addEventListener('select', this.onLicenseAspectRadioChange.bind(this)); + id('keep-rights-checkbox') + .addEventListener('CheckboxStateChange', this.onKeepRightsCheckboxChange.bind(this)); + this.wizard.getPageById('intro') + .addEventListener('pageshow', this.onIntroPageShow.bind(this)); + this.wizard.getPageById('choose-sharing') + .addEventListener('pageshow', this.onSharingPageShow.bind(this)); + this.wizard.getPageById('choose-license') + .addEventListener('pageshow', this.onLicensePageShow.bind(this)); + + this.wizard.addEventListener('wizardnext', this.onWizardNext.bind(this)); + this.wizard.addEventListener('wizardfinish', this.onFinish.bind(this)); + + // wizard.shadowRoot content isn't exposed to our css + this.wizard.shadowRoot + .querySelector('.wizard-header-label').style.fontSize = '16px'; - case 'cc': - return 'https://creativecommons.org/'; - - case 'cc0': - return "https://creativecommons.org/publicdomain/zero/1.0/"; - - default: - return "https://creativecommons.org/licenses/" + license.replace(/^cc-/, '') + "/4.0/" + this.updateNextButton(); + this.updateIntroPage(); + }, + + onIntroPageShow() { + this.updateNextButton(); + this.updateIntroPage(); + this.updateFocus(); + }, + + onSharingPageShow() { + this.updateSharingPage(); + this.updateNextButton(); + this.updateLicense(); + this.updateFocus(); + }, + + onLicensePageShow() { + this.updateNextButton(); + this.updateLicense(); + this.updateFocus(); + }, + + onWizardNext(ev) { + if ((this.wizard.currentPage.pageid === 'intro' && !id('include-files').checked) + || (this.wizard.currentPage.pageid === 'choose-sharing' + && (id('sharing-radiogroup').selectedItem.value !== 'cc' + || (this.io.hasRights === 'all' && id('keep-rights-checkbox').checked) + )) + ) { + ev.preventDefault(); + this.onFinish(); + window.close(); } - } - - - function _updateLicenseMoreInfo() { - var wizard = document.getElementById('zotero-publications-wizard'); - var currentPage = wizard.currentPage; - var s = _shareSettings.sharing; - - var div = currentPage.getElementsByAttribute('class', 'license-more-info')[0]; - if (s == 'cc0' || currentPage.pageid == 'choose-license') { - let links = { - cc: 'https://wiki.creativecommons.org/Considerations_for_licensors_and_licensees', - cc0: 'https://wiki.creativecommons.org/CC0_FAQ' - }; - div.innerHTML = Zotero.getString( - 'publications.' + s + '.moreInfo.text', - // Add link to localized string - '' - + Zotero.getString('publications.' + s + '.moreInfo.linkText') - + '' + }, + + onFinish() { + this.io.includeFiles = id('include-files').checked; + this.io.includeNotes = id('include-notes').checked; + this.io.keepRights = id('keep-rights-checkbox').checked; + if (this.wizard.currentPage.pageid !== 'intro') { + this.io.license = getLicense( + id('sharing-radiogroup').selectedItem.value, + id('choose-adaptations').selectedItem.value, + id('choose-commercial').selectedItem.value, + this.wizard.currentPage.pageid ); - Zotero.Utilities.Internal.updateHTMLInXUL(div, { linkEvent: { shiftKey: true } }); + this.io.licenseName = id('final-license-info').licenseName; } - else { - div.innerHTML = ""; + }, + + onIntroPageCheckboxChange() { + this.updateIntroPage(); + this.updateNextButton(); + }, + + onKeepRightsCheckboxChange() { + this.updateSharingPage(); + this.updateNextButton(); + }, + + onLicenseAspectRadioChange() { + this.updateNextButton(); + this.updateLicense(); + }, + + updateIntroPage() { + id('include-files').disabled = !this.io.hasFiles; + id('include-notes').disabled = !this.io.hasNotes; + id('confirm-authorship-checkbox').dataset.l10nId = id('include-files').checked + ? 'publications-intro-authorship-files' + : 'publications-intro-authorship'; + }, + + updateSharingPage() { + id('keep-rights').style.display + = this.io.hasRights === 'none' ? 'none' : ''; + + id('keep-rights-checkbox').disabled = this.io.hasRights === 'none'; + id('keep-rights-checkbox').dataset.l10nId + = this.io.hasRights === 'some' + ? 'publications-sharing-keep-rights-field-where-available' + : 'publications-sharing-keep-rights-field'; + id('choose-sharing-options').style.display + = this.io.hasRights === 'all' && id('keep-rights-checkbox').checked ? 'none' : ''; + }, + + updateLicense() { + const license = getLicense( + id('sharing-radiogroup').selectedItem.value, + id('choose-adaptations').selectedItem.value, + id('choose-commercial').selectedItem.value, + this.wizard.currentPage.pageid + ); + id('sharing-license-info').license = license; + id('final-license-info').license = license; + }, + + updateFocus() { + this.wizard.currentPage.querySelector('radiogroup:not([disabled]),checkbox:not([disabled])').focus(); + }, + + updateNextButton() { + const nextButton = this.wizard.getButton('next'); + this.wizard.canAdvance = id('confirm-authorship-checkbox').checked; + + if (this.io.hasRights === 'all' && id('keep-rights-checkbox').checked) { + nextButton.dataset.l10nId = 'publications-buttons-add-to-my-publications'; } - } -} + else if (this.wizard.currentPage.pageid === 'intro') { + nextButton.dataset.l10nId = id('include-files').checked + ? 'publications-buttons-next-sharing' + : 'publications-buttons-add-to-my-publications'; + } + else if (this.wizard.currentPage.pageid === 'choose-sharing') { + nextButton.dataset.l10nId + = id('sharing-radiogroup').selectedItem.value === 'cc' + ? 'publications-buttons-next-choose-license' + : 'publications-buttons-add-to-my-publications'; + } + }, + +}; diff --git a/chrome/content/zotero/publicationsDialog.xhtml b/chrome/content/zotero/publicationsDialog.xhtml new file mode 100644 index 0000000000..23e383efd3 --- /dev/null +++ b/chrome/content/zotero/publicationsDialog.xhtml @@ -0,0 +1,93 @@ + + + + + + + + + + + + +