diff --git a/.eslintrc b/.eslintrc index 5fce3175f4..faab80293b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -26,6 +26,8 @@ "Localization": false, "L10nFileSource": false, "L10nRegistry": false, + "ZoteroPane_Local": false, + "ZoteroPane": false }, "extends": [ "@zotero", diff --git a/chrome/content/zotero/elements/itemBox.js b/chrome/content/zotero/elements/itemBox.js index a9e290bb97..a98e0474dc 100644 --- a/chrome/content/zotero/elements/itemBox.js +++ b/chrome/content/zotero/elements/itemBox.js @@ -212,7 +212,7 @@ this._id('zotero-doi-menu-view-online').addEventListener( 'command', - event => ZoteroPane_Local.loadURI(this._doiMenu.dataset.doi, event) + event => ZoteroPane.loadURI(this._doiMenu.dataset.doi, event) ); this._id('zotero-doi-menu-copy').addEventListener( 'command', @@ -334,7 +334,7 @@ */ set visibleFields(val) { if (val.constructor.name != 'Array') { - throw ('visibleFields must be an array in .visibleFields'); + throw Error('visibleFields must be an array in .visibleFields'); } this._visibleFields = val; @@ -345,7 +345,7 @@ */ set hiddenFields(val) { if (val.constructor.name != 'Array') { - throw ('hiddenFields must be an array in .visibleFields'); + throw Error('hiddenFields must be an array in .visibleFields'); } this._hiddenFields = val; @@ -357,7 +357,7 @@ */ set clickableFields(val) { if (val.constructor.name != 'Array') { - throw ('clickableFields must be an array in .clickableFields'); + throw Error('clickableFields must be an array in .clickableFields'); } this._clickableFields = val; @@ -369,7 +369,7 @@ */ set editableFields(val) { if (val.constructor.name != 'Array') { - throw ('editableFields must be an array in .editableFields'); + throw Error('editableFields must be an array in .editableFields'); } this._editableFields = val; @@ -380,11 +380,11 @@ */ set fieldAlternatives(val) { if (val.constructor.name != 'Object') { - throw ('fieldAlternatives must be an Object in .fieldAlternatives'); + throw Error('fieldAlternatives must be an Object in .fieldAlternatives'); } if (this.mode != 'fieldmerge') { - throw ('fieldAlternatives is valid only in fieldmerge mode in .fieldAlternatives'); + throw Error('fieldAlternatives is valid only in fieldmerge mode in .fieldAlternatives'); } this._fieldAlternatives = val; @@ -396,7 +396,7 @@ */ set fieldOrder(val) { if (val.constructor.name != 'Array') { - throw ('fieldOrder must be an array in .fieldOrder'); + throw Error('fieldOrder must be an array in .fieldOrder'); } this._fieldOrder = val; @@ -437,7 +437,7 @@ // // Methods // - notify(event, type, ids) { + notify(event, _type, ids) { if (event != 'modify' || !this.item || !this.item.id) return; for (let i = 0; i < ids.length; i++) { let id = ids[i]; @@ -501,12 +501,12 @@ var fields = Zotero.ItemFields.getItemTypeFields(this.item.getField("itemTypeID")); - for (var i=0; i0 ? this._tabIndexMinFields + i : 1) : 0; + ? (i > 0 ? this._tabIndexMinFields + i : 1) + : 0; this._tabIndexMaxFields = Math.max(this._tabIndexMaxFields, tabindex); if (fieldIsClickable @@ -607,12 +608,12 @@ doi = "https://doi.org/" // Encode some characters that are technically valid in DOIs, // though generally not used. '/' doesn't need to be encoded. - + doi.replace(/#/g, '%23') + + doi.replace(/#/g, '%23') .replace(/\?/g, '%3f') .replace(/%/g, '%25') .replace(/"/g, '%22'); th.classList.add("pointer"); - th.addEventListener('click', event => ZoteroPane_Local.loadURI(doi, event)); + th.addEventListener('click', event => ZoteroPane.loadURI(doi, event)); th.setAttribute('title', Zotero.getString('pane.item.viewOnline.tooltip')); this._doiMenu.dataset.doi = doi; } @@ -696,12 +697,12 @@ var creatorTypes = Zotero.CreatorTypes.getTypesForItemType(this.item.itemTypeID); var localized = {}; - for (var i=0; i maxWidth) { + var maxWidth = boxWidth - leftHboxWidth - 140; + if (lastNameWidth > maxWidth) { //lastName.style.width = maxWidth+"px"; //lastName.style.maxWidth = maxWidth+"px"; - } else { + } + else { delete lastName.style.width; delete lastName.style.maxWidth; } } // Add firstname field to tabindex - var tab = parseInt(lastName.getAttribute('ztabindex')); + tab = parseInt(lastName.getAttribute('ztabindex')); firstName.setAttribute('ztabindex', tab + 1); - if (this._tabIndexMaxCreators == tab) - { + if (this._tabIndexMaxCreators == tab) { this._tabIndexMaxCreators++; } if (!initial) { // Move all but last word to first name field and show it - var last = this._getFieldValue(lastName); + let last = this._getFieldValue(lastName); if (last && last != this._defaultFullName) { var lastNameRE = /(.*?)[ ]*([^ ]+[ ]*)$/; var parts = lastNameRE.exec(last); - if (parts[2] && parts[2] != last) - { + if (parts[2] && parts[2] != last) { this._setFieldValue(lastName, parts[2]); this._setFieldValue(firstName, parts[1]); } @@ -1250,8 +1251,8 @@ // Add warning for shortTitle when moving from book to bookSection // when title will be transferred if (this.item.itemTypeID == bookTypeID && itemTypeID == bookSectionTypeID) { - var titleFieldID = Zotero.ItemFields.getID('title'); - var shortTitleFieldID = Zotero.ItemFields.getID('shortTitle'); + let titleFieldID = Zotero.ItemFields.getID('title'); + let shortTitleFieldID = Zotero.ItemFields.getID('shortTitle'); if (this.item.getField(titleFieldID) && this.item.getField(shortTitleFieldID)) { if (!fieldsToDelete) { fieldsToDelete = []; @@ -1266,9 +1267,9 @@ // if there's not also a title, since the book title is transferred // to title automatically in Zotero.Item.setType() if (this.item.itemTypeID == bookSectionTypeID && itemTypeID == bookTypeID) { - var titleFieldID = Zotero.ItemFields.getID('title'); + let titleFieldID = Zotero.ItemFields.getID('title'); var bookTitleFieldID = Zotero.ItemFields.getID('bookTitle'); - var shortTitleFieldID = Zotero.ItemFields.getID('shortTitle'); + let shortTitleFieldID = Zotero.ItemFields.getID('shortTitle'); if (this.item.getField(bookTitleFieldID) && !this.item.getField(titleFieldID)) { var index = fieldsToDelete.indexOf(bookTitleFieldID); fieldsToDelete.splice(index, 1); @@ -1280,17 +1281,17 @@ } var fieldNames = ""; - for (var i=0; i { this.disableButton(button); @@ -1360,8 +1361,8 @@ } createValueElement(valueText, fieldName, tabindex) { - valueText = valueText + ''; - + valueText += ''; + if (fieldName) { var fieldID = Zotero.ItemFields.getID(fieldName); } @@ -1378,11 +1379,11 @@ valueElement.setAttribute('id', `itembox-field-value-${fieldName}`); valueElement.className = 'value'; valueElement.setAttribute('fieldname', fieldName); - + if (this._fieldIsClickable(fieldName)) { valueElement.setAttribute('ztabindex', tabindex); valueElement.addEventListener('click', (event) => { - /* Skip right-click on Windows */ + // Skip right-click on Windows if (event.button) { return; } @@ -1402,9 +1403,7 @@ case 'dateModified': case 'accessDate': case 'date': - - // TEMP - NSF - case 'dateSent': + case 'dateSent': // TEMP - NSF case 'dateDue': case 'accepted': if (fieldName == 'date' && this.item._objectType != 'feedItem') { @@ -1441,9 +1440,9 @@ } // Display a context menu for certain fields - if (this.editable && (fieldName == 'seriesTitle' || fieldName == 'shortTitle' || - Zotero.ItemFields.isFieldOfBase(fieldID, 'title') || - Zotero.ItemFields.isFieldOfBase(fieldID, 'publicationTitle'))) { + if (this.editable && (fieldName == 'seriesTitle' || fieldName == 'shortTitle' + || Zotero.ItemFields.isFieldOfBase(fieldID, 'title') + || Zotero.ItemFields.isFieldOfBase(fieldID, 'publicationTitle'))) { valueElement.setAttribute('context', 'zotero-field-transform-menu'); valueElement.oncontextmenu = (event) => { document.popupNode = valueElement; @@ -1510,7 +1509,7 @@ // Enable the "+" button on the previous row var elems = this._infoTable.getElementsByClassName('zotero-clicky-plus'); - var button = elems[elems.length-1]; + var button = elems[elems.length - 1]; var creatorFields = this.getCreatorFields(button.closest('tr')); this._enablePlusButton(button, creatorFields.creatorTypeID, creatorFields.fieldMode); @@ -1547,34 +1546,34 @@ var tabindex = elem.getAttribute('ztabindex'); var [field, creatorIndex, creatorField] = fieldName.split('-'); + let value, itemID; if (field == 'creator') { - var value = this.item.getCreator(creatorIndex)[creatorField]; + value = this.item.getCreator(creatorIndex)[creatorField]; if (value === undefined) { value = ""; } - var itemID = this.item.id; + itemID = this.item.id; } else { - var value = this.item.getField(fieldName); - var itemID = this.item.id; + value = this.item.getField(fieldName); + itemID = this.item.id; // Access date needs to be converted from UTC if (value != '') { + let localDate; switch (fieldName) { case 'accessDate': - - // TEMP - NSF - case 'dateSent': + case 'dateSent': // TEMP - NSF case 'dateDue': case 'accepted': // If no time, interpret as local, not UTC if (Zotero.Date.isSQLDate(value)) { - var localDate = Zotero.Date.sqlToDate(value); + localDate = Zotero.Date.sqlToDate(value); } else { - var localDate = Zotero.Date.sqlToDate(value, true); + localDate = Zotero.Date.sqlToDate(value, true); } - var value = Zotero.Date.dateToSQL(localDate); + value = Zotero.Date.dateToSQL(localDate); // Don't show time in editor value = value.replace(' 00:00:00', ''); @@ -1765,8 +1764,6 @@ t.addEventListener('input', updateHeight); updateHeight(); } - - return t; } @@ -1794,14 +1791,13 @@ var [creatorID, numFields] = id.split('-'); // If result uses two fields, save both - if (numFields==2) - { + if (numFields == 2) { // Manually clear autocomplete controller's reference to // textbox to prevent error next time around textbox.mController.input = null; - var [field, creatorIndex, creatorField] = - textbox.getAttribute('fieldname').split('-'); + var [_field, creatorIndex, creatorField] + = textbox.getAttribute('fieldname').split('-'); if (stayFocused) { this._lastTabIndex = parseInt(textbox.getAttribute('ztabindex')); @@ -1817,15 +1813,16 @@ textbox.value = creator[creatorField]; // Update the other label - if (otherField=='firstName'){ - var label = textbox.nextSibling.nextSibling; + let label; + if (otherField == 'firstName') { + label = textbox.nextSibling.nextSibling; } - else if (otherField=='lastName'){ - var label = textbox.previousSibling.previousSibling; + else if (otherField == 'lastName') { + label = textbox.previousSibling.previousSibling; } //this._setFieldValue(label, creator[otherField]); - if (label.firstChild){ + if (label.firstChild) { label.firstChild.nodeValue = creator[otherField]; } else { @@ -1866,9 +1863,9 @@ }, 0); return; } - - switch (event.keyCode) - { + + let tree; + switch (event.keyCode) { case event.DOM_VK_RETURN: var fieldname = target.getAttribute('fieldname'); // Use shift-enter as the save action for the larger fields @@ -1910,7 +1907,7 @@ focused.blur(); // Return focus to items pane - var tree = document.getElementById('zotero-items-tree'); + tree = document.getElementById('zotero-items-tree'); if (tree) { tree.focus(); } @@ -1924,7 +1921,7 @@ focused.blur(); // Return focus to items pane - var tree = document.getElementById('zotero-items-tree'); + tree = document.getElementById('zotero-items-tree'); if (tree) { tree.focus(); } @@ -1999,7 +1996,8 @@ // Reset to '(first)'/'(last)'/'(name)' if (creatorField == 'lastName') { val = otherFields.fieldMode - ? this._defaultFullName : this._defaultLastName; + ? this._defaultFullName + : this._defaultLastName; } else if (creatorField == 'firstName') { val = this._defaultFirstName; @@ -2028,15 +2026,15 @@ } // If just date, don't convert to UTC else if (Zotero.Date.isSQLDate(value)) { - var localDate = Zotero.Date.sqlToDate(value); + let localDate = Zotero.Date.sqlToDate(value); value = Zotero.Date.dateToSQL(localDate).replace(' 00:00:00', ''); } else if (Zotero.Date.isSQLDateTime(value)) { - var localDate = Zotero.Date.sqlToDate(value); + let localDate = Zotero.Date.sqlToDate(value); value = Zotero.Date.dateToSQL(localDate, true); } else { - var d = Zotero.Date.strToDate(value); + let d = Zotero.Date.strToDate(value); value = null; if (d.year && d.month != undefined && d.day) { d = new Date(d.year, d.month, d.day); @@ -2050,11 +2048,11 @@ case 'dateDue': case 'accepted': if (Zotero.Date.isSQLDate(value)) { - var localDate = Zotero.Date.sqlToDate(value); + let localDate = Zotero.Date.sqlToDate(value); value = Zotero.Date.dateToSQL(localDate).replace(' 00:00:00', ''); } else { - var d = Zotero.Date.strToDate(value); + let d = Zotero.Date.strToDate(value); value = null; if (d.year && d.month != undefined && d.day) { d = new Date(d.year, d.month, d.day); @@ -2098,14 +2096,14 @@ } _rowIsClickable(fieldName) { - return this.clickByRow && - (this.clickable || - this._clickableFields.indexOf(fieldName) != -1); + return this.clickByRow + && (this.clickable + || this._clickableFields.indexOf(fieldName) != -1); } _fieldIsClickable(fieldName) { - return !this.clickByRow && - ((this.clickable && !Zotero.Items.isPrimaryField(fieldName)) + return !this.clickByRow + && ((this.clickable && !Zotero.Items.isPrimaryField(fieldName)) || this._clickableFields.indexOf(fieldName) != -1); } @@ -2140,8 +2138,9 @@ // capitalize after ?, ! and remove space(s) before those as well as colon analogous to capitalizeTitle function // also deal with initial punctuation here - open quotes and Spanish beginning punctuation marks val = val.toLowerCase().replace(/\s*:/, ":"); - val = val.replace(/(([\?!]\s*|^)([\'\"¡¿“‘„«\s]+)?[^\s])/g, function (x) { - return x.replace(/\s+/m, " ").toUpperCase();}); + val = val.replace(/(([?!]\s*|^)(['"¡¿“‘„«\s]+)?[^\s])/g, function (x) { + return x.replace(/\s+/m, " ").toUpperCase(); + }); return val; default: throw new Error("Invalid transform mode '" + mode + "' in ItemBox.textTransformString()"); @@ -2188,7 +2187,8 @@ lastName: label1.firstChild ? label1.firstChild.nodeValue : label1.value, firstName: label2.firstChild ? label2.firstChild.nodeValue : label2.value, fieldMode: label1.getAttribute('fieldMode') - ? parseInt(label1.getAttribute('fieldMode')) : 0, + ? parseInt(label1.getAttribute('fieldMode')) + : 0, creatorTypeID: parseInt(typeID), }; @@ -2206,16 +2206,13 @@ } modifyCreator(index, fields) { - var libraryID = this.item.libraryID; var firstName = fields.firstName; var lastName = fields.lastName; - var fieldMode = fields.fieldMode; - var creatorTypeID = fields.creatorTypeID; var oldCreator = this.item.getCreator(index); // Don't save empty creators - if (!firstName && !lastName){ + if (!firstName && !lastName) { if (!oldCreator) { return false; } @@ -2228,7 +2225,7 @@ /** * @return {Promise} */ - async swapNames(event) { + async swapNames(_event) { var row = document.popupNode.closest('tr'); var typeBox = row.querySelector('.creator-type-label'); var creatorIndex = parseInt(typeBox.getAttribute('fieldname').split('-')[1]); @@ -2254,7 +2251,7 @@ /** * @return {Promise} */ - async capitalizeCreatorName(event) { + async capitalizeCreatorName(_event) { var row = document.popupNode.closest('tr'); var typeBox = row.querySelector('.creator-type-label'); var creatorIndex = parseInt(typeBox.getAttribute('fieldname').split('-')[1]); @@ -2286,17 +2283,17 @@ var newIndex; switch (dir) { - case 'top': - newIndex = 0; - break; - - case 'up': - newIndex = index - 1; - break; - - case 'down': - newIndex = index + 1; - break; + case 'top': + newIndex = 0; + break; + + case 'up': + newIndex = index - 1; + break; + + case 'down': + newIndex = index + 1; + break; } let creator = this.item.getCreator(index); // When moving to top, increment index of all other creators @@ -2314,7 +2311,7 @@ this.item.setCreator(index, otherCreator); } if (this.saveOnEdit) { - return this.item.saveTx(); + this.item.saveTx(); } }, this); } @@ -2356,7 +2353,7 @@ /** * Advance the field focus forward or backward - * + * * Note: We're basically replicating the built-in tabindex functionality, * which doesn't work well with the weird label/textbox stuff we're doing. * (The textbox being tabbed away from is deleted before the blur() @@ -2414,12 +2411,13 @@ // 1) next.parentNode is always null for some reason // 2) For some reason it's necessary to scroll to the next element when // moving forward for the target element to be fully in view + let visElem; if (!back && tabbableFields[pos + 1]) { Zotero.debug("Scrolling to next field"); - var visElem = tabbableFields[pos + 1]; + visElem = tabbableFields[pos + 1]; } else { - var visElem = next; + visElem = next; } this.ensureElementIsVisible(visElem); @@ -2442,9 +2440,9 @@ /** * Available handlers: - * + * * - 'itemtypechange' - * + * * Note: 'this' in the function will be bound to the item box. */ addHandler(eventName, func) { @@ -2586,7 +2584,7 @@ let hideElem = this._id('retraction-hide'); hideElem.firstChild.textContent = Zotero.getString('retraction.replacedItem.hide'); hideElem.hidden = !allowHiding; - hideElem.firstChild.onclick = (event) => { + hideElem.firstChild.onclick = (_event) => { ZoteroPane.promptToHideRetractionForReplacedItem(item); };