Allow web translators to monitor DOM nodes for changes in order to re-trigger detectWeb

This commit is contained in:
aurimasv 2013-01-29 03:25:05 -06:00
parent f9978e8f02
commit b919d27d1e
2 changed files with 62 additions and 9 deletions

View file

@ -46,6 +46,7 @@ var Zotero_Browser = new function() {
this.toggleCollapsed = toggleCollapsed; this.toggleCollapsed = toggleCollapsed;
this.chromeLoad = chromeLoad; this.chromeLoad = chromeLoad;
this.contentLoad = contentLoad; this.contentLoad = contentLoad;
this.itemUpdated = itemUpdated;
this.contentHide = contentHide; this.contentHide = contentHide;
this.tabClose = tabClose; this.tabClose = tabClose;
this.resize = resize; this.resize = resize;
@ -344,7 +345,7 @@ var Zotero_Browser = new function() {
if(isHTML) { if(isHTML) {
var contentWin = doc.defaultView; var contentWin = doc.defaultView;
if(!contentWin.haveZoteroEventListener) { if(!contentWin.haveZoteroEventListener) {
contentWin.addEventListener("ZoteroItemUpdated", itemUpdated, false); contentWin.addEventListener("ZoteroItemUpdated", function(event) { itemUpdated(event.originalTarget) }, false);
contentWin.haveZoteroEventListener = true; contentWin.haveZoteroEventListener = true;
} }
} }
@ -380,14 +381,13 @@ var Zotero_Browser = new function() {
/** /**
* Called when item should be updated due to a DOM event * Called when item should be updated due to a DOM event
*/ */
function itemUpdated(event) { function itemUpdated(doc) {
try { try {
var doc = event.originalTarget; var rootDoc = (doc instanceof HTMLDocument ? doc.defaultView.top.document : doc);
var rootDoc = (doc instanceof HTMLDocument ? doc.defaultView.top.document : doc); var browser = Zotero_Browser.tabbrowser.getBrowserForDocument(rootDoc);
var browser = Zotero_Browser.tabbrowser.getBrowserForDocument(rootDoc); var tab = _getTabObject(browser);
var tab = _getTabObject(browser); if(doc == tab.page.document || doc == rootDoc) tab.clear();
if(doc == tab.page.document || doc == rootDoc) tab.clear(); tab.detectTranslators(rootDoc, doc);
tab.detectTranslators(rootDoc, doc);
} catch(e) { } catch(e) {
Zotero.debug(e); Zotero.debug(e);
} }
@ -649,6 +649,7 @@ Zotero_Browser.Tab.prototype.detectTranslators = function(rootDoc, doc) {
var translate = new Zotero.Translate.Web(); var translate = new Zotero.Translate.Web();
translate.setDocument(doc); translate.setDocument(doc);
translate.setHandler("translators", function(obj, item) { me._translatorsAvailable(obj, item) }); translate.setHandler("translators", function(obj, item) { me._translatorsAvailable(obj, item) });
translate.setHandler("pageModified", function(translate, doc) { Zotero_Browser.itemUpdated(doc) });
translate.getTranslators(true); translate.getTranslators(true);
} else if(doc.documentURI.substr(0, 7) == "file://") { } else if(doc.documentURI.substr(0, 7) == "file://") {
this._attemptLocalFileImport(doc); this._attemptLocalFileImport(doc);

View file

@ -635,6 +635,52 @@ Zotero.Translate.Sandbox = {
// call super // call super
Zotero.Translate.Sandbox.Base._itemDone(translate, item); Zotero.Translate.Sandbox.Base._itemDone(translate, item);
},
/**
* Tells Zotero to monitor changes to the DOM and re-trigger detectWeb
* Can only be set during the detectWeb call
* @param {DOMNode} target Document node to monitor for changes
* @param {MutationObserverInit} [config] specifies which DOM mutations should be reported
*/
"monitorDOMChanges":function(translate, target, config) {
if(translate._currentState != "detect") {
Zotero.debug("Translate: monitorDOMChanges can only be called during the 'detect' stage");
return;
}
var window = translate.document.defaultView
var mutationObserver = window && ( window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver );
if(!mutationObserver) {
Zotero.debug("Translate: This browser does not support mutation observers.");
return;
}
var translator = translate._potentialTranslators[0];
if(!translate._registeredDOMObservers[translator.translatorID])
translate._registeredDOMObservers[translator.translatorID] = [];
var obs = translate._registeredDOMObservers[translator.translatorID];
//do not re-register observer by the same translator for the same node
if(obs.indexOf(target) != -1) {
Zotero.debug("Translate: Already monitoring this node");
return;
}
obs.push(target);
var observer = new mutationObserver(function(mutations, observer) {
obs.splice(obs.indexOf(target),1);
observer.disconnect();
Zotero.debug("Translate: Page modified.");
//we don't really care what got updated
var doc = mutations[0].target.ownerDocument;
translate._runHandler("pageModified", doc);
});
observer.observe(target, config || {childList: true, subtree: true});
Zotero.debug("Translate: Mutation observer registered on <" + target.nodeName + "> node");
} }
}, },
@ -843,6 +889,11 @@ Zotero.Translate.Base.prototype = {
* complete * complete
* passed: an array of appropriate translators * passed: an array of appropriate translators
* returns: N/A * returns: N/A
* pageModified
* valid: web
* called: when a web page has been modified
* passed: the document object for the modified page
* returns: N/A
* @param {Function} handler Callback function. All handlers will be passed the current * @param {Function} handler Callback function. All handlers will be passed the current
* translate instance as the first argument. The second argument is dependent on the handler. * translate instance as the first argument. The second argument is dependent on the handler.
*/ */
@ -909,7 +960,7 @@ Zotero.Translate.Base.prototype = {
if(this._handlers[type]) { if(this._handlers[type]) {
// compile list of arguments // compile list of arguments
if(this._parentTranslator) { if(this._parentTranslator) {
// if there is a parent translator, make sure we don't the Zotero.Translate // if there is a parent translator, make sure we don't pass the Zotero.Translate
// object, since it could open a security hole // object, since it could open a security hole
var args = [null]; var args = [null];
} else { } else {
@ -1528,6 +1579,7 @@ Zotero.Translate.Base.prototype = {
* this Translate instance. * this Translate instance.
*/ */
Zotero.Translate.Web = function() { Zotero.Translate.Web = function() {
this._registeredDOMObservers = {}
this.init(); this.init();
} }
Zotero.Translate.Web.prototype = new Zotero.Translate.Base(); Zotero.Translate.Web.prototype = new Zotero.Translate.Base();