httpIntegrationClient.js (7772B)
1 /* 2 ***** BEGIN LICENSE BLOCK ***** 3 4 Copyright © 2017 Center for History and New Media 5 George Mason University, Fairfax, Virginia, USA 6 http://zotero.org 7 8 This file is part of Zotero. 9 10 Zotero is free software: you can redistribute it and/or modify 11 it under the terms of the GNU Affero General Public License as published by 12 the Free Software Foundation, either version 3 of the License, or 13 (at your option) any later version. 14 15 Zotero is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU Affero General Public License for more details. 19 20 You should have received a copy of the GNU Affero General Public License 21 along with Zotero. If not, see <http://www.gnu.org/licenses/>. 22 23 ***** END LICENSE BLOCK ***** 24 */ 25 26 /** 27 * This is a HTTP-based integration interface for Zotero. The actual 28 * heavy lifting occurs in the connector and/or wherever the connector delegates the heavy 29 * lifting to. 30 */ 31 Zotero.HTTPIntegrationClient = { 32 deferredResponse: null, 33 sendCommandPromise: Zotero.Promise.resolve(), 34 sendCommand: async function(command, args=[]) { 35 let payload = JSON.stringify({command, arguments: args}); 36 function sendCommand() { 37 Zotero.HTTPIntegrationClient.deferredResponse = Zotero.Promise.defer(); 38 Zotero.HTTPIntegrationClient.sendResponse.apply(Zotero.HTTPIntegrationClient, 39 [200, 'application/json', payload]); 40 return Zotero.HTTPIntegrationClient.deferredResponse.promise; 41 } 42 // Force issued commands to occur sequentially, since these are really just 43 // a sequence of HTTP requests and responses. 44 // We might want to consider something better later, but this has the advantage of 45 // being easy to interface with as a Client, as you don't need SSE or WS. 46 if (command != 'Document.complete') { 47 Zotero.HTTPIntegrationClient.sendCommandPromise = 48 Zotero.HTTPIntegrationClient.sendCommandPromise.then(sendCommand, sendCommand); 49 } else { 50 await Zotero.HTTPIntegrationClient.sendCommandPromise; 51 sendCommand(); 52 } 53 return Zotero.HTTPIntegrationClient.sendCommandPromise; 54 } 55 }; 56 57 Zotero.HTTPIntegrationClient.Application = function() { 58 this.primaryFieldType = "Http"; 59 this.secondaryFieldType = "Http"; 60 this.outputFormat = 'html'; 61 this.supportedNotes = ['footnotes']; 62 }; 63 Zotero.HTTPIntegrationClient.Application.prototype = { 64 getActiveDocument: async function() { 65 let result = await Zotero.HTTPIntegrationClient.sendCommand('Application.getActiveDocument'); 66 this.outputFormat = result.outputFormat || this.outputFormat; 67 this.supportedNotes = result.supportedNotes || this.supportedNotes; 68 return new Zotero.HTTPIntegrationClient.Document(result.documentID); 69 } 70 }; 71 72 /** 73 * See integrationTests.js 74 */ 75 Zotero.HTTPIntegrationClient.Document = function(documentID) { 76 this._documentID = documentID; 77 }; 78 for (let method of ["activate", "canInsertField", "displayAlert", "getDocumentData", 79 "setDocumentData", "setBibliographyStyle"]) { 80 Zotero.HTTPIntegrationClient.Document.prototype[method] = async function() { 81 return Zotero.HTTPIntegrationClient.sendCommand("Document."+method, 82 [this._documentID].concat(Array.prototype.slice.call(arguments))); 83 }; 84 } 85 86 // @NOTE Currently unused, prompts are done using the connector 87 Zotero.HTTPIntegrationClient.Document.prototype._displayAlert = async function(dialogText, icon, buttons) { 88 var ps = Services.prompt; 89 var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_OK) 90 + (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_IS_STRING); 91 92 switch (buttons) { 93 case DIALOG_BUTTONS_OK: 94 buttonFlags = ps.BUTTON_POS_0_DEFAULT + ps.BUTTON_POS_0 * ps.BUTTON_TITLE_OK; break; 95 case DIALOG_BUTTONS_OK_CANCEL: 96 buttonFlags = ps.BUTTON_POS_0_DEFAULT + ps.STD_OK_CANCEL_BUTTONS; break; 97 case DIALOG_BUTTONS_YES_NO: 98 buttonFlags = ps.BUTTON_POS_0_DEFAULT + ps.STD_YES_NO_BUTTONS; break; 99 case DIALOG_BUTTONS_YES_NO_CANCEL: 100 buttonFlags = ps.BUTTON_POS_0_DEFAULT + ps.BUTTON_POS_0 * ps.BUTTON_TITLE_YES + 101 ps.BUTTON_POS_1 * ps.BUTTON_TITLE_NO + 102 ps.BUTTON_POS_2 * ps.BUTTON_TITLE_CANCEL; break; 103 } 104 105 var result = ps.confirmEx( 106 null, 107 "Zotero", 108 dialogText, 109 buttonFlags, 110 null, null, null, 111 null, 112 {} 113 ); 114 115 switch (buttons) { 116 default: 117 break; 118 case DIALOG_BUTTONS_OK_CANCEL: 119 case DIALOG_BUTTONS_YES_NO: 120 result = (result+1)%2; break; 121 case DIALOG_BUTTONS_YES_NO_CANCEL: 122 result = result == 0 ? 2 : result == 2 ? 0 : 1; break; 123 } 124 await this.activate(); 125 return result; 126 } 127 Zotero.HTTPIntegrationClient.Document.prototype.cleanup = async function() {}; 128 Zotero.HTTPIntegrationClient.Document.prototype.cursorInField = async function(fieldType) { 129 var retVal = await Zotero.HTTPIntegrationClient.sendCommand("Document.cursorInField", [this._documentID, fieldType]); 130 if (!retVal) return null; 131 return new Zotero.HTTPIntegrationClient.Field(this._documentID, retVal); 132 }; 133 Zotero.HTTPIntegrationClient.Document.prototype.insertField = async function(fieldType, noteType) { 134 var retVal = await Zotero.HTTPIntegrationClient.sendCommand("Document.insertField", [this._documentID, fieldType, parseInt(noteType) || 0]); 135 return new Zotero.HTTPIntegrationClient.Field(this._documentID, retVal); 136 }; 137 Zotero.HTTPIntegrationClient.Document.prototype.getFields = async function(fieldType) { 138 var retVal = await Zotero.HTTPIntegrationClient.sendCommand("Document.getFields", [this._documentID, fieldType]); 139 return retVal.map(field => new Zotero.HTTPIntegrationClient.Field(this._documentID, field)); 140 }; 141 Zotero.HTTPIntegrationClient.Document.prototype.convert = async function(fields, fieldType, noteTypes) { 142 fields = fields.map((f) => f._id); 143 await Zotero.HTTPIntegrationClient.sendCommand("Field.convert", [this._documentID, fields, fieldType, noteTypes]); 144 }; 145 Zotero.HTTPIntegrationClient.Document.prototype.complete = async function() { 146 Zotero.HTTPIntegrationClient.inProgress = false; 147 Zotero.HTTPIntegrationClient.sendCommand("Document.complete", [this._documentID]); 148 }; 149 150 /** 151 * See integrationTests.js 152 */ 153 Zotero.HTTPIntegrationClient.Field = function(documentID, json) { 154 this._documentID = documentID; 155 this._id = json.id; 156 this._code = json.code; 157 this._text = json.text; 158 this._noteIndex = json.noteIndex; 159 }; 160 Zotero.HTTPIntegrationClient.Field.prototype = {}; 161 162 for (let method of ["delete", "select", "removeCode"]) { 163 Zotero.HTTPIntegrationClient.Field.prototype[method] = async function() { 164 return Zotero.HTTPIntegrationClient.sendCommand("Field."+method, 165 [this._documentID, this._id].concat(Array.prototype.slice.call(arguments))); 166 }; 167 } 168 Zotero.HTTPIntegrationClient.Field.prototype.getText = async function() { 169 return this._text; 170 }; 171 Zotero.HTTPIntegrationClient.Field.prototype.setText = async function(text, isRich) { 172 // The HTML will be stripped by Google Docs and and since we're 173 // caching this value, we need to strip it ourselves 174 var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"] 175 .createInstance(Components.interfaces.nsIDOMParser); 176 var doc = parser.parseFromString(text, "text/html"); 177 this._text = doc.documentElement.textContent; 178 return Zotero.HTTPIntegrationClient.sendCommand("Field.setText", [this._documentID, this._id, text, true]); 179 }; 180 Zotero.HTTPIntegrationClient.Field.prototype.getCode = async function() { 181 return this._code; 182 }; 183 Zotero.HTTPIntegrationClient.Field.prototype.setCode = async function(code) { 184 this._code = code; 185 return Zotero.HTTPIntegrationClient.sendCommand("Field.setCode", [this._documentID, this._id, code]); 186 }; 187 Zotero.HTTPIntegrationClient.Field.prototype.getNoteIndex = async function() { 188 return this._noteIndex; 189 }; 190 Zotero.HTTPIntegrationClient.Field.prototype.equals = async function(arg) { 191 return this._id === arg._id; 192 };