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
Next revisionBoth sides next revision
dev:client_coding:javascript_api [2019/01/22 00:42] – [An Easy Debugging Environment] dstillmandev:client_coding:javascript_api [2019/06/11 03:44] – [Running Ad Hoc JavaScript in Zotero] dstillman
Line 1: Line 1:
-<html><p id="zotero-5-update-warning" style="color: red; font-weight: bold">We’re 
-in the process of updating the documentation for 
-<a href="https://www.zotero.org/blog/zotero-5-0">Zotero 5.0</a>. Some documentation 
-may be outdated in the meantime. Thanks for your understanding.</p></html> 
- 
- 
 ====== Zotero JavaScript API ====== ====== Zotero JavaScript API ======
  
Line 11: Line 5:
 Note that the (mostly user-contributed) documentation of the JavaScript API is not comprehensive. If you use the JavaScript API in ways beyond what's described here, please consider expanding this wiki page. Note that the (mostly user-contributed) documentation of the JavaScript API is not comprehensive. If you use the JavaScript API in ways beyond what's described here, please consider expanding this wiki page.
  
-===== Helpful Resources ===== 
- 
-For this section, you’ll likely find the following helpful: 
- 
-  * A basic understanding of how to create a Firefox extension 
-    * [[http://developer.mozilla.org|The Mozilla Developer Center]] (including [[http://developer.mozilla.org/en/docs/Building_an_Extension|Building an Extension]]) 
-    * [[https://developer.mozilla.org/en/Setting_up_extension_development_environment|Setting up an extension development environment]] 
-  * A decent grasp of object-oriented JavaScript 
-    * [[http://javascript.crockford.com/private.html|public, private and privileged methods and members]]; object literal notation; closures 
-    * [[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference|MDC Core JavaScript 1.5 Reference]] (also note [[http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6|New in JavaScript 1.6]] and [[http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7|New in JavaScript 1.7]]) 
  
 ===== Running Ad Hoc JavaScript in Zotero ===== ===== Running Ad Hoc JavaScript in Zotero =====
  
-Zotero 5.0.61 and later include an option to run arbitrary privileged JavaScript:+Zotero includes an option to run arbitrary privileged JavaScript:
  
   - In the Advanced pane of the Zotero preferences, select Config Editor, and then set ''devtools.chrome.enabled'' to ''true'' and restart Zotero.   - In the Advanced pane of the Zotero preferences, select Config Editor, and then set ''devtools.chrome.enabled'' to ''true'' and restart Zotero.
   - In the Tools menu, select Run JavaScript. Open the Error Console, which also appears in Tools, will also be helpful.   - In the Tools menu, select Run JavaScript. Open the Error Console, which also appears in Tools, will also be helpful.
-  - In the window that opens, enter JavaScript in the Code textbox and click Run or press Cmd-R/Ctrl-R. The return value of the last line will appear in the textbox on the right.+  - In the window that opens, enter JavaScript in the Code textbox and click Run or press Cmd-R/Ctrl-R.
  
-(Before Zotero 5.0.61 is releasedyou'll need to install the [[:dev_builds|Zotero beta]] to use this feature.+To run asynchronous codecheck the "Run as async function" checkbox. This runs the entered code wrapped in an [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function|async function]], allowing you to use ''await'' to wait for the resolution of promises returned by functionsMost 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.
-===== The Zotero Object ====+
  
-Zotero exposes an object-oriented JavaScript API that can be used to access and modify Zotero data. Within Zotero itselfmost SQL statements are limited to the data layer, with all other elements (including the entire UI) using the data API to access the dataThrough the base Zotero XPCOM service, this functionality is available to all privileged code in Firefox, including other loaded extensions.+In synchronous mode, the value of the final line will appear in the right-hand pane. 
 +===== Zotero Code Architecture =====
  
-==== XPCOM ====+==== Window Scope vs. Non-Window Scope ===
  
-A common problem in developing Mozilla extensions is figuring out how to pass data between different windows, which have their own scopes and do not by default share the same variables and code. While there are various mechanisms to get around this, the [[http://developer.mozilla.org/en/docs/Working_with_windows_in_chrome_code#Using_an_XPCOM_singleton_component|recommended method]], and the method used by Zotero, is to use an XPCOM singleton component to store common data, which can then be accessed from any window that imports the component. (XPCOM is the //cross-platform component object model//---the framework---that forms the basis for the Mozilla application environment.)+Zotero code exists in either window scope and non-window scope.
  
-The base Zotero service is an XPCOM component written in JavaScriptWhile normally XPCOM components implement various predefined interfaces themselvesin Zotero the data layer and most of the core functionality are stored within a JavaScript object that is then stuffed into the special ''wrappedJSObject'' property of the component. The component itself does not define any XPCOM interfaces. (This is vaguely a hackbut it addresses our needs sufficiently and is an approach used by several other extensions.) Chrome overlays and windows in Zotero import the core object via the script include.js, which calls ''getService()'' on the component and assigns the wrapped object to the variable ''Zotero''. Zotero methods can then be called from anywhere within the window’s scope simply by calling, for example, ''var item = Zotero.Items.get(1)''.+Window scope applies to code that runs within either the main Zotero window or a secondary window (e.g., the Advanced Search window). It has access to the window's DOM and can interact with the UI. The main window-scope object in Zotero is ''ZoteroPane'', from zoteroPane.js, which controls most interactions triggered in the main Zotero window.
  
-Access to the Zotero service is not limited to Zotero itselfhowever. As a standard XPCOM component, the Zotero service---andspecifically, the wrapped JavaScript object---can be accessed from anywhere within privileged code, including other loaded extensions.+Non-window scope applies to lower-level code that doesn't have access to the DOM. This includes the core ''Zotero'' objectwhich contains all other non-window codeincluding the data layer used for retrieving and modifying library data. In Zotero, non-window code is contained within the ''xpcom'' subdirectory.
  
-To access the data API in your own extension, you will need access to the core Zotero JavaScript 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 either by including the script %%chrome://zotero/content/include.js%% within a XUL file (recommended) or by manually calling ''getService()'' directly on the Zotero XPCOM service and assigning the wrapped JS object to a variable.+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);''.
  
-%%chrome://zotero/content/include.js:%% +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: 
-<code javascript+ 
-var Zotero Components.classes["@zotero.org/Zotero;1"+<code html
- .getService(Components.interfaces.nsISupports) +<script src="chrome://zotero/content/include.js"><script>
- .wrappedJSObject;+
 </code> </code>
  
-===== Notification System =====+Once you have ''Zotero'', you can get the current ''ZoteroPane'' object: 
 +<code javascript> 
 +var zp Zotero.getActiveZoteroPane(); 
 +var items = zp.getSelectedItems(); 
 +</code>  
 +(The Zotero pane will always be available unless the main window is closed, as is possible on macOS.) 
 + 
 +==== Notification System ====
  
-Zotero has a built-in notification system that allows other privileged code to be notified when a change is made via the data layer---for example, when an item is added to the library. Within Zotero itself, this is used mostly to update the UI when items change, but external extensions can use the system to perform additional operations when specific events occur---say, to sync item metadata with a web-based tool.+Zotero has a built-in notification system that allows other privileged code to be notified when a change is made via the data layer — for example, when an item is added to the library. Within Zotero itself, this is used mostly to update the UI when items change, but extensions can use the system to perform additional operations when specific events occur — say, to sync item metadata with a web-based API.
  
 Available events: Available events:
Line 71: Line 61:
  
 //The Zotero JavaScript API is under-documented, and at present requires a lot of looking around in the source code.  The most useful parts of the source code are in chrome/content/zotero/xpcom and xpcom/data, and the chrome/content/zotero (particularly zoteroPane.js and fileInterface.js).// //The Zotero JavaScript API is under-documented, and at present requires a lot of looking around in the source code.  The most useful parts of the source code are in chrome/content/zotero/xpcom and xpcom/data, and the chrome/content/zotero (particularly zoteroPane.js and fileInterface.js).//
- 
-Once you have access to the core Zotero object, you can use the objects and methods provided by the Zotero JavaScript API. 
- 
-Zotero uses a combination of instantiatable objects (e.g. ''Zotero.Item = function(){...}'') and singletons (''Zotero.Items = **new** function(){...}''). The most important example of the former is ''Zotero.Item'', which represents a single item in the database. Singletons are used mostly to group related static methods into a single namespace. 
  
 ==== Adding items and modifying data ==== ==== Adding items and modifying data ====
  
-A typical operation might include a call to ''Items.get()'' to retrieve an ''Item'' instance, calls to ''Item'' methods on the retrieved object to modify data, and finally a ''save()'' to save the modified data to the database.+A typical operation might include a call to ''Zotero.Items.get()'' to retrieve ''Zotero.Item'' instance, calls to ''Zotero.Item'' methods on the retrieved object to modify data, and finally a ''save()'' (within a transaction) or ''saveTx()'' (outside a transaction) to save the modified data to the database.
  
 <code javascript> <code javascript>
-var creator = new Zotero.Creator; +var item = new Zotero.Item('book');
-creator.firstName = 'William'; +
-creator.lastName = 'Shakespeare'; +
-creator.save(); +
- +
-var item = new Zotero.Item+
-item.setType(Zotero.ItemTypes.getID('book'));+
 item.setField('title', 'Much Ado About Nothing'); item.setField('title', 'Much Ado About Nothing');
-item.setCreator(0creator'author'); +item.setCreators( 
-var itemID = item.save();+    [ 
 +        { 
 +            firstName: "William", 
 +            lastName: "Shakespeare", 
 +            creatorType: "author
 +        } 
 +    ] 
 +); 
 +var itemID = await item.save()
 +return itemID;
 </code> </code>
  
Line 102: Line 91:
 alert(item.getCreator(0)); // {'firstName'=>'William', 'lastName'=>'Shakespeare', alert(item.getCreator(0)); // {'firstName'=>'William', 'lastName'=>'Shakespeare',
                            //   'creatorTypeID'=>1, 'fieldMode'=>0}                            //   'creatorTypeID'=>1, 'fieldMode'=>0}
 +// Alternative format
 +alert(item.getCreatorJSON(0)); // {'firstName'=>'William', 'lastName'=>'Shakespeare',
 +                           //   'creatorType'=>'author'}
 +
 item.setField('place', 'England'); item.setField('place', 'England');
 item.setField('date', 1599); item.setField('date', 1599);
-item.save(); // update database with new data+await item.saveTx(); // update database with new data
  
 </code> </code>
  
-==== Create new Zotero object ==== +==== Get the Zotero Pane to interact with the Zotero UI ====
- +
-This is the first thing that you need to do when interacting with Zotero'+
-internals.  The code to do so is:+
  
 <code javascript> <code javascript>
-var Zotero Components.classes["@zotero.org/Zotero;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;+var ZoteroPane = Zotero.getActiveZoteroPane();
 </code> </code>
  
-==== Get the Zotero Pane to interact with the Zotero GUI ====+Then grab the currently selected items from the Zotero pane:
  
 <code javascript> <code javascript>
-var ZoteroPane = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow("navigator:browser").ZoteroPane; +// Get first selected item 
-</code> +var selectedItems = ZoteroPane.getSelectedItems(); 
- +var item = selectedItems[0];
-Then grab the currently selected items from the zotero pane: +
- +
-<code javascript> +
-//get first selected item +
-var selected_items = ZoteroPane.getSelectedItems(); +
-var item = selected_items[0];+
  
-// proced if selected item is neither a collection nor a note +// Proceed if an item is selected and it isn'a note 
-if ( item.isCollection() & ! item.isNote()) {+if (item && !item.isNote()) {
     if (item.isAttachment()) {     if (item.isAttachment()) {
         // find out about attachment         // find out about attachment
     }     }
     if (item.isRegularItem()) {     if (item.isRegularItem()) {
-        // we could grab attachments: +        // We could grab attachments: 
-        // var att_ids = item.getAttachments(false); +        // let attachmentIDs = item.getAttachments(); 
-        // if (att_ids.length>1) exit(); // bailout +        // let attachment = Zotero.Items.get(attachmentIDs[0]);
-        // item_att=Zotero.Items.get(att_ids[0]);+
     }     }
     alert(item.id);     alert(item.id);
Line 145: Line 128:
 </code> </code>
  
-==== Setup a Zotero search ====+==== Collection Operations ====
  
-If you are focused on data access, then the first thing you will want to do +=== Get the items in the selected collection ===
-will be to retrieve items from your Zotero.  Creating an in-memory search is a +
-good start.+
  
-<code javascript>    var search new z.Search(); </code>+<code javascript> 
 +var collection ZoteroPane.getSelectedCollection(); 
 +var items = collection.getChildItems(); 
 +// or you can obtain an array of itemIDs instead: 
 +var itemIDs = collection.getChildItems(true); 
 +</code>
  
-====  Search for items containing specific tag ====+=== Create subcollection of the selected collection ===
  
-Starting with the code from "Setup a Zotero search" we then use the following +<code javascript> 
-code to retrieve items with a particular tag:+var currentCollection = ZoteroPane.getSelectedCollection(); 
 +var collection = new Zotero.Collection(); 
 +collection.name = name; 
 +collection.parentID = currentCollection.id; 
 +var collectionID = await collection.saveTx(); 
 +return collectionID; 
 +</code>
  
-<code javascript>    search.addCondition('tag', 'is', 'tag name here');</code>+==== Zotero Search Basics ====
  
-==== Zotero Collection Operations ==== +If you are focused on data access, the first thing you will want to do 
- +will be to retrieve items from your Zotero library. Creating an in-memory search is a 
-=== Get the collection tree and display as a series of nested ordered lists === +good start.
- +
-This code was developed in the Firefox extension Plain Old Webserver server side JavaScript.  Note that it'recursive function. With a bit of jQuery the nested ordered list can be easily transformed into a tree widget.+
  
 <code javascript> <code javascript>
-var Zotero Components.classes["@zotero.org/Zotero;1".getService(Components.interfaces.nsISupports).wrappedJSObject+var new Zotero.Search(); 
- +s.libraryID = Zotero.Libraries.userLibraryID;
-var render_collection = function(coll) { +
-    if (!coll) {  +
-        coll = null;  +
-    } +
-    var collections = Zotero.getCollections(coll); +
-    document.writeln("<ul>"); +
-    for (c in collections) { +
-        document.writeln('<li>' + '<a href="view_collection.sjs?name=' + encodeURI(collections[c].name) + '&id=' + collections[c].id + '">' + collections[c].name  + '</a></li>'); +
-        if (collections[c].hasChildCollections) { +
-    var childCol = render_collection(collections[c].id); +
-        } +
-    }    +
-    document.writeln("</ul>"); +
-+
- +
-render_collection();+
 </code> </code>
  
-=== Get the items for a particular collection ===+=== Search for items containing specific tag ===
  
-<code javascript> +Starting with the above code, we then use the following code to retrieve items in My Library with particular tag:
-var Zotero = Components.classes["@zotero.org/Zotero;1"] .getService(Components.interfaces.nsISupports).wrappedJSObject; +
-var collectionid = pow_server.GET.id; // or some other way of finding the collectionID here +
-var collection = z.Collections.get(collectionid); +
-var items = collection.getChildItems(); +
-// or you can obtain an array of itemIDs instead: +
-var itemids = collection.getChildItems(true); +
-</code+
- +
-=== Create a New Collection in a function ===+
  
 <code javascript> <code javascript>
-async function createCollection(name) { +s.addCondition('tag', 'is', 'tag name here'); 
-    var currentCollection = ZoteroPane.getSelectedCollection(); +var itemIDs = await s.search();
-    var collection = new Zotero.Collection(); +
-    collection.name = name; +
-    collection.parentID = currentCollection.id; +
-    var collectionID = await collection.saveTx(); +
-    return collectionID; +
-}+
 </code> </code>
  
-This function creates a new collection with a given name and makes +=== Advanced searches ===
-it a subcollection of the currently selected one. Since the saving +
-will result in a Promise object, we add the ''await'' before the +
-function call and make sure that this is within an ''async'' function. +
- +
-==== Zotero Search Basics ==== +
- +
-=== Set up the search ===+
  
 <code javascript> <code javascript>
 var s = new Zotero.Search(); var s = new Zotero.Search();
 +s.libraryID = Zotero.Libraries.userLibraryID;
 s.addCondition('joinMode', 'any'); // joinMode defaults to 'all' as per the  s.addCondition('joinMode', 'any'); // joinMode defaults to 'all' as per the 
-                                        // advanced search GUI+                                        // advanced search UI
 </code> </code>
  
-To add the other conditions available in the advanced search GUI, use the following:+To add the other conditions available in the advanced search UI, use the following:
  
 <code javascript> <code javascript>
Line 244: Line 197:
 === Search by collection === === Search by collection ===
  
-To search for a collection or a saved search you need to know the ID:+To search for a collection or a saved search you need to know the ID or key:
  
 <code javascript> <code javascript>
-s.addCondition('collectionID', 'is', collectionID);+s.addCondition('collectionID', 'is', collectionID); // e.g., 52
 s.addCondition('savedSearchID', 'is', savedSearchID); s.addCondition('savedSearchID', 'is', savedSearchID);
 +</code>
 +
 +<code javascript>
 +s.addCondition('collection', 'is', collectionKey); // e.g., 'C72FDAP2'
 +s.addCondition('savedSearch', 'is', savedSearchKey);
 </code> </code>
  
Line 256: Line 214:
  
 <code javascript> <code javascript>
-    var tagname = 'something'; +var tagName = 'something'; 
-    search.addCondition('tag', 'is', tagname);+s.addCondition('tag', 'is', tagName);
 </code> </code>
  
Line 269: Line 227:
 results: results:
  
-<code javascript>var results = search.search();</code>+<code javascript>var results = await s.search();</code>
  
-This returns the item ids in the search as an array [I could be wrong ... ]. +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:
-The next thing to do is to get the Zotero items for the array of IDs:+
  
-<code javascript>var items = z.Items.get(results);</code>+<code javascript>var items = await Zotero.Items.getAsync(results);</code>
  
 ===== Managing citations and bibliographies ===== ===== Managing citations and bibliographies =====
Line 287: Line 244:
 First we start with a list of as in the previous entry. First we start with a list of as in the previous entry.
  
-<code javascript>  var qc = z.QuickCopy; +<code javascript>var qc = Zotero.QuickCopy; 
-  var biblio = qc.getContentFromItems(new Array(item), +var biblio = qc.getContentFromItems([item]Zotero.Prefs.get("export.quickCopy.setting")); 
-                                      z.Prefs.get("export.quickCopy.setting")); +var biblio_html_format = cite.html; 
-    var biblio_html_format = cite.html; +var biblio_txt  = cite.text; 
-    var biblio_txt         = cite.text; +
 </code> </code>
  
Line 297: Line 253:
  
 <code javascript>  <code javascript> 
-      var styles = zotero.Styles.getVisible(); +await Zotero.Schema.schemeUpdatePromise; 
-      var style_info = []; +var styles = Zotero.Styles.getVisible(); 
-      for each var s in styles) { +var styleInfo = []; 
-           style_info.push( { "ids.styleID, "names.title } ); +for (let style of styles) { 
-       +    styleInfo.push({ id: style.styleID, name: style.title }); 
-      JSON.stringify(style_info)// e.g. to return json from the mozrepl+
 +return styleInfo;
 </code> </code>
  
Line 315: Line 272:
 To get an item's abstract, we get the 'abstractNote' field from the Zotero item: To get an item's abstract, we get the 'abstractNote' field from the Zotero item:
  
-<code javascript>    var abstract = item.getField('abstractNote'); </code>+<code javascript>var abstract = item.getField('abstractNote');</code>
  
 ==== Get child notes for an item ==== ==== Get child notes for an item ====
Line 321: Line 278:
 To get the child notes for an item, we use the following code: To get the child notes for an item, we use the following code:
  
-<code javascript>     var notes = item.getNotes(); </code>+<code javascript>var noteIDs = item.getNotes();</code>
  
-This returns an array of notes.  Each note is in HTML format To get each note +This returns an array of ids of note items. To get each note in turn we just iterate through the array:
-in turn we just iterate through the array:+
  
 <code javascript> <code javascript>
-    for (var j=0;j<notes.length;j++) { +for (let id of noteIDs) { 
-        var note = z.Items.get(notes[j]); +    let note = Zotero.Items.get(id); 
-        var note_html = note.getNote(); +    let noteHTML = note.getNote(); 
-    +
 </code> </code>
  
 ==== Get an item's related items ==== ==== Get an item's related items ====
  
-This technique works for anything that can have related items attached within +<code javascript>var relatedItems = item.relatedItems;</code>
-the Zotero database.  This includes items and notes. +
- +
-<code javascript>  var related_items = item.relatedItems</code>+
  
 ==== Set two items as related to each other  ==== ==== Set two items as related to each other  ====
Line 351: Line 304:
  
  
-==== Get an Item'Attachments ===+==== Get an item'attachments ===
  
-Here's some example code to get the full text of HTML and PDF items in storage and puts the data in an array:+Here's some example code to get the full text of HTML and PDF items in storage and put the data in an array:
  
 <code javascript> <code javascript>
-var item = 'some item' // some Zotero Item obtained previously +var item = ZoteroPane.getSelectedItems()[0]
-var fulltext = new Array;+var fulltext = [];
 if (item.isRegularItem()) { // not an attachment already if (item.isRegularItem()) { // not an attachment already
-    var attachments selected_items[item].getAttachments(false); +    let attachmentIDs = item.getAttachments(); 
-    for (a in attachments) { +    for (let id of attachmentIDs) { 
-        var a_item = Zotero.Items.get(attachments[a]); +        let attachment = Zotero.Items.get(id); 
-        if (a_item.attachmentMIMEType == 'application/pdf' +        if (attachment.attachmentContentType == 'application/pdf' 
-            || a_item.attachmentMIMEType == 'text/html') { +                || attachment.attachmentContentType == 'text/html') { 
-            fulltext.push(a_item.attachmentText);+            fulltext.push(await attachment.attachmentText);
         }         }
     }     }
 } }
 +return fulltext;
 </code> </code>
  
Line 384: Line 338:
 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 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.
  
-Firstinstall the [[https://addons.mozilla.org/en-US/firefox/addon/execute-js/|Execute JS]] Firefox extension to interact with Zotero via JavaScript. (Advanced users can also use the Firefox Browser Console or Scratchpad in Browser mode after enable chrome/add-on debugging in the Web Console settings.) Back up your database first, and temporarily disable auto-sync in the Sync pane of the Zotero preferences+Before proceedingback up your [[:zotero_data|Zotero data directory]] and temporarily disable auto-sync in the Sync pane of the Zotero preferences.
- +
-In Execute JS, switch the target window to an open browser window, paste the relevant code into the "JS-Code to execute" box, make any necessary changes, and click "Execute".+
  
 ==== Example: Item Field Changes ==== ==== Example: Item Field Changes ====
Line 397: Line 349:
  
 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.addCondition(fieldName, 'is', oldValue); s.addCondition(fieldName, 'is', oldValue);
-var ids = s.search(); +var ids = await s.search(); 
-if (ids) { +if (!ids.length) { 
- for(var i in ids) { +    return "No items found";
- var item = Zotero.Items.get(ids[i]); +
- var mappedFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(item.itemTypeID, fieldName); +
- item.setField(mappedFieldID ? mappedFieldID : fieldID, newValue); +
- item.save(); +
-+
- alert(ids.length + " items updated");+
 } }
-else +await Zotero.DB.executeTransaction(async function () 
- alert("No items found"); +    for (let id of ids) { 
-}</code> +        let item = await Zotero.Items.getAsync(id); 
- +        let mappedFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(item.itemTypeID, fieldName); 
-The list of field names to use can be retrieved via the server API: https://api.zotero.org/itemFields?pprint=1.+        item.setField(mappedFieldID ? mappedFieldID : fieldID, newValue); 
 +        await item.save(); 
 +    
 +}); 
 +return ids.length + " item(s) updated";</code>
  
-==== ExampleDelete All Automatic Tags ====+The list of field names to use can be retrieved via the web API:
  
-<code javascript>var tagType = 1; // automatic +https://api.zotero.org/itemFields?pprint=1.
-Zotero.Tags.erase(Object.keys(Zotero.Tags.getAll([tagType])))</code>+
  
 ==== Example: Delete Tags By Name ==== ==== Example: Delete Tags By Name ====
 +
 +<html><p id="zotero-5-update-warning" style="color: red; font-weight: bold">This example has not been updated for Zotero 5 and should not currently be used.</p></html>
  
 <code javascript>var tags = ["foo", "bar", "baz"]; <code javascript>var tags = ["foo", "bar", "baz"];
Line 435: Line 387:
  
 ==== Example: Delete Tags By Part of Name ==== ==== Example: Delete Tags By Part of Name ====
 +
 +<html><p id="zotero-5-update-warning" style="color: red; font-weight: bold">This example has not been updated for Zotero 5 and should not currently be used.</p></html>
  
 <code javascript>var tags = ["foo", "bar", "baz"]; <code javascript>var tags = ["foo", "bar", "baz"];
dev/client_coding/javascript_api.txt · Last modified: 2022/07/02 18:22 by dstillman