Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
dev:client_coding:javascript_api [2019/08/05 05:54] – [Running Ad Hoc JavaScript in Zotero] dstillmandev:client_coding:javascript_api [2022/07/02 18:22] (current) – [Executing the search] dstillman
Line 11: Line 11:
  
   - In the Tools → Developer menu, select Run JavaScript. Opening the Error Console, which appears in the same menu, will also be helpful.   - In the Tools → Developer menu, select Run JavaScript. Opening the Error Console, which appears in the same menu, will also be helpful.
-  - In the window that opens, enter JavaScript in the Code textbox and click Run or press Cmd-R/Ctrl-R.+  - In the window that opens, enter some JavaScript in the Code textbox and click Run or press Cmd-R/Ctrl-R.
  
-When running asynchronous code containing ''await'', the entered code is wrapped in an [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function|async function]], allowing you to wait for the resolution of promises returned by functions. Most Zotero functions that access the database, disk, or network are asynchronous. In this mode, the value of a ''return'' statement will be displayed in the right-hand pane upon successful completion.+When running **asynchronous** code containing ''await'', the entered code is wrapped in an [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function|async function]], allowing you to wait for the resolution of promises returned by functions. Most Zotero functions that access the database, disk, or network are asynchronous. In this mode, the value of a ''return'' statement will be displayed in the right-hand pane upon successful completion. E.g. returning the currently selected item(s)
  
-In synchronous mode, the value of the final line will appear in the right-hand pane.+<code javascript> 
 +var items = Zotero.getActiveZoteroPane().getSelectedItems(); 
 +return items; 
 +</code> 
 + 
 +In **synchronous** mode, the value of the final line will appear in the right-hand pane. The same result as above could be achieved in synchronous mode with 
 + 
 +<code javascript> 
 +var items = Zotero.getActiveZoteroPane().getSelectedItems(); 
 +items; 
 +</code>
 ===== Zotero Code Architecture ===== ===== Zotero Code Architecture =====
  
Line 26: Line 36:
 Non-window scope applies to lower-level code that doesn't have access to the DOM. This includes the core ''Zotero'' object, which contains all other non-window code, including the data layer used for retrieving and modifying library data. In Zotero, non-window code is contained within the ''xpcom'' subdirectory. Non-window scope applies to lower-level code that doesn't have access to the DOM. This includes the core ''Zotero'' object, which contains all other non-window code, including the data layer used for retrieving and modifying library data. In Zotero, non-window code is contained within the ''xpcom'' subdirectory.
  
-Overlays and windows in Zotero can import the core ''Zotero'' object via the include.js script. Zotero methods can then be called from anywhere within the window's scope simply by calling, for example, ''var item = Zotero.Items.get(1);''.+Windows in Zotero can import the core ''Zotero'' object via the include.js script. Zotero methods can then be called from anywhere within the window's scope simply by calling, for example, ''var item = Zotero.Items.get(1);''.
  
-To access Zotero functionality from your own extension, you will need access to the core ''Zotero'' object. If your extension operates within the main browser overlay, you already have access to the ''Zotero'' object and don’t need to take further steps. Otherwise, you can import the Zotero object into other windows by including the script %%chrome://zotero/content/include.js%% within an HTML or XUL file:+To access Zotero functionality from your own extension, you will need access to the core ''Zotero'' object. If your extension operates within the main Zotero window, you already have access to the ''Zotero'' object and don’t need to take further steps. Otherwise, you can import the Zotero object into other windows by including the script %%chrome://zotero/content/include.js%% within an HTML or XUL file:
  
 <code html> <code html>
Line 77: Line 87:
     ]     ]
 ); );
-var itemID = await item.save();+var itemID = await item.saveTx();
 return itemID; return itemID;
 </code> </code>
Line 206: Line 216:
 s.addCondition('collection', 'is', collectionKey); // e.g., 'C72FDAP2' s.addCondition('collection', 'is', collectionKey); // e.g., 'C72FDAP2'
 s.addCondition('savedSearch', 'is', savedSearchKey); s.addCondition('savedSearch', 'is', savedSearchKey);
 +</code>
 +
 +=== Search by creator === 
 +
 +<code javascript>
 +var name = 'smith';
 +s.addCondition('creator', 'contains', name);
 </code> </code>
  
Line 226: Line 243:
 results: results:
  
-<code javascript>var results = await s.search();</code>+<code javascript>var itemIDs = await s.search();</code>
  
 This returns the item ids in the search as an array. The next thing to do is to get the Zotero items for the array of IDs: This returns the item ids in the search as an array. The next thing to do is to get the Zotero items for the array of IDs:
  
-<code javascript>var items = await Zotero.Items.getAsync(results);</code>+<code javascript>var items = await Zotero.Items.getAsync(itemIDs);</code>
  
-===== Managing citations and bibliographies =====+==== Managing citations and bibliographies ====
  
 TODO:  this is pretty sparse.  the rtfscan code is a good place to look for some guidance. TODO:  this is pretty sparse.  the rtfscan code is a good place to look for some guidance.
  
-==== Getting a bibliography for an array of items: ====+=== Getting a bibliography for an array of items: ===
  
 Here we use Zotero's Quick Copy functions to get a bibliography in the style Here we use Zotero's Quick Copy functions to get a bibliography in the style
-specified in Zotero's preferences.+specified in Zotero's preferences. We will in the following example create this 
 +bibliography from all currently selected items.
  
-First we start with a list of as in the previous entry. +<code javascript>var items = Zotero.getActiveZoteroPane().getSelectedItems(); 
- +var qc = Zotero.QuickCopy; 
-<code javascript>var qc = Zotero.QuickCopy; +var format = Zotero.Prefs.get("export.quickCopy.setting")
-var biblio qc.getContentFromItems([item], Zotero.Prefs.get("export.quickCopy.setting")); +if (format.split("=")[0] !== "bibliography") { 
-var biblio_html_format = cite.html; +   alert("No bibliography style is choosen in the settings for QuickCopy."); 
-var biblio_txt  cite.text; +
 +var biblio = qc.getContentFromItems(items, format); 
 +var biblio_html_format = biblio.html; 
 +var biblio_txt = biblio.text;
 </code> </code>
  
-==== Get a list of available styles ====+If you instead want to have the citation string then simply replace the 7th 
 +line with ''var biblio qc.getContentFromItems(items, format, null, true);''
 + 
 + 
 +=== Get a list of available styles ===
  
 <code javascript>  <code javascript> 
Line 261: Line 286:
 </code> </code>
  
-TODO:  get citations.  change the style.  get stuff in other formats,+TODO:  change the style.  get stuff in other formats,
 especially RTF especially RTF
  
Line 322: Line 347:
 return fulltext; return fulltext;
 </code> </code>
 +
 +==== File I/O ====
 +
 +=== Getting the contents of a file ===
 +
 +<code javascript>
 +var path = '/Users/user/Desktop/data.json';
 +var data = await Zotero.File.getContentsAsync(path);
 +</code>
 +
 +=== Saving data to a file ===
 +
 +<code javascript>
 +var path = '/Users/user/Desktop/file.txt';
 +var data = "This is some text.";
 +await Zotero.File.putContentsAsync(path, data);
 +</code>
 +
  
 ==== To Do === ==== To Do ===
Line 335: Line 378:
 =====  Batch Editing ===== =====  Batch Editing =====
  
-The JavaScript API can provide a powerful way to script changes to your Zotero library. The common case of search-and-replace is accomplished easily using a basic script.+The JavaScript API provides a powerful way to script changes to your Zotero library. The common case of search-and-replace is accomplished easily using a basic script in the [[#running_ad_hoc_javascript_in_zotero|JavaScript runner]].
  
 Before proceeding, back up your [[:zotero_data|Zotero data directory]] and temporarily disable auto-sync in the Sync pane of the Zotero preferences. Before proceeding, back up your [[:zotero_data|Zotero data directory]] and temporarily disable auto-sync in the Sync pane of the Zotero preferences.
 +
 +All examples operate on the currently selected library.
  
 ==== Example: Item Field Changes ==== ==== Example: Item Field Changes ====
Line 349: Line 394:
 var fieldID = Zotero.ItemFields.getID(fieldName); var fieldID = Zotero.ItemFields.getID(fieldName);
 var s = new Zotero.Search(); var s = new Zotero.Search();
-s.libraryID = Zotero.Libraries.userLibraryID;+s.libraryID = ZoteroPane.getSelectedLibraryID();
 s.addCondition(fieldName, 'is', oldValue); s.addCondition(fieldName, 'is', oldValue);
 var ids = await s.search(); var ids = await s.search();
Line 369: Line 414:
 https://api.zotero.org/itemFields?pprint=1. https://api.zotero.org/itemFields?pprint=1.
  
-==== Example: Delete Tags By Name ====+==== Example: Creator Name Changes ====
  
-<html><p id="zotero-5-update-warning" style="colorred; font-weight: bold">This example has not been updated for Zotero 5 and should not currently be used.</p></html>+Edit the first four lines as necessary:
  
-<code javascript>var tags ["foo""bar""baz"]+<code javascript>var oldName = "Robert L. Smith"
-var ids []+var newFirstName = "Robert"
-var allTags = Zotero.Tags.search(); +var newLastName = "Smith"; 
-tags tags.map(tag => tag.toLowerCase()); +var newFieldMode 0// 0: two-field, 1: one-field (with empty first name) 
-for (var id in allTags) { +  
-    if (tags.indexOf(allTags[id].name.toLowerCase()) !-1) { +var new Zotero.Search(); 
-      ids.push(id);+s.libraryID ZoteroPane.getSelectedLibraryID(); 
 +s.addCondition('creator', 'is', oldName); 
 +var ids await s.search()
 +if (!ids.length
 +    return "No items found"
 +
 +await Zotero.DB.executeTransaction(async function () { 
 +    for (let id of ids) { 
 +        let item = await Zotero.Items.getAsync(id); 
 +        let creators = item.getCreators(); 
 +        let newCreators = []
 +        for (let creator of creators) { 
 +        if (`${creator.firstName} ${creator.lastName}`.trim() == oldName) { 
 +         creator.firstName = newFirstName; 
 +        creator.lastName = newLastName; 
 +        creator.fieldMode = newFieldMode; 
 +        } 
 +        newCreators.push(creator); 
 +        } 
 +        item.setCreators(newCreators); 
 +        await item.save();
     }     }
 +});
 +return ids.length + " item(s) updated";</code>
 +
 +==== Example: Convert Manual Tag to Automatic ====
 +
 +Note that this will change all instances of the tag in the library.
 +
 +Replace "Foo" in the first line with the tag to change:
 +
 +<code javascript>var tag = "Foo";
 +var s = new Zotero.Search();
 +s.libraryID = ZoteroPane.getSelectedLibraryID();
 +s.addCondition('tag', 'is', tag);
 +var ids = await s.search();
 +if (!ids.length) {
 +    return "No items found";
 } }
-Zotero.Tags.erase(ids); +await Zotero.DB.executeTransaction(async function () { 
-</code>+    for (let id of ids) { 
 +        let item = Zotero.Items.get(id); 
 +        item.addTag(tag, 1); 
 +        await item.save({ 
 +            skipDateModifiedUpdate: true 
 +        }); 
 +    } 
 +}); 
 +return ids.length + " tag(s) updated";</code>
  
 ==== Example: Delete Tags By Part of Name ==== ==== Example: Delete Tags By Part of Name ====
dev/client_coding/javascript_api.1564998895.txt.gz · Last modified: 2019/08/05 05:54 by dstillman