Remove styled-textbox XBL binding
This commit is contained in:
parent
af892e5cbd
commit
071162f914
2 changed files with 0 additions and 827 deletions
|
@ -1,813 +0,0 @@
|
|||
<?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">
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<binding id="styled-textbox">
|
||||
<implementation>
|
||||
<field name="_editable"/>
|
||||
<field name="_mode"/>
|
||||
<field name="_format"/>
|
||||
<field name="_changed"/>
|
||||
<field name="_loadHandler"/>
|
||||
<field name="_commandString"/>
|
||||
<field name="_eventHandler"/>
|
||||
<field name="_editor"/>
|
||||
<field name="_value"/>
|
||||
<field name="_timer"/>
|
||||
<field name="_focus"/>
|
||||
<field name="_constructed"/>
|
||||
<field name="_loadOnConstruct"/>
|
||||
|
||||
<constructor><![CDATA[
|
||||
this.mode = this.getAttribute('mode');
|
||||
|
||||
this._iframe = document.getAnonymousElementByAttribute(this, "anonid", "rt-view");
|
||||
|
||||
// Atomic units, HTML -> RTF (cleanup)
|
||||
//[/<\/p>(?!\s*$)/g, "\\par{}"],
|
||||
//[/ /g, " "],
|
||||
//[/\u00A0/g, " "],
|
||||
this._htmlRTFmap = [
|
||||
[/<br \/>/g, "\x0B"],
|
||||
[/<span class=\"tab\"> <\/span>/g, "\\tab{}"],
|
||||
[/‘/g, "‘"],
|
||||
[/’/g, "’"],
|
||||
[/“/g, "“"],
|
||||
[/”/g, "”"],
|
||||
[/ /g, "\u00A0"],
|
||||
[/"(\w)/g, "“$1"],
|
||||
[/([\w,.?!])"/g, "$1”"],
|
||||
[/<p>/g, ""],
|
||||
[/<\/?div[^>]*>/g, ""]
|
||||
];
|
||||
|
||||
// Atomic units, RTF -> HTML (cleanup)
|
||||
this._rtfHTMLmap = [
|
||||
[/\\uc0\{?\\u([0-9]+)\}?(?:{}| )?/g, function(wholeStr, aCode) { return String.fromCharCode(aCode) }],
|
||||
[/\\tab(?:\{\}| )/g, '<span class="tab"> </span>'],
|
||||
[/(?:\\par{}|\\\r?\n)/g, "</p><p>"]
|
||||
];
|
||||
|
||||
this.prepare = function() {
|
||||
// DEBUG: Does this actually happen?
|
||||
if (this.prepared) return;
|
||||
|
||||
// Tag data
|
||||
var _rexData = [
|
||||
[
|
||||
[
|
||||
["<span +style=\"font-variant: *small-caps;\">"],
|
||||
["{\\scaps ", "{\\scaps{}"]
|
||||
],
|
||||
[
|
||||
["<\/span>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<span +style=\"text-decoration: *underline;\">"],
|
||||
["{\\ul{}", "{\\ul "]
|
||||
],
|
||||
[
|
||||
["<\/span>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<sup>"],
|
||||
["\\super ", "\\super{}"]
|
||||
],
|
||||
[
|
||||
["</sup>"],
|
||||
["\\nosupersub{}", "\\nosupersub "]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<sub>"],
|
||||
["\\sub ", "\\sub{}"]
|
||||
],
|
||||
[
|
||||
["</sub>"],
|
||||
["\\nosupersub{}", "\\nosupersub "]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<em>"],
|
||||
["{\\i{}", "{\\i "]
|
||||
],
|
||||
[
|
||||
["</em>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<i>"],
|
||||
["{\\i{}", "{\\i "]
|
||||
],
|
||||
[
|
||||
["</i>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<b>"],
|
||||
["{\\b{}", "{\\b "]
|
||||
],
|
||||
[
|
||||
["</b>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<strong>"],
|
||||
["{\\b{}", "{\\b "]
|
||||
],
|
||||
[
|
||||
["</strong>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<span +style=\"font-variant: *normal;\">"],
|
||||
["{\\scaps0{}", "{\\scaps0 "]
|
||||
],
|
||||
[
|
||||
["</span>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<span +style=\"font-style: *normal;\">"],
|
||||
["{\\i0{}", "{\\i0 "]
|
||||
],
|
||||
[
|
||||
["</span>"],
|
||||
["}"]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
["<span +style=\"font-weight: *normal;\">"],
|
||||
["{\\b0{}", "{\\b0 "]
|
||||
],
|
||||
[
|
||||
["</span>"],
|
||||
["}"]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
function longestFirst(a, b) {
|
||||
if (a.length < b.length) {
|
||||
return 1;
|
||||
} else if (a.length > b.length) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeRegExpString(str) {
|
||||
if (!str) return str;
|
||||
return str.replace(/\s+/g, " ")
|
||||
.replace(/(?:[\+]|\s[\*])/g, "")
|
||||
.replace(/[\']/g, '\"')
|
||||
.replace(/:\s/g, ":");
|
||||
}
|
||||
|
||||
this.normalizeRegExpString = normalizeRegExpString;
|
||||
|
||||
function composeRex(rexes, noGlobal) {
|
||||
var lst = [];
|
||||
for (var rex in rexes) {
|
||||
lst.push(rex);
|
||||
}
|
||||
lst.sort(longestFirst);
|
||||
var rexStr = "(?:" + lst.join("|") + ")";
|
||||
return new RegExp(rexStr, "g");
|
||||
}
|
||||
|
||||
// Create splitting regexps
|
||||
function splitRexMaker(segment) {
|
||||
var rexes = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
for (var j=0,jlen=_rexData[i].length; j < jlen; j++) {
|
||||
for (var k=0,klen=_rexData[i][j][segment].length; k < klen; k++) {
|
||||
rexes[_rexData[i][j][segment][k].replace("\\", "\\\\")] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
var ret = composeRex(rexes, true);
|
||||
return ret;
|
||||
}
|
||||
this.rtfHTMLsplitRex = splitRexMaker(1);
|
||||
this.htmlRTFsplitRex = splitRexMaker(0);
|
||||
|
||||
// Create open-tag sniffing regexp
|
||||
function openSniffRexMaker(segment) {
|
||||
var rexes = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
for (var j=0,jlen=_rexData[i][0][segment].length; j < jlen; j++) {
|
||||
rexes[_rexData[i][0][segment][j].replace("\\", "\\\\")] = true;
|
||||
}
|
||||
}
|
||||
return composeRex(rexes);
|
||||
}
|
||||
this.rtfHTMLopenSniffRex = openSniffRexMaker(1);
|
||||
this.htmlRTFopenSniffRex = openSniffRexMaker(0);
|
||||
|
||||
// Create open-tag remapper
|
||||
function openTagRemapMaker(segment) {
|
||||
var ret = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
var primaryVal = normalizeRegExpString(_rexData[i][0][segment][0]);
|
||||
for (var j=0,jlen=_rexData[i][0][segment].length; j < jlen; j++) {
|
||||
var key = normalizeRegExpString(_rexData[i][0][segment][j]);
|
||||
ret[key] = primaryVal;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
this.rtfHTMLopenTagRemap = openTagRemapMaker(1);
|
||||
this.htmlRTFopenTagRemap = openTagRemapMaker(0);
|
||||
|
||||
// Create open-tag-keyed close-tag sniffing regexps
|
||||
function closeTagRexMaker(segment) {
|
||||
var ret = {};
|
||||
var rexes = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
var primaryVal = _rexData[i][0][segment][0];
|
||||
for (var j=0,jlen=_rexData[i][1][segment].length; j < jlen; j++) {
|
||||
rexes[_rexData[i][1][segment][j]] = true;
|
||||
}
|
||||
ret[primaryVal] = composeRex(rexes);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
this.rtfHTMLcloseTagRex = closeTagRexMaker(1);
|
||||
this.htmlRTFcloseTagRex = closeTagRexMaker(0);
|
||||
|
||||
// Create open-tag-keyed open/close tag registry
|
||||
function tagRegistryMaker(segment) {
|
||||
var antisegment = 1;
|
||||
if (segment == 1) {
|
||||
antisegment = 0;
|
||||
}
|
||||
var ret = {};
|
||||
for (var i=0,ilen=_rexData.length; i < ilen; i++) {
|
||||
var primaryVal = normalizeRegExpString(_rexData[i][0][segment][0]);
|
||||
ret[primaryVal] = {
|
||||
open: normalizeRegExpString(_rexData[i][0][antisegment][0]),
|
||||
close: _rexData[i][1][antisegment][0]
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
this.rtfHTMLtagRegistry = tagRegistryMaker(1);
|
||||
this.htmlRTFtagRegistry = tagRegistryMaker(0);
|
||||
|
||||
this.prepared = true;
|
||||
}
|
||||
this.prepare();
|
||||
|
||||
this.getSplit = function(mode, txt) {
|
||||
if (!txt) return [];
|
||||
var splt = txt.split(this[mode + "splitRex"]);
|
||||
var mtch = txt.match(this[mode + "splitRex"]);
|
||||
var lst = [splt[0]];
|
||||
for (var i=1,ilen=splt.length; i < ilen; i++) {
|
||||
lst.push(mtch[i-1]);
|
||||
lst.push(splt[i]);
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
this.getOpenTag = function(mode, str) {
|
||||
var m = str.match(this[mode + "openSniffRex"]);
|
||||
if (m) {
|
||||
m = this[mode + "openTagRemap"][this.normalizeRegExpString(m[0])];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
this.convert = function(mode, txt) {
|
||||
var lst = this.getSplit(mode, txt);
|
||||
var sdepth = 0;
|
||||
var depth = 0;
|
||||
for (var i=1,ilen=lst.length; i < ilen; i += 2) {
|
||||
var openTag = this.getOpenTag(mode, lst[i]);
|
||||
if (openTag) {
|
||||
sdepth++;
|
||||
depth = sdepth;
|
||||
for (var j=(i+2),jlen=lst.length; j < jlen; j += 2) {
|
||||
var closeTag = !this.getOpenTag(mode, lst[j]);
|
||||
if (closeTag) {
|
||||
if (depth === sdepth && lst[j].match(this[mode + "closeTagRex"][openTag])) {
|
||||
lst[i] = this[mode + "tagRegistry"][openTag].open;
|
||||
lst[j] = this[mode + "tagRegistry"][openTag].close;
|
||||
break;
|
||||
}
|
||||
depth--;
|
||||
} else {
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sdepth--;
|
||||
}
|
||||
}
|
||||
return lst.join("");
|
||||
}
|
||||
|
||||
this.htmlToRTF = function(txt) {
|
||||
txt = this.convert("htmlRTF", txt);
|
||||
for (var i=0,ilen=this._htmlRTFmap.length; i < ilen; i++) {
|
||||
var entry = this._htmlRTFmap[i];
|
||||
txt = txt.replace(entry[0], entry[1]);
|
||||
}
|
||||
txt = Zotero.Utilities.unescapeHTML(txt);
|
||||
txt = txt.replace(/[\x7F-\uFFFF]/g, function(aChar) { return "\\uc0\\u"+aChar.charCodeAt(0).toString()+"{}"});
|
||||
return txt.trim();
|
||||
}
|
||||
|
||||
this.rtfToHTML = function(txt) {
|
||||
for (var i=0,ilen=this._rtfHTMLmap.length; i < ilen; i++) {
|
||||
var entry = this._rtfHTMLmap[i];
|
||||
txt = txt.replace(entry[0], entry[1]);
|
||||
}
|
||||
txt = this.convert("rtfHTML", txt);
|
||||
return txt.trim();
|
||||
}
|
||||
|
||||
this._constructed = true;
|
||||
|
||||
// Don't load if a value hasn't yet been set
|
||||
if (this._loadOnConstruct) {
|
||||
this._load();
|
||||
}
|
||||
]]></constructor>
|
||||
|
||||
<property name="mode">
|
||||
<getter><![CDATA[
|
||||
if (!this._mode) {
|
||||
throw ("mode is not defined in styled-textbox.xml");
|
||||
}
|
||||
return this._mode;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
Zotero.debug("Setting mode to " + val);
|
||||
switch (val) {
|
||||
case 'note':
|
||||
this._eventHandler = function (event) {
|
||||
// Necessary in Fx32+
|
||||
if (event.wrappedJSObject) {
|
||||
event = event.wrappedJSObject;
|
||||
}
|
||||
|
||||
var commandEvent = false;
|
||||
|
||||
if (Zotero.Prefs.get('debugNoteEvents')) {
|
||||
Zotero.debug(event.type);
|
||||
Zotero.debug(event.which);
|
||||
}
|
||||
switch (event.type) {
|
||||
case 'keydown':
|
||||
// Handle forward-delete, which doesn't register as a keypress
|
||||
// when a selection is cleared
|
||||
if (event.which == event.DOM_VK_DELETE) {
|
||||
this._changed = true;
|
||||
commandEvent = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'keypress':
|
||||
// Ignore keypresses that don't change
|
||||
// any text
|
||||
//Zotero.debug(event.which);
|
||||
if (!event.which &&
|
||||
event.keyCode != event.DOM_VK_DELETE &&
|
||||
event.keyCode != event.DOM_VK_BACK_SPACE) {
|
||||
//Zotero.debug("Not a char");
|
||||
return;
|
||||
}
|
||||
this._changed = true;
|
||||
commandEvent = true;
|
||||
break;
|
||||
|
||||
// 'change' includes text added via drag-and-drop
|
||||
case 'change':
|
||||
case 'undo':
|
||||
case 'redo':
|
||||
this._changed = true;
|
||||
commandEvent = true;
|
||||
break;
|
||||
|
||||
case 'ZoteroLinkClick':
|
||||
var zp = typeof ZoteroPane != 'undefined'
|
||||
? ZoteroPane
|
||||
: window.opener.ZoteroPane;
|
||||
zp.loadURI(event.value);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger command on change
|
||||
if (commandEvent && this.timeout) {
|
||||
if (this._timer) {
|
||||
clearTimeout(this._timer);
|
||||
}
|
||||
|
||||
this._timer = setTimeout(function () {
|
||||
var attr = this.getAttribute('oncommand');
|
||||
attr = attr.replace('this', 'thisObj');
|
||||
var func = new Function('thisObj', 'event', attr);
|
||||
func(this, event);
|
||||
}.bind(this), this.timeout);
|
||||
}
|
||||
|
||||
return true;
|
||||
}.bind(this);
|
||||
break;
|
||||
|
||||
case 'integration':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ("Invalid mode '" + val + "' in styled-textbox.xml");
|
||||
}
|
||||
return this._mode = val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<!-- Sets or returns formatting (currently, HTML or Integration) of rich text box -->
|
||||
<property name="initialized">
|
||||
<getter><![CDATA[
|
||||
return !!this._editor;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<!-- Sets or returns formatting (currently, HTML or Integration) of rich text box -->
|
||||
<property name="format">
|
||||
<getter><![CDATA[
|
||||
return this._format;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
return this._format = val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<!-- Sets or returns contents of rich text box -->
|
||||
<property name="value">
|
||||
<getter><![CDATA[
|
||||
if (!this._editor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var output = this._editor.getContent().trim();
|
||||
|
||||
if(this._format == "RTF") {
|
||||
// strip divs
|
||||
if(output.substr(0, 5) == "<div>" && output.substr(-6) == "</div>") {
|
||||
output = output.slice(0, output.length-6).slice(5).trim();
|
||||
}
|
||||
output = this.htmlToRTF(output)
|
||||
}
|
||||
|
||||
return output;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
if (self._timer) {
|
||||
clearTimeout(self._timer);
|
||||
}
|
||||
|
||||
if(!this._editor) {
|
||||
Zotero.debug('No editor yet');
|
||||
|
||||
this._value = val;
|
||||
if (!this._constructed) {
|
||||
Zotero.debug('Styled textbox not yet constructed', 2);
|
||||
this._loadOnConstruct = true;
|
||||
}
|
||||
else if (!this._loaded) {
|
||||
this._load();
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
// Hack to ignore incomplete editors due to rapid note creation in tests
|
||||
if (Zotero.test && !this._editor.getContent) {
|
||||
Zotero.logError("editor.getContent doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.value == val) {
|
||||
Zotero.debug("Textbox value hasn't changed");
|
||||
this._changed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var html = val;
|
||||
if(this._format == "RTF") {
|
||||
var bodyStyle = "";
|
||||
if(html.substr(0, 3) == "\\li") {
|
||||
// try to show paragraph formatting
|
||||
var returnIndex = html.indexOf("\r\n");
|
||||
|
||||
var tags = html.substr(1, returnIndex).split("\\");
|
||||
html = html.substr(returnIndex+2);
|
||||
|
||||
for(var i=0; i<tags.length; i++) {
|
||||
var tagName = tags[i].substr(0, 2);
|
||||
var tagValue = tags[i].substring(2, tags[i].length-1);
|
||||
if(tagName == "li") {
|
||||
var li = parseInt(tagValue, 10);
|
||||
} else if(tagName == "fi") {
|
||||
var fi = parseInt(tagValue, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// don't negatively indent
|
||||
if(fi < 0 && li == 0) li = -fi;
|
||||
|
||||
bodyStyle = "margin-left:"+(li/20+6)+"pt;text-indent:"+(fi/20)+"pt;";
|
||||
}
|
||||
|
||||
html = this.rtfToHTML(html);
|
||||
|
||||
html = '<div style="'+bodyStyle+'"><p>'+html+"</p></div>";
|
||||
}
|
||||
|
||||
Zotero.debug("Setting content to " + html);
|
||||
|
||||
this._editor.setContent(html);
|
||||
this._changed = false;
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="timeout"
|
||||
onset="this.setAttribute('timeout', val); return val;"
|
||||
onget="return parseInt(this.getAttribute('timeout')) || 0;"/>
|
||||
|
||||
<property name="changed" onget="return this._changed;" onset="this._changed = !!val;"/>
|
||||
|
||||
<method name="focus">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._editor) {
|
||||
this._iframe.focus();
|
||||
this._editor.focus();
|
||||
this._focus = false;
|
||||
}
|
||||
else {
|
||||
this._focus = true;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="hasFocus">
|
||||
<body>
|
||||
<![CDATA[
|
||||
return this._editor ? this._editor.hasFocus() : false;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="clearUndo">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._editor) {
|
||||
this._editor.undoManager.clear();
|
||||
this._editor.undoManager.add();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="onInit">
|
||||
<parameter name="callback"/>
|
||||
<body><![CDATA[
|
||||
if (this.initialized) {
|
||||
// Hack to ignore incomplete editors due to rapid note creation in tests
|
||||
if (Zotero.test && !this._editor.setMode) {
|
||||
Zotero.logError("editor.setMode doesn't exist after initialization");
|
||||
return;
|
||||
}
|
||||
callback(this._editor);
|
||||
}
|
||||
else {
|
||||
if (!this._onInitCallbacks) {
|
||||
this._onInitCallbacks = [];
|
||||
}
|
||||
this._onInitCallbacks.push(callback);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<field name="_loaded"/>
|
||||
<method name="_load">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._loaded = true;
|
||||
|
||||
// Unless we find a better way, use a separate HTML file
|
||||
// for read-only mode
|
||||
var htmlFile = this.mode + (this.getAttribute('readonly') != 'true' ? "" : "view");
|
||||
|
||||
var url = `resource://zotero/tinymce/${htmlFile}.html`
|
||||
// Pass directionality (LTR/RTL) and locale in URL
|
||||
+ "?locale=" + encodeURIComponent(Zotero.locale)
|
||||
+ "&dir=" + Zotero.dir;
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
var uri = Services.io.newURI(url, null, null);
|
||||
|
||||
Zotero.debug("Loading " + uri.spec);
|
||||
|
||||
// Register handler for deferred setting of content
|
||||
var self = this;
|
||||
var matchTo = null;
|
||||
var listener = function(e) {
|
||||
var win = self._iframe.contentWindow;
|
||||
var SJOW = win.wrappedJSObject;
|
||||
|
||||
// only fire if the target matches, or _zoteroMatchTo, which we set last
|
||||
// time the target matched, matches
|
||||
if(e.target !== self._iframe.contentDocument
|
||||
&& (!SJOW._zoteroMatchTo || SJOW._zoteroMatchTo !== matchTo)) return;
|
||||
|
||||
if (!SJOW.tinyMCE) {
|
||||
Zotero.getInstalledExtensions().then(function(exts) {
|
||||
for (let ext of exts) {
|
||||
if (ext.indexOf('NoScript') != -1 && ext.indexOf('disabled') == -1) {
|
||||
var doc = win.document;
|
||||
var div = doc.getElementById('tinymce');
|
||||
var warning = doc.createElement('div');
|
||||
warning.id = 'noScriptWarning';
|
||||
var str = "The NoScript extension is preventing Zotero "
|
||||
+ "from displaying notes. To use NoScript and Zotero together, "
|
||||
+ "whitelist the 'file:' scheme in the NoScript preferences "
|
||||
+ "and restart " + Zotero.appName + ".";
|
||||
warning.appendChild(document.createTextNode(str));
|
||||
div.appendChild(warning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SJOW.zoteroInit) {
|
||||
SJOW.zoteroInit = function(editor) {
|
||||
// Necessary in Fx32+
|
||||
if (editor.wrappedJSObject) {
|
||||
self._editor = editor.wrappedJSObject;
|
||||
}
|
||||
else {
|
||||
self._editor = editor;
|
||||
}
|
||||
if (self._value) {
|
||||
self.value = self._value;
|
||||
|
||||
// Prevent undoing to empty note after initialization
|
||||
self._editor.undoManager.clear();
|
||||
self._editor.undoManager.add();
|
||||
}
|
||||
if (self._focus) {
|
||||
setTimeout(function () {
|
||||
self._iframe.focus();
|
||||
self._editor.focus();
|
||||
});
|
||||
self._focus = false;
|
||||
}
|
||||
|
||||
// Add CSS rules to notes
|
||||
if (self.mode == 'note') {
|
||||
let fontSize = Zotero.Prefs.get('note.fontSize');
|
||||
// Fix empty old font prefs before a value was enforced
|
||||
if (fontSize < 6) {
|
||||
fontSize = 11;
|
||||
}
|
||||
var css = "body#zotero-tinymce-note, "
|
||||
+ "body#zotero-tinymce-note p, "
|
||||
+ "body#zotero-tinymce-note th, "
|
||||
+ "body#zotero-tinymce-note td, "
|
||||
+ "body#zotero-tinymce-note pre { "
|
||||
+ "font-size: " + fontSize + "px; "
|
||||
+ "} "
|
||||
+ "body#zotero-tinymce-note, "
|
||||
+ "body#zotero-tinymce-note p { "
|
||||
+ "font-family: "
|
||||
+ Zotero.Prefs.get('note.fontFamily') + "; "
|
||||
+ "}"
|
||||
+ Zotero.Prefs.get('note.css');
|
||||
|
||||
var doc = editor.contentDocument;
|
||||
var head = doc.getElementsByTagName("head")[0];
|
||||
var style = doc.createElement("style");
|
||||
style.innerHTML = css;
|
||||
head.appendChild(style);
|
||||
}
|
||||
|
||||
let cb;
|
||||
if (this._onInitCallbacks) {
|
||||
while (cb = this._onInitCallbacks.shift()) {
|
||||
// Hack to ignore incomplete editors due to rapid note creation in tests
|
||||
if (Zotero.test && !this._editor.setMode) {
|
||||
Zotero.logError("editor.setMode doesn't exist");
|
||||
return;
|
||||
}
|
||||
cb(this._editor);
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
var editor = SJOW.tinyMCE.get("tinymce");
|
||||
if (!editor) {
|
||||
Zotero.debug("editor not ready");
|
||||
|
||||
// this is a hack; I'm not sure why we can't identify the event target
|
||||
// next time without it, but apparently we can't
|
||||
matchTo = Zotero.randomString();
|
||||
SJOW._zoteroMatchTo = matchTo;
|
||||
|
||||
// Not ready yet
|
||||
return;
|
||||
}
|
||||
|
||||
self._iframe.removeEventListener("DOMContentLoaded", listener, false);
|
||||
|
||||
if (self._eventHandler) {
|
||||
win.wrappedJSObject.zoteroHandleEvent = self._eventHandler;
|
||||
}
|
||||
|
||||
// Run Cut/Copy/Paste with chrome privileges
|
||||
win.wrappedJSObject.zoteroExecCommand = function (doc, command, ui, value) {
|
||||
return doc.execCommand(command, ui, value);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
this._iframe.addEventListener("DOMContentLoaded", listener, false);
|
||||
|
||||
let loadURIOptions = {
|
||||
triggeringPrincipal: null,
|
||||
csp: null,
|
||||
loadFlags: Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY,
|
||||
referrerInfo: null,
|
||||
postData: null,
|
||||
};
|
||||
this._iframe.webNavigation.loadURI(uri.spec, loadURIOptions);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
|
||||
<content>
|
||||
<xul:iframe flex="1" anonid="rt-view" class="rt-view" type="content"
|
||||
xbl:inherits="onfocus,onblur,flex,width,height,hidden"
|
||||
style="overflow: hidden"/>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
|
@ -15,20 +15,6 @@
|
|||
padding:0;
|
||||
}
|
||||
|
||||
/* Bindings */
|
||||
textbox[type="styled"]
|
||||
{
|
||||
-moz-binding: url('chrome://zotero/content/bindings/styled-textbox.xml#styled-textbox');
|
||||
}
|
||||
|
||||
zoteromergegroup {
|
||||
-moz-binding: url('chrome://zotero/content/bindings/merge.xml#merge-group');
|
||||
}
|
||||
|
||||
zoteromergepane {
|
||||
-moz-binding: url('chrome://zotero/content/bindings/merge.xml#merge-pane');
|
||||
}
|
||||
|
||||
richlistitem {
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue