Improve the new UI:
- Rollback all redundant changes made in the last few months - Introduce `contextPane` - Show child notes in the notes pane - Fix splitter styling - Various bug fixes - Fix contextPane switching and states persistence - Persist reader sidebar open/close state - Fix bottom pane placeholder updating concurrency issues - Fix toolbar placeholder width updating - Display titles for split button - Fix toolbar position when switching tabs - Add PDF tab loading cover - Improve notes and citations insertion - Clean up and refactor code - Fixes and cleanups to PDF reader
6
.gitmodules
vendored
|
@ -31,13 +31,13 @@
|
||||||
url = https://github.com/gildas-lormeau/SingleFile.git
|
url = https://github.com/gildas-lormeau/SingleFile.git
|
||||||
[submodule "pdf-reader"]
|
[submodule "pdf-reader"]
|
||||||
path = pdf-reader
|
path = pdf-reader
|
||||||
url = https://github.com/zotero/pdf-reader.git
|
url = ssh://git@github.com/zotero/pdf-reader.git
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "pdf-worker"]
|
[submodule "pdf-worker"]
|
||||||
path = pdf-worker
|
path = pdf-worker
|
||||||
url = https://github.com/zotero/pdf-worker.git
|
url = ssh://git@github.com/zotero/pdf-worker.git
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "zotero-note-editor"]
|
[submodule "zotero-note-editor"]
|
||||||
path = zotero-note-editor
|
path = zotero-note-editor
|
||||||
url = https://github.com/zotero/zotero-note-editor.git
|
url = ssh://git@github.com/zotero/zotero-note-editor.git
|
||||||
branch = master
|
branch = master
|
||||||
|
|
|
@ -129,7 +129,7 @@ input {
|
||||||
|
|
||||||
.zotero-editpane-tabs {
|
.zotero-editpane-tabs {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
/*background: -moz-linear-gradient(top, #ededed, #cccccc);*/
|
background: -moz-linear-gradient(top, #ededed, #cccccc);
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 0 0 1px 0;
|
border-width: 0 0 1px 0;
|
||||||
border-color: #bdbdbd;
|
border-color: #bdbdbd;
|
||||||
|
@ -217,7 +217,8 @@ input {
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-collections-splitter:not([state=collapsed]),
|
#zotero-collections-splitter:not([state=collapsed]),
|
||||||
#zotero-items-splitter:not([state=collapsed])[orient=horizontal]
|
#zotero-items-splitter:not([state=collapsed])[orient=horizontal],
|
||||||
|
#zotero-context-splitter:not([state=collapsed])[orient=horizontal]
|
||||||
{
|
{
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
border-inline-start: 1px solid #bdbdbd;
|
border-inline-start: 1px solid #bdbdbd;
|
||||||
|
@ -228,7 +229,8 @@ input {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-items-splitter[orient=vertical]
|
#zotero-items-splitter[orient=vertical],
|
||||||
|
#zotero-context-splitter-stacked
|
||||||
{
|
{
|
||||||
-moz-border-start: none !important;
|
-moz-border-start: none !important;
|
||||||
-moz-border-end: none !important;
|
-moz-border-end: none !important;
|
||||||
|
@ -239,17 +241,25 @@ input {
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-collections-splitter:not([state=collapsed]) > grippy,
|
#zotero-collections-splitter:not([state=collapsed]) > grippy,
|
||||||
#zotero-items-splitter:not([state=collapsed]) > grippy
|
#zotero-items-splitter:not([state=collapsed]) > grippy,
|
||||||
|
#zotero-context-splitter:not([state=collapsed]) > grippy,
|
||||||
|
#zotero-context-splitter-stacked:not([state=collapsed]) > grippy
|
||||||
{
|
{
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-collections-splitter[state=collapsed], #zotero-items-splitter[state=collapsed] {
|
#zotero-collections-splitter[state=collapsed],
|
||||||
|
#zotero-items-splitter[state=collapsed],
|
||||||
|
#zotero-context-splitter[state=collapsed],
|
||||||
|
#zotero-context-splitter-stacked[state=collapsed]
|
||||||
|
{
|
||||||
border: 0 solid #d6d6d6 !important;
|
border: 0 solid #d6d6d6 !important;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-collections-splitter[state=collapsed], #zotero-items-splitter[state=collapsed][orient=horizontal]
|
#zotero-collections-splitter[state=collapsed],
|
||||||
|
#zotero-items-splitter[state=collapsed][orient=horizontal],
|
||||||
|
#zotero-context-splitter[state=collapsed][orient=horizontal]
|
||||||
{
|
{
|
||||||
background-image: url("chrome://zotero/skin/mac/vsplitter.png");
|
background-image: url("chrome://zotero/skin/mac/vsplitter.png");
|
||||||
background-repeat: repeat-y;
|
background-repeat: repeat-y;
|
||||||
|
@ -258,7 +268,8 @@ input {
|
||||||
width: 8px !important;
|
width: 8px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-items-splitter[state=collapsed][orient=vertical]
|
#zotero-items-splitter[state=collapsed][orient=vertical],
|
||||||
|
#zotero-context-splitter-stacked[state=collapsed][orient=vertical]
|
||||||
{
|
{
|
||||||
background-image: url("chrome://zotero/skin/mac/hsplitter.png");
|
background-image: url("chrome://zotero/skin/mac/hsplitter.png");
|
||||||
background-repeat: repeat-x;
|
background-repeat: repeat-x;
|
||||||
|
@ -271,11 +282,17 @@ input {
|
||||||
border-right-width: 1px !important;
|
border-right-width: 1px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-items-splitter[state=collapsed] {
|
#zotero-items-splitter[state=collapsed],
|
||||||
|
#zotero-context-splitter[state=collapsed],
|
||||||
|
#zotero-context-splitter-stacked[state=collapsed]
|
||||||
|
{
|
||||||
border-left-width: 1px !important;
|
border-left-width: 1px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-collections-splitter[state=collapsed] > grippy, #zotero-items-splitter[state=collapsed] > grippy
|
#zotero-collections-splitter[state=collapsed] > grippy,
|
||||||
|
#zotero-items-splitter[state=collapsed] > grippy,
|
||||||
|
#zotero-context-splitter[state=collapsed] > grippy,
|
||||||
|
#zotero-context-splitter-stacked[state=collapsed] > grippy
|
||||||
{
|
{
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
background: url(chrome://zotero/skin/mac/vgrippy.png) center/auto 8px no-repeat;
|
background: url(chrome://zotero/skin/mac/vgrippy.png) center/auto 8px no-repeat;
|
||||||
|
@ -301,11 +318,20 @@ input {
|
||||||
height: 8px;
|
height: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-tags-splitter > grippy:hover, #zotero-collections-splitter > grippy:hover, #zotero-items-splitter > grippy:hover
|
#zotero-tags-splitter > grippy:hover,
|
||||||
|
#zotero-collections-splitter > grippy:hover,
|
||||||
|
#zotero-items-splitter > grippy:hover,
|
||||||
|
#zotero-context-splitter > grippy:hover,
|
||||||
|
#zotero-context-splitter-stacked > grippy:hover
|
||||||
{
|
{
|
||||||
background-color:transparent;
|
background-color:transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#zotero-context-toolbar-extension {
|
||||||
|
/* To cover #zotero-context-splitter 1px border */
|
||||||
|
margin-inline-start: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
#zotero-items-tree
|
#zotero-items-tree
|
||||||
{
|
{
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
|
|
|
@ -76,3 +76,9 @@ tab {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#zotero-context-splitter-stacked {
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-color: #ececec;
|
||||||
|
border-top: 1px solid hsla(0, 0%, 0%, 0.2);
|
||||||
|
}
|
||||||
|
|
|
@ -42,15 +42,19 @@
|
||||||
<field name="displayTags">false</field>
|
<field name="displayTags">false</field>
|
||||||
<field name="displayRelated">false</field>
|
<field name="displayRelated">false</field>
|
||||||
<field name="displayButton">false</field>
|
<field name="displayButton">false</field>
|
||||||
|
<field name="hideLinksContainer"/>
|
||||||
|
|
||||||
<field name="buttonCaption"/>
|
<field name="buttonCaption"/>
|
||||||
<field name="parentClickHandler"/>
|
<field name="parentClickHandler"/>
|
||||||
<field name="keyDownHandler"/>
|
<field name="keyDownHandler"/>
|
||||||
<field name="commandHandler"/>
|
<field name="commandHandler"/>
|
||||||
<field name="clickHandler"/>
|
<field name="clickHandler"/>
|
||||||
<field name="navigateHandler"/>
|
<field name="navigateHandler"/>
|
||||||
|
|
||||||
|
<field name="returnHandler"/>
|
||||||
|
|
||||||
<constructor><![CDATA[
|
<constructor><![CDATA[
|
||||||
|
this._destroyed = false;
|
||||||
this._noteEditorID = Zotero.Utilities.randomString();
|
this._noteEditorID = Zotero.Utilities.randomString();
|
||||||
this._iframe = document.getAnonymousElementByAttribute(this, 'anonid', 'editor-view');
|
this._iframe = document.getAnonymousElementByAttribute(this, 'anonid', 'editor-view');
|
||||||
this._iframe.addEventListener('DOMContentLoaded', (e) => {
|
this._iframe.addEventListener('DOMContentLoaded', (e) => {
|
||||||
|
@ -99,6 +103,7 @@
|
||||||
popup: document.getAnonymousElementByAttribute(this, 'anonid', 'editor-menu'),
|
popup: document.getAnonymousElementByAttribute(this, 'anonid', 'editor-menu'),
|
||||||
onNavigate: this._navigateHandler,
|
onNavigate: this._navigateHandler,
|
||||||
readOnly: !this.editable,
|
readOnly: !this.editable,
|
||||||
|
onReturn: this._returnHandler,
|
||||||
placeholder: this.placeholder
|
placeholder: this.placeholder
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -137,7 +142,7 @@
|
||||||
this._lastHtmlValue = this.item.note;
|
this._lastHtmlValue = this.item.note;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._id('links-container').hidden = !(this.displayTags && this.displayRelated);
|
this._id('links-container').hidden = !(this.displayTags && this.displayRelated) || this._hideLinksContainer;
|
||||||
this._id('links-box').refresh();
|
this._id('links-box').refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,12 +184,21 @@
|
||||||
this._mode = val;
|
this._mode = val;
|
||||||
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
||||||
this._id('links-box').mode = val;
|
this._id('links-box').mode = val;
|
||||||
this._id('links-container').hidden = !(this.displayTags && this.displayRelated);
|
this._id('links-container').hidden = !(this.displayTags && this.displayRelated) || this._hideLinksContainer;
|
||||||
this._id('links-box').refresh();
|
this._id('links-box').refresh();
|
||||||
]]>
|
]]>
|
||||||
</setter>
|
</setter>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<field name="returnHandler"/>
|
||||||
|
<property name="returnHandler" onget="return this._returnHandler;">
|
||||||
|
<setter>
|
||||||
|
<![CDATA[
|
||||||
|
this._returnHandler = val;
|
||||||
|
]]>
|
||||||
|
</setter>
|
||||||
|
</property>
|
||||||
|
|
||||||
<field name="_parentItem"/>
|
<field name="_parentItem"/>
|
||||||
<property name="parentItem" onget="return this._parentItem;">
|
<property name="parentItem" onget="return this._parentItem;">
|
||||||
<setter>
|
<setter>
|
||||||
|
@ -261,6 +275,15 @@
|
||||||
]]>
|
]]>
|
||||||
</setter>
|
</setter>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property name="hideLinksContainer">
|
||||||
|
<setter>
|
||||||
|
<![CDATA[
|
||||||
|
this._hideLinksContainer = val;
|
||||||
|
this._id('links-container').hidden = val;
|
||||||
|
]]>
|
||||||
|
</setter>
|
||||||
|
</property>
|
||||||
|
|
||||||
<field name="collection"/>
|
<field name="collection"/>
|
||||||
|
|
||||||
|
@ -271,6 +294,8 @@
|
||||||
this._editorInstance.uninit();
|
this._editorInstance.uninit();
|
||||||
}
|
}
|
||||||
this._destroyed = true;
|
this._destroyed = true;
|
||||||
|
this._initialized = false;
|
||||||
|
this._editorInstance = null;
|
||||||
]]>
|
]]>
|
||||||
</destructor>
|
</destructor>
|
||||||
|
|
||||||
|
@ -307,8 +332,8 @@
|
||||||
</implementation>
|
</implementation>
|
||||||
|
|
||||||
<content>
|
<content>
|
||||||
<xul:vbox xbl:inherits="flex">
|
<xul:vbox xbl:inherits="flex" style="display: flex;flex-direction: column;flex-grow: 1;">
|
||||||
<xul:iframe tooltip="editor-tooltip" anonid="editor-view" flex="1" overflow="auto" style="width: 100%;margin-right: 5px;border: 0"
|
<xul:iframe tooltip="editor-tooltip" anonid="editor-view" flex="1" overflow="auto" style="width: 100%;margin-right: 5px;border: 0;width: 100%;margin-right: 5px;border: 0;flex-grow: 1;"
|
||||||
frameBorder="0" src="resource://zotero/zotero-note-editor/editor.html" type="content"/>
|
frameBorder="0" src="resource://zotero/zotero-note-editor/editor.html" type="content"/>
|
||||||
<xul:hbox id="links-container" hidden="true">
|
<xul:hbox id="links-container" hidden="true">
|
||||||
<xul:linksbox id="links-box" flex="1" xbl:inherits="notitle"/>
|
<xul:linksbox id="links-box" flex="1" xbl:inherits="notitle"/>
|
||||||
|
@ -512,7 +537,7 @@
|
||||||
<xul:menupopup id="tagsPopup" ignorekeys="true"
|
<xul:menupopup id="tagsPopup" ignorekeys="true"
|
||||||
onpopupshown="if (!document.commandDispatcher.focusedElement || document.commandDispatcher.focusedElement.tagName=='xul:label'){ /* DEBUG: it would be nice to make this work -- if (this.firstChild.count==0){ this.firstChild.newTag(); } */ this.setAttribute('showing', 'true'); }"
|
onpopupshown="if (!document.commandDispatcher.focusedElement || document.commandDispatcher.focusedElement.tagName=='xul:label'){ /* DEBUG: it would be nice to make this work -- if (this.firstChild.count==0){ this.firstChild.newTag(); } */ this.setAttribute('showing', 'true'); }"
|
||||||
onpopuphidden="if (!document.commandDispatcher.focusedElement || document.commandDispatcher.focusedElement.tagName=='xul:label'){ this.setAttribute('showing', 'false'); }">
|
onpopuphidden="if (!document.commandDispatcher.focusedElement || document.commandDispatcher.focusedElement.tagName=='xul:label'){ this.setAttribute('showing', 'false'); }">
|
||||||
<xul:tagsbox id="tags" flex="1" mode="edit"/>
|
<xul:tagsbox id="tags" flex="1" mode="edit" style="display: flex"/>
|
||||||
</xul:menupopup>
|
</xul:menupopup>
|
||||||
</xul:popupset>
|
</xul:popupset>
|
||||||
</xul:vbox>
|
</xul:vbox>
|
||||||
|
|
|
@ -25,14 +25,18 @@
|
||||||
|
|
||||||
import React, { forwardRef, useImperativeHandle, useState } from 'react';
|
import React, { forwardRef, useImperativeHandle, useState } from 'react';
|
||||||
|
|
||||||
const NoteRow = ({ title, body, date, onClick }) => {
|
const NoteRow = ({ parentTitle, parentImageSrc, title, body, date, onClick }) => {
|
||||||
return (
|
return (
|
||||||
<div className="note-row" onClick={onClick}>
|
<div className="note-row" onClick={onClick}>
|
||||||
<div className="inner">
|
<div className="inner">
|
||||||
<div className="first-line">
|
{parentTitle !== null && <div className="first-line">
|
||||||
|
<div className="icon"><img src={parentImageSrc}/></div>
|
||||||
|
<div className="title">{parentTitle}</div>
|
||||||
|
</div>}
|
||||||
|
<div className="second-line">
|
||||||
<div className="title">{title}</div>
|
<div className="title">{title}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="second-line">
|
<div className="third-line">
|
||||||
<div className="date">{date}</div>
|
<div className="date">{date}</div>
|
||||||
<div className="body">{body}</div>
|
<div className="body">{body}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
791
chrome/content/zotero/contextPane.js
Normal file
|
@ -0,0 +1,791 @@
|
||||||
|
/*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2020 Corporation for Digital Scholarship
|
||||||
|
Vienna, Virginia, USA
|
||||||
|
https://digitalscholar.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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Fix import/require related isues that might be
|
||||||
|
// related with `require` not reusing the context
|
||||||
|
var React = require('react');
|
||||||
|
var ReactDOM = require('react-dom');
|
||||||
|
var TagsBoxContainer = require('containers/tagsBoxContainer').default;
|
||||||
|
var NotesList = require('components/itemPane/notesList').default;
|
||||||
|
|
||||||
|
var ZoteroContextPane = new function () {
|
||||||
|
const HTML_NS = 'http://www.w3.org/1999/xhtml';
|
||||||
|
|
||||||
|
var _tabCover;
|
||||||
|
var _contextPane;
|
||||||
|
var _contextPaneInner;
|
||||||
|
var _contextPaneSplitter;
|
||||||
|
var _contextPaneSplitterStacked;
|
||||||
|
var _itemToggle;
|
||||||
|
var _notesToggle;
|
||||||
|
var _panesDeck;
|
||||||
|
var _itemPaneDeck;
|
||||||
|
var _notesPaneDeck;
|
||||||
|
|
||||||
|
var _itemToolbar;
|
||||||
|
var _splitButton;
|
||||||
|
var _itemPaneToggle;
|
||||||
|
var _notesPaneToggle;
|
||||||
|
var _toolbar;
|
||||||
|
var _tabToolbarContainer;
|
||||||
|
|
||||||
|
var _itemContexts = [];
|
||||||
|
var _notesContexts = [];
|
||||||
|
|
||||||
|
// Using attribute instead of propery to set 'selectedIndex'
|
||||||
|
// is more reliable
|
||||||
|
|
||||||
|
this.update = _update;
|
||||||
|
this.getActiveEditor = _getActiveEditor;
|
||||||
|
|
||||||
|
this.onLoad = function () {
|
||||||
|
if (!Zotero) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tabCover = document.getElementById('zotero-tab-cover');
|
||||||
|
_itemToggle = document.getElementById('zotero-tb-toggle-item-pane');
|
||||||
|
_notesToggle = document.getElementById('zotero-tb-toggle-notes-pane');
|
||||||
|
_contextPane = document.getElementById('zotero-context-pane');
|
||||||
|
_contextPaneInner = document.getElementById('zotero-context-pane-inner');
|
||||||
|
_contextPaneSplitter = document.getElementById('zotero-context-splitter');
|
||||||
|
_contextPaneSplitterStacked = document.getElementById('zotero-context-splitter-stacked');
|
||||||
|
|
||||||
|
_itemToolbar = document.getElementById('zotero-item-toolbar');
|
||||||
|
_splitButton = document.getElementById('zotero-tb-split');
|
||||||
|
_itemPaneToggle = document.getElementById('zotero-tb-toggle-item-pane');
|
||||||
|
_notesPaneToggle = document.getElementById('zotero-tb-toggle-notes-pane');
|
||||||
|
_toolbar = document.getElementById('zotero-toolbar');
|
||||||
|
_tabToolbarContainer = document.getElementById('zotero-tab-toolbar-container');
|
||||||
|
|
||||||
|
_init();
|
||||||
|
|
||||||
|
this._unregisterID = Zotero.Notifier.registerObserver(this, ['item', 'tab'], 'contextPane');
|
||||||
|
window.addEventListener('resize', _update);
|
||||||
|
_itemToggle.addEventListener('click', () => {
|
||||||
|
_togglePane(0);
|
||||||
|
});
|
||||||
|
_notesToggle.addEventListener('click', () => {
|
||||||
|
_togglePane(1);
|
||||||
|
});
|
||||||
|
Zotero.Reader.onChangeSidebarWidth = _updatePaneWidth;
|
||||||
|
Zotero.Reader.onChangeSidebarOpen = _updatePaneWidth;
|
||||||
|
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
_updateToolbarWidth();
|
||||||
|
// Sometimes XUL is late to reflow
|
||||||
|
setTimeout(_updateToolbarWidth, 100);
|
||||||
|
});
|
||||||
|
observer.observe(_tabToolbarContainer, { attributes: true, childList: true, subtree: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
this.onUnload = function () {
|
||||||
|
Zotero.Notifier.unregisterObserver(this._unregisterID);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.notify = Zotero.Promise.coroutine(function* (action, type, ids, extraData) {
|
||||||
|
if (type == 'item') {
|
||||||
|
// TODO: Filter library and seriously thing about the performance of this part
|
||||||
|
for (let context of _itemContexts) {
|
||||||
|
let item = Zotero.Items.get(context.itemID);
|
||||||
|
if (item && item.parentID != context.parentID) {
|
||||||
|
_removeItemContext(context.tabID);
|
||||||
|
_addItemContext(context.tabID, context.itemID);
|
||||||
|
}
|
||||||
|
context.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let context of _notesContexts) {
|
||||||
|
context.updateNotesList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == 'tab') {
|
||||||
|
if (action == 'add') {
|
||||||
|
_addItemContext(ids[0], extraData[ids[0]].itemID);
|
||||||
|
}
|
||||||
|
else if (action == 'close') {
|
||||||
|
_removeItemContext(ids[0]);
|
||||||
|
}
|
||||||
|
else if (action == 'select') {
|
||||||
|
if (Zotero_Tabs.selectedIndex == 0) {
|
||||||
|
_contextPaneSplitter.setAttribute('hidden', true);
|
||||||
|
_contextPane.setAttribute('collapsed', true);
|
||||||
|
_toolbar.append(_itemToolbar);
|
||||||
|
_itemToolbar.classList.remove('tab-mode');
|
||||||
|
_splitButton.classList.add('hidden');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
||||||
|
if (reader) {
|
||||||
|
_tabCover.hidden = false;
|
||||||
|
(async () => {
|
||||||
|
await reader._initPromise;
|
||||||
|
_tabCover.hidden = true;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
_contextPaneSplitter.setAttribute('hidden', false);
|
||||||
|
_contextPane.setAttribute('collapsed', !(_contextPaneSplitter.getAttribute('state') != 'collapsed'));
|
||||||
|
_tabToolbarContainer.append(_itemToolbar);
|
||||||
|
_itemToolbar.classList.add('tab-mode');
|
||||||
|
_splitButton.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = _itemContexts.find(x => x.tabID == ids[0]);
|
||||||
|
if (context) {
|
||||||
|
_selectNotesContext(context.libraryID);
|
||||||
|
}
|
||||||
|
_selectItemContext(ids[0], extraData[ids[0]].type);
|
||||||
|
_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function _removeNote(id) {
|
||||||
|
var ps = Components.classes['@mozilla.org/embedcomp/prompt-service;1']
|
||||||
|
.getService(Components.interfaces.nsIPromptService);
|
||||||
|
if (ps.confirm(null, '', Zotero.getString('pane.item.notes.delete.confirm'))) {
|
||||||
|
Zotero.Items.trashTx(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _getActiveEditor() {
|
||||||
|
var splitter;
|
||||||
|
if (Zotero.Prefs.get('layout') == 'stacked') {
|
||||||
|
splitter = _contextPaneSplitterStacked;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
splitter = _contextPaneSplitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitter.getAttribute('state') != 'collapsed') {
|
||||||
|
if (_panesDeck.selectedIndex == 0) {
|
||||||
|
let child = _itemPaneDeck.selectedPanel;
|
||||||
|
var tabPanels = child.querySelector('tabpanels');
|
||||||
|
if (tabPanels && tabPanels.selectedIndex == 1) {
|
||||||
|
var notesDeck = child.querySelector('.notes-deck');
|
||||||
|
if (notesDeck.selectedIndex == 1) {
|
||||||
|
return child.querySelector('zoteronoteeditor');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var node = _notesPaneDeck.selectedPanel;
|
||||||
|
if (node.selectedIndex == 1) {
|
||||||
|
return node.querySelector('zoteronoteeditor');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updateAddToNote() {
|
||||||
|
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
||||||
|
if (reader) {
|
||||||
|
var editor = _getActiveEditor();
|
||||||
|
reader.enableAddToNote(!!editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updatePaneWidth() {
|
||||||
|
var stacked = Zotero.Prefs.get('layout') == 'stacked';
|
||||||
|
var width = Zotero.Reader.getSidebarWidth() + 'px';
|
||||||
|
if (!Zotero.Reader.getSidebarOpen()) {
|
||||||
|
width = 0;
|
||||||
|
}
|
||||||
|
_contextPane.style.left = stacked ? width : 'unset';
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updateToolbarWidth() {
|
||||||
|
var stacked = Zotero.Prefs.get('layout') == 'stacked';
|
||||||
|
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
||||||
|
if (reader) {
|
||||||
|
if ((stacked || _contextPaneSplitter.getAttribute('state') == 'collapsed')) {
|
||||||
|
reader.setToolbarPlaceholderWidth(_tabToolbarContainer.boxObject.width);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reader.setToolbarPlaceholderWidth(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _update() {
|
||||||
|
if (Zotero_Tabs.selectedIndex == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var splitter;
|
||||||
|
var stacked = Zotero.Prefs.get('layout') == 'stacked';
|
||||||
|
if (stacked) {
|
||||||
|
_contextPaneSplitterStacked.setAttribute('hidden', false);
|
||||||
|
_contextPaneSplitter.setAttribute('state', 'open');
|
||||||
|
_contextPaneSplitter.setAttribute('hidden', true);
|
||||||
|
_contextPane.classList.add('stacked');
|
||||||
|
_contextPane.classList.remove('standard');
|
||||||
|
splitter = _contextPaneSplitterStacked;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_contextPaneSplitter.setAttribute('hidden', false);
|
||||||
|
_contextPaneSplitterStacked.setAttribute('hidden', true);
|
||||||
|
_contextPaneSplitterStacked.setAttribute('state', 'open');
|
||||||
|
_contextPane.classList.add('standard');
|
||||||
|
_contextPane.classList.remove('stacked');
|
||||||
|
splitter = _contextPaneSplitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
var collapsed = splitter.getAttribute('state') == 'collapsed';
|
||||||
|
|
||||||
|
var selectedIndex = _panesDeck.selectedIndex;
|
||||||
|
if (!collapsed && selectedIndex == 0) {
|
||||||
|
_itemPaneToggle.classList.add('toggled');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_itemPaneToggle.classList.remove('toggled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!collapsed && selectedIndex == 1) {
|
||||||
|
_notesPaneToggle.classList.add('toggled');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_notesPaneToggle.classList.remove('toggled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Zotero_Tabs.selectedIndex > 0) {
|
||||||
|
var height = 0;
|
||||||
|
if (Zotero.Prefs.get('layout') == 'stacked'
|
||||||
|
&& _contextPane.getAttribute('collapsed') != 'true') {
|
||||||
|
height = _contextPaneInner.boxObject.height;
|
||||||
|
}
|
||||||
|
Zotero.Reader.setBottomPlaceholderHeight(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updatePaneWidth();
|
||||||
|
_updateToolbarWidth();
|
||||||
|
_updateAddToNote();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _togglePane(paneIndex) {
|
||||||
|
var splitter;
|
||||||
|
var stacked = Zotero.Prefs.get('layout') == 'stacked';
|
||||||
|
if (stacked) {
|
||||||
|
splitter = _contextPaneSplitterStacked;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
splitter = _contextPaneSplitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isOpen = splitter.getAttribute('state') != 'collapsed';
|
||||||
|
var hide = false;
|
||||||
|
|
||||||
|
var currentPane = _panesDeck.selectedIndex;
|
||||||
|
|
||||||
|
if (isOpen && currentPane == paneIndex) {
|
||||||
|
hide = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_panesDeck.setAttribute('selectedIndex', paneIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = _itemContexts.find(x => x.tabID == Zotero_Tabs.selectedID);
|
||||||
|
context.selectedIndex = paneIndex;
|
||||||
|
|
||||||
|
splitter.setAttribute('state', hide ? 'collapsed' : 'open');
|
||||||
|
_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _init() {
|
||||||
|
// vbox
|
||||||
|
var vbox = document.createElement('vbox');
|
||||||
|
vbox.setAttribute('flex', '1');
|
||||||
|
|
||||||
|
_contextPaneInner.append(vbox);
|
||||||
|
|
||||||
|
// Toolbar extension
|
||||||
|
var toolbarExtension = document.createElement('box');
|
||||||
|
toolbarExtension.style.height = '32px';
|
||||||
|
toolbarExtension.id = 'zotero-context-toolbar-extension';
|
||||||
|
|
||||||
|
_panesDeck = document.createElement('deck');
|
||||||
|
_panesDeck.setAttribute('flex', 1);
|
||||||
|
_panesDeck.setAttribute('selectedIndex', 0);
|
||||||
|
|
||||||
|
vbox.append(toolbarExtension, _panesDeck);
|
||||||
|
|
||||||
|
// Item pane deck
|
||||||
|
_itemPaneDeck = document.createElement('deck');
|
||||||
|
// Notes pane deck
|
||||||
|
_notesPaneDeck = document.createElement('deck');
|
||||||
|
_notesPaneDeck.style.backgroundColor = 'white';
|
||||||
|
_notesPaneDeck.setAttribute('flex', 1);
|
||||||
|
_notesPaneDeck.className = 'notes-pane-deck';
|
||||||
|
|
||||||
|
_panesDeck.append(_itemPaneDeck, _notesPaneDeck);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _addNotesContext(libraryID) {
|
||||||
|
var list = document.createElement('vbox');
|
||||||
|
list.setAttribute('flex', 1);
|
||||||
|
list.className = 'zotero-context-notes-list';
|
||||||
|
|
||||||
|
var noteContainer = document.createElement('vbox');
|
||||||
|
var editor = document.createElement('zoteronoteeditor');
|
||||||
|
editor.className = 'zotero-context-pane-pinned-note';
|
||||||
|
editor.setAttribute('flex', 1);
|
||||||
|
noteContainer.appendChild(editor);
|
||||||
|
|
||||||
|
let contextNode = document.createElement('deck');
|
||||||
|
contextNode.append(list, noteContainer);
|
||||||
|
_notesPaneDeck.append(contextNode);
|
||||||
|
|
||||||
|
contextNode.className = 'context-node';
|
||||||
|
contextNode.setAttribute('selectedIndex', 0);
|
||||||
|
|
||||||
|
editor.returnHandler = () => {
|
||||||
|
contextNode.setAttribute('selectedIndex', 0);
|
||||||
|
_updateAddToNote();
|
||||||
|
};
|
||||||
|
|
||||||
|
var head = document.createElement('hbox');
|
||||||
|
head.style.display = 'flex';
|
||||||
|
|
||||||
|
var label = document.createElement('label');
|
||||||
|
var button = document.createElement('button');
|
||||||
|
button.setAttribute('label', Zotero.Intl.strings['zotero.item.add']);
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
contextNode.setAttribute('selectedIndex', 1);
|
||||||
|
var item = new Zotero.Item('note');
|
||||||
|
item.libraryID = libraryID;
|
||||||
|
// item.parentKey = parentItem.key;
|
||||||
|
editor.mode = 'edit';
|
||||||
|
editor.item = item;
|
||||||
|
editor.parentItem = null;
|
||||||
|
editor.focus();
|
||||||
|
_updateAddToNote();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var vbox1 = document.createElement('vbox');
|
||||||
|
vbox1.append(label, button);
|
||||||
|
|
||||||
|
var vbox2 = document.createElement('vbox');
|
||||||
|
vbox2.style.flex = '1';
|
||||||
|
var input = document.createElement('textbox');
|
||||||
|
input.setAttribute('type', 'search');
|
||||||
|
input.setAttribute('timeout', '250');
|
||||||
|
input.addEventListener('command', () => {
|
||||||
|
updateNotesList();
|
||||||
|
});
|
||||||
|
vbox2.append(input);
|
||||||
|
|
||||||
|
head.append(vbox2, vbox1);
|
||||||
|
|
||||||
|
var listBox = document.createElement('vbox');
|
||||||
|
listBox.style.display = 'flex';
|
||||||
|
listBox.setAttribute('flex', '1');
|
||||||
|
var listInner = document.createElementNS(HTML_NS, 'div');
|
||||||
|
listInner.className = 'notes-list-container';
|
||||||
|
listBox.append(listInner);
|
||||||
|
|
||||||
|
list.append(head, listBox);
|
||||||
|
|
||||||
|
var notesListRef = React.createRef();
|
||||||
|
|
||||||
|
var updateNotesList = async (reset) => {
|
||||||
|
if (reset) {
|
||||||
|
input.value = '';
|
||||||
|
contextNode.setAttribute('selectedIndex', 0);
|
||||||
|
}
|
||||||
|
var text = input.value;
|
||||||
|
|
||||||
|
await Zotero.Schema.schemaUpdatePromise;
|
||||||
|
var s = new Zotero.Search();
|
||||||
|
s.addCondition('libraryID', 'is', libraryID);
|
||||||
|
s.addCondition('itemType', 'is', 'note');
|
||||||
|
s.addCondition('noChildren', 'false');
|
||||||
|
if (text) {
|
||||||
|
s.addCondition('note', 'contains', text, true);
|
||||||
|
}
|
||||||
|
var notes = await s.search();
|
||||||
|
notes = Zotero.Items.get(notes);
|
||||||
|
notes.sort((a, b) => {
|
||||||
|
a = a.getField('dateModified');
|
||||||
|
b = b.getField('dateModified');
|
||||||
|
return b.localeCompare(a);
|
||||||
|
});
|
||||||
|
|
||||||
|
notesListRef.current.setNotes(notes.map(note => {
|
||||||
|
var text2 = note.note.slice(0, 500);
|
||||||
|
text2 = text2.trim();
|
||||||
|
// TODO: Fix a potential performance issuse
|
||||||
|
text2 = Zotero.Utilities.unescapeHTML(text2);
|
||||||
|
var parts = text2.split('\n').map(x => x.trim()).filter(x => x.length);
|
||||||
|
var parent = null;
|
||||||
|
if (note.parentID) {
|
||||||
|
parent = Zotero.Items.get(note.parentID);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: note.id,
|
||||||
|
parentTitle: parent && parent.getDisplayTitle(),
|
||||||
|
parentImageSrc: parent && parent.getImageSrc(),
|
||||||
|
title: parts[0] || Zotero.getString('pane.item.notes.untitled'),
|
||||||
|
body: parts[1] || '',
|
||||||
|
date: (new Date(note.dateModified).toLocaleDateString(Zotero.locale))
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
var c = notes.length;
|
||||||
|
var str = 'pane.item.notes.count.' + (c == 0 && 'zero' || c == 1 && 'singular' || 'plural');
|
||||||
|
label.value = Zotero.getString(str, [c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<NotesList
|
||||||
|
ref={notesListRef}
|
||||||
|
onClick={(id) => {
|
||||||
|
_setPinnedNote(libraryID, id);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
listInner,
|
||||||
|
() => {
|
||||||
|
updateNotesList();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
var context = {
|
||||||
|
libraryID,
|
||||||
|
node: contextNode,
|
||||||
|
updateNotesList,
|
||||||
|
editor
|
||||||
|
};
|
||||||
|
|
||||||
|
_notesContexts.push(context);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _getNotesContext(libraryID) {
|
||||||
|
var context = _notesContexts.find(x => x.libraryID == libraryID);
|
||||||
|
if (!context) {
|
||||||
|
context = _addNotesContext(libraryID);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _selectNotesContext(libraryID) {
|
||||||
|
let context = _getNotesContext(libraryID);
|
||||||
|
_notesPaneDeck.setAttribute('selectedIndex', Array.from(_notesPaneDeck.children).findIndex(x => x == context.node));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _removeNotesContext(libraryID) {
|
||||||
|
var context = _notesContexts.find(x => x.libraryID == libraryID);
|
||||||
|
context.node.remove();
|
||||||
|
_notesContexts = _notesContexts.filter(x => x.libraryID != libraryID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _libraryEditable(libraryID) {
|
||||||
|
var type = Zotero.Libraries.get(libraryID).libraryType;
|
||||||
|
if (type == 'group') {
|
||||||
|
var groupID = Zotero.Groups.getGroupIDFromLibraryID(libraryID);
|
||||||
|
var group = Zotero.Groups.get(groupID);
|
||||||
|
return group.editable;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _setPinnedNote(libraryID, itemID) {
|
||||||
|
var editable = _libraryEditable(libraryID);
|
||||||
|
var context = _getNotesContext(libraryID);
|
||||||
|
if (context) {
|
||||||
|
let { editor, node } = context;
|
||||||
|
node.setAttribute('selectedIndex', 1);
|
||||||
|
editor.mode = editable ? 'edit' : 'view';
|
||||||
|
editor.item = Zotero.Items.get(itemID);
|
||||||
|
editor.parentItem = null;
|
||||||
|
editor.hideLinksContainer = true;
|
||||||
|
_updateAddToNote();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _appendNoteRows(notes, list, editable, onClick, onDelete) {
|
||||||
|
for (var i = 0; i < notes.length; i++) {
|
||||||
|
var note = notes[i];
|
||||||
|
var id = notes[i].id;
|
||||||
|
|
||||||
|
var icon = document.createElement('image');
|
||||||
|
icon.className = 'zotero-box-icon';
|
||||||
|
icon.setAttribute('src', `chrome://zotero/skin/treeitem-note${Zotero.hiDPISuffix}.png`);
|
||||||
|
|
||||||
|
var label = document.createElement('label');
|
||||||
|
label.className = 'zotero-box-label';
|
||||||
|
var title = note.getNoteTitle();
|
||||||
|
title = title ? title : Zotero.getString('pane.item.notes.untitled');
|
||||||
|
label.setAttribute('value', title);
|
||||||
|
label.setAttribute('flex', '1'); //so that the long names will flex smaller
|
||||||
|
label.setAttribute('crop', 'end');
|
||||||
|
|
||||||
|
var box = document.createElement('box');
|
||||||
|
box.setAttribute('class', 'zotero-clicky');
|
||||||
|
box.addEventListener('click', () => {
|
||||||
|
onClick(id);
|
||||||
|
});
|
||||||
|
box.appendChild(icon);
|
||||||
|
box.appendChild(label);
|
||||||
|
|
||||||
|
if (editable) {
|
||||||
|
var removeButton = document.createElement('label');
|
||||||
|
removeButton.setAttribute('value', '-');
|
||||||
|
removeButton.setAttribute('class', 'zotero-clicky zotero-clicky-minus');
|
||||||
|
removeButton.addEventListener('click', function () {
|
||||||
|
onDelete(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var row = document.createElement('row');
|
||||||
|
row.appendChild(box);
|
||||||
|
if (editable) {
|
||||||
|
row.appendChild(removeButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.appendChild(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _removeItemContext(tabID) {
|
||||||
|
document.getElementById(tabID + '-context').remove();
|
||||||
|
_itemContexts = _itemContexts.filter(x => x.tabID != tabID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _selectItemContext(tabID, type) {
|
||||||
|
let selectedIndex = Array.from(_itemPaneDeck.children).findIndex(x => x.id == tabID + '-context');
|
||||||
|
if (selectedIndex != -1) {
|
||||||
|
_itemPaneDeck.setAttribute('selectedIndex', selectedIndex);
|
||||||
|
var context = _itemContexts.find(x => x.tabID == tabID);
|
||||||
|
if (context && Zotero_Tabs.selectedIndex > 0) {
|
||||||
|
_panesDeck.setAttribute('selectedIndex', context.selectedIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _addItemContext(tabID, itemID) {
|
||||||
|
var container = document.createElement('vbox');
|
||||||
|
container.id = tabID + '-context';
|
||||||
|
container.className = 'zotero-item-pane-content';
|
||||||
|
_itemPaneDeck.appendChild(container);
|
||||||
|
|
||||||
|
var item = Zotero.Items.get(itemID);
|
||||||
|
var libraryID = item.libraryID;
|
||||||
|
var editable = _libraryEditable(libraryID);
|
||||||
|
var parentID = item.parentID;
|
||||||
|
|
||||||
|
var context = {
|
||||||
|
tabID,
|
||||||
|
itemID,
|
||||||
|
parentID,
|
||||||
|
libraryID,
|
||||||
|
selectedIndex: 0,
|
||||||
|
update: () => {}
|
||||||
|
};
|
||||||
|
_itemContexts.push(context);
|
||||||
|
|
||||||
|
if (!parentID) {
|
||||||
|
var vbox = document.createElement('vbox');
|
||||||
|
vbox.setAttribute('flex', '1');
|
||||||
|
vbox.setAttribute('align', 'center');
|
||||||
|
vbox.setAttribute('pack', 'center');
|
||||||
|
var description = document.createElement('description');
|
||||||
|
vbox.append(description);
|
||||||
|
description.append(Zotero.getString('pane.context.noParent'));
|
||||||
|
container.append(vbox);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parentItem = Zotero.Items.get(item.parentID);
|
||||||
|
|
||||||
|
// tabbox
|
||||||
|
var tabbox = document.createElement('tabbox');
|
||||||
|
tabbox.setAttribute('flex', '1');
|
||||||
|
tabbox.className = 'zotero-view-tabbox';
|
||||||
|
|
||||||
|
container.append(tabbox);
|
||||||
|
|
||||||
|
// tabs
|
||||||
|
var tabs = document.createElement('tabs');
|
||||||
|
tabs.className = 'zotero-editpane-tabs';
|
||||||
|
// tabpanels
|
||||||
|
var tabpanels = document.createElement('tabpanels');
|
||||||
|
tabpanels.setAttribute('flex', '1');
|
||||||
|
tabpanels.className = 'zotero-view-item';
|
||||||
|
tabpanels.addEventListener('select', () => {
|
||||||
|
_updateAddToNote();
|
||||||
|
});
|
||||||
|
|
||||||
|
tabbox.append(tabs, tabpanels);
|
||||||
|
|
||||||
|
// Info tab
|
||||||
|
var tabInfo = document.createElement('tab');
|
||||||
|
tabInfo.setAttribute('label', Zotero.Intl.strings['zotero.tabs.info.label']);
|
||||||
|
// Notes tab
|
||||||
|
var tabNotes = document.createElement('tab');
|
||||||
|
tabNotes.setAttribute('label', Zotero.Intl.strings['zotero.tabs.notes.label']);
|
||||||
|
// Tags tab
|
||||||
|
var tabTags = document.createElement('tab');
|
||||||
|
tabTags.setAttribute('label', Zotero.Intl.strings['zotero.tabs.tags.label']);
|
||||||
|
// Related tab
|
||||||
|
var tabRelated = document.createElement('tab');
|
||||||
|
tabRelated.setAttribute('label', Zotero.Intl.strings['zotero.tabs.related.label']);
|
||||||
|
|
||||||
|
tabs.append(tabInfo, tabNotes, tabTags, tabRelated);
|
||||||
|
|
||||||
|
// Info panel
|
||||||
|
var panelInfo = document.createElement('tabpanel');
|
||||||
|
panelInfo.setAttribute('flex', '1');
|
||||||
|
panelInfo.className = 'zotero-editpane-item-box';
|
||||||
|
var itemBox = document.createElement('zoteroitembox');
|
||||||
|
itemBox.setAttribute('flex', '1');
|
||||||
|
panelInfo.append(itemBox);
|
||||||
|
// Notes panel
|
||||||
|
var panelNotes = document.createElement('tabpanel');
|
||||||
|
panelNotes.setAttribute('flex', '1');
|
||||||
|
panelNotes.setAttribute('orient', 'vertical');
|
||||||
|
var deck = document.createElement('deck');
|
||||||
|
deck.className = 'notes-deck';
|
||||||
|
deck.setAttribute('flex', '1');
|
||||||
|
panelNotes.append(deck);
|
||||||
|
var vbox2 = document.createElement('vbox');
|
||||||
|
var note = document.createElement('zoteronoteeditor');
|
||||||
|
note.setAttribute('flex', 1);
|
||||||
|
vbox2.append(note);
|
||||||
|
var vbox = document.createElement('vbox');
|
||||||
|
vbox.setAttribute('flex', '1');
|
||||||
|
vbox.setAttribute('class', 'zotero-box');
|
||||||
|
vbox.style.overflowY = 'auto';
|
||||||
|
panelNotes.append(vbox);
|
||||||
|
var hbox = document.createElement('hbox');
|
||||||
|
hbox.setAttribute('align', 'center');
|
||||||
|
var label = document.createElement('label');
|
||||||
|
var button = document.createElement('button');
|
||||||
|
// TODO: Should not depend on the current ZoteroPane state
|
||||||
|
button.hidden = !editable;
|
||||||
|
button.setAttribute('label', Zotero.Intl.strings['zotero.item.add']);
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
deck.setAttribute('selectedIndex', 1);
|
||||||
|
var item = new Zotero.Item('note');
|
||||||
|
item.libraryID = parentItem.libraryID;
|
||||||
|
item.parentID = parentItem.id;
|
||||||
|
note.returnHandler = () => {
|
||||||
|
deck.setAttribute('selectedIndex', 0);
|
||||||
|
_updateAddToNote();
|
||||||
|
};
|
||||||
|
note.mode = editable ? 'edit' : 'view';
|
||||||
|
note.item = item;
|
||||||
|
note.focus();
|
||||||
|
_updateAddToNote();
|
||||||
|
});
|
||||||
|
hbox.append(label, button);
|
||||||
|
var grid = document.createElement('grid');
|
||||||
|
grid.setAttribute('flex', 1);
|
||||||
|
var columns = document.createElement('columns');
|
||||||
|
var column = document.createElement('column');
|
||||||
|
column.setAttribute('flex', 1);
|
||||||
|
columns.append(column);
|
||||||
|
var column = document.createElement('column');
|
||||||
|
columns.append(column);
|
||||||
|
grid.append(columns);
|
||||||
|
var rows = document.createElement('rows');
|
||||||
|
rows.setAttribute('flex', 1);
|
||||||
|
grid.append(rows);
|
||||||
|
vbox.append(hbox, grid);
|
||||||
|
deck.append(vbox, vbox2);
|
||||||
|
deck.setAttribute('selectedIndex', 0);
|
||||||
|
// Tags panel
|
||||||
|
var panelTags = document.createElement('tabpanel');
|
||||||
|
panelTags.setAttribute('orient', 'vertical');
|
||||||
|
panelTags.setAttribute('context', 'tags-context-menu');
|
||||||
|
panelTags.className = 'tags-pane';
|
||||||
|
panelTags.style.display = 'flex';
|
||||||
|
var div = document.createElementNS(HTML_NS, 'div');
|
||||||
|
div.className = 'tags-box-container';
|
||||||
|
div.style.display = 'flex';
|
||||||
|
div.style.flexGrow = '1';
|
||||||
|
panelTags.append(div);
|
||||||
|
var tagsBoxRef = React.createRef();
|
||||||
|
ReactDOM.render(
|
||||||
|
<TagsBoxContainer
|
||||||
|
key={'tagsBox-' + parentItem.id}
|
||||||
|
item={parentItem}
|
||||||
|
editable={editable}
|
||||||
|
ref={tagsBoxRef}
|
||||||
|
/>,
|
||||||
|
div
|
||||||
|
);
|
||||||
|
// Related panel
|
||||||
|
var panelRelated = document.createElement('tabpanel');
|
||||||
|
var relatedBox = document.createElement('relatedbox');
|
||||||
|
relatedBox.setAttribute('flex', '1');
|
||||||
|
relatedBox.className = 'zotero-editpane-related';
|
||||||
|
panelRelated.addEventListener('click', (event) => {
|
||||||
|
if (event.originalTarget.closest('.zotero-clicky')) {
|
||||||
|
Zotero_Tabs.select('zotero-pane');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
panelRelated.append(relatedBox);
|
||||||
|
|
||||||
|
tabpanels.append(panelInfo, panelNotes, panelTags, panelRelated);
|
||||||
|
tabbox.selectedIndex = 0;
|
||||||
|
|
||||||
|
|
||||||
|
itemBox.mode = editable ? 'edit' : 'view';
|
||||||
|
itemBox.item = parentItem;
|
||||||
|
|
||||||
|
relatedBox.mode = editable ? 'edit' : 'view';
|
||||||
|
relatedBox.item = parentItem;
|
||||||
|
|
||||||
|
function _renderNotesPanel() {
|
||||||
|
rows.innerHTML = '';
|
||||||
|
var parentNotes = Zotero.Items.get(parentItem.getNotes());
|
||||||
|
_appendNoteRows(parentNotes, rows, editable, (id) => {
|
||||||
|
deck.setAttribute('selectedIndex', 1);
|
||||||
|
note.returnHandler = () => {
|
||||||
|
deck.setAttribute('selectedIndex', 0);
|
||||||
|
_updateAddToNote();
|
||||||
|
};
|
||||||
|
note.mode = editable ? 'edit' : 'view';
|
||||||
|
note.item = Zotero.Items.get(id);
|
||||||
|
note.parentItem = null;
|
||||||
|
_updateAddToNote();
|
||||||
|
}, (id) => {
|
||||||
|
_removeNote(id);
|
||||||
|
});
|
||||||
|
var c = parentNotes.length;
|
||||||
|
var str = 'pane.item.notes.count.' + (c == 0 && 'zero' || c == 1 && 'singular' || 'plural');
|
||||||
|
label.value = Zotero.getString(str, [c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.update = _renderNotesPanel;
|
||||||
|
_renderNotesPanel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
addEventListener('load', function (e) { ZoteroContextPane.onLoad(e); }, false);
|
||||||
|
addEventListener('unload', function (e) { ZoteroContextPane.onUnload(e); }, false);
|
|
@ -26,17 +26,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import TagsBoxContainer from 'containers/tagsBoxContainer';
|
import TagsBoxContainer from 'containers/tagsBoxContainer';
|
||||||
import NotesList from 'components/itemPane/notesList';
|
|
||||||
|
|
||||||
var ZoteroItemPane = new function() {
|
var ZoteroItemPane = new function() {
|
||||||
const HTML_NS = 'http://www.w3.org/1999/xhtml';
|
|
||||||
|
|
||||||
var _lastItem, _itemBox, _notesLabel, _notesButton, _notesList, _tagsBox, _relatedBox;
|
var _lastItem, _itemBox, _notesLabel, _notesButton, _notesList, _tagsBox, _relatedBox;
|
||||||
var _selectedNoteID;
|
var _selectedNoteID;
|
||||||
var _translationTarget;
|
var _translationTarget;
|
||||||
var _noteIDs;
|
var _noteIDs;
|
||||||
var _contextNoteUpdaters = [];
|
|
||||||
let _pdfTabHidden = false;
|
|
||||||
|
|
||||||
this.onLoad = function () {
|
this.onLoad = function () {
|
||||||
if (!Zotero) {
|
if (!Zotero) {
|
||||||
|
@ -60,15 +55,7 @@ var ZoteroItemPane = new function() {
|
||||||
};
|
};
|
||||||
_relatedBox = document.getElementById('zotero-editpane-related');
|
_relatedBox = document.getElementById('zotero-editpane-related');
|
||||||
|
|
||||||
this._unregisterID = Zotero.Notifier.registerObserver(this, ['item', 'tab'], 'itemPane');
|
this._unregisterID = Zotero.Notifier.registerObserver(this, ['item'], 'itemPane');
|
||||||
|
|
||||||
document.getElementById('temp-toggle-1').addEventListener('click', () => {
|
|
||||||
this.togglePane();
|
|
||||||
});
|
|
||||||
document.getElementById('temp-toggle-2').addEventListener('click', () => {
|
|
||||||
this.togglePane();
|
|
||||||
});
|
|
||||||
this.initStandaloneNotesView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,8 +102,6 @@ var ZoteroItemPane = new function() {
|
||||||
|
|
||||||
_lastItem = item;
|
_lastItem = item;
|
||||||
|
|
||||||
_updateTitle();
|
|
||||||
|
|
||||||
var viewBox = document.getElementById('zotero-view-item');
|
var viewBox = document.getElementById('zotero-view-item');
|
||||||
viewBox.classList.remove('no-tabs');
|
viewBox.classList.remove('no-tabs');
|
||||||
|
|
||||||
|
@ -228,32 +213,15 @@ var ZoteroItemPane = new function() {
|
||||||
|
|
||||||
|
|
||||||
this.notify = Zotero.Promise.coroutine(function* (action, type, ids, extraData) {
|
this.notify = Zotero.Promise.coroutine(function* (action, type, ids, extraData) {
|
||||||
if(type == 'item') {
|
var viewBox = document.getElementById('zotero-view-item');
|
||||||
var viewBox = document.getElementById('zotero-view-item');
|
// If notes pane is selected, refresh it if any of the notes change or are deleted
|
||||||
// If notes pane is selected, refresh it if any of the notes change or are deleted
|
if (viewBox.selectedIndex == 1 && (action == 'modify' || action == 'delete')) {
|
||||||
if (viewBox.selectedIndex == 1 && (action == 'modify' || action == 'delete')) {
|
let refresh = false;
|
||||||
let refresh = false;
|
if (ids.some(id => _noteIDs.has(id))) {
|
||||||
if (ids.some(id => _noteIDs.has(id))) {
|
refresh = true;
|
||||||
refresh = true;
|
|
||||||
}
|
|
||||||
if (refresh) {
|
|
||||||
yield this.viewItem(_lastItem, null, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.updateStandaloneNotesList();
|
if (refresh) {
|
||||||
for (let updater of _contextNoteUpdaters) {
|
yield this.viewItem(_lastItem, null, 1);
|
||||||
updater.callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type == 'tab') {
|
|
||||||
if (action == 'add') {
|
|
||||||
this.addPDFTabContext(ids[0], extraData.itemID);
|
|
||||||
}
|
|
||||||
else if (action == 'close') {
|
|
||||||
this.removeTabContext(ids[0]);
|
|
||||||
}
|
|
||||||
else if (action == 'select') {
|
|
||||||
this.selectTabContext(ids[0], extraData.type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -311,7 +279,6 @@ var ZoteroItemPane = new function() {
|
||||||
// noteEditor.clearUndo();
|
// noteEditor.clearUndo();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
document.getElementById('zotero-view-note-sidebar-button').hidden = !!item.parentID;
|
|
||||||
document.getElementById('zotero-view-note-button').hidden = !editable;
|
document.getElementById('zotero-view-note-button').hidden = !editable;
|
||||||
document.getElementById('zotero-item-pane-content').selectedIndex = 2;
|
document.getElementById('zotero-item-pane-content').selectedIndex = 2;
|
||||||
};
|
};
|
||||||
|
@ -321,17 +288,6 @@ var ZoteroItemPane = new function() {
|
||||||
// ZoteroPane.setItemPaneMessage(Zotero.getString('pane.item.notes.editingInWindow'));
|
// ZoteroPane.setItemPaneMessage(Zotero.getString('pane.item.notes.editingInWindow'));
|
||||||
};
|
};
|
||||||
|
|
||||||
this.openNoteSidebar = async function () {
|
|
||||||
var selectedNote = Zotero.Items.get(_selectedNoteID);
|
|
||||||
|
|
||||||
if (!selectedNote.parentID) {
|
|
||||||
let editor = document.getElementById('zotero-item-pane-pinned-note');
|
|
||||||
editor.mode = 'edit';
|
|
||||||
editor.item = selectedNote;
|
|
||||||
document.getElementById('zotero-item-pane-pin-deck2').setAttribute('selectedIndex', 1);
|
|
||||||
this.togglePane(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select the parent item and open the note editor
|
* Select the parent item and open the note editor
|
||||||
|
@ -480,11 +436,6 @@ var ZoteroItemPane = new function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function _updateTitle() {
|
|
||||||
document.getElementById('item-pane-title').textContent = _lastItem.getDisplayTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function _updateNoteCount() {
|
function _updateNoteCount() {
|
||||||
var c = _notesList.childNodes.length;
|
var c = _notesList.childNodes.length;
|
||||||
|
|
||||||
|
@ -503,508 +454,6 @@ var ZoteroItemPane = new function() {
|
||||||
|
|
||||||
_notesLabel.value = Zotero.getString(str, [c]);
|
_notesLabel.value = Zotero.getString(str, [c]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getActiveNote = function () {
|
|
||||||
let mainDeck = document.getElementById('zotero-item-pane-main-deck');
|
|
||||||
if (mainDeck.selectedIndex == 0) {
|
|
||||||
let contextualDeck = document.getElementById('zotero-item-pane-contextual-deck');
|
|
||||||
if (contextualDeck.selectedIndex > 0) {
|
|
||||||
let child = contextualDeck.children[contextualDeck.selectedIndex];
|
|
||||||
if (child.querySelector('deck').selectedIndex == 1) {
|
|
||||||
return child.querySelector('zoteronoteeditor');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let pinnedDeck = document.getElementById('zotero-item-pane-pin-deck2');
|
|
||||||
if (pinnedDeck.selectedIndex == 1) {
|
|
||||||
return pinnedDeck.querySelector('zoteronoteeditor');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.togglePane = function (forceItem) {
|
|
||||||
var pane = document.getElementById('zotero-item-pane');
|
|
||||||
let mainDeck = document.getElementById('zotero-item-pane-main-deck');
|
|
||||||
let value;
|
|
||||||
if (forceItem !== undefined) {
|
|
||||||
value = forceItem ? 0 : 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
value = mainDeck.selectedIndex == 0 ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value == 0) {
|
|
||||||
pane.setAttribute('data-mode', 'item');
|
|
||||||
document.getElementById('temp-toggle-1').innerHTML = '[📄] 📒';
|
|
||||||
document.getElementById('temp-toggle-2').innerHTML = '[📄] 📒';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pane.setAttribute('data-mode', 'notes');
|
|
||||||
document.getElementById('temp-toggle-1').innerHTML = '📄 [📒]';
|
|
||||||
document.getElementById('temp-toggle-2').innerHTML = '📄 [📒]';
|
|
||||||
}
|
|
||||||
|
|
||||||
mainDeck.selectedIndex = value;
|
|
||||||
|
|
||||||
let contextualDeck = document.getElementById('zotero-item-pane-contextual-deck');
|
|
||||||
contextualDeck.children[contextualDeck.selectedIndex].setAttribute('state', value);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initStandaloneNotesView = async function () {
|
|
||||||
let container = document.getElementById('zotero-item-pane-pin-deck');
|
|
||||||
|
|
||||||
let bar = document.createElement('hbox');
|
|
||||||
container.appendChild(bar);
|
|
||||||
let inner = document.createElement('deck');
|
|
||||||
inner.id = 'zotero-item-pane-pin-deck2';
|
|
||||||
inner.style.backgroundColor = 'white';
|
|
||||||
inner.setAttribute('flex', 1);
|
|
||||||
container.appendChild(inner);
|
|
||||||
|
|
||||||
var listLabel = document.createElementNS(HTML_NS, 'div');
|
|
||||||
listLabel.className = 'notes-list-label';
|
|
||||||
listLabel.textContent = Zotero.getString('pane.item.notes.allNotes');
|
|
||||||
|
|
||||||
let list = document.createElement('vbox');
|
|
||||||
list.setAttribute('flex', 1);
|
|
||||||
list.className = 'zotero-box';
|
|
||||||
|
|
||||||
list.appendChild(listLabel);
|
|
||||||
|
|
||||||
var noteContainer = document.createElement('vbox');
|
|
||||||
var backButton = document.createElementNS(HTML_NS, 'div');
|
|
||||||
backButton.className = 'item-pane-back-button';
|
|
||||||
backButton.textContent = (Zotero.dir == 'ltr' ? '←' : '→') + ' '
|
|
||||||
+ Zotero.getString('general.back');
|
|
||||||
backButton.addEventListener('click', () => {
|
|
||||||
inner.setAttribute('selectedIndex', 0);
|
|
||||||
});
|
|
||||||
let note = document.createElement('zoteronoteeditor');
|
|
||||||
note.id = 'zotero-item-pane-pinned-note';
|
|
||||||
note.setAttribute('flex', 1);
|
|
||||||
noteContainer.appendChild(backButton);
|
|
||||||
noteContainer.appendChild(note);
|
|
||||||
|
|
||||||
inner.append(list, noteContainer);
|
|
||||||
inner.setAttribute('selectedIndex', 0);
|
|
||||||
|
|
||||||
let head = document.createElement('hbox');
|
|
||||||
let label = document.createElement('label');
|
|
||||||
let button = document.createElement('button');
|
|
||||||
button.setAttribute('label', Zotero.Intl.strings['zotero.item.add']);
|
|
||||||
button.addEventListener('click', async () => {
|
|
||||||
inner.setAttribute('selectedIndex', 1);
|
|
||||||
let item = new Zotero.Item('note');
|
|
||||||
item.libraryID = ZoteroPane_Local.getSelectedLibraryID();
|
|
||||||
// item.parentKey = parentItem.key;
|
|
||||||
note.mode = 'edit';
|
|
||||||
note.item = item;
|
|
||||||
note.parentItem = null;
|
|
||||||
note.focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
head.style.paddingRight = '10px';
|
|
||||||
|
|
||||||
|
|
||||||
let input = document.createElement('textbox');
|
|
||||||
input.setAttribute('type', 'search');
|
|
||||||
input.setAttribute('timeout', '250');
|
|
||||||
|
|
||||||
input.addEventListener('command', (event) => {
|
|
||||||
_updateStandaloneNotesList();
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
let vbox1 = document.createElement('vbox');
|
|
||||||
vbox1.append(label, button);
|
|
||||||
|
|
||||||
let vbox2 = document.createElement('vbox');
|
|
||||||
vbox2.append(input);
|
|
||||||
|
|
||||||
head.append(vbox2, vbox1);
|
|
||||||
|
|
||||||
head.style.display = 'flex';
|
|
||||||
vbox2.style.flex = '1';
|
|
||||||
|
|
||||||
|
|
||||||
let listBox = document.createElement('vbox');
|
|
||||||
listBox.style.display = 'flex';
|
|
||||||
listBox.setAttribute('flex', '1')
|
|
||||||
|
|
||||||
var listInner = document.createElementNS(HTML_NS, 'div');
|
|
||||||
listInner.className = 'notes-list-container';
|
|
||||||
list.append(head, listBox);
|
|
||||||
|
|
||||||
listBox.append(listInner);
|
|
||||||
|
|
||||||
let noteListRef = React.createRef();
|
|
||||||
|
|
||||||
let _updateStandaloneNotesList = async (reset) => {
|
|
||||||
if (reset) {
|
|
||||||
input.value = '';
|
|
||||||
inner.setAttribute('selectedIndex', 0);
|
|
||||||
}
|
|
||||||
let text = input.value;
|
|
||||||
|
|
||||||
await Zotero.Schema.schemaUpdatePromise;
|
|
||||||
var s = new Zotero.Search();
|
|
||||||
s.addCondition('libraryID', 'is', ZoteroPane_Local.getSelectedLibraryID());
|
|
||||||
s.addCondition('itemType', 'is', 'note');
|
|
||||||
s.addCondition('noChildren', 'true');
|
|
||||||
if (text) {
|
|
||||||
s.addCondition('note', 'contains', text, true);
|
|
||||||
}
|
|
||||||
let notes = await s.search();
|
|
||||||
notes = Zotero.Items.get(notes);
|
|
||||||
notes.sort((a, b) => {
|
|
||||||
a = a.getField('dateModified');
|
|
||||||
b = b.getField('dateModified');
|
|
||||||
return b.localeCompare(a);
|
|
||||||
});
|
|
||||||
|
|
||||||
noteListRef.current.setNotes(notes.map(note => {
|
|
||||||
let text2 = note.note;
|
|
||||||
text2 = text2.trim();
|
|
||||||
// TODO: Fix a potential performance issuse
|
|
||||||
text2 = Zotero.Utilities.unescapeHTML(text2);
|
|
||||||
let parts = text2.split('\n').map(x => x.trim()).filter(x => x.length);
|
|
||||||
return {
|
|
||||||
id: note.id,
|
|
||||||
title: parts[0] || Zotero.getString('pane.item.notes.untitled'),
|
|
||||||
body: parts[1] || '',
|
|
||||||
date: (new Date(note.dateModified).toLocaleDateString(Zotero.locale))
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
var c = notes.length;
|
|
||||||
var str = 'pane.item.notes.count.' + (c == 0 && 'zero' || c == 1 && 'singular' || 'plural');
|
|
||||||
label.value = Zotero.getString(str, [c]);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactDOM.render(
|
|
||||||
<NotesList
|
|
||||||
ref={noteListRef}
|
|
||||||
onClick={(id) => {
|
|
||||||
this._setPinnedNote(id);
|
|
||||||
}}
|
|
||||||
/>,
|
|
||||||
listInner,
|
|
||||||
() => {
|
|
||||||
_updateStandaloneNotesList();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
this.updateStandaloneNotesList = _updateStandaloneNotesList;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._setPinnedNote = function (itemID) {
|
|
||||||
let pinnedDeck = document.getElementById('zotero-item-pane-pin-deck2');
|
|
||||||
pinnedDeck.setAttribute('selectedIndex', 1);
|
|
||||||
let pinnedNote = document.getElementById('zotero-item-pane-pinned-note');
|
|
||||||
pinnedNote.mode = 'edit';
|
|
||||||
pinnedNote.item = Zotero.Items.get(itemID);
|
|
||||||
pinnedNote.parentItem = null;
|
|
||||||
this.togglePane(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._appendNoteRows = function (notes, list, editable, onClick, onDelete) {
|
|
||||||
for (var i = 0; i < notes.length; i++) {
|
|
||||||
let note = notes[i];
|
|
||||||
let id = notes[i].id;
|
|
||||||
|
|
||||||
var icon = document.createElement('image');
|
|
||||||
icon.className = 'zotero-box-icon';
|
|
||||||
icon.setAttribute('src', `chrome://zotero/skin/treeitem-note${Zotero.hiDPISuffix}.png`);
|
|
||||||
|
|
||||||
var label = document.createElement('label');
|
|
||||||
label.className = 'zotero-box-label';
|
|
||||||
var title = note.getNoteTitle();
|
|
||||||
title = title ? title : Zotero.getString('pane.item.notes.untitled');
|
|
||||||
label.setAttribute('value', title);
|
|
||||||
label.setAttribute('flex', '1'); //so that the long names will flex smaller
|
|
||||||
label.setAttribute('crop', 'end');
|
|
||||||
|
|
||||||
var box = document.createElement('box');
|
|
||||||
box.setAttribute('class', 'zotero-clicky');
|
|
||||||
box.addEventListener('click', () => {
|
|
||||||
onClick(id);
|
|
||||||
});
|
|
||||||
box.appendChild(icon);
|
|
||||||
box.appendChild(label);
|
|
||||||
|
|
||||||
if (editable) {
|
|
||||||
var removeButton = document.createElement('label');
|
|
||||||
removeButton.setAttribute('value', '-');
|
|
||||||
removeButton.setAttribute('class', 'zotero-clicky zotero-clicky-minus');
|
|
||||||
removeButton.addEventListener('click', function () {
|
|
||||||
onDelete(id)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var row = document.createElement('row');
|
|
||||||
row.appendChild(box);
|
|
||||||
if (editable) {
|
|
||||||
row.appendChild(removeButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
list.appendChild(row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.removeTabContext = function (tabID) {
|
|
||||||
document.getElementById(tabID + '-context').remove();
|
|
||||||
_contextNoteUpdaters = _contextNoteUpdaters.filter(x => x.tabID != tabID);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.selectTabContext = function (tabID, type) {
|
|
||||||
var pane = document.getElementById('zotero-item-pane');
|
|
||||||
pane.setAttribute('data-type', type);
|
|
||||||
|
|
||||||
let contextualDeck = document.getElementById('zotero-item-pane-contextual-deck');
|
|
||||||
let prevIndex = contextualDeck.selectedIndex;
|
|
||||||
contextualDeck.selectedIndex = Array.from(contextualDeck.children).findIndex(x => x.id == tabID + '-context');
|
|
||||||
|
|
||||||
let toolbar = document.getElementById('zotero-pane-horizontal-space');
|
|
||||||
let extendedToolbar = document.getElementById('zotero-item-pane-padding-top');
|
|
||||||
let itemPane = document.getElementById('zotero-item-pane');
|
|
||||||
|
|
||||||
if (prevIndex != 0) {
|
|
||||||
_pdfTabHidden = itemPane.hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == 'library') {
|
|
||||||
toolbar.hidden = false;
|
|
||||||
extendedToolbar.hidden = true;
|
|
||||||
itemPane.hidden = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
toolbar.hidden = true;
|
|
||||||
extendedToolbar.hidden = false;
|
|
||||||
itemPane.hidden = _pdfTabHidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
let state = contextualDeck.children[contextualDeck.selectedIndex].getAttribute('state');
|
|
||||||
let mainDeck = document.getElementById('zotero-item-pane-main-deck');
|
|
||||||
if (state == 0) {
|
|
||||||
pane.setAttribute('data-mode', 'item');
|
|
||||||
document.getElementById('temp-toggle-1').innerHTML = '[📄] 📒';
|
|
||||||
document.getElementById('temp-toggle-2').innerHTML = '[📄] 📒';
|
|
||||||
mainDeck.selectedIndex = state;
|
|
||||||
}
|
|
||||||
else if (state == 1) {
|
|
||||||
pane.setAttribute('data-mode', 'notes');
|
|
||||||
document.getElementById('temp-toggle-1').innerHTML = '📄 [📒]';
|
|
||||||
document.getElementById('temp-toggle-2').innerHTML = '📄 [📒]';
|
|
||||||
mainDeck.selectedIndex = state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
this.addPDFTabContext = function (tabID, itemID) {
|
|
||||||
let contextualDeck = document.getElementById('zotero-item-pane-contextual-deck');
|
|
||||||
|
|
||||||
let container = document.createElement('vbox');
|
|
||||||
container.id = tabID + '-context';
|
|
||||||
container.className = 'zotero-item-pane-content';
|
|
||||||
contextualDeck.appendChild(container);
|
|
||||||
|
|
||||||
var item = Zotero.Items.get(itemID);
|
|
||||||
if (!item.parentID) {
|
|
||||||
container.append('The PDF doesn\'t have a parent');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let parentID = item.parentID;
|
|
||||||
|
|
||||||
let mainDeck = document.getElementById('zotero-item-pane-main-deck');
|
|
||||||
let pinDeck = document.getElementById('zotero-item-pane-pin-deck2');
|
|
||||||
container.setAttribute('state', (mainDeck.selectedIndex == 1 && pinDeck.selectedIndex == 1) ? 1 : 0)
|
|
||||||
|
|
||||||
|
|
||||||
let parentItem = Zotero.Items.get(parentID);
|
|
||||||
|
|
||||||
let tabbox = document.createElement('tabbox');
|
|
||||||
tabbox.setAttribute('flex', '1');
|
|
||||||
tabbox.className = 'zotero-view-tabbox';
|
|
||||||
let tabs = document.createElement('tabs');
|
|
||||||
tabs.className = 'zotero-editpane-tabs';
|
|
||||||
|
|
||||||
container.append(tabbox);
|
|
||||||
|
|
||||||
|
|
||||||
let tabInfo = document.createElement('tab');
|
|
||||||
tabInfo.setAttribute('label', Zotero.Intl.strings['zotero.tabs.info.label']);
|
|
||||||
let tabNotes = document.createElement('tab');
|
|
||||||
tabNotes.setAttribute('label', Zotero.Intl.strings['zotero.tabs.notes.label']);
|
|
||||||
let tabTags = document.createElement('tab');
|
|
||||||
tabTags.setAttribute('label', Zotero.Intl.strings['zotero.tabs.tags.label']);
|
|
||||||
let tabRelated = document.createElement('tab');
|
|
||||||
tabRelated.setAttribute('label', Zotero.Intl.strings['zotero.tabs.related.label']);
|
|
||||||
tabs.append(tabInfo, tabNotes, tabTags, tabRelated);
|
|
||||||
|
|
||||||
let tabpanels = document.createElement('tabpanels');
|
|
||||||
tabpanels.setAttribute('flex', '1');
|
|
||||||
tabpanels.className = 'zotero-view-item';
|
|
||||||
|
|
||||||
tabbox.append(tabs, tabpanels);
|
|
||||||
|
|
||||||
let panelInfo = document.createElement('tabpanel');
|
|
||||||
panelInfo.setAttribute('flex', '1')
|
|
||||||
panelInfo.className = 'zotero-editpane-item-box';
|
|
||||||
let itemBox = document.createElement('zoteroitembox');
|
|
||||||
itemBox.setAttribute('flex', '1');
|
|
||||||
panelInfo.append(itemBox);
|
|
||||||
|
|
||||||
let panelNotes = document.createElement('tabpanel');
|
|
||||||
panelNotes.setAttribute('flex', '1');
|
|
||||||
panelNotes.setAttribute('orient', 'vertical');
|
|
||||||
|
|
||||||
var deck = document.createElement('deck');
|
|
||||||
deck.setAttribute('flex', '1');
|
|
||||||
|
|
||||||
panelNotes.append(deck);
|
|
||||||
|
|
||||||
var vbox2 = document.createElement('vbox');
|
|
||||||
|
|
||||||
var backButton = document.createElementNS(HTML_NS, 'div');
|
|
||||||
backButton.className = 'item-pane-back-button';
|
|
||||||
backButton.textContent = (Zotero.dir == 'ltr' ? '←' : '→') + ' '
|
|
||||||
+ Zotero.getString('general.back');
|
|
||||||
backButton.addEventListener('click', () => {
|
|
||||||
deck.setAttribute('selectedIndex', 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
let note = document.createElement('zoteronoteeditor');
|
|
||||||
note.setAttribute('flex', 1);
|
|
||||||
|
|
||||||
vbox2.append(backButton, note);
|
|
||||||
|
|
||||||
|
|
||||||
var vbox = document.createElement('vbox');
|
|
||||||
vbox.setAttribute('flex', '1');
|
|
||||||
vbox.setAttribute('class', 'zotero-box');
|
|
||||||
panelNotes.append(vbox);
|
|
||||||
|
|
||||||
var hbox = document.createElement('hbox');
|
|
||||||
hbox.setAttribute('align', 'center');
|
|
||||||
|
|
||||||
var label = document.createElement('label');
|
|
||||||
var button = document.createElement('button');
|
|
||||||
button.setAttribute('label', Zotero.Intl.strings['zotero.item.add']);
|
|
||||||
button.addEventListener('click', () => {
|
|
||||||
deck.setAttribute('selectedIndex', 1);
|
|
||||||
let item = new Zotero.Item('note');
|
|
||||||
item.libraryID = parentItem.libraryID;
|
|
||||||
item.parentItemID = parentItem.id;
|
|
||||||
note.mode = 'edit';
|
|
||||||
note.item = item;
|
|
||||||
note.focus();
|
|
||||||
});
|
|
||||||
hbox.append(label, button);
|
|
||||||
|
|
||||||
var grid = document.createElement('grid');
|
|
||||||
grid.setAttribute('flex', 1);
|
|
||||||
var columns = document.createElement('columns');
|
|
||||||
var column = document.createElement('column');
|
|
||||||
column.setAttribute('flex', 1);
|
|
||||||
columns.append(column);
|
|
||||||
var column = document.createElement('column');
|
|
||||||
columns.append(column);
|
|
||||||
grid.append(columns);
|
|
||||||
var rows = document.createElement('rows');
|
|
||||||
rows.setAttribute('flex', 1);
|
|
||||||
grid.append(rows);
|
|
||||||
|
|
||||||
vbox.append(hbox, grid);
|
|
||||||
|
|
||||||
deck.append(vbox, vbox2);
|
|
||||||
|
|
||||||
deck.setAttribute('selectedIndex', 0);
|
|
||||||
deck.className = 'zotero-item-pane-content';
|
|
||||||
|
|
||||||
|
|
||||||
let panelTags = document.createElement('tabpanel');
|
|
||||||
panelTags.setAttribute('orient', 'vertical');
|
|
||||||
panelTags.setAttribute('context', 'tags-context-menu');
|
|
||||||
panelTags.className = 'tags-pane';
|
|
||||||
panelTags.style.display = 'flex';
|
|
||||||
|
|
||||||
var div = document.createElementNS(HTML_NS, 'div');
|
|
||||||
div.className = 'tags-box-container';
|
|
||||||
div.style.display = 'flex';
|
|
||||||
div.style.flexGrow = '1';
|
|
||||||
panelTags.append(div);
|
|
||||||
|
|
||||||
let panelRelated = document.createElement('tabpanel');
|
|
||||||
let relatedBox = document.createElement('relatedbox');
|
|
||||||
relatedBox.setAttribute('flex', '1');
|
|
||||||
relatedBox.className = 'zotero-editpane-related';
|
|
||||||
panelRelated.append(relatedBox);
|
|
||||||
|
|
||||||
tabpanels.append(panelInfo, panelNotes, panelTags, panelRelated);
|
|
||||||
|
|
||||||
itemBox.mode = 'edit';
|
|
||||||
itemBox.item = Zotero.Items.get(parentID);
|
|
||||||
|
|
||||||
relatedBox.mode = 'edit';
|
|
||||||
relatedBox.item = parentItem;
|
|
||||||
|
|
||||||
panelRelated.addEventListener('click', (event) => {
|
|
||||||
if (event.originalTarget.closest('.zotero-clicky')) {
|
|
||||||
Zotero_Tabs.select('zotero-pane');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let _renderNotesPanel = () => {
|
|
||||||
while (rows.firstChild) {
|
|
||||||
rows.firstChild.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
let parentNotes = Zotero.Items.get(parentItem.getNotes());
|
|
||||||
this._appendNoteRows(parentNotes, rows, true, (id) => {
|
|
||||||
deck.setAttribute('selectedIndex', 1);
|
|
||||||
note.mode = 'edit';
|
|
||||||
note.item = Zotero.Items.get(id);
|
|
||||||
note.parentItem = null;
|
|
||||||
}, (id) => {
|
|
||||||
ZoteroItemPane.removeNote(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
var c = parentNotes.length;
|
|
||||||
var str = 'pane.item.notes.count.' + (c == 0 && 'zero' || c == 1 && 'singular' || 'plural');
|
|
||||||
label.value = Zotero.getString(str, [c]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_contextNoteUpdaters.push({
|
|
||||||
tabID,
|
|
||||||
callback: _renderNotesPanel
|
|
||||||
});
|
|
||||||
|
|
||||||
_renderNotesPanel();
|
|
||||||
|
|
||||||
let mode = 'edit';
|
|
||||||
|
|
||||||
let _tagsBox = { current: null };
|
|
||||||
let focusItemsList = false;
|
|
||||||
|
|
||||||
let _renderTagsPanel = () => {
|
|
||||||
ReactDOM.render(
|
|
||||||
<TagsBoxContainer
|
|
||||||
key={'tagsBox-' + parentItem.id}
|
|
||||||
item={parentItem}
|
|
||||||
editable={mode != 'view'}
|
|
||||||
ref={_tagsBox}
|
|
||||||
onResetSelection={focusItemsList}
|
|
||||||
/>,
|
|
||||||
div
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderTagsPanel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventListener("load", function(e) { ZoteroItemPane.onLoad(e); }, false);
|
addEventListener("load", function(e) { ZoteroItemPane.onLoad(e); }, false);
|
||||||
|
|
|
@ -34,138 +34,116 @@
|
||||||
<script src="include.js"/>
|
<script src="include.js"/>
|
||||||
<script src="itemPane.js"></script>
|
<script src="itemPane.js"></script>
|
||||||
|
|
||||||
<vbox id="zotero-item-pane"
|
<vbox id="zotero-item-pane" zotero-persist="width height">
|
||||||
zotero-persist="width height"
|
<!-- My Publications -->
|
||||||
data-type="library"
|
<hbox id="zotero-item-pane-top-buttons-my-publications" class="zotero-item-pane-top-buttons" hidden="true">
|
||||||
data-mode="item"
|
<button id="zotero-item-collection-show-hide"/>
|
||||||
>
|
|
||||||
<hbox id="zotero-item-pane-padding-top" height="32" hidden="true" align="right">
|
|
||||||
<button id="temp-toggle-2" style="min-width: 37px; padding: 2px; font-size: 13px;">[📄] 📒</button>
|
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<html:div id="item-pane-title"/>
|
<!-- Trash -->
|
||||||
|
<hbox id="zotero-item-pane-top-buttons-trash" class="zotero-item-pane-top-buttons" hidden="true">
|
||||||
|
<button id="zotero-item-restore-button" label="&zotero.items.menu.restoreToLibrary;"
|
||||||
|
oncommand="ZoteroPane_Local.restoreSelectedItems()"/>
|
||||||
|
<button id="zotero-item-delete-button" label="&zotero.item.deletePermanently;"
|
||||||
|
oncommand="ZoteroPane_Local.deleteSelectedItems()"/>
|
||||||
|
</hbox>
|
||||||
|
|
||||||
<deck id="zotero-item-pane-main-deck" flex="1" selectedIndex="0">
|
<!-- Feed -->
|
||||||
<deck id="zotero-item-pane-contextual-deck" selectedIndex="0">
|
<hbox id="zotero-item-pane-top-buttons-feed" class="zotero-item-pane-top-buttons" hidden="true">
|
||||||
<vbox id="zotero-pane-context">
|
<button id="zotero-feed-item-toggleRead-button"
|
||||||
<!-- My Publications -->
|
oncommand="ZoteroPane_Local.toggleSelectedItemsRead();"/>
|
||||||
<hbox id="zotero-item-pane-top-buttons-my-publications" class="zotero-item-pane-top-buttons" hidden="true">
|
<button id="zotero-feed-item-addTo-button" type="menu-button"
|
||||||
<button id="zotero-item-collection-show-hide"/>
|
oncommand="ZoteroItemPane.translateSelectedItems()">
|
||||||
</hbox>
|
<menupopup id="zotero-item-addTo-menu" onpopupshowing="ZoteroItemPane.buildTranslateSelectContextMenu(event);"/>
|
||||||
|
</button>
|
||||||
<!-- Trash -->
|
</hbox>
|
||||||
<hbox id="zotero-item-pane-top-buttons-trash" class="zotero-item-pane-top-buttons" hidden="true">
|
|
||||||
<button id="zotero-item-restore-button" label="&zotero.items.menu.restoreToLibrary;"
|
<!-- Commons -->
|
||||||
oncommand="ZoteroPane_Local.restoreSelectedItems()"/>
|
<button id="zotero-item-show-original" label="Show Original"
|
||||||
<button id="zotero-item-delete-button" label="&zotero.item.deletePermanently;"
|
oncommand="ZoteroPane_Local.showOriginalItem()" hidden="true"/>
|
||||||
oncommand="ZoteroPane_Local.deleteSelectedItems()"/>
|
|
||||||
</hbox>
|
<deck id="zotero-item-pane-content" class="zotero-item-pane-content" selectedIndex="0" flex="1">
|
||||||
|
<!-- Center label (for zero or multiple item selection) -->
|
||||||
<!-- Feed -->
|
<groupbox id="zotero-item-pane-groupbox" pack="center" align="center">
|
||||||
<hbox id="zotero-item-pane-top-buttons-feed" class="zotero-item-pane-top-buttons" hidden="true">
|
<vbox id="zotero-item-pane-message-box"/>
|
||||||
<button id="zotero-feed-item-toggleRead-button"
|
</groupbox>
|
||||||
oncommand="ZoteroPane_Local.toggleSelectedItemsRead();"/>
|
|
||||||
<button id="zotero-feed-item-addTo-button" type="menu-button"
|
|
||||||
oncommand="ZoteroItemPane.translateSelectedItems()">
|
|
||||||
<menupopup id="zotero-item-addTo-menu" onpopupshowing="ZoteroItemPane.buildTranslateSelectContextMenu(event);"/>
|
|
||||||
</button>
|
|
||||||
</hbox>
|
|
||||||
|
|
||||||
<!-- Commons -->
|
|
||||||
<button id="zotero-item-show-original" label="Show Original"
|
|
||||||
oncommand="ZoteroPane_Local.showOriginalItem()" hidden="true"/>
|
|
||||||
|
|
||||||
<deck id="zotero-item-pane-content" class="zotero-item-pane-content" selectedIndex="0" flex="1">
|
|
||||||
<!-- Center label (for zero or multiple item selection) -->
|
|
||||||
<groupbox id="zotero-item-pane-groupbox" pack="center" align="center">
|
|
||||||
<vbox id="zotero-item-pane-message-box"/>
|
|
||||||
</groupbox>
|
|
||||||
|
|
||||||
<!-- Regular item -->
|
|
||||||
<tabbox id="zotero-view-tabbox" class="zotero-view-tabbox" flex="1" onselect="if (!ZoteroPane_Local.collectionsView.selection || event.originalTarget.localName != 'tabpanels') { return; }; ZoteroItemPane.viewItem(ZoteroPane_Local.getSelectedItems()[0], ZoteroPane_Local.collectionsView.editable ? 'edit' : 'view', this.selectedIndex)">
|
|
||||||
<tabs id="zotero-editpane-tabs" class="zotero-editpane-tabs">
|
|
||||||
<tab id="zotero-editpane-info-tab" label="&zotero.tabs.info.label;"/>
|
|
||||||
<tab id="zotero-editpane-notes-tab" label="&zotero.tabs.notes.label;"/>
|
|
||||||
<tab id="zotero-editpane-tags-tab" label="&zotero.tabs.tags.label;"/>
|
|
||||||
<tab id="zotero-editpane-related-tab" label="&zotero.tabs.related.label;"/>
|
|
||||||
</tabs>
|
|
||||||
<tabpanels id="zotero-view-item" class="zotero-view-item" flex="1">
|
|
||||||
<tabpanel flex="1">
|
|
||||||
<zoteroitembox id="zotero-editpane-item-box" class="zotero-editpane-item-box" flex="1"/>
|
|
||||||
</tabpanel>
|
|
||||||
|
|
||||||
<tabpanel flex="1" orient="vertical">
|
|
||||||
<vbox flex="1" id="zotero-editpane-notes" class="zotero-box">
|
|
||||||
<hbox align="center">
|
|
||||||
<label id="zotero-editpane-notes-label"/>
|
|
||||||
<button id="zotero-editpane-notes-add" label="&zotero.item.add;" oncommand="ZoteroItemPane.addNote(event.shiftKey);"/>
|
|
||||||
</hbox>
|
|
||||||
<grid flex="1">
|
|
||||||
<columns>
|
|
||||||
<column flex="1"/>
|
|
||||||
<column/>
|
|
||||||
</columns>
|
|
||||||
<rows id="zotero-editpane-dynamic-notes" flex="1"/>
|
|
||||||
</grid>
|
|
||||||
</vbox>
|
|
||||||
</tabpanel>
|
|
||||||
|
|
||||||
<tabpanel id="tags-pane" class="tags-pane" orient="vertical" context="tags-context-menu">
|
|
||||||
<html:div id="tags-box-container" class="tags-box-container"></html:div>
|
|
||||||
</tabpanel>
|
|
||||||
|
|
||||||
<tabpanel>
|
|
||||||
<relatedbox id="zotero-editpane-related" class="zotero-editpane-related" flex="1"/>
|
|
||||||
</tabpanel>
|
|
||||||
</tabpanels>
|
|
||||||
</tabbox>
|
|
||||||
|
|
||||||
<!-- Note item -->
|
|
||||||
<groupbox id="zotero-view-note" flex="1">
|
|
||||||
<!--
|
|
||||||
'onerror' handler crashes the app on a save error to prevent typing in notes
|
|
||||||
while they're not being saved
|
|
||||||
-->
|
|
||||||
<zoteronoteeditor id="zotero-note-editor" flex="1" notitle="1"
|
|
||||||
previousfocus="zotero-items-tree"
|
|
||||||
onerror="return;ZoteroPane.displayErrorMessage(); /*this.mode = 'view'*/"/>
|
|
||||||
<!-- TODO: Localize -->
|
|
||||||
<button id="zotero-view-note-sidebar-button"
|
|
||||||
label="Edit in notes sidebar"
|
|
||||||
oncommand="ZoteroItemPane.openNoteSidebar()"/>
|
|
||||||
<button id="zotero-view-note-button"
|
|
||||||
label="&zotero.notes.separate;"
|
|
||||||
oncommand="ZoteroItemPane.openNoteWindow()"/>
|
|
||||||
</groupbox>
|
|
||||||
|
|
||||||
<!-- Attachment item -->
|
|
||||||
<groupbox>
|
|
||||||
<zoteroattachmentbox id="zotero-attachment-box" flex="1"/>
|
|
||||||
</groupbox>
|
|
||||||
|
|
||||||
<!-- Duplicate merging -->
|
|
||||||
<vbox id="zotero-duplicates-merge-pane" flex="1">
|
|
||||||
<groupbox>
|
|
||||||
<button id="zotero-duplicates-merge-button" oncommand="Zotero_Duplicates_Pane.merge()"/>
|
|
||||||
</groupbox>
|
|
||||||
|
|
||||||
<groupbox id="zotero-duplicates-merge-version-select">
|
|
||||||
<description>&zotero.duplicatesMerge.versionSelect;</description>
|
|
||||||
<hbox>
|
|
||||||
<listbox id="zotero-duplicates-merge-original-date" onselect="Zotero_Duplicates_Pane.setMaster(this.selectedIndex)" rows="0"/>
|
|
||||||
</hbox>
|
|
||||||
</groupbox>
|
|
||||||
|
|
||||||
<groupbox flex="1">
|
|
||||||
<description id="zotero-duplicates-merge-field-select">&zotero.duplicatesMerge.fieldSelect;</description>
|
|
||||||
<zoteroitembox id="zotero-duplicates-merge-item-box" flex="1"/>
|
|
||||||
</groupbox>
|
|
||||||
</vbox>
|
|
||||||
</deck>
|
|
||||||
</vbox>
|
|
||||||
</deck>
|
|
||||||
|
|
||||||
<vbox id="zotero-item-pane-pin-deck"></vbox>
|
<!-- Regular item -->
|
||||||
|
<tabbox id="zotero-view-tabbox" class="zotero-view-tabbox" flex="1" onselect="if (!ZoteroPane_Local.collectionsView.selection || event.originalTarget.localName != 'tabpanels') { return; }; ZoteroItemPane.viewItem(ZoteroPane_Local.getSelectedItems()[0], ZoteroPane_Local.collectionsView.editable ? 'edit' : 'view', this.selectedIndex)">
|
||||||
|
<tabs id="zotero-editpane-tabs" class="zotero-editpane-tabs">
|
||||||
|
<tab id="zotero-editpane-info-tab" label="&zotero.tabs.info.label;"/>
|
||||||
|
<tab id="zotero-editpane-notes-tab" label="&zotero.tabs.notes.label;"/>
|
||||||
|
<tab id="zotero-editpane-tags-tab" label="&zotero.tabs.tags.label;"/>
|
||||||
|
<tab id="zotero-editpane-related-tab" label="&zotero.tabs.related.label;"/>
|
||||||
|
</tabs>
|
||||||
|
<tabpanels id="zotero-view-item" class="zotero-view-item" flex="1">
|
||||||
|
<tabpanel flex="1">
|
||||||
|
<zoteroitembox id="zotero-editpane-item-box" class="zotero-editpane-item-box" flex="1"/>
|
||||||
|
</tabpanel>
|
||||||
|
|
||||||
|
<tabpanel flex="1" orient="vertical">
|
||||||
|
<vbox flex="1" id="zotero-editpane-notes" class="zotero-box">
|
||||||
|
<hbox align="center">
|
||||||
|
<label id="zotero-editpane-notes-label"/>
|
||||||
|
<button id="zotero-editpane-notes-add" label="&zotero.item.add;" oncommand="ZoteroItemPane.addNote(event.shiftKey);"/>
|
||||||
|
</hbox>
|
||||||
|
<grid flex="1">
|
||||||
|
<columns>
|
||||||
|
<column flex="1"/>
|
||||||
|
<column/>
|
||||||
|
</columns>
|
||||||
|
<rows id="zotero-editpane-dynamic-notes" flex="1"/>
|
||||||
|
</grid>
|
||||||
|
</vbox>
|
||||||
|
</tabpanel>
|
||||||
|
|
||||||
|
<tabpanel id="tags-pane" class="tags-pane" orient="vertical" context="tags-context-menu">
|
||||||
|
<html:div id="tags-box-container" class="tags-box-container"></html:div>
|
||||||
|
</tabpanel>
|
||||||
|
|
||||||
|
<tabpanel>
|
||||||
|
<relatedbox id="zotero-editpane-related" class="zotero-editpane-related" flex="1"/>
|
||||||
|
</tabpanel>
|
||||||
|
</tabpanels>
|
||||||
|
</tabbox>
|
||||||
|
|
||||||
|
<!-- Note item -->
|
||||||
|
<groupbox id="zotero-view-note" flex="1">
|
||||||
|
<!--
|
||||||
|
'onerror' handler crashes the app on a save error to prevent typing in notes
|
||||||
|
while they're not being saved
|
||||||
|
-->
|
||||||
|
<zoteronoteeditor id="zotero-note-editor" flex="1" notitle="1"
|
||||||
|
previousfocus="zotero-items-tree"
|
||||||
|
onerror="ZoteroPane.displayErrorMessage(); this.mode = 'view'"/>
|
||||||
|
<button id="zotero-view-note-button"
|
||||||
|
label="&zotero.notes.separate;"
|
||||||
|
oncommand="ZoteroItemPane.openNoteWindow()"/>
|
||||||
|
</groupbox>
|
||||||
|
|
||||||
|
<!-- Attachment item -->
|
||||||
|
<groupbox>
|
||||||
|
<zoteroattachmentbox id="zotero-attachment-box" flex="1"/>
|
||||||
|
</groupbox>
|
||||||
|
|
||||||
|
<!-- Duplicate merging -->
|
||||||
|
<vbox id="zotero-duplicates-merge-pane" flex="1">
|
||||||
|
<groupbox>
|
||||||
|
<button id="zotero-duplicates-merge-button" oncommand="Zotero_Duplicates_Pane.merge()"/>
|
||||||
|
</groupbox>
|
||||||
|
|
||||||
|
<groupbox id="zotero-duplicates-merge-version-select">
|
||||||
|
<description>&zotero.duplicatesMerge.versionSelect;</description>
|
||||||
|
<hbox>
|
||||||
|
<listbox id="zotero-duplicates-merge-original-date" onselect="Zotero_Duplicates_Pane.setMaster(this.selectedIndex)" rows="0"/>
|
||||||
|
</hbox>
|
||||||
|
</groupbox>
|
||||||
|
|
||||||
|
<groupbox flex="1">
|
||||||
|
<description id="zotero-duplicates-merge-field-select">&zotero.duplicatesMerge.fieldSelect;</description>
|
||||||
|
<zoteroitembox id="zotero-duplicates-merge-item-box" flex="1"/>
|
||||||
|
</groupbox>
|
||||||
|
</vbox>
|
||||||
</deck>
|
</deck>
|
||||||
</vbox>
|
</vbox>
|
||||||
</overlay>
|
</overlay>
|
|
@ -24,9 +24,10 @@
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||||
</script>
|
</script>
|
||||||
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
|
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
|
||||||
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
|
<script type="application/javascript" src="chrome://global/content/contentAreaUtils.js"/>
|
||||||
<script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
|
<script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
|
||||||
|
<script src="include.js"/>
|
||||||
<commandset id="mainCommandSet">
|
<commandset id="mainCommandSet">
|
||||||
<!--FILE-->
|
<!--FILE-->
|
||||||
<command id="cmd_quitApplication" oncommand="goQuitApplication();"/>
|
<command id="cmd_quitApplication" oncommand="goQuitApplication();"/>
|
||||||
|
@ -115,27 +116,5 @@
|
||||||
<popupset id="zotero-reader-popupset">
|
<popupset id="zotero-reader-popupset">
|
||||||
</popupset>
|
</popupset>
|
||||||
</vbox>
|
</vbox>
|
||||||
<splitter id="zotero-reader-splitter"
|
|
||||||
hidden="true"
|
|
||||||
resizebefore="closest"
|
|
||||||
resizeafter="closest"
|
|
||||||
collapse="after"
|
|
||||||
orient="horizontal"
|
|
||||||
zotero-persist="state orient" />
|
|
||||||
<vbox flex="0" id="zotero-reader-note-sidebar" width="350" hidden="true">
|
|
||||||
<vbox id="zotero-reader-sidebar-cover" flex="1">
|
|
||||||
<label>Drag a note here…</label>
|
|
||||||
</vbox>
|
|
||||||
<vbox id="zotero-reader-sidebar-container" flex="1" style="overflow:auto;" hidden="true">
|
|
||||||
<zoteronoteeditor id="zotero-reader-editor" flex="1" notitle="1"
|
|
||||||
previousfocus="zotero-items-tree"
|
|
||||||
onerror="/*this.mode = 'view'*/"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<button id="zotero-view-note-button" label="Close"
|
|
||||||
oncommand="document.getElementById('zotero-reader-sidebar-container').hidden = true;document.getElementById('zotero-reader-sidebar-cover').hidden = false;"/>
|
|
||||||
</vbox>
|
|
||||||
</vbox>
|
|
||||||
</hbox>
|
</hbox>
|
||||||
<script src="include.js"/>
|
|
||||||
</window>
|
</window>
|
||||||
|
|
|
@ -54,7 +54,8 @@ const ZoteroStandalone = new function() {
|
||||||
notify: async (action, type, ids, extraData) => {
|
notify: async (action, type, ids, extraData) => {
|
||||||
if (action == 'select') {
|
if (action == 'select') {
|
||||||
// "library" or "reader"
|
// "library" or "reader"
|
||||||
this.switchMenuType(extraData.type);
|
this.switchMenuType(extraData[ids[0]].type);
|
||||||
|
setTimeout(() => ZoteroPane.updateToolbarPosition(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -113,7 +113,7 @@ var Zotero_Tabs = new function () {
|
||||||
index = index || this._tabs.length;
|
index = index || this._tabs.length;
|
||||||
this._tabs.splice(index, 0, tab);
|
this._tabs.splice(index, 0, tab);
|
||||||
this._update();
|
this._update();
|
||||||
Zotero.Notifier.trigger('add', 'tab', id, notifierData);
|
Zotero.Notifier.trigger('add', 'tab', [id], { [id]: notifierData });
|
||||||
if (select) {
|
if (select) {
|
||||||
this.select(id);
|
this.select(id);
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ var Zotero_Tabs = new function () {
|
||||||
if (tab.onClose) {
|
if (tab.onClose) {
|
||||||
tab.onClose();
|
tab.onClose();
|
||||||
}
|
}
|
||||||
Zotero.Notifier.trigger('close', 'tab', tab.id);
|
Zotero.Notifier.trigger('close', 'tab', [tab.id]);
|
||||||
this._update();
|
this._update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ var Zotero_Tabs = new function () {
|
||||||
this._selectedID = id;
|
this._selectedID = id;
|
||||||
this.deck.selectedIndex = Array.from(this.deck.children).findIndex(x => x.id == id);
|
this.deck.selectedIndex = Array.from(this.deck.children).findIndex(x => x.id == id);
|
||||||
this._update();
|
this._update();
|
||||||
Zotero.Notifier.trigger('select', 'tab', tab.id, { type: tab.type });
|
Zotero.Notifier.trigger('select', 'tab', [tab.id], { [tab.id]: { type: tab.type } });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,6 +33,7 @@ class EditorInstance {
|
||||||
this.onNavigate = options.onNavigate;
|
this.onNavigate = options.onNavigate;
|
||||||
this._item = options.item;
|
this._item = options.item;
|
||||||
this._readOnly = options.readOnly;
|
this._readOnly = options.readOnly;
|
||||||
|
this._onReturn = options.onReturn;
|
||||||
this._iframeWindow = options.iframeWindow;
|
this._iframeWindow = options.iframeWindow;
|
||||||
this._popup = options.popup;
|
this._popup = options.popup;
|
||||||
this._state = options.state;
|
this._state = options.state;
|
||||||
|
@ -63,6 +64,7 @@ class EditorInstance {
|
||||||
action: 'init',
|
action: 'init',
|
||||||
value: this._state || this._item.note,
|
value: this._state || this._item.note,
|
||||||
readOnly: this._readOnly,
|
readOnly: this._readOnly,
|
||||||
|
enableReturnButton: !!this._onReturn,
|
||||||
placeholder: options.placeholder,
|
placeholder: options.placeholder,
|
||||||
dir: Zotero.dir,
|
dir: Zotero.dir,
|
||||||
font: this._getFont(),
|
font: this._getFont(),
|
||||||
|
@ -139,6 +141,30 @@ class EditorInstance {
|
||||||
_handleFontChange = () => {
|
_handleFontChange = () => {
|
||||||
this._postMessage({ action: 'updateFont', font: this._getFont() });
|
this._postMessage({ action: 'updateFont', font: this._getFont() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _digestExternalNote(itemID) {
|
||||||
|
let item = await Zotero.Items.getAsync(itemID);
|
||||||
|
item._loaded.childItems = true;
|
||||||
|
let note = item.note;
|
||||||
|
let attachments = await Zotero.Items.getAsync(item.getAttachments());
|
||||||
|
for (let attachment of attachments) {
|
||||||
|
let path = await attachment.getFilePathAsync();
|
||||||
|
let buf = await OS.File.read(path, {});
|
||||||
|
buf = new Uint8Array(buf).buffer;
|
||||||
|
let blob = new this._iframeWindow.Blob([buf], { type: attachment.attachmentContentType });
|
||||||
|
let clonedAttachment = await Zotero.Attachments.importEmbeddedImage({
|
||||||
|
blob,
|
||||||
|
parentItemID: this._item.id,
|
||||||
|
saveOptions: {
|
||||||
|
notifierData: {
|
||||||
|
noteEditorID: this.instanceID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
note = note.replace(attachment.key, clonedAttachment.key);
|
||||||
|
}
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
async _annotationsToInsertionList(annotations) {
|
async _annotationsToInsertionList(annotations) {
|
||||||
let list = [];
|
let list = [];
|
||||||
|
@ -148,25 +174,28 @@ class EditorInstance {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let item = attachmentItem.parentID && await Zotero.Items.getAsync(attachmentItem.parentID) || attachmentItem;
|
let item = attachmentItem.parentID && await Zotero.Items.getAsync(attachmentItem.parentID) || attachmentItem;
|
||||||
|
annotation.uri = Zotero.URI.getItemURI(attachmentItem);
|
||||||
if (item !== attachmentItem) {
|
if (item !== attachmentItem) {
|
||||||
annotation.parentURI = Zotero.URI.getItemURI(item);
|
annotation.parentURI = Zotero.URI.getItemURI(item);
|
||||||
|
|
||||||
|
let citationItem = {
|
||||||
|
uris: [Zotero.URI.getItemURI(item)],
|
||||||
|
itemData: Zotero.Cite.System.prototype.retrieveItem(item),
|
||||||
|
locator: annotation.pageLabel
|
||||||
|
};
|
||||||
|
|
||||||
|
annotation.citationItem = citationItem;
|
||||||
|
|
||||||
|
let citation = {
|
||||||
|
citationItems: [citationItem],
|
||||||
|
properties: {}
|
||||||
|
};
|
||||||
|
let formattedCitation = (await this._getFormattedCitationParts(citation)).join(';');
|
||||||
|
list.push({ annotation, citation, formattedCitation });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list.push({ annotation });
|
||||||
}
|
}
|
||||||
annotation.uri = Zotero.URI.getItemURI(attachmentItem);
|
|
||||||
|
|
||||||
let citationItem = {
|
|
||||||
uris: [Zotero.URI.getItemURI(item)],
|
|
||||||
itemData: Zotero.Cite.System.prototype.retrieveItem(item),
|
|
||||||
locator: annotation.pageLabel
|
|
||||||
};
|
|
||||||
|
|
||||||
annotation.citationItem = citationItem;
|
|
||||||
|
|
||||||
let citation = {
|
|
||||||
citationItems: [citationItem],
|
|
||||||
properties: {}
|
|
||||||
};
|
|
||||||
let formattedCitation = (await this._getFormattedCitationParts(citation)).join(';');
|
|
||||||
list.push({ annotation, citation, formattedCitation });
|
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -187,18 +216,24 @@ class EditorInstance {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let citation = {
|
if (item.isRegularItem()) {
|
||||||
citationItems: [{
|
let citation = {
|
||||||
uris: [Zotero.URI.getItemURI(item)],
|
citationItems: [{
|
||||||
itemData: Zotero.Cite.System.prototype.retrieveItem(item)
|
uris: [Zotero.URI.getItemURI(item)],
|
||||||
}],
|
itemData: Zotero.Cite.System.prototype.retrieveItem(item)
|
||||||
properties: {}
|
}],
|
||||||
};
|
properties: {}
|
||||||
|
};
|
||||||
|
|
||||||
let formattedCitation = (await this._getFormattedCitationParts(citation)).join(';');
|
let formattedCitation = (await this._getFormattedCitationParts(citation)).join(';');
|
||||||
|
|
||||||
list.push({ citation, formattedCitation });
|
list.push({ citation, formattedCitation });
|
||||||
|
}
|
||||||
|
else if (item.isNote()) {
|
||||||
|
let note = await this._digestExternalNote(item.id);
|
||||||
|
list.push({ note });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type === 'zotero/annotation') {
|
else if (type === 'zotero/annotation') {
|
||||||
|
@ -343,6 +378,10 @@ class EditorInstance {
|
||||||
this._openPopup(x, y, pos, itemGroups);
|
this._openPopup(x, y, pos, itemGroups);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case 'return': {
|
||||||
|
this._onReturn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,17 +8,21 @@ class ReaderInstance {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.pdfStateFileName = '.zotero-pdf-state';
|
this.pdfStateFileName = '.zotero-pdf-state';
|
||||||
this.annotationItemIDs = [];
|
this.annotationItemIDs = [];
|
||||||
|
this.onChangeSidebarWidth = null;
|
||||||
this._instanceID = Zotero.Utilities.randomString();
|
this._instanceID = Zotero.Utilities.randomString();
|
||||||
this._window = null;
|
this._window = null;
|
||||||
this._iframeWindow = null;
|
this._iframeWindow = null;
|
||||||
this._itemID = null;
|
this._itemID = null;
|
||||||
this._state = null;
|
this._state = null;
|
||||||
this._prevHistory = [];
|
|
||||||
this._nextHistory = [];
|
|
||||||
this._isReaderInitialized = false;
|
this._isReaderInitialized = false;
|
||||||
|
this._showItemPaneToggle = false;
|
||||||
|
this._initPromise = new Promise((resolve, reject) => {
|
||||||
|
this._resolveInitPromise = resolve;
|
||||||
|
this._rejectInitPromise = reject;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async open({ itemID, state, location, skipHistory }) {
|
async open({ itemID, state, location }) {
|
||||||
if (itemID === this._itemID) {
|
if (itemID === this._itemID) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -26,13 +30,6 @@ class ReaderInstance {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this._itemID && !skipHistory) {
|
|
||||||
this._prevHistory.push({
|
|
||||||
itemID: this._itemID,
|
|
||||||
state: this._state
|
|
||||||
});
|
|
||||||
this._nextHistory = [];
|
|
||||||
}
|
|
||||||
this._itemID = item.id;
|
this._itemID = item.id;
|
||||||
let path = await item.getFilePathAsync();
|
let path = await item.getFilePathAsync();
|
||||||
let buf = await OS.File.read(path, {});
|
let buf = await OS.File.read(path, {});
|
||||||
|
@ -51,9 +48,11 @@ class ReaderInstance {
|
||||||
annotations,
|
annotations,
|
||||||
state,
|
state,
|
||||||
location,
|
location,
|
||||||
enablePrev: !!this._prevHistory.length,
|
promptImport: !!Zotero.PDF.hasUnmachedAnnotations[this._itemID],
|
||||||
enableNext: !!this._nextHistory.length,
|
showItemPaneToggle: this._showItemPaneToggle,
|
||||||
promptImport: !!Zotero.PDF.hasUnmachedAnnotations[this._itemID]
|
sidebarWidth: this._sidebarWidth,
|
||||||
|
sidebarOpen: this._sidebarOpen,
|
||||||
|
bottomPlaceholderHeight: this._bottomPlaceholderHeight
|
||||||
}, [buf]);
|
}, [buf]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +96,28 @@ class ReaderInstance {
|
||||||
toggleImportPrompt(enable) {
|
toggleImportPrompt(enable) {
|
||||||
this._postMessage({ action: 'toggleImportPrompt', enable });
|
this._postMessage({ action: 'toggleImportPrompt', enable });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableAddToNote(enable) {
|
||||||
|
this._postMessage({ action: 'enableAddToNote', enable });
|
||||||
|
}
|
||||||
|
|
||||||
|
setSidebarWidth(width) {
|
||||||
|
this._postMessage({ action: 'setSidebarWidth', width });
|
||||||
|
}
|
||||||
|
|
||||||
|
setSidebarOpen(open) {
|
||||||
|
this._postMessage({ action: 'setSidebarOpen', open });
|
||||||
|
}
|
||||||
|
|
||||||
|
async setBottomPlaceholderHeight(height) {
|
||||||
|
await this._initPromise;
|
||||||
|
this._postMessage({ action: 'setBottomPlaceholderHeight', height });
|
||||||
|
}
|
||||||
|
|
||||||
|
async setToolbarPlaceholderWidth(width) {
|
||||||
|
await this._initPromise;
|
||||||
|
this._postMessage({ action: 'setToolbarPlaceholderWidth', width });
|
||||||
|
}
|
||||||
|
|
||||||
async _saveState(state) {
|
async _saveState(state) {
|
||||||
let item = Zotero.Items.get(this._itemID);
|
let item = Zotero.Items.get(this._itemID);
|
||||||
|
@ -137,20 +158,6 @@ class ReaderInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Pass sidebar state to the responsible pdf-reader button
|
|
||||||
_toggleNoteSidebar(isToggled) {
|
|
||||||
let splitter = this._window.document.getElementById('zotero-reader-splitter');
|
|
||||||
let sidebar = this._window.document.getElementById('zotero-reader-note-sidebar');
|
|
||||||
if (isToggled) {
|
|
||||||
splitter.hidden = false;
|
|
||||||
sidebar.hidden = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
splitter.hidden = true;
|
|
||||||
sidebar.hidden = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_getColorIcon(color, selected) {
|
_getColorIcon(color, selected) {
|
||||||
let stroke = selected ? 'lightgray' : 'transparent';
|
let stroke = selected ? 'lightgray' : 'transparent';
|
||||||
let fill = '%23' + color.slice(1);
|
let fill = '%23' + color.slice(1);
|
||||||
|
@ -176,20 +183,23 @@ class ReaderInstance {
|
||||||
popup.addEventListener('popuphidden', function () {
|
popup.addEventListener('popuphidden', function () {
|
||||||
popup.remove();
|
popup.remove();
|
||||||
});
|
});
|
||||||
|
let menuitem;
|
||||||
// Add to note
|
// Add to note
|
||||||
let menuitem = this._window.document.createElement('menuitem');
|
if (this._window.ZoteroContextPane.getActiveEditor()) {
|
||||||
menuitem.setAttribute('label', 'Add to Note');
|
menuitem = this._window.document.createElement('menuitem');
|
||||||
menuitem.addEventListener('command', () => {
|
menuitem.setAttribute('label', 'Add to Note');
|
||||||
let data = {
|
menuitem.addEventListener('command', () => {
|
||||||
action: 'popupCmd',
|
let data = {
|
||||||
cmd: 'addToNote',
|
action: 'popupCmd',
|
||||||
id: annotationId
|
cmd: 'addToNote',
|
||||||
};
|
id: annotationId
|
||||||
this._postMessage(data);
|
};
|
||||||
});
|
this._postMessage(data);
|
||||||
popup.appendChild(menuitem);
|
});
|
||||||
// Separator
|
popup.appendChild(menuitem);
|
||||||
popup.appendChild(this._window.document.createElement('menuseparator'));
|
// Separator
|
||||||
|
popup.appendChild(this._window.document.createElement('menuseparator'));
|
||||||
|
}
|
||||||
// Colors
|
// Colors
|
||||||
for (let color of colors) {
|
for (let color of colors) {
|
||||||
menuitem = this._window.document.createElement('menuitem');
|
menuitem = this._window.document.createElement('menuitem');
|
||||||
|
@ -270,26 +280,8 @@ class ReaderInstance {
|
||||||
Zotero.debug('Received message from pdf-reader iframe: ' + JSON.stringify(data));
|
Zotero.debug('Received message from pdf-reader iframe: ' + JSON.stringify(data));
|
||||||
message = data.message;
|
message = data.message;
|
||||||
switch (message.action) {
|
switch (message.action) {
|
||||||
case 'navigatePrev': {
|
case 'initialized': {
|
||||||
let prev = this._prevHistory.pop();
|
this._resolveInitPromise();
|
||||||
if (prev) {
|
|
||||||
this._nextHistory.push({
|
|
||||||
itemID: this._itemID,
|
|
||||||
state: this._state
|
|
||||||
});
|
|
||||||
this.open({ itemID: prev.itemID, state: prev.state, skipHistory: true });
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case 'navigateNext': {
|
|
||||||
let next = this._nextHistory.pop();
|
|
||||||
if (next) {
|
|
||||||
this._prevHistory.push({
|
|
||||||
itemID: this._itemID,
|
|
||||||
state: this._state
|
|
||||||
});
|
|
||||||
this.open({ itemID: next.itemID, state: next.state, skipHistory: true });
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case 'setAnnotation': {
|
case 'setAnnotation': {
|
||||||
|
@ -395,6 +387,20 @@ class ReaderInstance {
|
||||||
this._toggleNoteSidebar(isToggled);
|
this._toggleNoteSidebar(isToggled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case 'changeSidebarWidth': {
|
||||||
|
let { width } = message;
|
||||||
|
if (this.onChangeSidebarWidth) {
|
||||||
|
this.onChangeSidebarWidth(width);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case 'changeSidebarOpen': {
|
||||||
|
let { open } = message;
|
||||||
|
if (this.onChangeSidebarOpen) {
|
||||||
|
this.onChangeSidebarOpen(open);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
@ -459,8 +465,12 @@ class ReaderInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReaderTab extends ReaderInstance {
|
class ReaderTab extends ReaderInstance {
|
||||||
constructor(itemID) {
|
constructor({ itemID, sidebarWidth, sidebarOpen, bottomPlaceholderHeight }) {
|
||||||
super();
|
super();
|
||||||
|
this._sidebarWidth = sidebarWidth;
|
||||||
|
this._sidebarOpen = sidebarOpen;
|
||||||
|
this._bottomPlaceholderHeight = bottomPlaceholderHeight;
|
||||||
|
this._showItemPaneToggle = true;
|
||||||
this._window = Services.wm.getMostRecentWindow('navigator:browser');
|
this._window = Services.wm.getMostRecentWindow('navigator:browser');
|
||||||
let { id, container } = this._window.Zotero_Tabs.add({
|
let { id, container } = this._window.Zotero_Tabs.add({
|
||||||
type: 'reader',
|
type: 'reader',
|
||||||
|
@ -493,7 +503,7 @@ class ReaderTab extends ReaderInstance {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this._iframe.setAttribute('tooltip', 'iframeTooltip');
|
this._iframe.setAttribute('tooltip', 'html-tooltip');
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
@ -534,7 +544,7 @@ class ReaderTab extends ReaderInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
_addToNote(annotations) {
|
_addToNote(annotations) {
|
||||||
let noteEditor = this._window.ZoteroItemPane.getActiveNote();
|
let noteEditor = this._window.ZoteroContextPane.getActiveEditor();
|
||||||
if (!noteEditor) {
|
if (!noteEditor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -548,9 +558,11 @@ class ReaderTab extends ReaderInstance {
|
||||||
|
|
||||||
|
|
||||||
class ReaderWindow extends ReaderInstance {
|
class ReaderWindow extends ReaderInstance {
|
||||||
constructor() {
|
constructor({ sidebarWidth, sidebarOpen, bottomPlaceholderHeight }) {
|
||||||
super();
|
super();
|
||||||
|
this._sidebarWidth = sidebarWidth;
|
||||||
|
this._sidebarOpen = sidebarOpen;
|
||||||
|
this._bottomPlaceholderHeight = bottomPlaceholderHeight;
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,8 +576,6 @@ class ReaderWindow extends ReaderInstance {
|
||||||
|
|
||||||
this._window.addEventListener('DOMContentLoaded', (event) => {
|
this._window.addEventListener('DOMContentLoaded', (event) => {
|
||||||
if (event.target === this._window.document) {
|
if (event.target === this._window.document) {
|
||||||
this._window.addEventListener('dragover', this._handleDragOver, true);
|
|
||||||
this._window.addEventListener('drop', this._handleDrop, true);
|
|
||||||
this._window.addEventListener('keypress', this._handleKeyPress);
|
this._window.addEventListener('keypress', this._handleKeyPress);
|
||||||
|
|
||||||
this._popupset = this._window.document.getElementById('zotero-reader-popupset');
|
this._popupset = this._window.document.getElementById('zotero-reader-popupset');
|
||||||
|
@ -583,23 +593,6 @@ class ReaderWindow extends ReaderInstance {
|
||||||
this._postMessage(data);
|
this._postMessage(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
let editor = this._window.document.getElementById('zotero-reader-editor');
|
|
||||||
editor.navigateHandler = async (uri, location) => {
|
|
||||||
let item = await Zotero.URI.getURIItem(uri);
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (item.id === this._itemID) {
|
|
||||||
this.navigate(location);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
await this.open({
|
|
||||||
itemID: item.id,
|
|
||||||
location
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this._iframe = this._window.document.getElementById('reader');
|
this._iframe = this._window.document.getElementById('reader');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,78 +611,82 @@ class ReaderWindow extends ReaderInstance {
|
||||||
this._window.document.title = title;
|
this._window.document.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleDragOver = (event) => {
|
|
||||||
if (event.dataTransfer.getData('zotero/item')) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleDrop = (event) => {
|
|
||||||
let data;
|
|
||||||
if (!(data = event.dataTransfer.getData('zotero/item'))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ids = data.split(',').map(id => parseInt(id));
|
|
||||||
let item = Zotero.Items.get(ids[0]);
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.isNote()) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
let cover = this._window.document.getElementById('zotero-reader-sidebar-cover');
|
|
||||||
let container = this._window.document.getElementById('zotero-reader-sidebar-container');
|
|
||||||
let splitter = this._window.document.getElementById('zotero-reader-splitter');
|
|
||||||
|
|
||||||
cover.hidden = true;
|
|
||||||
container.hidden = false;
|
|
||||||
splitter.hidden = false;
|
|
||||||
|
|
||||||
let editor = this._window.document.getElementById('zotero-reader-editor');
|
|
||||||
let notebox = this._window.document.getElementById('zotero-reader-note-sidebar');
|
|
||||||
editor.mode = 'edit';
|
|
||||||
notebox.hidden = false;
|
|
||||||
editor.item = item;
|
|
||||||
}
|
|
||||||
else if (item.isAttachment() && item.attachmentContentType === 'application/pdf') {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
this.open({ itemID: item.id });
|
|
||||||
}
|
|
||||||
else if (item.isRegularItem()) {
|
|
||||||
let attachments = item.getAttachments();
|
|
||||||
if (attachments.length === 1) {
|
|
||||||
let id = attachments[0];
|
|
||||||
let attachment = Zotero.Items.get(id);
|
|
||||||
if (attachment.attachmentContentType === 'application/pdf') {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
this.open({ itemID: attachment.id });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleKeyPress = (event) => {
|
_handleKeyPress = (event) => {
|
||||||
if ((Zotero.isMac && event.metaKey || event.ctrlKey)
|
if ((Zotero.isMac && event.metaKey || event.ctrlKey)
|
||||||
&& !event.shiftKey && !event.altKey && event.key === 'w') {
|
&& !event.shiftKey && !event.altKey && event.key === 'w') {
|
||||||
this._window.close();
|
this._window.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Reader {
|
class Reader {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this._sidebarWidth = 200;
|
||||||
|
this._sidebarOpen = false;
|
||||||
|
this._bottomPlaceholderHeight = 800;
|
||||||
this._readers = [];
|
this._readers = [];
|
||||||
this._notifierID = Zotero.Notifier.registerObserver(this, ['item'], 'reader');
|
this._notifierID = Zotero.Notifier.registerObserver(this, ['item'], 'reader');
|
||||||
|
this.onChangeSidebarWidth = null;
|
||||||
|
this.onChangeSidebarOpen = null;
|
||||||
|
|
||||||
|
this._debounceSidebarWidthUpdate = Zotero.Utilities.debounce(() => {
|
||||||
|
let readers = this._readers.filter(r => r instanceof ReaderTab);
|
||||||
|
for (let reader of readers) {
|
||||||
|
reader.setSidebarWidth(this._sidebarWidth);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSidebarWidth() {
|
||||||
|
return this._sidebarWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadSidebarOpenState() {
|
||||||
|
let win = Zotero.getMainWindow();
|
||||||
|
if (win) {
|
||||||
|
let pane = win.document.getElementById('zotero-reader-sidebar-pane');
|
||||||
|
this._sidebarOpen = pane.getAttribute('collapsed') == 'false';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setSidebarOpenState() {
|
||||||
|
let win = Zotero.getMainWindow();
|
||||||
|
if (win) {
|
||||||
|
let pane = win.document.getElementById('zotero-reader-sidebar-pane');
|
||||||
|
pane.setAttribute('collapsed', this._sidebarOpen ? 'false' : 'true');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSidebarOpen() {
|
||||||
|
return this._sidebarOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSidebarWidth(width) {
|
||||||
|
this._sidebarWidth = width;
|
||||||
|
let readers = this._readers.filter(r => r instanceof ReaderTab);
|
||||||
|
for (let reader of readers) {
|
||||||
|
reader.setSidebarWidth(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setSidebarOpen(open) {
|
||||||
|
this._sidebarOpen = open;
|
||||||
|
let readers = this._readers.filter(r => r instanceof ReaderTab);
|
||||||
|
for (let reader of readers) {
|
||||||
|
reader.setSidebarOpen(open);
|
||||||
|
}
|
||||||
|
this._setSidebarOpenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
setBottomPlaceholderHeight(height) {
|
||||||
|
this._bottomPlaceholderHeight = height;
|
||||||
|
let readers = this._readers.filter(r => r instanceof ReaderTab);
|
||||||
|
for (let reader of readers) {
|
||||||
|
reader.setBottomPlaceholderHeight(height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
notify(event, type, ids, extraData) {
|
notify(event, type, ids, extraData) {
|
||||||
// Listen for the parent item, PDF attachment and its annotation items updates
|
// Listen for the parent item, PDF attachment and its annotation items updates
|
||||||
for (let readerWindow of this._readers) {
|
for (let readerWindow of this._readers) {
|
||||||
|
@ -746,6 +743,7 @@ class Reader {
|
||||||
}
|
}
|
||||||
|
|
||||||
async open(itemID, location, openWindow) {
|
async open(itemID, location, openWindow) {
|
||||||
|
this._loadSidebarOpenState();
|
||||||
this.triggerAnnotationsImportCheck(itemID);
|
this.triggerAnnotationsImportCheck(itemID);
|
||||||
let reader;
|
let reader;
|
||||||
|
|
||||||
|
@ -762,21 +760,44 @@ class Reader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (openWindow) {
|
else if (openWindow) {
|
||||||
reader = new ReaderWindow();
|
reader = new ReaderWindow({
|
||||||
|
sidebarWidth: this._sidebarWidth,
|
||||||
|
sidebarOpen: this._sidebarOpen,
|
||||||
|
bottomPlaceholderHeight: this._bottomPlaceholderHeight
|
||||||
|
});
|
||||||
|
this._readers.push(reader);
|
||||||
if (!(await reader.open({ itemID, location }))) {
|
if (!(await reader.open({ itemID, location }))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._readers.push(reader);
|
|
||||||
reader._window.addEventListener('unload', () => {
|
reader._window.addEventListener('unload', () => {
|
||||||
this._readers.splice(this._readers.indexOf(reader), 1);
|
this._readers.splice(this._readers.indexOf(reader), 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reader = new ReaderTab(itemID);
|
reader = new ReaderTab({
|
||||||
|
itemID,
|
||||||
|
sidebarWidth: this._sidebarWidth,
|
||||||
|
sidebarOpen: this._sidebarOpen,
|
||||||
|
bottomPlaceholderHeight: this._bottomPlaceholderHeight
|
||||||
|
});
|
||||||
|
this._readers.push(reader);
|
||||||
if (!(await reader.open({ itemID, location }))) {
|
if (!(await reader.open({ itemID, location }))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._readers.push(reader);
|
reader.onChangeSidebarWidth = (width) => {
|
||||||
|
this._sidebarWidth = width;
|
||||||
|
this._debounceSidebarWidthUpdate();
|
||||||
|
if (this.onChangeSidebarWidth) {
|
||||||
|
this.onChangeSidebarWidth(width);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.onChangeSidebarOpen = (open) => {
|
||||||
|
this._sidebarOpen = open;
|
||||||
|
this.setSidebarOpen(open);
|
||||||
|
if (this.onChangeSidebarOpen) {
|
||||||
|
this.onChangeSidebarOpen(open);
|
||||||
|
}
|
||||||
|
};
|
||||||
reader.onClose = () => {
|
reader.onClose = () => {
|
||||||
this._readers.splice(this._readers.indexOf(reader), 1);
|
this._readers.splice(this._readers.indexOf(reader), 1);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1199,8 +1199,6 @@ var ZoteroPane = new function()
|
||||||
// Rename tab
|
// Rename tab
|
||||||
Zotero_Tabs.rename('zotero-pane', collectionTreeRow.getName());
|
Zotero_Tabs.rename('zotero-pane', collectionTreeRow.getName());
|
||||||
|
|
||||||
ZoteroItemPane.updateStandaloneNotesList(true);
|
|
||||||
|
|
||||||
// Clear quick search and tag selector when switching views
|
// Clear quick search and tag selector when switching views
|
||||||
document.getElementById('zotero-tb-search').value = "";
|
document.getElementById('zotero-tb-search').value = "";
|
||||||
if (ZoteroPane.tagSelector) {
|
if (ZoteroPane.tagSelector) {
|
||||||
|
@ -5060,6 +5058,7 @@ var ZoteroPane = new function()
|
||||||
|
|
||||||
this.updateToolbarPosition();
|
this.updateToolbarPosition();
|
||||||
this.updateTagsBoxSize();
|
this.updateTagsBoxSize();
|
||||||
|
ZoteroContextPane.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5195,8 +5194,6 @@ var ZoteroPane = new function()
|
||||||
|
|
||||||
// Allow item pane to shrink to available height in stacked mode, but don't expand to be too
|
// Allow item pane to shrink to available height in stacked mode, but don't expand to be too
|
||||||
// wide when there's no persisted width in non-stacked mode
|
// wide when there's no persisted width in non-stacked mode
|
||||||
|
|
||||||
// TODO: Fix this together with stacked view
|
|
||||||
itemPane.setAttribute("flex", stackedLayout ? 1 : 0);
|
itemPane.setAttribute("flex", stackedLayout ? 1 : 0);
|
||||||
|
|
||||||
this.handleTagSelectorResize();
|
this.handleTagSelectorResize();
|
||||||
|
|
|
@ -156,6 +156,8 @@
|
||||||
<!ENTITY zotero.toolbar.attachment.add "Store Copy of File…">
|
<!ENTITY zotero.toolbar.attachment.add "Store Copy of File…">
|
||||||
<!ENTITY zotero.toolbar.attachment.weblink "Save Link to Current Page">
|
<!ENTITY zotero.toolbar.attachment.weblink "Save Link to Current Page">
|
||||||
<!ENTITY zotero.toolbar.attachment.snapshot "Take Snapshot of Current Page">
|
<!ENTITY zotero.toolbar.attachment.snapshot "Take Snapshot of Current Page">
|
||||||
|
<!ENTITY zotero.toolbar.context.item "Item">
|
||||||
|
<!ENTITY zotero.toolbar.context.notes "Notes">
|
||||||
|
|
||||||
<!ENTITY zotero.tagSelector.noTagsToDisplay "No tags to display">
|
<!ENTITY zotero.tagSelector.noTagsToDisplay "No tags to display">
|
||||||
<!ENTITY zotero.tagSelector.loadingTags "Loading tags…">
|
<!ENTITY zotero.tagSelector.loadingTags "Loading tags…">
|
||||||
|
|
|
@ -401,6 +401,8 @@ pane.item.related.count.singular = %S related:
|
||||||
pane.item.related.count.plural = %S related:
|
pane.item.related.count.plural = %S related:
|
||||||
pane.item.parentItem = Parent Item:
|
pane.item.parentItem = Parent Item:
|
||||||
|
|
||||||
|
pane.context.noParent = No parent item
|
||||||
|
|
||||||
noteEditor.editNote = Edit Note
|
noteEditor.editNote = Edit Note
|
||||||
|
|
||||||
itemTypes.note = Note
|
itemTypes.note = Note
|
||||||
|
|
71
chrome/skin/default/zotero/contextPane.css
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#tabs-deck {
|
||||||
|
min-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-context-pane {
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-context-pane.stacked {
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
font-size: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-context-pane.stacked #zotero-context-toolbar-extension {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-context-pane .stacked-context-placeholder {
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-context-pane.standard .stacked-context-placeholder {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-context-splitter-stacked {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-context-pane-inner {
|
||||||
|
width: 0;
|
||||||
|
font: message-box;
|
||||||
|
min-height: 100px;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*#zotero-context-pane.standard .stacked-splitter {*/
|
||||||
|
/* display: none;*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
#zotero-tab-toolbar-container {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
right: 0;
|
||||||
|
height: 32px;
|
||||||
|
-moz-appearance: none;
|
||||||
|
background: linear-gradient(to top, #aeaeae 0, #aeaeae 1px, #d3d3d3 1px, #e3e3e3 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-tab-toolbar-container #zotero-tb-locate,
|
||||||
|
#zotero-tab-toolbar-container #zotero-pq-buttons {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-context-toolbar-extension {
|
||||||
|
height: 32px;
|
||||||
|
/* To cover the splitter that has a higher stacking order than our parent */
|
||||||
|
opacity: 0.99;
|
||||||
|
width: 100%;
|
||||||
|
margin-inline-start: -5px;
|
||||||
|
background: linear-gradient(to top, #aeaeae 0, #aeaeae 1px, #d3d3d3 1px, #e3e3e3 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.zotero-context-notes-list {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
|
@ -45,51 +45,13 @@
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-item-pane[data-type='library'] #item-pane-title,
|
.zotero-context-pane-pinned-note {
|
||||||
#zotero-item-pane[data-mode='notes'] #item-pane-title {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#item-pane-title {
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 0 10px 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#zotero-item-pane-contextual-deck .item-pane-back-button {
|
|
||||||
font-size: 12px;
|
|
||||||
margin: 4px 5px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#zotero-item-pane-pin-deck .item-pane-back-button {
|
|
||||||
font-size: 12px;
|
|
||||||
margin: 7px 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#zotero-item-pane-padding-top {
|
|
||||||
/*border-bottom: 1px solid lightgray;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#zotero-item-pane-pinned-note {
|
|
||||||
border-top: 1px solid #d9d9d9;
|
border-top: 1px solid #d9d9d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zotero-editpane-tabs {
|
/*.zotero-editpane-tabs {*/
|
||||||
background: #ececec;
|
/* background: #ececec;*/
|
||||||
}
|
/*}*/
|
||||||
|
|
||||||
#temp-toggle-1.mode-item, #temp-toggle-2.mode-item {
|
|
||||||
list-style-image: url(chrome://zotero/skin/treeitem.png);
|
|
||||||
}
|
|
||||||
|
|
||||||
#temp-toggle-1.mode-notes, #temp-toggle-2.mode-notes {
|
|
||||||
list-style-image: url(chrome://zotero/skin/treeitem-note.png);
|
|
||||||
}
|
|
||||||
|
|
||||||
.notes-list-label {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 8px 10px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#retraction-box {
|
#retraction-box {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
BIN
chrome/skin/default/zotero/mac/item-white.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
chrome/skin/default/zotero/mac/item-white@2x.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
chrome/skin/default/zotero/mac/item.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
chrome/skin/default/zotero/mac/item@2x.png
Normal file
After Width: | Height: | Size: 211 B |
BIN
chrome/skin/default/zotero/mac/menubutton-end-active-pressed.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
BIN
chrome/skin/default/zotero/mac/menubutton-end-active.png
Normal file
After Width: | Height: | Size: 233 B |
BIN
chrome/skin/default/zotero/mac/menubutton-end-active@2x.png
Normal file
After Width: | Height: | Size: 399 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.8 KiB |
BIN
chrome/skin/default/zotero/mac/menubutton-start-active.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
chrome/skin/default/zotero/mac/menubutton-start-active@2x.png
Normal file
After Width: | Height: | Size: 543 B |
BIN
chrome/skin/default/zotero/mac/notes-white.png
Normal file
After Width: | Height: | Size: 204 B |
BIN
chrome/skin/default/zotero/mac/notes-white@2x.png
Normal file
After Width: | Height: | Size: 286 B |
BIN
chrome/skin/default/zotero/mac/notes.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
chrome/skin/default/zotero/mac/notes@2x.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
|
@ -708,9 +708,23 @@
|
||||||
display: inherit !important;
|
display: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#zotero-tab-cover {
|
||||||
|
z-index: 2;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: #ececec;
|
||||||
|
position: fixed;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-tab-cover label {
|
||||||
|
padding-top: 30px;
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.zotero-box {
|
.zotero-box {
|
||||||
/*margin-left: 5px;*/
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zotero-box-icon {
|
.zotero-box-icon {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1da855a9e2447ff0a1409401bc2ba87f9b307038
|
Subproject commit be1fa9a77fb9090a1aad9a9cd40b8ebb22ee4281
|
|
@ -1 +1 @@
|
||||||
Subproject commit 886e714d3344534b66370010e855ea857f460627
|
Subproject commit e3121e75eb82df8bea6381d390983917bd44395b
|
|
@ -11,6 +11,7 @@
|
||||||
@import "abstracts/mixins";
|
@import "abstracts/mixins";
|
||||||
@import "abstracts/placeholders";
|
@import "abstracts/placeholders";
|
||||||
@import "abstracts/utilities";
|
@import "abstracts/utilities";
|
||||||
|
@import "abstracts/split-button";
|
||||||
|
|
||||||
// Theme
|
// Theme
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
489
scss/abstracts/_split-button.scss
Normal file
|
@ -0,0 +1,489 @@
|
||||||
|
|
||||||
|
// The split button was originally created by flachware for pdf-reader:
|
||||||
|
// https://github.com/zotero/pdf-reader/blob/master/src/stylesheets/abstracts/mixins/_split-button.scss
|
||||||
|
|
||||||
|
$accent-color: #0a6cf5; // 215° 96 96
|
||||||
|
$accent-color-darken-6: darken($accent-color, 6%);
|
||||||
|
|
||||||
|
$blue-btn: #90c8f6;
|
||||||
|
|
||||||
|
$toolbar-btn-height: 22px;
|
||||||
|
$toolbar-btn-bg: linear-gradient(to bottom, #fafafa, #f2f2f2);
|
||||||
|
$toolbar-btn-padding: 3px 11px;
|
||||||
|
$toolbar-btn-border: 0;
|
||||||
|
$toolbar-btn-border-radius: 3.75px;
|
||||||
|
$toolbar-btn-margin-x: 4px;
|
||||||
|
$toolbar-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.33), 0 0 0 1px rgba(0, 0, 0, 0.08), 0 1px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
$toolbar-btn-box-shadow-2x: inset 0 0.5px 0.5px rgba(255, 255, 255, 1), 0 0 0 0.5px rgba(0, 0, 0, 0.1), 0 0.75px 0 rgba(0, 0, 0, 0.125);
|
||||||
|
$toolbar-btn-focus-box-shadow: 0 0 0 4px rgba($accent-color, 0.5), $toolbar-btn-box-shadow;
|
||||||
|
$toolbar-btn-focus-box-shadow-2x: 0 0 0 4px rgba($accent-color, 0.5), $toolbar-btn-box-shadow-2x;
|
||||||
|
$toolbar-btn-hover-bg: null;
|
||||||
|
$toolbar-btn-border-hover-color: null;
|
||||||
|
$toolbar-btn-active-bg: linear-gradient(to bottom, #e4e4e4, #ddd);
|
||||||
|
$toolbar-btn-blurred-bg: transparent;
|
||||||
|
$toolbar-btn-blurred-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.11);
|
||||||
|
$toolbar-btn-border-active-color: $blue-btn;
|
||||||
|
$toolbar-btn-icon-active-offset: 0;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// String functions
|
||||||
|
//
|
||||||
|
|
||||||
|
@function str-replace($string, $token, $replace: "") {
|
||||||
|
$i: str-index($string, $token);
|
||||||
|
|
||||||
|
@while (str-index($string, $token) != null) {
|
||||||
|
$first-part: str-slice($string, 1, ($i - 1));
|
||||||
|
$last-part: str-slice($string, ($i + str-length($token)));
|
||||||
|
$string: str-slice($string, 1, ($i - 1)) + $replace + $last-part;
|
||||||
|
|
||||||
|
$i: str-index($string, $token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@function str-parse($string, $token) {
|
||||||
|
$i: str-index($string, $token);
|
||||||
|
|
||||||
|
@if $i {
|
||||||
|
$first-part: str-slice($string, 1, ($i - 1));
|
||||||
|
$string: str-parse(str-slice($string, ($i + str-length($token))), $token);
|
||||||
|
|
||||||
|
@return join(simple-selectors($first-part), $string);
|
||||||
|
}
|
||||||
|
|
||||||
|
@return simple-selectors($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// State mixin
|
||||||
|
@mixin state($states...) {
|
||||||
|
|
||||||
|
@each $state in $states {
|
||||||
|
$string: $state;
|
||||||
|
|
||||||
|
@each $token in ">", "+", "~" {
|
||||||
|
$string: str-replace($string, $token, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
$string: str-replace($string, " ", " ");
|
||||||
|
|
||||||
|
$selectors: str-parse($string, " ");
|
||||||
|
|
||||||
|
@each $sel in $selectors {
|
||||||
|
@if str-index("#{&}", $sel) != null {
|
||||||
|
@at-root #{selector-replace(&, $sel, $state)} {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variant mixin (alias)
|
||||||
|
@mixin variant($args...) {
|
||||||
|
@include state($args...) {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Media queries
|
||||||
|
//
|
||||||
|
|
||||||
|
@mixin retina {
|
||||||
|
@media screen and (min-resolution: 1.25dppx) {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Asset URLs
|
||||||
|
//
|
||||||
|
|
||||||
|
@function asset-url($type, $path) {
|
||||||
|
@return url(unquote("#{$type}/#{$path}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@function icon-url($path) {
|
||||||
|
@return asset-url("chrome://zotero/skin", $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@function image-url($path) {
|
||||||
|
@return asset-url("chrome://zotero/skin", $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Icon
|
||||||
|
//
|
||||||
|
|
||||||
|
@mixin icon($file-name, $size: 16px) {
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
width: $size;
|
||||||
|
height: $size;
|
||||||
|
background-image: icon-url("#{$file-name}.png");
|
||||||
|
background-size: 100%;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background-image: icon-url("#{$file-name}@2x.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.toolbarButton::before {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbarButton > span:first-child {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbarButton {
|
||||||
|
height: $toolbar-btn-height;
|
||||||
|
background: $toolbar-btn-bg;
|
||||||
|
padding: $toolbar-btn-padding;
|
||||||
|
border: $toolbar-btn-border;
|
||||||
|
border-radius: $toolbar-btn-border-radius;
|
||||||
|
margin: 0 $toolbar-btn-margin-x;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: $toolbar-btn-box-shadow;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
box-shadow: $toolbar-btn-box-shadow-2x;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
box-shadow: $toolbar-btn-focus-box-shadow;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
box-shadow: $toolbar-btn-focus-box-shadow-2x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:-moz-focusring {
|
||||||
|
box-shadow: $toolbar-btn-focus-box-shadow;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
box-shadow: $toolbar-btn-focus-box-shadow-2x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $toolbar-btn-hover-bg;
|
||||||
|
border-color: $toolbar-btn-border-hover-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active,
|
||||||
|
&.active {
|
||||||
|
background: $toolbar-btn-active-bg;
|
||||||
|
border-color: $toolbar-btn-border-active-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
@include state(".toolbarButton:active", ".toolbarButton.active") {
|
||||||
|
top: $toolbar-btn-icon-active-offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label for screen readers
|
||||||
|
> span:first-child {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-button {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Split button
|
||||||
|
//
|
||||||
|
|
||||||
|
@mixin split-button($height, $button, $padding-x, $padding-y) {
|
||||||
|
height: $height;
|
||||||
|
padding: $padding-y $padding-x $padding-y ($padding-x + 1px);
|
||||||
|
background: none;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
z-index: 2; // Chrome
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: inset 0 0 0 1px rgba($accent-color, 0.5), 0 0 0 3px rgba($accent-color, 0.5);
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
box-shadow: inset 0 0 0 1px rgba($accent-color, 0.5), 0 0 0 2.5px rgba($accent-color, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:-moz-focusring {
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: inset 0 0 0 1px rgba($accent-color, 0.5), 0 0 0 3px rgba($accent-color, 0.5);
|
||||||
|
z-index: 2; // Firefox
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
box-shadow: inset 0 0 0 1px rgba($accent-color, 0.5), 0 0 0 2.5px rgba($accent-color, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-right: 0;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
&::after {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:-moz-focusring {
|
||||||
|
&::after {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding: $padding-y ($padding-x + 1px);
|
||||||
|
margin-left: 0;
|
||||||
|
background: image-url("mac/#{$button}-end.png") no-repeat right top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-end@2x.png") no-repeat right top / auto $height;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: image-url("mac/#{$button}-end-pressed.png") no-repeat right top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-end-pressed@2x.png") no-repeat right top / auto $height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton.toggled") {
|
||||||
|
background: image-url("mac/#{$button}-end-active.png") no-repeat right top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-end-active@2x.png") no-repeat right top / auto $height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton:active") {
|
||||||
|
background: image-url("mac/#{$button}-end-active-pressed.png") no-repeat right top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-end-active-pressed@2x.png") no-repeat right top / auto $height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
&::after {
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:-moz-focusring {
|
||||||
|
&::after {
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> span:first-child {
|
||||||
|
clip: initial;
|
||||||
|
margin: initial;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-indent: -99em;
|
||||||
|
background:
|
||||||
|
linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)) no-repeat left center / 1px ($height - 2px),
|
||||||
|
image-url("mac/#{$button}-start.png") no-repeat center top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background:
|
||||||
|
linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)) no-repeat left center / 1px ($height - 2px),
|
||||||
|
image-url("mac/#{$button}-start@2x.png") no-repeat center top / auto $height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton:active") {
|
||||||
|
background: image-url("mac/#{$button}-start-pressed.png") no-repeat center top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-start-pressed@2x.png") no-repeat center top / auto $height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton.toggled") {
|
||||||
|
background: image-url("mac/#{$button}-start-active.png") no-repeat center top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-start-active@2x.png") no-repeat center top / auto $height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton:active") {
|
||||||
|
background: image-url("mac/#{$button}-start-active-pressed.png") no-repeat center top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-start-active-pressed@2x.png") no-repeat center top / auto $height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton.toggled + .toolbarButton:not(:active)") {
|
||||||
|
background: image-url("mac/#{$button}-start.png") no-repeat center top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-start@2x.png") no-repeat center top / auto $height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include variant(".toolbarButton:first-child") {
|
||||||
|
background: image-url("mac/#{$button}-start.png") no-repeat left top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-start@2x.png") no-repeat left top / auto $height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton:active") {
|
||||||
|
background: image-url("mac/#{$button}-start-pressed.png") no-repeat left top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-start-pressed@2x.png") no-repeat left top / auto $height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton.toggled") {
|
||||||
|
background: image-url("mac/#{$button}-start-active.png") no-repeat left top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-start-active@2x.png") no-repeat left top / auto $height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include state(".toolbarButton:active") {
|
||||||
|
background: image-url("mac/#{$button}-start-active-pressed.png") no-repeat left top;
|
||||||
|
|
||||||
|
@include retina {
|
||||||
|
background: image-url("mac/#{$button}-start-active-pressed@2x.png") no-repeat left top / auto $height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include variant(".toolbarButton:last-child") {
|
||||||
|
width: calc(100% - 17px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Move this out from mixins
|
||||||
|
#zotero-tb-split {
|
||||||
|
$item-tool-icon: "mac/item";
|
||||||
|
$item-tool-icon-active: "mac/item-white";
|
||||||
|
$notes-tool-icon: "mac/notes";
|
||||||
|
$notes-tool-icon-active: "mac/notes-white";
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
@include icon($item-tool-icon);
|
||||||
|
|
||||||
|
&.toggled {
|
||||||
|
@include icon($item-tool-icon-active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notes {
|
||||||
|
@include icon($notes-tool-icon);
|
||||||
|
|
||||||
|
&.toggled {
|
||||||
|
@include icon($notes-tool-icon-active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbarButton {
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
@include split-button(
|
||||||
|
$height: 24px,
|
||||||
|
$button: "menubutton",
|
||||||
|
$padding-x: 11px,
|
||||||
|
$padding-y: 4px
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,9 +24,31 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.inner {
|
.inner {
|
||||||
|
> *:not(:first-child) {
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
.first-line {
|
.first-line {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
flex-grow: 1;
|
||||||
|
width: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.second-line {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
@ -37,10 +59,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.second-line {
|
.third-line {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
|
color: $shade-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 2px 0 0; // Leave space for textbox border on top tag
|
padding: 2px 0 0; // Leave space for textbox border on top tag
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.tags-box-list > li {
|
ul.tags-box-list > li {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit f4374cdb6386ba5cdd818ff6e3ece74aae83b394
|
Subproject commit a271598218fa8f52cd6d571d5c1b28e913803409
|