zotero/chrome/content/zotero/bindings/noteeditor.xml
Dan Stillman 33de40ad95 Adds sync support for related items
Might fix (or break) other stuff, but who remembers?
2008-06-25 00:26:55 +00:00

468 lines
No EOL
13 KiB
XML

<?xml version="1.0"?>
<!--
***** BEGIN LICENSE BLOCK *****
Copyright (c) 2006 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://chnm.gmu.edu
Licensed under the Educational Community License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.opensource.org/licenses/ecl1.php
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
***** END LICENSE BLOCK *****
-->
<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="note-editor">
<resources>
<stylesheet src="chrome://zotero/skin/bindings/noteeditor.css"/>
</resources>
<implementation>
<!--
Public properties
-->
<field name="editable">false</field>
<field name="saveOnEdit">false</field>
<field name="displayTags">false</field>
<field name="displayRelated">false</field>
<field name="displayButton">false</field>
<field name="parentClickHandler"/>
<field name="keyDownHandler"/>
<field name="commandHandler"/>
<field name="clickHandler"/>
<field name="buttonCaption"/>
<!-- Modes are predefined settings groups for particular tasks -->
<field name="_mode">"view"</field>
<property name="mode" onget="return this._mode;">
<setter>
<![CDATA[
// Duplicate default property settings here
this.editable = false;
this.saveOnEdit = false;
this.displayTags = false;
this.displayRelated = false;
this.displayButton = false;
switch (val) {
case 'view':
break;
case 'edit':
this.editable = true;
this.saveOnEdit = true;
this.parentClickHandler = this.selectParent;
this.keyDownHandler = this.handleKeyDown;
this.commandHandler = this.save;
this.displayTags = true;
this.displayRelated = true;
break;
case 'merge':
this.displayButton = true;
break;
case 'mergeedit':
this.editable = true;
this.keyDownHandler = this.handleKeyDown;
break;
default:
throw ("Invalid mode '" + val + "' in noteeditor.xml");
}
this._mode = val;
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
]]>
</setter>
</property>
<field name="_parent"/>
<property name="parent" onget="return this._parent;">
<setter>
<![CDATA[
this._parent = val;
var citeLabel = this._id('citeLabel');
if (citeLabel.firstChild) {
citeLabel.removeChild(citeLabel.firstChild);
}
if (this.parent && !this.getAttribute('notitle') == '1') {
citeLabel.appendChild(document.createTextNode(this.parent.getDisplayTitle(true)));
}
]]>
</setter>
</property>
<field name="_item"/>
<property name="item" onget="return this._item;">
<setter>
<![CDATA[
this._item = val;
var parent = this.item.getSource();
if (parent) {
this.parent = Zotero.Items.get(parent);
}
this._id('links').item = this.item;
this.refresh();
]]>
</setter>
</property>
<property name="note"
onget="Zotero.debug('Getting note with .note deprecated -- use .item in zoteronoteeditor'); return this._item"
onset="Zotero.debug('Setting note with .note deprecated -- use .item in zoteronoteeditor'); this.item = val"/>
<property name="ref" onget="return this._item" onset="this.item = val"/>
<field name="collection"/>
<property name="noteField" onget="return this._id('noteField')" readonly="true"/>
<property name="value" onget="return this._id('noteField').value;" onset="this._id('noteField').value = val;"/>
<method name="refresh">
<body>
<![CDATA[
Zotero.debug('Refreshing note editor');
var parentbox = this._id('citeLabel');
var textbox = this._id('noteField');
var button = this._id('goButton');
var button = this._id('goButton');
if (this.editable) {
textbox.removeAttribute('readonly');
}
else {
textbox.setAttribute('readonly', 'true');
}
var scrollPos = textbox.inputField.scrollTop;
if (this.item) {
textbox.value = this.item.getNote();
}
textbox.inputField.scrollTop = scrollPos;
this._id('linksbox').hidden = !(this.displayTags && this.displayRelated);
if (this.parentClickHandler) {
parentbox.setAttribute('onclick',
'document.getBindingParent(this).clickHandler(this)');
}
else {
parentbox.removeAttribute('onclick');
}
if (this.keyDownHandler) {
textbox.setAttribute('onkeydown',
'document.getBindingParent(this).handleKeyDown(event)');
}
else {
textbox.removeAttribute('onkeydown');
}
if (this.commandHandler) {
textbox.setAttribute('oncommand',
'document.getBindingParent(this).commandHandler()');
}
else {
textbox.removeAttribute('oncommand');
}
if (this.displayButton) {
button.label = this.buttonCaption;
button.hidden = false;
button.setAttribute('oncommand',
'document.getBindingParent(this).clickHandler(this)');
}
else {
button.hidden = true;
}
]]>
</body>
</method>
<method name="save">
<body>
<![CDATA[
var noteField = this._id('noteField');
// Update note
if (this.item) {
this.item.setNote(noteField.value);
if (this.saveOnEdit) {
this.item.save();
}
return;
}
// Create new note
var item = new Zotero.Item(false, 'note');
item.setNote(noteField.value);
if (this.parent) {
item.setSource(this.parent.id);
}
if (this.saveOnEdit) {
var id = item.save();
if (this.parent && this.collection) {
this.collection.addItem(id);
}
}
this.item = Zotero.Items.get(id);
]]>
</body>
</method>
<!-- Used to insert a tab manually -->
<method name="handleKeyDown">
<parameter name="event"/>
<body>
<![CDATA[
switch (event.keyCode) {
// Insert tab manually
case 9:
if (event.shiftKey || event.ctrlKey || event.altKey) {
return;
}
// From http://kb.mozillazine.org/Inserting_text_at_cursor
try {
var command = "cmd_insertText";
var controller = document.commandDispatcher.getControllerForCommand(command);
if (controller && controller.isCommandEnabled(command)) {
controller = controller.QueryInterface(Components.interfaces.nsICommandController);
var params = Components.classes["@mozilla.org/embedcomp/command-params;1"]
.createInstance(Components.interfaces.nsICommandParams);
params.setStringValue("state_data", "\t");
controller.doCommandWithParams(command, params);
}
}
catch (e) {
Zotero.debug("Can't do cmd_insertText!\n" + e, 1);
}
event.stopPropagation();
event.preventDefault();
// DEBUG: is there a better way to prevent blur()?
setTimeout(function() { event.target.focus(); }, 1);
break;
}
]]>
</body>
</method>
<method name="focus">
<body>
<![CDATA[
this._id('noteField').focus();
]]>
</body>
</method>
<method name="selectParent">
<body>
<![CDATA[
if (!this.item.id) {
return;
}
if (document.getElementById('zotero-pane')) {
var zp = ZoteroPane;
}
else {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var lastWin = wm.getMostRecentWindow("navigator:browser");
if (!lastWin) {
window.open();
var newWindow = wm.getMostRecentWindow("navigator:browser");
var b = newWindow.getBrowser();
return;
}
if (lastWin.document.getElementById('zotero-pane').getAttribute('hidden') == 'true') {
lastWin.ZoteroPane.toggleDisplay();
// DEBUG: The actions below seem to crash Firefox 2.0.0.1 on OS X if
// the Z pane isn't already open, so we don't try
return;
}
var zp = lastWin.ZoteroPane;
}
zp.clearQuicksearch();
zp.selectItem(this.item.id);
]]>
</body>
</method>
<method name="disableUndo">
<body>
<![CDATA[
this.noteField.editor.enableUndo(true);
]]>
</body>
</method>
<method name="enableUndo">
<body>
<![CDATA[
this.noteField.editor.enableUndo(false);
]]>
</body>
</method>
<method name="clearUndo">
<body>
<![CDATA[
this.disableUndo();
this.enableUndo();
]]>
</body>
</method>
<method name="_id">
<parameter name="id"/>
<body>
<![CDATA[
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
]]>
</body>
</method>
</implementation>
<content>
<xul:vbox xbl:inherits="flex">
<xul:label id="citeLabel"/>
<xul:textbox id="noteField" multiline="true" type="timed" timeout="1000" flex="1"/>
<xul:hbox id="linksbox" hidden="true">
<xul:linksbox id="links" flex="1"/>
</xul:hbox>
<xul:button id="goButton" hidden="true"/>
</xul:vbox>
</content>
</binding>
<binding id="links-box">
<implementation>
<field name="itemRef"/>
<property name="item" onget="return this.itemRef;">
<setter>
<![CDATA[
this.itemRef = val;
this.id('tags').item = this.item;
this.updateTagsSummary();
this.id('seeAlso').item = this.item;
this.updateSeeAlsoSummary();
]]>
</setter>
</property>
<method name="tagsClick">
<body>
<![CDATA[
this.id('tags').reload();
this.id('tagsPopup').showPopup(this.id('tagsLabel'),-1,-1,'popup');
]]>
</body>
</method>
<method name="updateTagsSummary">
<body>
<![CDATA[
// TODO: localize
var v = this.id('tags').summary;
if (!v || v == "") {
v = "[" + Zotero.getString('pane.item.noteEditor.clickHere') + "]";
}
this.id('tagsLabel').value = Zotero.getString('pane.item.tags') + " " + v;
]]>
</body>
</method>
<method name="seeAlsoClick">
<body>
<![CDATA[
var relatedList = this.item.relatedItemsBidirectional;
if (relatedList.length > 0) {
this.id('seeAlsoPopup').showPopup(this.id('seeAlsoLabel'),-1,-1,'popup',0,0);
}
else {
this.id('seeAlso').add();
}
]]>
</body>
</method>
<method name="updateSeeAlsoSummary">
<body>
<![CDATA[
var v = this.id('seeAlso').summary;
if (!v || v == "") {
v = "[" + Zotero.getString('pane.item.noteEditor.clickHere') + "]";
}
this.id('seeAlsoLabel').value = Zotero.getString('pane.item.related') + " " + v;
]]>
</body>
</method>
<method name="id">
<parameter name="id"/>
<body>
<![CDATA[
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id',id)[0];
]]>
</body>
</method>
</implementation>
<content>
<xul:vbox xbl:inherits="flex">
<xul:label id="seeAlsoLabel" class="zotero-clicky" crop="end" onclick="document.getBindingParent(this).seeAlsoClick();"/>
<xul:label id="tagsLabel" class="zotero-clicky" crop="end" onclick="document.getBindingParent(this).tagsClick();"/>
<xul:popupset>
<xul:popup id="seeAlsoPopup" width="300" onpopupshowing="this.firstChild.reload();">
<xul:seealsobox id="seeAlso" flex="1"/>
</xul:popup>
<!-- The onpopup* stuff is an ugly hack to keep track of when the
popup is open (and not the descendent autocomplete popup, which also
seems to get triggered by these events for reasons that are less than
clear) so that we can manually refresh the popup if it's open after
autocomplete is used to prevent it from becoming unresponsive
Note: Code in tagsbox.xml is dependent on the DOM path between the
tagsbox and tagsLabel above, so be sure to update fixPopup() if it changes
-->
<xul:popup 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.new(); } */ this.setAttribute('showing', 'true'); }"
onpopuphidden="if (!document.commandDispatcher.focusedElement || document.commandDispatcher.focusedElement.tagName=='xul:label'){ this.setAttribute('showing', 'false'); }">
<xul:tagsbox id="tags" flex="1"/>
</xul:popup>
</xul:popupset>
</xul:vbox>
</content>
</binding>
</bindings>