Improve bidi & RTL support (#2415)
- Render cell text in its native direction - Fix context menu positioning - Fix item box (localizations needed) - Fix column resizing - Fix bidi text in collection tree - Always right-align in RTL, always left-align in LTR. I'm going off advice from this excellent guide for RTL website design by Ahmad Shadeed: https://rtlstyling.com/posts/rtl-styling#tables - Join creators in the tree ("Smith and Jones") using a format string to support languages like Arabic and Hebrew where there shouldn't be a space after the "and". - Fix tabs - Fix toolbar on Mac, flip icons on other platforms
This commit is contained in:
parent
93bba41dd5
commit
74492e40c4
24 changed files with 254 additions and 145 deletions
|
@ -1,10 +1,10 @@
|
|||
#zotero-items-toolbar[state=collapsed]
|
||||
{
|
||||
margin-left: -8px !important;
|
||||
margin-inline-start: -8px !important;
|
||||
}
|
||||
|
||||
#zotero-pane toolbarseparator {
|
||||
margin-left: 7px;
|
||||
margin-inline-start: 7px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync-stop .toolbarbutton-icon,
|
||||
|
@ -19,14 +19,19 @@
|
|||
.zotero-tb-button,
|
||||
.zotero-tb-button:first-child,
|
||||
.zotero-tb-button:last-child {
|
||||
-moz-margin-start: 0 !important;
|
||||
-moz-margin-end: 3px !important;
|
||||
-moz-padding-end: 10px !important;
|
||||
margin-inline-start: 0 !important;
|
||||
margin-inline-end: 3px !important;
|
||||
padding-right: 10px !important;
|
||||
background: url("chrome://zotero/skin/mac/menubutton-end.png") right center/auto 24px no-repeat;
|
||||
}
|
||||
|
||||
.zotero-tb-button[type=menu] {
|
||||
-moz-padding-end: 8px !important;
|
||||
padding-inline-end: 8px !important;
|
||||
}
|
||||
|
||||
.zotero-tb-button > .toolbarbutton-icon {
|
||||
background: url("chrome://zotero/skin/mac/menubutton-start.png") left center/auto 24px no-repeat;
|
||||
padding: 4px 4px 4px 11px;
|
||||
}
|
||||
|
||||
.zotero-tb-button > .toolbarbutton-icon {
|
||||
|
@ -36,12 +41,35 @@
|
|||
|
||||
/* For menu buttons, decrease left padding by 1px */
|
||||
.zotero-tb-button[type=menu] > .toolbarbutton-icon {
|
||||
-moz-padding-start: 9px;
|
||||
padding-left: 9px;
|
||||
max-width: 29px;
|
||||
}
|
||||
|
||||
/* A decent hack: reverse the effective order of the dropmarker and icon in RTL
|
||||
mode so that the above CSS, which places the menubutton-start.png background
|
||||
on the toolbarbutton-icon, will make sense. (Otherwise the dropmarker appears
|
||||
outside the button.) Then just flip the entire thing horizontally! We want to
|
||||
do that anyway so that the Locate button will point to the left and Sync will
|
||||
rotate counter-clockwise.
|
||||
|
||||
The other way to do this would be to set direction: ltr on buttons in the
|
||||
RTL toolbar, but that breaks popup positioning. */
|
||||
#zotero-pane[dir=rtl] .zotero-tb-button > .toolbarbutton-menu-dropmarker {
|
||||
-moz-box-ordinal-group: 0;
|
||||
}
|
||||
|
||||
#zotero-pane[dir=rtl] .zotero-tb-button > .toolbarbutton-icon {
|
||||
-moz-box-ordinal-group: 1;
|
||||
}
|
||||
|
||||
#zotero-pane[dir=rtl] .zotero-tb-button,
|
||||
#zotero-pane[dir=rtl] .zotero-tb-button:first-child,
|
||||
#zotero-pane[dir=rtl] .zotero-tb-button:last-child {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
#zotero-collections-toolbar {
|
||||
padding-left: 0;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
.zotero-tb-button:-moz-window-inactive {
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#zotero-pane[dir=rtl] .zotero-tb-button > .toolbarbutton-icon {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
/* Fixes tabs missing styling on (GTK 3.20) Ubuntu 16.10. See https://bugzilla.mozilla.org/show_bug.cgi?id=1306425 */
|
||||
tabpanels {
|
||||
-moz-appearance: none;
|
||||
|
|
|
@ -44,6 +44,10 @@
|
|||
padding-left: 2px;
|
||||
}
|
||||
|
||||
#zotero-pane[dir=rtl] .zotero-tb-button > .toolbarbutton-icon {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
#zotero-collections-splitter:not([state=collapsed]),
|
||||
#zotero-items-splitter:not([state=collapsed]),
|
||||
#zotero-tags-splitter:not([state=collapsed]),
|
||||
|
|
|
@ -278,6 +278,7 @@ var CollectionTree = class CollectionTree extends LibraryTree {
|
|||
let label = document.createElement('span');
|
||||
label.innerText = treeRow.getName();
|
||||
label.className = 'cell-text';
|
||||
label.dir = 'auto';
|
||||
|
||||
// Editing input
|
||||
div.classList.toggle('editing', treeRow == this._editing);
|
||||
|
|
|
@ -282,7 +282,7 @@ const TabBar = forwardRef(function (props, ref) {
|
|||
onDragStart={(event) => handleDragStart(event, id, index)}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<div className="tab-name">{iconBackgroundImage &&
|
||||
<div className="tab-name" dir="auto">{iconBackgroundImage &&
|
||||
<span className="icon-bg" style={{ backgroundImage: iconBackgroundImage }}/>}{title}</div>
|
||||
<div
|
||||
className="tab-close"
|
||||
|
@ -323,6 +323,7 @@ const TabBar = forwardRef(function (props, ref) {
|
|||
onDragOver={handleTabBarDragOver}
|
||||
onMouseOut={handleTabBarMouseOut}
|
||||
onScroll={updateScrollArrows}
|
||||
dir={Zotero.dir}
|
||||
>
|
||||
{tabs.map((tab, index) => renderTab(tab, index))}
|
||||
</div>
|
||||
|
|
|
@ -805,8 +805,8 @@ class VirtualizedTable extends React.Component {
|
|||
const aRect = a.getBoundingClientRect();
|
||||
const bRect = b.getBoundingClientRect();
|
||||
const resizingRect = resizing.getBoundingClientRect();
|
||||
let offset = aRect.x;
|
||||
if (aColumn.dataKey != resizingColumn.dataKey) {
|
||||
let offset = aRect.left;
|
||||
if (aColumn.dataKey != resizingColumn.dataKey && !Zotero.rtl) {
|
||||
offset += resizingRect.width;
|
||||
}
|
||||
const widthSum = aRect.width + bRect.width;
|
||||
|
@ -1165,6 +1165,10 @@ class VirtualizedTable extends React.Component {
|
|||
ref: ref => this._topDiv = ref,
|
||||
tabIndex: 0,
|
||||
role: this.props.role,
|
||||
// XUL's chromedir attribute doesn't work with CSS :dir selectors,
|
||||
// so we'll manually propagate the locale's script direction to the
|
||||
// table.
|
||||
dir: Zotero.Locale.defaultScriptDirection(Zotero.locale),
|
||||
};
|
||||
if (this.props.hide) {
|
||||
props.style = { display: "none" };
|
||||
|
@ -1592,17 +1596,19 @@ var Columns = class {
|
|||
}
|
||||
};
|
||||
|
||||
function renderCell(index, data, column) {
|
||||
column = column || { columnName: "" }
|
||||
function renderCell(index, data, column, dir = null) {
|
||||
column = column || { columnName: "" };
|
||||
let span = document.createElement('span');
|
||||
span.className = `cell ${column.className}`;
|
||||
span.innerText = data;
|
||||
if (dir) span.dir = dir;
|
||||
return span;
|
||||
}
|
||||
|
||||
function renderCheckboxCell(index, data, column) {
|
||||
function renderCheckboxCell(index, data, column, dir = null) {
|
||||
let span = document.createElement('span');
|
||||
span.className = `cell checkbox ${column.className}`;
|
||||
if (dir) span.dir = dir;
|
||||
span.setAttribute('role', 'checkbox');
|
||||
span.setAttribute('aria-checked', data);
|
||||
if (data) {
|
||||
|
|
|
@ -922,7 +922,7 @@
|
|||
|
||||
// Comma
|
||||
var comma = document.createElement("span");
|
||||
comma.textContent = ',';
|
||||
comma.textContent = Zotero.getString('punctuation.comma');
|
||||
comma.className = 'comma';
|
||||
firstlast.appendChild(comma);
|
||||
|
||||
|
@ -1447,7 +1447,25 @@
|
|||
}
|
||||
|
||||
valueElement.textContent = valueText;
|
||||
|
||||
// Attempt to make bidi things work automatically:
|
||||
// If we have text to work off of, let the layout engine try to guess the text direction
|
||||
if (valueText) {
|
||||
valueElement.dir = 'auto';
|
||||
}
|
||||
// If not, assume it follows the locale's direction
|
||||
else {
|
||||
valueElement.dir = Zotero.dir;
|
||||
}
|
||||
|
||||
// Regardless, align the text in the label consistently, following the locale's direction
|
||||
if (Zotero.rtl) {
|
||||
valueElement.style.textAlign = 'right';
|
||||
}
|
||||
else {
|
||||
valueElement.style.textAlign = 'left';
|
||||
}
|
||||
|
||||
if (isMultiline) {
|
||||
valueElement.classList.add('multiline');
|
||||
}
|
||||
|
@ -1677,6 +1695,9 @@
|
|||
t.style.mozBoxFlex = 1;
|
||||
t.setAttribute('fieldname', fieldName);
|
||||
t.setAttribute('ztabindex', tabindex);
|
||||
// We set dir in createValueElement(), so figure out what it was computed as
|
||||
// and then propagate to the new text field
|
||||
t.dir = getComputedStyle(elem).direction;
|
||||
|
||||
var box = elem.parentNode;
|
||||
box.replaceChild(t, elem);
|
||||
|
|
|
@ -38,8 +38,9 @@
|
|||
event.preventDefault();
|
||||
|
||||
let rect = this.getBoundingClientRect();
|
||||
let dir = getComputedStyle(this).direction;
|
||||
popup.openPopupAtScreen(
|
||||
window.screenX + rect.left,
|
||||
window.screenX + (dir == 'rtl' ? rect.right : rect.left),
|
||||
window.screenY + rect.bottom,
|
||||
true
|
||||
);
|
||||
|
@ -59,7 +60,7 @@
|
|||
static get dropmarkerFragment() {
|
||||
let frag = document.importNode(
|
||||
MozXULElement.parseXULToFragment(`
|
||||
<image src="chrome://zotero/skin/searchbar-dropmarker${Zotero.hiDPISuffix}.png" width="7" height="4"/>
|
||||
<image src="chrome://zotero/skin/searchbar-dropmarker${Zotero.hiDPISuffix}.png" width="7" height="4" class="toolbarbutton-menu-dropmarker"/>
|
||||
`),
|
||||
true
|
||||
);
|
||||
|
|
|
@ -1373,17 +1373,6 @@ var ItemTree = class ItemTree extends LibraryTree {
|
|||
|
||||
var creatorSortCache = {};
|
||||
|
||||
// Regexp to extract the whole string up to an optional "and" or "et al."
|
||||
var andEtAlRegExp = new RegExp(
|
||||
// Extract the beginning of the string in non-greedy mode
|
||||
"^.+?"
|
||||
// up to either the end of the string, "et al." at the end of string
|
||||
+ "(?=(?: " + Zotero.getString('general.etAl').replace('.', '\\.') + ")?$"
|
||||
// or ' and '
|
||||
+ "| " + Zotero.getString('general.and').replace('.', '\\.') + " "
|
||||
+ ")"
|
||||
);
|
||||
|
||||
function creatorSort(a, b) {
|
||||
var itemA = a.ref;
|
||||
var itemB = b.ref;
|
||||
|
@ -1401,24 +1390,12 @@ var ItemTree = class ItemTree extends LibraryTree {
|
|||
var sortStringB = itemB[prop];
|
||||
if (fieldA === undefined) {
|
||||
let firstCreator = Zotero.Items.getSortTitle(sortStringA);
|
||||
if (sortCreatorAsString) {
|
||||
var fieldA = firstCreator;
|
||||
}
|
||||
else {
|
||||
var matches = andEtAlRegExp.exec(firstCreator);
|
||||
fieldA = matches ? matches[0] : '';
|
||||
}
|
||||
fieldA = firstCreator;
|
||||
creatorSortCache[aItemID] = fieldA;
|
||||
}
|
||||
if (fieldB === undefined) {
|
||||
let firstCreator = Zotero.Items.getSortTitle(sortStringB);
|
||||
if (sortCreatorAsString) {
|
||||
var fieldB = firstCreator;
|
||||
}
|
||||
else {
|
||||
matches = andEtAlRegExp.exec(firstCreator);
|
||||
fieldB = matches ? matches[0] : '';
|
||||
}
|
||||
fieldB = firstCreator;
|
||||
creatorSortCache[bItemID] = fieldB;
|
||||
}
|
||||
|
||||
|
@ -2750,6 +2727,7 @@ var ItemTree = class ItemTree extends LibraryTree {
|
|||
}
|
||||
let textSpanAriaLabel = [textWithFullStop, itemTypeAriaLabel, tagAriaLabel, retractedAriaLabel].join(' ');
|
||||
textSpan.className = "cell-text";
|
||||
textSpan.dir = 'auto';
|
||||
textSpan.setAttribute('aria-label', textSpanAriaLabel);
|
||||
|
||||
span.append(twisty, icon, retracted, ...tagSpans, textSpan);
|
||||
|
|
|
@ -1723,7 +1723,9 @@ Zotero.Items = function() {
|
|||
if (matches.length === 2) {
|
||||
let a = matches[0];
|
||||
let b = matches[1];
|
||||
return a.lastName + " " + Zotero.getString('general.and') + " " + b.lastName;
|
||||
// \u2068 FIRST STRONG ISOLATE: Isolates the directionality of characters that follow
|
||||
// \u2069 POP DIRECTIONAL ISOLATE: Pops the above isolation
|
||||
return Zotero.getString('general.andJoiner', [`\u2068${a.lastName}\u2069`, `\u2068${b.lastName}\u2069`]);
|
||||
}
|
||||
if (matches.length >= 3) {
|
||||
return matches[0].lastName + " " + Zotero.getString('general.etAl');
|
||||
|
@ -1786,8 +1788,8 @@ Zotero.Items = function() {
|
|||
var contributorCreatorTypeID = Zotero.CreatorTypes.getID('contributor');
|
||||
|
||||
/* This whole block is to get the firstCreator */
|
||||
var localizedAnd = Zotero.getString('general.and');
|
||||
var localizedEtAl = Zotero.getString('general.etAl');
|
||||
var localizedAnd = Zotero.getString('general.andJoiner').replace(/%S/g, '%s');
|
||||
var localizedEtAl = Zotero.getString('general.etAl');
|
||||
var sql = "COALESCE(" +
|
||||
// First try for primary creator types
|
||||
"CASE (" +
|
||||
|
@ -1804,16 +1806,21 @@ Zotero.Items = function() {
|
|||
"WHERE itemID=O.itemID AND primaryField=1" +
|
||||
") " +
|
||||
"WHEN 2 THEN (" +
|
||||
"SELECT " +
|
||||
"(SELECT lastName FROM itemCreators IC NATURAL JOIN creators " +
|
||||
"LEFT JOIN itemTypeCreatorTypes ITCT " +
|
||||
"ON (IC.creatorTypeID=ITCT.creatorTypeID AND ITCT.itemTypeID=O.itemTypeID) " +
|
||||
"WHERE itemID=O.itemID AND primaryField=1 ORDER BY orderIndex LIMIT 1)" +
|
||||
" || ' " + localizedAnd + " ' || " +
|
||||
"(SELECT lastName FROM itemCreators IC NATURAL JOIN creators " +
|
||||
"LEFT JOIN itemTypeCreatorTypes ITCT " +
|
||||
"ON (IC.creatorTypeID=ITCT.creatorTypeID AND ITCT.itemTypeID=O.itemTypeID) " +
|
||||
"WHERE itemID=O.itemID AND primaryField=1 ORDER BY orderIndex LIMIT 1,1)" +
|
||||
"SELECT PRINTF(" +
|
||||
`'${localizedAnd}'` +
|
||||
", " +
|
||||
// \u2068 FIRST STRONG ISOLATE: Isolates the directionality of characters that follow
|
||||
// \u2069 POP DIRECTIONAL ISOLATE: Pops the above isolation
|
||||
"(SELECT '\u2068' || lastName || '\u2069' FROM itemCreators IC NATURAL JOIN creators " +
|
||||
"LEFT JOIN itemTypeCreatorTypes ITCT " +
|
||||
"ON (IC.creatorTypeID=ITCT.creatorTypeID AND ITCT.itemTypeID=O.itemTypeID) " +
|
||||
"WHERE itemID=O.itemID AND primaryField=1 ORDER BY orderIndex LIMIT 1)" +
|
||||
", " +
|
||||
"(SELECT '\u2068' || lastName || '\u2069' FROM itemCreators IC NATURAL JOIN creators " +
|
||||
"LEFT JOIN itemTypeCreatorTypes ITCT " +
|
||||
"ON (IC.creatorTypeID=ITCT.creatorTypeID AND ITCT.itemTypeID=O.itemTypeID) " +
|
||||
"WHERE itemID=O.itemID AND primaryField=1 ORDER BY orderIndex LIMIT 1,1)" +
|
||||
")" +
|
||||
") " +
|
||||
"ELSE (" +
|
||||
"SELECT " +
|
||||
|
@ -1836,14 +1843,17 @@ Zotero.Items = function() {
|
|||
`WHERE itemID=O.itemID AND creatorTypeID=${editorCreatorTypeID}` +
|
||||
") " +
|
||||
"WHEN 2 THEN (" +
|
||||
"SELECT " +
|
||||
"(SELECT lastName FROM itemCreators NATURAL JOIN creators " +
|
||||
`WHERE itemID=O.itemID AND creatorTypeID=${editorCreatorTypeID} ` +
|
||||
"ORDER BY orderIndex LIMIT 1)" +
|
||||
" || ' " + localizedAnd + " ' || " +
|
||||
"(SELECT lastName FROM itemCreators NATURAL JOIN creators " +
|
||||
`WHERE itemID=O.itemID AND creatorTypeID=${editorCreatorTypeID} ` +
|
||||
"ORDER BY orderIndex LIMIT 1,1) " +
|
||||
"SELECT PRINTF(" +
|
||||
`'${localizedAnd}'` +
|
||||
", " +
|
||||
"(SELECT '\u2068' || lastName || '\u2069' FROM itemCreators NATURAL JOIN creators " +
|
||||
`WHERE itemID=O.itemID AND creatorTypeID=${editorCreatorTypeID} ` +
|
||||
"ORDER BY orderIndex LIMIT 1)" +
|
||||
", " +
|
||||
"(SELECT '\u2068' || lastName || '\u2069' FROM itemCreators NATURAL JOIN creators " +
|
||||
`WHERE itemID=O.itemID AND creatorTypeID=${editorCreatorTypeID} ` +
|
||||
"ORDER BY orderIndex LIMIT 1,1) " +
|
||||
")" +
|
||||
") " +
|
||||
"ELSE (" +
|
||||
"SELECT " +
|
||||
|
@ -1865,14 +1875,17 @@ Zotero.Items = function() {
|
|||
`WHERE itemID=O.itemID AND creatorTypeID=${contributorCreatorTypeID}` +
|
||||
") " +
|
||||
"WHEN 2 THEN (" +
|
||||
"SELECT " +
|
||||
"(SELECT lastName FROM itemCreators NATURAL JOIN creators " +
|
||||
`WHERE itemID=O.itemID AND creatorTypeID=${contributorCreatorTypeID} ` +
|
||||
"ORDER BY orderIndex LIMIT 1)" +
|
||||
" || ' " + localizedAnd + " ' || " +
|
||||
"(SELECT lastName FROM itemCreators NATURAL JOIN creators " +
|
||||
`WHERE itemID=O.itemID AND creatorTypeID=${contributorCreatorTypeID} ` +
|
||||
"ORDER BY orderIndex LIMIT 1,1) " +
|
||||
"SELECT PRINTF(" +
|
||||
`'${localizedAnd}'` +
|
||||
", " +
|
||||
"(SELECT '\u2068' || lastName || '\u2069' FROM itemCreators NATURAL JOIN creators " +
|
||||
`WHERE itemID=O.itemID AND creatorTypeID=${contributorCreatorTypeID} ` +
|
||||
"ORDER BY orderIndex LIMIT 1)" +
|
||||
", " +
|
||||
"(SELECT '\u2068' || lastName || '\u2069' FROM itemCreators NATURAL JOIN creators " +
|
||||
`WHERE itemID=O.itemID AND creatorTypeID=${contributorCreatorTypeID} ` +
|
||||
"ORDER BY orderIndex LIMIT 1,1) " +
|
||||
")" +
|
||||
") " +
|
||||
"ELSE (" +
|
||||
"SELECT " +
|
||||
|
|
|
@ -1628,7 +1628,9 @@ class EditorInstanceUtilities {
|
|||
else if (authors.length === 2) {
|
||||
let a = authors[0].family || authors[0].literal;
|
||||
let b = authors[1].family || authors[1].literal;
|
||||
str = a + ' ' + Zotero.getString('general.and') + ' ' + b;
|
||||
// \u2068 FIRST STRONG ISOLATE: Isolates the directionality of characters that follow
|
||||
// \u2069 POP DIRECTIONAL ISOLATE: Pops the above isolation
|
||||
str = Zotero.getString('general.andJoiner', [`\u2068${a}\u2069`, `\u2068${b}\u2069`]);
|
||||
}
|
||||
else if (authors.length >= 3) {
|
||||
str = (authors[0].family || authors[0].literal) + ' ' + Zotero.getString('general.etAl');
|
||||
|
|
|
@ -2775,6 +2775,11 @@ var ZoteroPane = new function()
|
|||
|
||||
return this.itemsView.getSortDirection();
|
||||
}
|
||||
|
||||
|
||||
function openPopup(popup, clientX, clientY) {
|
||||
popup.openPopupAtScreen(clientX + 1, clientY + 1, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -2782,9 +2787,9 @@ var ZoteroPane = new function()
|
|||
*/
|
||||
this.onCollectionsContextMenuOpen = async function (event, x, y) {
|
||||
await ZoteroPane.buildCollectionContextMenu();
|
||||
x = x || event.screenX;
|
||||
y = y || event.screenY;
|
||||
document.getElementById('zotero-collectionmenu').openPopupAtScreen(x + 1, y + 1, true);
|
||||
x = x || event.clientX;
|
||||
y = y || event.clientY;
|
||||
openPopup(document.getElementById('zotero-collectionmenu'), x, y);
|
||||
};
|
||||
|
||||
|
||||
|
@ -2793,9 +2798,9 @@ var ZoteroPane = new function()
|
|||
*/
|
||||
this.onItemsContextMenuOpen = async function (event, x, y) {
|
||||
await ZoteroPane.buildItemContextMenu();
|
||||
x = x || event.screenX;
|
||||
y = y || event.screenY;
|
||||
document.getElementById('zotero-itemmenu').openPopupAtScreen(x + 1, y + 1, true);
|
||||
x = x || event.clientX;
|
||||
y = y || event.clientY;
|
||||
openPopup(document.getElementById('zotero-itemmenu'), x, y);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ general.notNow = Not Now
|
|||
general.passed = Passed
|
||||
general.failed = Failed
|
||||
general.and = and
|
||||
general.andJoiner = %S and %S
|
||||
general.etAl = et al.
|
||||
general.accessDenied = Access Denied
|
||||
general.permissionDenied = Permission Denied
|
||||
|
@ -116,6 +117,7 @@ punctuation.closingQMark = ”
|
|||
punctuation.colon = :
|
||||
punctuation.colon.withString = %S:
|
||||
punctuation.ellipsis = …
|
||||
punctuation.comma = ,
|
||||
|
||||
install.quickStartGuide = Zotero Quick Start Guide
|
||||
install.quickStartGuide.message.welcome = Welcome to Zotero!
|
||||
|
|
|
@ -207,12 +207,12 @@
|
|||
}
|
||||
|
||||
#zotero-collections-toolbar {
|
||||
margin-right: 10px; /* Set to width of splitter for visual aesthetics */
|
||||
padding-left: 2px;
|
||||
margin-inline-end: 10px; /* Set to width of splitter for visual aesthetics */
|
||||
padding-inline-start: 2px;
|
||||
}
|
||||
|
||||
#zotero-items-toolbar {
|
||||
margin-right: 10px;
|
||||
margin-inline-end: 10px;
|
||||
}
|
||||
|
||||
.zotero-tb-button {
|
||||
|
@ -223,18 +223,18 @@
|
|||
}
|
||||
|
||||
.zotero-tb-button:first-child {
|
||||
margin-left: 0 !important;
|
||||
margin-inline-start: 0 !important;
|
||||
}
|
||||
|
||||
.zotero-tb-button:last-child {
|
||||
margin-right: 0 !important;
|
||||
margin-inline-end: 0 !important;
|
||||
}
|
||||
|
||||
.zotero-tb-button[type="menu"] {
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
margin-left: 4px;
|
||||
margin-right: 2px;
|
||||
padding-inline-start: 3px;
|
||||
padding-inline-end: 3px;
|
||||
margin-inline-start: 4px;
|
||||
margin-inline-end: 2px;
|
||||
}
|
||||
|
||||
.zotero-tb-button:hover:active {
|
||||
|
@ -480,7 +480,7 @@
|
|||
#zotero-tb-sync-stop
|
||||
{
|
||||
list-style-image: url(chrome://zotero/skin/control_stop_blue.png);
|
||||
margin-right: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
#zotero-tb-sync-progress
|
||||
|
@ -488,7 +488,7 @@
|
|||
min-width: 50px;
|
||||
width: 50px;
|
||||
height: 10px;
|
||||
margin-left: 0;
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
#zotero-tb-sync-progress-tooltip-progress {
|
||||
|
@ -532,7 +532,7 @@
|
|||
|
||||
/* Sync error panel */
|
||||
#zotero-sync-error-panel, #zotero-sync-reminder-panel {
|
||||
margin-right: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
#zotero-sync-error-panel .error-header, #zotero-sync-reminder-panel .header {
|
||||
|
@ -561,9 +561,9 @@
|
|||
|
||||
#zotero-tb-sync {
|
||||
list-style-image: url(chrome://zotero/skin/arrow_rotate_static.png);
|
||||
margin-left: -6px;
|
||||
margin-right: -2px;
|
||||
padding-right: 6px;
|
||||
margin-inline-start: -6px;
|
||||
margin-inline-end: -2px;
|
||||
padding-inline-end: 6px;
|
||||
}
|
||||
|
||||
#zotero-tb-sync .toolbarbutton-icon {
|
||||
|
@ -606,7 +606,7 @@
|
|||
}
|
||||
|
||||
.zotero-box {
|
||||
margin-left: 5px;
|
||||
margin-inline-start: 5px;
|
||||
}
|
||||
|
||||
.zotero-box-icon {
|
||||
|
@ -615,7 +615,7 @@
|
|||
}
|
||||
|
||||
.zotero-box-label {
|
||||
margin-left: 3px !important;
|
||||
margin-inline-start: 3px !important;
|
||||
}
|
||||
|
||||
#item-box-container {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#prefs-search-container {
|
||||
height: 40px;
|
||||
padding-right: 8px;
|
||||
padding-inline-end: 8px;
|
||||
}
|
||||
|
||||
#prefs-search {
|
||||
|
@ -113,8 +113,7 @@ groupbox > label > h2, groupbox > * > label > h2 {
|
|||
width: 0;
|
||||
height: 0;
|
||||
left: calc(50% - 3px);
|
||||
border-right: 6px solid transparent;
|
||||
border-left: 6px solid transparent;
|
||||
border-inline: 6px solid transparent;
|
||||
}
|
||||
|
||||
.search-tooltip::before {
|
||||
|
@ -199,11 +198,11 @@ description label[class=zotero-text-link], label[class=zotero-text-link]
|
|||
|
||||
/* General pane */
|
||||
#zotero-prefpane-general .statusLine {
|
||||
margin-left: .75em;
|
||||
margin-inline-start: .75em;
|
||||
}
|
||||
|
||||
.indented-pref {
|
||||
margin-left: 2em;
|
||||
margin-inline-start: 2em;
|
||||
}
|
||||
|
||||
.fileHandler-menu .menulist-icon {
|
||||
|
@ -230,28 +229,26 @@ description label[class=zotero-text-link], label[class=zotero-text-link]
|
|||
|
||||
#zotero-prefpane-sync .form-grid > hbox
|
||||
{
|
||||
margin-left: 4px;
|
||||
margin-inline-start: 4px;
|
||||
}
|
||||
|
||||
#zotero-prefpane-sync .form-grid > hbox label:first-child,
|
||||
#zotero-prefpane-sync .form-grid > hbox menulist:first-child
|
||||
{
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-inline: 0;
|
||||
}
|
||||
#zotero-prefpane-sync .form-grid > hbox textbox
|
||||
{
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
margin-inline: 3px;
|
||||
}
|
||||
#zotero-prefpane-sync .form-grid > hbox label:last-child
|
||||
{
|
||||
margin-left: 0;
|
||||
margin-right: 10px;
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 10px;
|
||||
}
|
||||
|
||||
#zotero-prefpane-sync #sync-auth-button {
|
||||
margin-left: 0;
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
#zotero-prefpane-sync #sync-status-indicator
|
||||
|
@ -280,34 +277,34 @@ description label[class=zotero-text-link], label[class=zotero-text-link]
|
|||
|
||||
.storage-settings-download-options
|
||||
{
|
||||
margin-left: 40px;
|
||||
margin-inline-start: 40px;
|
||||
}
|
||||
|
||||
#storage-verify, #storage-abort, #storage-clean
|
||||
{
|
||||
margin-left: 0;
|
||||
margin-inline-start: 0;
|
||||
min-width: 8em;
|
||||
}
|
||||
|
||||
#storage-terms label
|
||||
{
|
||||
margin-left: 0;
|
||||
margin-inline-start: 0;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
#storage-terms label:first-child
|
||||
{
|
||||
margin-right: .25em;
|
||||
margin-inline-end: .25em;
|
||||
}
|
||||
|
||||
#storage-terms label[class=zotero-text-link]
|
||||
{
|
||||
margin-right: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
/* Reset tab */
|
||||
#sync-reset-form {
|
||||
margin-left: 1em;
|
||||
margin-inline-start: 1em;
|
||||
}
|
||||
|
||||
#reset-sync-warning {
|
||||
|
@ -325,7 +322,7 @@ description label[class=zotero-text-link], label[class=zotero-text-link]
|
|||
|
||||
#sync-reset-library-menu {
|
||||
width: 14em;
|
||||
margin-left: .25em;
|
||||
margin-inline-start: .25em;
|
||||
font-size: 15px;
|
||||
height: 1.6em;
|
||||
}
|
||||
|
@ -365,7 +362,7 @@ description label[class=zotero-text-link], label[class=zotero-text-link]
|
|||
}
|
||||
|
||||
#sync-reset-radiogroup > div radio .radio-check {
|
||||
margin-right: 1.05em;
|
||||
margin-inline-end: 1.05em;
|
||||
}
|
||||
|
||||
#sync-reset-radiogroup > div[disabled] span {
|
||||
|
@ -446,7 +443,7 @@ description label[class=zotero-text-link], label[class=zotero-text-link]
|
|||
/* Shortcut Keys pane */
|
||||
#zotero-prefpane-advanced-keys-tab input
|
||||
{
|
||||
margin-left: -1px;
|
||||
margin-inline-start: -1px;
|
||||
}
|
||||
|
||||
/* Advanced pane */
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
.zotero-clicky-minus, .zotero-clicky-plus {
|
||||
color: transparent !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 5px 0 0 !important;
|
||||
margin: 0 !important;
|
||||
margin-inline-end: 5px !important;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
|
|
@ -40,9 +40,10 @@ td > input {
|
|||
th > label {
|
||||
margin-top: 1px !important;
|
||||
margin-bottom: 1px !important;
|
||||
-moz-margin-start: 1px !important;
|
||||
-moz-margin-end: 5px !important;
|
||||
padding: 0 2px 0 2px;
|
||||
-moz-box-pack: start;
|
||||
margin-inline-start: 1px !important;
|
||||
margin-inline-end: 5px !important;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
td > [fieldname] {
|
||||
|
@ -74,6 +75,7 @@ td > [fieldname] {
|
|||
min-height: 1.5em !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
margin-inline-end: 5px !important;
|
||||
max-height: 1.5em !important;
|
||||
flex: 1;
|
||||
|
||||
|
@ -122,8 +124,8 @@ th {
|
|||
align-self: stretch;
|
||||
font-weight: normal;
|
||||
text-align: right;
|
||||
margin-left: 5px !important;
|
||||
margin-right: 2px !important;
|
||||
margin-inline-start: 5px !important;
|
||||
margin-inline-end: 2px !important;
|
||||
}
|
||||
|
||||
#more-creators-label
|
||||
|
@ -149,7 +151,7 @@ row label
|
|||
|
||||
.creator-type-label, .creator-type-value {
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: end;
|
||||
-moz-box-pack: right;
|
||||
}
|
||||
|
||||
.creator-name-box {
|
||||
|
@ -171,8 +173,9 @@ row label
|
|||
|
||||
.creator-type-label > label
|
||||
{
|
||||
margin: 1px 4px 1px 0 !important;
|
||||
padding-right: 2px !important;
|
||||
margin: 1px 0 !important;
|
||||
margin-inline-end: 4px !important;
|
||||
padding-inline-end: 2px !important;
|
||||
}
|
||||
|
||||
.creator-type-dropmarker {
|
||||
|
@ -185,17 +188,21 @@ row label
|
|||
}
|
||||
|
||||
.creator-name-box, .date-box > span {
|
||||
margin: 1px 0 1px 0;
|
||||
margin: 1px 0 !important;
|
||||
margin-inline-start: 1px !important;
|
||||
}
|
||||
|
||||
.comma {
|
||||
margin: 1px 3px 1px 0 !important;
|
||||
margin: 1px 0 !important;
|
||||
margin-inline-end: 3px !important;
|
||||
}
|
||||
|
||||
#zotero-date-field-status
|
||||
{
|
||||
color: #666;
|
||||
padding: 0 10px 0 1px !important;
|
||||
padding: 0 !important;
|
||||
padding-inline-start: 1px !important;
|
||||
padding-inline-end: 10px !important;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
@ -205,7 +212,8 @@ row label
|
|||
max-width: 27px !important;
|
||||
min-width: 27px !important;
|
||||
height: 14px;
|
||||
margin: 0 5px 0 0 !important;
|
||||
margin: 0 !important;
|
||||
margin-inline-end: 5px !important;
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: center !important;
|
||||
border-width: 0 !important;
|
||||
|
|
|
@ -144,7 +144,15 @@
|
|||
|
||||
.tab-close {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
|
||||
&:dir(ltr) {
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
&:dir(rtl) {
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
top: 6px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
cursor: default;
|
||||
white-space: nowrap;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.primary {
|
||||
|
@ -56,7 +55,7 @@
|
|||
}
|
||||
|
||||
.cell-text {
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
margin-inline-start: 5px;
|
||||
|
@ -64,6 +63,23 @@
|
|||
|
||||
.twisty + .cell-text, .spacer-twisty + .cell-text {
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
// Put the margin on the other side if the directionality of the
|
||||
// .cell-text is the opposite of that of the table
|
||||
&:dir(ltr) .cell-text:dir(rtl),
|
||||
&:dir(rtl) .cell-text:dir(ltr) {
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 6px;
|
||||
}
|
||||
|
||||
&:dir(ltr) .cell-text {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&:dir(rtl) .cell-text {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
input {
|
||||
padding: 1px 2px 1px 1px;
|
||||
margin: -1px 0 -1px 0;
|
||||
input
|
||||
{
|
||||
padding: 1px 0;
|
||||
padding-inline-start: 1px;
|
||||
padding-inline-end: 2px;
|
||||
margin: -1px 0;
|
||||
}
|
|
@ -24,8 +24,11 @@ th > label, .creator-type-label, #more-creators-label {
|
|||
max-height: 7px;
|
||||
}
|
||||
|
||||
td > input, .creator-name-box > input {
|
||||
margin: -1px 5px -2.5px 0;
|
||||
td > input {
|
||||
margin-top: -1px;
|
||||
margin-bottom: -2.5px;
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 5px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
background-image: linear-gradient(#ddd, #ddd);
|
||||
background-size: 1px 80%;
|
||||
background-position: left;
|
||||
&:dir(rtl) {
|
||||
background-position: right;
|
||||
}
|
||||
background-repeat: no-repeat;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ row > vbox
|
|||
|
||||
row vbox[fieldname]
|
||||
{
|
||||
margin-left: 1px;
|
||||
margin-inline-start: 1px;
|
||||
}
|
||||
|
||||
.creator-type-label image {
|
||||
|
@ -17,12 +17,16 @@ row vbox[fieldname]
|
|||
}
|
||||
|
||||
input {
|
||||
padding: 2px 2px 2px 2px;
|
||||
margin: -1px 0 -1px 1px;
|
||||
padding: 2px;
|
||||
margin: -1px 0;
|
||||
margin-inline-start: 1px;
|
||||
}
|
||||
|
||||
#item-type-menu
|
||||
{
|
||||
padding: 0 0 0 1px !important;
|
||||
margin: 0 5px 0 1px !important;
|
||||
padding: 0 !important;
|
||||
padding-inline-start: 1px !important;
|
||||
margin: 0 !important;
|
||||
margin-inline-start: 1px !important;
|
||||
margin-inline-end: 5px !important;
|
||||
}
|
|
@ -1116,7 +1116,7 @@ describe("Zotero.Items", function () {
|
|||
}
|
||||
]
|
||||
),
|
||||
'B ' + Zotero.getString('general.and') + ' D',
|
||||
Zotero.getString('general.andJoiner', ['B', 'D']),
|
||||
creatorType
|
||||
);
|
||||
}
|
||||
|
@ -1186,7 +1186,7 @@ describe("Zotero.Items", function () {
|
|||
}
|
||||
]
|
||||
),
|
||||
'D ' + Zotero.getString('general.and') + ' H',
|
||||
Zotero.getString('general.andJoiner', ['D', 'H']),
|
||||
creatorType
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue