551 lines
16 KiB
XML
551 lines
16 KiB
XML
<?xml version="1.0"?>
|
|
<!--
|
|
***** BEGIN LICENSE BLOCK *****
|
|
|
|
Copyright © 2009 Center for History and New Media
|
|
George Mason University, Fairfax, Virginia, USA
|
|
http://zotero.org
|
|
|
|
This file is part of Zotero.
|
|
|
|
Zotero is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Zotero is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***** END LICENSE BLOCK *****
|
|
-->
|
|
|
|
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
|
<!-- <!DOCTYPE bindings SYSTEM "chrome://zotero/locale/attachmentbox.dtd"> -->
|
|
|
|
<bindings xmlns="http://www.mozilla.org/xbl"
|
|
xmlns:xbl="http://www.mozilla.org/xbl"
|
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
|
|
<binding id="attachment-box">
|
|
<resources>
|
|
<stylesheet src="chrome://zotero/skin/bindings/attachmentbox.css"/>
|
|
<stylesheet src="chrome://zotero-platform/content/attachmentbox.css"/>
|
|
</resources>
|
|
|
|
<implementation>
|
|
<!--
|
|
Public properties
|
|
-->
|
|
<field name="editable">false</field>
|
|
<field name="clickableLink">false</field>
|
|
<field name="displayButton">false</field>
|
|
<field name="displayNote">false</field>
|
|
|
|
<field name="buttonCaption"/>
|
|
<field name="clickHandler"/>
|
|
|
|
<!-- Modes are predefined settings groups for particular tasks -->
|
|
<field name="_mode">"view"</field>
|
|
<property name="mode" onget="return this._mode;">
|
|
<setter>
|
|
<![CDATA[
|
|
Zotero.debug("Setting mode to '" + val + "'");
|
|
|
|
this.editable = false;
|
|
this.displayURL = false;
|
|
this.displayFileName = false;
|
|
this.clickableLink = false;
|
|
this.displayAccessed = false;
|
|
this.displayPages = false;
|
|
this.displayDateModified = false;
|
|
this.displayIndexed = false;
|
|
this.displayNote = false;
|
|
this.displayNoteIfEmpty = false;
|
|
|
|
switch (val) {
|
|
case 'view':
|
|
this.displayURL = true;
|
|
this.displayFileName = true;
|
|
this.clickableLink = true;
|
|
this.displayAccessed = true;
|
|
this.displayPages = true;
|
|
this.displayIndexed = true;
|
|
this.displayNote = true;
|
|
this.displayDateModified = true;
|
|
break;
|
|
|
|
case 'edit':
|
|
this.editable = true;
|
|
this.displayURL = true;
|
|
this.displayFileName = true;
|
|
this.clickableLink = true;
|
|
this.displayAccessed = true;
|
|
this.displayPages = true;
|
|
this.displayIndexed = true;
|
|
this.displayNote = true;
|
|
this.displayNoteIfEmpty = true;
|
|
this.displayDateModified = true;
|
|
break;
|
|
|
|
case 'merge':
|
|
this.displayURL = true;
|
|
this.displayFileName = true;
|
|
this.displayAccessed = true;
|
|
this.displayNote = true;
|
|
this.displayButton = true;
|
|
this.displayDateModified = true;
|
|
break;
|
|
|
|
case 'mergeedit':
|
|
this.editable = true;
|
|
this.displayURL = true;
|
|
this.displayFileName = true;
|
|
this.displayAccessed = true;
|
|
this.displayNote = true;
|
|
// Notes aren't currently editable in mergeedit pane
|
|
this.displayNoteIfEmpty = false;
|
|
this.displayDateModified = true;
|
|
break;
|
|
|
|
default:
|
|
throw ("Invalid mode '" + val + "' in attachmentbox.xml");
|
|
}
|
|
|
|
this._mode = val;
|
|
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
|
]]>
|
|
</setter>
|
|
</property>
|
|
|
|
<field name="_item"/>
|
|
<property name="item"
|
|
onget="return this._item;"
|
|
onset="this._item = val; this.refresh();">
|
|
</property>
|
|
|
|
<!-- .ref is an alias for .item -->
|
|
<property name="ref"
|
|
onget="return this._item;"
|
|
onset="this._item = val; this.refresh();">
|
|
</property>
|
|
|
|
|
|
<!-- Private properties -->
|
|
|
|
<method name="refresh">
|
|
<body>
|
|
<![CDATA[
|
|
Zotero.debug('Refreshing attachment box');
|
|
|
|
var attachmentBox = document.getAnonymousNodes(this)[0];
|
|
var title = this._id('title');
|
|
var fileNameRow = this._id('fileNameRow');
|
|
var urlField = this._id('url');
|
|
var accessed = this._id('accessedRow');
|
|
var pagesRow = this._id('pagesRow');
|
|
var dateModifiedRow = this._id('dateModifiedRow');
|
|
var indexStatusRow = this._id('indexStatusRow');
|
|
var selectButton = this._id('select-button');
|
|
|
|
// DEBUG: this is annoying -- we really want to use an abstracted
|
|
// version of createValueElement() from itemPane.js
|
|
// (ideally in an XBL binding)
|
|
|
|
// Wrap title to multiple lines if necessary
|
|
while (title.hasChildNodes()) {
|
|
title.removeChild(title.firstChild);
|
|
}
|
|
var val = this.item.getField('title');
|
|
|
|
if (typeof val != 'string') {
|
|
val += "";
|
|
}
|
|
|
|
var firstSpace = val.indexOf(" ");
|
|
// Crop long uninterrupted text
|
|
if ((firstSpace == -1 && val.length > 29 ) || firstSpace > 29) {
|
|
title.setAttribute('crop', 'end');
|
|
title.setAttribute('value', val);
|
|
}
|
|
// Create a <description> element, essentially
|
|
else {
|
|
title.removeAttribute('value');
|
|
title.appendChild(document.createTextNode(val));
|
|
}
|
|
|
|
if (this.editable) {
|
|
title.className = 'zotero-clicky';
|
|
|
|
// For the time being, use a silly little popup
|
|
title.addEventListener('click', this.editTitle, false);
|
|
}
|
|
|
|
var isImportedURL = this.item.attachmentLinkMode ==
|
|
Zotero.Attachments.LINK_MODE_IMPORTED_URL;
|
|
|
|
// Metadata for URL's
|
|
if (this.item.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_URL
|
|
|| isImportedURL) {
|
|
|
|
// URL
|
|
if (this.displayURL) {
|
|
var urlSpec = this.item.getField('url');
|
|
urlField.setAttribute('value', urlSpec);
|
|
urlField.setAttribute('hidden', false);
|
|
if (this.clickableLink) {
|
|
urlField.onclick = function (event) {
|
|
ZoteroPane_Local.loadURI(this.value, event)
|
|
};
|
|
urlField.className = 'text-link';
|
|
}
|
|
else {
|
|
urlField.className = '';
|
|
}
|
|
urlField.hidden = false;
|
|
}
|
|
else {
|
|
urlField.hidden = true;
|
|
}
|
|
|
|
// Access date
|
|
if (this.displayAccessed) {
|
|
this._id("accessed-label").value = Zotero.getString('itemFields.accessDate')+":";
|
|
this._id("accessed").value = Zotero.Date.sqlToDate(
|
|
this.item.getField('accessDate'), true
|
|
).toLocaleString();
|
|
accessed.hidden = false;
|
|
}
|
|
else {
|
|
accessed.hidden = true;
|
|
}
|
|
}
|
|
// Metadata for files
|
|
else {
|
|
urlField.hidden = true;
|
|
accessed.hidden = true;
|
|
}
|
|
|
|
if (this.item.attachmentLinkMode
|
|
!= Zotero.Attachments.LINK_MODE_LINKED_URL
|
|
&& this.displayFileName) {
|
|
// TODO: localize
|
|
var fileName = this.item.getFilename();
|
|
|
|
if (fileName) {
|
|
// TODO: localize
|
|
this._id("fileName-label").value = "Filename:";
|
|
this._id("fileName").value = fileName;
|
|
fileNameRow.hidden = false;
|
|
}
|
|
else {
|
|
fileNameRow.hidden = true;
|
|
}
|
|
}
|
|
else {
|
|
fileNameRow.hidden = true;
|
|
}
|
|
|
|
// Page count
|
|
if (this.displayPages) {
|
|
var pages = Zotero.Fulltext.getPages(this.item.id);
|
|
var pages = pages ? pages.total : null;
|
|
if (pages) {
|
|
// TODO: localize colon
|
|
this._id("pages-label").value = Zotero.getString('itemFields.pages') + ':';
|
|
this._id("pages").value = pages;
|
|
pagesRow.hidden = false;
|
|
}
|
|
else {
|
|
pagesRow.hidden = true;
|
|
}
|
|
}
|
|
else {
|
|
pagesRow.hidden = true;
|
|
}
|
|
|
|
if (this.displayDateModified) {
|
|
this._id("dateModified-label").value = Zotero.getString('itemFields.dateModified')+':';
|
|
var mtime = this.item.attachmentModificationTime;
|
|
if (mtime) {
|
|
this._id("dateModified").value = new Date(mtime).toLocaleString();
|
|
}
|
|
// Use the item's mod time as a backup (e.g., when sync
|
|
// passes in the mod time for the nonexistent remote file)
|
|
else {
|
|
this._id("dateModified").value = Zotero.Date.sqlToDate(
|
|
this.item.getField('dateModified'), true
|
|
).toLocaleString();
|
|
}
|
|
dateModifiedRow.hidden = false;
|
|
}
|
|
else {
|
|
dateModifiedRow.hidden = true;
|
|
}
|
|
|
|
// Full-text index information
|
|
if (this.displayIndexed) {
|
|
this.updateItemIndexedState();
|
|
indexStatusRow.hidden = false;
|
|
}
|
|
else {
|
|
indexStatusRow.hidden = true;
|
|
}
|
|
|
|
// Note editor
|
|
var noteEditor = this._id('note-editor');
|
|
if (this.displayNote) {
|
|
if (this.displayNoteIfEmpty || this.item.getNote() != '') {
|
|
Zotero.debug("setting links on top");
|
|
noteEditor.linksOnTop = true;
|
|
noteEditor.hidden = false;
|
|
|
|
// Don't make note editable (at least for now)
|
|
if (this.mode == 'merge' || this.mode == 'mergeedit') {
|
|
noteEditor.mode = 'merge';
|
|
noteEditor.displayButton = false;
|
|
}
|
|
else {
|
|
noteEditor.mode = this.mode;
|
|
}
|
|
noteEditor.parent = null;
|
|
noteEditor.item = this.item;
|
|
}
|
|
}
|
|
else {
|
|
noteEditor.hidden = true;
|
|
}
|
|
|
|
|
|
if (this.displayButton) {
|
|
selectButton.label = this.buttonCaption;
|
|
selectButton.hidden = false;
|
|
selectButton.setAttribute('oncommand',
|
|
'document.getBindingParent(this).clickHandler(this)');
|
|
}
|
|
else {
|
|
selectButton.hidden = true;
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="editTitle">
|
|
<body>
|
|
<![CDATA[
|
|
var item = document.getBindingParent(this).item;
|
|
var oldTitle = item.getField('title');
|
|
|
|
var nsIPS = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
.getService(Components.interfaces.nsIPromptService);
|
|
|
|
var newTitle = { value: oldTitle };
|
|
var checkState = { value: Zotero.Prefs.get('lastRenameAssociatedFile') };
|
|
|
|
while (true) {
|
|
// Don't show "Rename associated file" option for
|
|
// linked URLs
|
|
if (item.attachmentLinkMode ==
|
|
Zotero.Attachments.LINK_MODE_LINKED_URL) {
|
|
var result = nsIPS.prompt(
|
|
window,
|
|
'',
|
|
Zotero.getString('pane.item.attachments.rename.title'),
|
|
newTitle,
|
|
null,
|
|
{}
|
|
);
|
|
|
|
// If they hit cancel or left it blank
|
|
if (!result || !newTitle.value) {
|
|
return;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
var result = nsIPS.prompt(
|
|
window,
|
|
'',
|
|
Zotero.getString('pane.item.attachments.rename.title'),
|
|
newTitle,
|
|
Zotero.getString('pane.item.attachments.rename.renameAssociatedFile'),
|
|
checkState
|
|
);
|
|
|
|
// If they hit cancel or left it blank
|
|
if (!result || !newTitle.value) {
|
|
return;
|
|
}
|
|
|
|
Zotero.Prefs.set('lastRenameAssociatedFile', checkState.value);
|
|
|
|
// Rename associated file
|
|
if (checkState.value) {
|
|
var renamed = item.renameAttachmentFile(newTitle.value);
|
|
if (renamed == -1) {
|
|
var confirmed = nsIPS.confirm(
|
|
window,
|
|
'',
|
|
newTitle.value + ' exists. Overwrite existing file?'
|
|
);
|
|
if (confirmed) {
|
|
item.renameAttachmentFile(newTitle.value, true);
|
|
break;
|
|
}
|
|
// If they said not to overwrite existing file,
|
|
// start again
|
|
continue;
|
|
}
|
|
else if (renamed == -2) {
|
|
nsIPS.alert(
|
|
window,
|
|
Zotero.getString('general.error'),
|
|
Zotero.getString('pane.item.attachments.rename.error')
|
|
);
|
|
return;
|
|
}
|
|
else if (!renamed) {
|
|
nsIPS.alert(
|
|
window,
|
|
Zotero.getString('pane.item.attachments.fileNotFound.title'),
|
|
Zotero.getString('pane.item.attachments.fileNotFound.text')
|
|
);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (newTitle.value != oldTitle) {
|
|
item.setField('title', newTitle.value);
|
|
item.save();
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="onViewClick">
|
|
<parameter name="event"/>
|
|
<body>
|
|
<![CDATA[
|
|
ZoteroPane_Local.viewAttachment(this.item.id, event, !this.editable);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="onShowClick">
|
|
<parameter name="event"/>
|
|
<body>
|
|
<![CDATA[
|
|
ZoteroPane_Local.showAttachmentInFilesystem(this.item.id, event.originalTarget, !this.editable);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<!--
|
|
Update Indexed: (Yes|No|Partial) line
|
|
-->
|
|
<method name="updateItemIndexedState">
|
|
<body>
|
|
<![CDATA[
|
|
var indexStatus = this._id('index-status');
|
|
var reindexButton = this._id('reindex');
|
|
|
|
var status = Zotero.Fulltext.getIndexedState(this.item.id);
|
|
var str = 'fulltext.indexState.';
|
|
switch (status) {
|
|
case Zotero.Fulltext.INDEX_STATE_UNAVAILABLE:
|
|
str += 'unavailable';
|
|
break;
|
|
case Zotero.Fulltext.INDEX_STATE_UNINDEXED:
|
|
str = 'general.no';
|
|
break;
|
|
case Zotero.Fulltext.INDEX_STATE_PARTIAL:
|
|
str += 'partial';
|
|
break;
|
|
case Zotero.Fulltext.INDEX_STATE_INDEXED:
|
|
str = 'general.yes';
|
|
break;
|
|
}
|
|
this._id("index-status-label").value = Zotero.getString('fulltext.indexState.indexed') + ':';
|
|
indexStatus.value = Zotero.getString(str);
|
|
|
|
// Reindex button tooltip (string stored in zotero.properties)
|
|
var str = Zotero.getString('pane.items.menu.reindexItem');
|
|
reindexButton.setAttribute('tooltiptext', str);
|
|
|
|
if (this.editable && Zotero.Fulltext.canReindex(this.item.id)) {
|
|
reindexButton.setAttribute('hidden', false);
|
|
}
|
|
else {
|
|
reindexButton.setAttribute('hidden', true);
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="_id">
|
|
<parameter name="id"/>
|
|
<body>
|
|
<![CDATA[
|
|
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id', id)[0];
|
|
]]>
|
|
</body>
|
|
</method>
|
|
</implementation>
|
|
|
|
<content>
|
|
<vbox id="attachment-box" flex="1" orient="vertical"
|
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
<label id="title"/>
|
|
<label id="url" crop="end"
|
|
ondragstart="var dt = event.dataTransfer; dt.setData('text/x-moz-url', this.value); dt.setData('text/uri-list', this.value); dt.setData('text/plain', this.value);"/>
|
|
<grid>
|
|
<columns>
|
|
<column/>
|
|
<column flex="1"/>
|
|
</columns>
|
|
<rows>
|
|
<row id="fileNameRow">
|
|
<label id="fileName-label"/>
|
|
<label id="fileName" crop="end"/>
|
|
</row>
|
|
<row id="accessedRow">
|
|
<label id="accessed-label"/>
|
|
<label id="accessed"/>
|
|
</row>
|
|
<row id="pagesRow">
|
|
<label id="pages-label"/>
|
|
<label id="pages"/>
|
|
</row>
|
|
<row id="dateModifiedRow">
|
|
<label id="dateModified-label"/>
|
|
<label id="dateModified"/>
|
|
</row>
|
|
<row id="indexStatusRow">
|
|
<label id="index-status-label"/>
|
|
<hbox>
|
|
<label id="index-status"/>
|
|
<toolbarbutton id="reindex" oncommand="this.hidden = true; setTimeout(function () { ZoteroPane_Local.reindexItem(); }, 50)"/>
|
|
</hbox>
|
|
</row>
|
|
</rows>
|
|
</grid>
|
|
|
|
<zoteronoteeditor id="note-editor" notitle="1" flex="1"/>
|
|
|
|
<button id="select-button" hidden="true"/>
|
|
</vbox>
|
|
</content>
|
|
</binding>
|
|
</bindings>
|