33de40ad95
Might fix (or break) other stuff, but who remembers?
468 lines
No EOL
13 KiB
XML
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> |