diff --git a/chrome/content/zotero-platform/win/overlay.css b/chrome/content/zotero-platform/win/overlay.css index 464090cbc..b90ec7c58 100644 --- a/chrome/content/zotero-platform/win/overlay.css +++ b/chrome/content/zotero-platform/win/overlay.css @@ -78,6 +78,11 @@ border-width: 0 1px 1px 0; } +/* Restore row highlighting on drag over, though I'm not sure how we're losing it to begin with. */ +#zotero-collections-tree treechildren::-moz-tree-row(dropOn) { + background-color: Highlight; +} + #zotero-items-tree { border-width: 0 1px; } diff --git a/chrome/content/zotero/xpcom/itemTreeView.js b/chrome/content/zotero/xpcom/itemTreeView.js index 23e1ac159..6b0c8de16 100644 --- a/chrome/content/zotero/xpcom/itemTreeView.js +++ b/chrome/content/zotero/xpcom/itemTreeView.js @@ -2558,7 +2558,7 @@ Zotero.ItemTreeCommandController.prototype.onEvent = function(evt) Zotero.ItemTreeView.prototype.onDragStart = function (event) { // See note in LibraryTreeView::_setDropEffect() if (Zotero.isWin) { - event.dataTransfer.effectAllowed = 'move'; + event.dataTransfer.effectAllowed = 'copy'; } var itemIDs = this.saveSelection(); @@ -2896,7 +2896,7 @@ Zotero.ItemTreeView.prototype.canDropCheck = function (row, orient, dataTransfer var itemGroup = this._itemGroup; - if (orient == 0) { + if (row != -1 && orient == 0) { var rowItem = this._getItemAtRow(row).ref; // the item we are dragging over } @@ -2904,7 +2904,7 @@ Zotero.ItemTreeView.prototype.canDropCheck = function (row, orient, dataTransfer var items = Zotero.Items.get(ids); // Directly on a row - if (orient == 0) { + if (rowItem) { var canDrop = false; for each(var item in items) { @@ -2981,7 +2981,7 @@ Zotero.ItemTreeView.prototype.canDropCheck = function (row, orient, dataTransfer } else if (dataType == "text/x-moz-url" || dataType == 'application/x-moz-file') { // Disallow direct drop on a non-regular item (e.g. note) - if (orient == 0) { + if (rowItem) { if (!rowItem.isRegularItem()) { return false; } diff --git a/chrome/content/zotero/xpcom/libraryTreeView.js b/chrome/content/zotero/xpcom/libraryTreeView.js index 0bb15fe16..701334794 100644 --- a/chrome/content/zotero/xpcom/libraryTreeView.js +++ b/chrome/content/zotero/xpcom/libraryTreeView.js @@ -197,20 +197,25 @@ Zotero.LibraryTreeView.prototype = { _setDropEffect: function (event, effect) { - // On Windows (in Fx26), Firefox uses 'move' for unmodified drags, - // and 'copy'/'link' for drags with system-default modifier keys, + // On Windows (in Fx26), Firefox uses 'move' for unmodified drags + // and 'copy'/'link' for drags with system-default modifier keys // as long as the actions are allowed by the initial effectAllowed set // in onDragStart, regardless of the effectAllowed or dropEffect set - // in onDragOver. To prevent inaccurate 'copy'/'link' cursors, we set - // effectAllowed to 'move' in onDragStart, which locks the cursor at - // 'move'. ('none' still changes the cursor, but 'copy'/'link' do not.) + // in onDragOver. It doesn't seem to be possible to use 'copy' for + // the default and 'move' for modified, as we need to in the collections + // tree. To prevent inaccurate cursor feedback, we set effectAllowed to + // 'copy' in onDragStart, which locks the cursor at 'copy'. ('none' still + // changes the cursor, but 'move'/'link' do not.) It'd be better to use + // the unadorned 'move', but we use 'copy' instead because with 'move' text + // can't be dragged to some external programs (e.g., Chrome, Notepad++), + // which seems worse than always showing 'copy' feedback. // - // However, since effectAllowed is enforced, leaving it at 'move' - // would prevent our default 'copy' from working, so we also have to - // set effectAllowed here (called from onDragOver) to the same action - // as the dropEffect. This allows the dropEffect setting (which we use - // in the tree's canDrop() and drop() to determine the desired action) - // to be changed, even if the cursor doesn't reflect the new setting. + // However, since effectAllowed is enforced, leaving it at 'copy' + // would prevent our modified 'move' in the collections tree from working, + // so we also have to set effectAllowed here (called from onDragOver) to + // the same action as the dropEffect. This allows the dropEffect setting + // (which we use in the tree's canDrop() and drop() to determine the desired + // action) to be changed, even if the cursor doesn't reflect the new setting. if (Zotero.isWin) { event.dataTransfer.effectAllowed = effect; } diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index 888cd44f8..d895ef404 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -344,6 +344,7 @@ Zotero.Translate.Sandbox = { if(!Zotero.Utilities.isEmpty(sandbox.exports)) { sandbox.exports.Zotero = sandbox.Zotero; sandbox = sandbox.exports; + if(Zotero.isFx && sandbox.wrappedJSObject) sandbox = sandbox.wrappedJSObject; } else { translate._debug("COMPAT WARNING: "+translation.translator[0].label+" does "+ "not export any properties. Only detect"+translation._entryFunctionSuffix+ diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index 4ede8e264..ffe902654 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -1494,7 +1494,8 @@ Components.utils.import("resource://gre/modules/osfile.jsm"); locale = locale.match(/^[a-z]{2}(\-[A-Z]{2})?/)[0]; var collator = new Intl.Collator(locale, { ignorePunctuation: true, - numeric: true + numeric: true, + sensitivity: 'base' }); } catch (e) { @@ -1508,10 +1509,44 @@ Components.utils.import("resource://gre/modules/osfile.jsm"); }; } + // Grab all ASCII punctuation and space at the begining of string + var initPunctuationRE = /^[\x20-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]+/; + // Punctuation that should be ignored when sorting + var ignoreInitRE = /["'[{(]+$/; + // Until old code is updated, pretend we're returning an nsICollation return this.collation = { compareString: function (_, a, b) { - return collator.compare(a, b); + if (!a && !b) return 0; + if (!a || !b) return b ? -1 : 1; + + // Compare initial punctuation + var aInitP = initPunctuationRE.exec(a) || ''; + var bInitP = initPunctuationRE.exec(b) || ''; + + var aWordStart = 0, bWordStart = 0; + if (aInitP) { + aWordStart = aInitP[0].length; + aInitP = aInitP[0].replace(ignoreInitRE, ''); + } + if (bInitP) { + bWordStart = bInitP.length; + bInitP = bInitP[0].replace(ignoreInitRE, ''); + } + + // If initial punctuation is equivalent, use collator comparison + // that ignores all punctuation + if (aInitP == bInitP || !aInitP && !bInitP) return collator.compare(a, b); + + // Otherwise consider "attached" words as well, e.g. the order should be + // "__ n", "__z", "_a" + // We don't actually care what the attached word is, just whether it's + // there, since at this point we're guaranteed to have non-equivalent + // initial punctuation + if (aWordStart < a.length) aInitP += 'a'; + if (bWordStart < b.length) bInitP += 'a'; + + return aInitP.localeCompare(bInitP); } }; }