forked from zotero/translators
-
Notifications
You must be signed in to change notification settings - Fork 2
/
ARTstor.js
494 lines (456 loc) · 18.2 KB
/
ARTstor.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
{
"translatorID": "5278b20c-7c2c-4599-a785-12198ea648bf",
"label": "ARTstor",
"creator": "Charles Zeng & John Justin",
"target": "^https?://([^/]+\\.)?(artstor|sscommons)\\.org/(open)?library",
"minVersion": "3.0",
"maxVersion": "",
"priority": 100,
"inRepository": true,
"translatorType": 4,
"browserSupport": "gcs",
"lastUpdated": "2016-04-26 18:25:36"
}
/*
Artstor Translator
Copyright (C) Charles Zeng & John Justin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
detectWeb is run to determine whether item metadata can indeed be retrieved from the webpage.
The return value of this function should be the detected item type (e.g. “journalArticle”,
see the overview of Zotero item types), or, if multiple items are found, “multiple”.
**/
function detectWeb(doc, url) {
var itemType = false; // default - ignore
if (url.search(/\/iv2\.|ExternalIV\.jsp/) != -1) {
// Image viewer window
itemType = "artwork";
} else if (url.search(/\#3\|/) != -1) {
// Thumbnail window page
if ((doc.getElementsByClassName('MetaDataWidgetRoot') != null) &&
(doc.getElementsByClassName('MetaDataWidgetRoot').length > 0)) {
// There are multiple metadata windows visible
itemType = "artwork";
} else if ((doc.getElementById("floatingPlaceHolder") != null) &&
(doc.getElementById("floatingPlaceHolder").style.display == "block")) {
// Don't capture date if small window is present, ignore
} else if ((doc.getElementById("thumbNavSave1") != null) &&
(doc.getElementById("thumbNavSave1").style.display == "block")) {
// Don't capture data if image group window is in editing state. Ignore
} else if ((doc.getElementById("ssContentWrap") != null) &&
(doc.getElementById("ssContentWrap").style.display == "inline")) {
// Don't capture data if slide show window is present, ignore
} else {
// Allow thumbnail window.
itemType = "multiple";
}
}
// all other page, data can not be captured.
return itemType;
}
/**
Overall logic:
- Detect the page context:
- check if the page is main window (ignore)
- check if the page is collection splash (ignore)
- check if the page is a viewer
- get the image id and type, process it.
- check if the page is thumbnail page
- ignore small window
- check if metadata window is visisble. If so, get the image id from each
small window and process them
- if no small window, get the selected object and process them
get the object ids from selected objects, then process the ids.
- otherwise, select all objects in the thumbnails and prompt user
get the object ids from users, then process the ids.
- Process the id
- find the object type.
- get the metadta service url from id using service call [domain]/[approot]/secure/metadata/id
- fetch and convert the metadata from the metadata service call
- take into consideration of different metadata field for the portals
- may need to convert/format the data values.
- fetch the item notes using:
- get the resource link url from id: :[domain]/[approot]/secure/metadata/id?_method=FpHtml
- fetch the resource from resource url
- set the item title and item mine type.
doWeb is run when a user, wishing to save one or more items, activates the selected translator.
Sidestepping the retrieval of item metadata, we'll first focus on how doWeb can be used to save
retrieved item metadata (as well as attachments and notes) to your Zotero library.
**/
function doWeb(doc, url) {
if (url.match(/\/iv2\.|ExternalIV.jsp/)) {
doImageViewer(doc, url);
}
if (url.match(/\#3\|/)) {
// Thumbnail window page
if ((doc.getElementsByClassName('MetaDataWidgetRoot') != null) &&
(doc.getElementsByClassName('MetaDataWidgetRoot').length > 0)) {
doMetadataWindow(doc, url);
} else {
doList(doc, url);
}
}
}
/**
Process the thumbnail list by grabing the data from DOM
and add it to the list for user to select.
Once the items are selected, process them and add them to
Zotero.
**/
function doList(doc, url) {
var visibleDomIdName = "custom";
var zinfoDomNamePre = "custom";
var zinfoDomNamePost = "_thumbMetaWrap";
var selectDomIdNamePre = "custom";
var selectDomIdNamePost = "_imageHolder";
var candidateItems = new Object();
var selectItems = new Object();
if ((doc.getElementById("listContentWrap") != null) &&
(doc.getElementById("listContentWrap").style.display == "block")) {
// If list view is active.
visibleDomIdName = "largeCustom";
zinfoDomNamePre = "largeCustom";
zinfoDomNamePost = "_MainArea";
selectDomIdNamePre = "largeCustom";
selectDomIdNamePost = "_imageHolder";
}
var i = 1;
var found = true;
do {
var visibleDom = doc.getElementById(visibleDomIdName + i);
if ((visibleDom != null) &&
(visibleDom.style.display == "block")) {
getDomData(doc, candidateItems, selectItems,
zinfoDomNamePre + i + zinfoDomNamePost,
selectDomIdNamePre + i + selectDomIdNamePost);
} else {
found = false;
}
i++;
} while (found);
if (Object.keys(selectItems).length > 0) {
candidateItems = selectItems;
}
// Now we got candidate list, have user select it
Zotero.selectItems(candidateItems, function(selectedItems) {
var objItems = [];
for (var objItem in selectedItems) {
objItems.push(objItem);
}
processObjects(doc, url, objItems);
});
}
/**
Get the data from DOM and added it to candidateItems.
If the item is selected, also adds it to the selectItems.
**/
function getDomData(doc, candidateItems, selectItems, zinfoName, selectName) {
var zinfoDom = doc.getElementById(zinfoName);
var selectDom = doc.getElementById(selectName);
var ztitle = zinfoDom.getAttribute("ztitle");
var zid = zinfoDom.getAttribute("zid");
var ztid = zinfoDom.getAttribute("ztid");
var key = zid + ":" + ztid;
candidateItems[key] = htmlDecode(doc, ztitle);
if (selectDom.className.indexOf("thumbNailImageSelected") > -1) {
// The item is selected.
selectItems[key] = htmlDecode(doc, ztitle);
}
}
/**
This procedure gets the image id and type from the DOM, added it to
the list and sends the list to processor.
**/
function doImageViewer(doc, url) {
var objID = doc.getElementById("objID");
if (objID != null) {
var objItems = [];
var objItem = objID.title;
// Get the image id and object type from the title attribute.
// This contains the objId and object type separate by : as in "AWSS35953_35953_25701160:11"
objItems.push(objItem);
processObjects(doc, url, objItems);
}
}
/**
Process the metadata window data by getting the ID from the
window DOM and retries data with extra calls.
**/
function doMetadataWindow(doc, url) {
// get object id from metadata window.
var metaWindows = doc.getElementsByClassName('MetaDataWidgetRoot');
var objItems = [];
for (var i = 0; i < metaWindows.length; i++) {
// the dom id is in the form "mdwSS7730455_7730455_8806769"
// that is object id prefixed with mdw.
var id = metaWindows[i].id.substring(3);
objItems.push(id + ":10"); // default type to image
}
processObjects(doc, url, objItems);
}
/**
This functions removes extra format tag from string and also decodes the
html entity string.
**/
function htmlDecode(doc, input) {
var fieldValue = input.replace(/<wbr\/>/g, "");
fieldValue = fieldValue.replace(/<br\/>/g, "");
return ZU.unescapeHTML(fieldValue);
}
/**
processObjects gets the object data using service call.
objIds has the following member: id, type
**/
function processObjects(doc, url, objIds) {
for (var i = 0; i < objIds.length; i++) {
var objItem = objIds[i];
var dataItem = new Zotero.Item('artwork');
dataItem.attachments.push({
title: "Artstor Thumbnails",
document: doc
});
getMetaDataItem(doc, url, objItem, dataItem);
}
}
function getMetaDataItem(doc, url, objItem, dataItem) {
var portalMap = {
'flexspace': {
'Campus': 'title',
'Square Footage': 'artworkSize',
'General Description': 'abstractNote',
'Comments (Technology Integration)': 'abstractNote',
'Rights': 'rights'
},
'archaeology': {
'Site Name': 'title',
'Artifact Title': 'title',
'Artifact Description': 'abstractNote',
'Artifact Repository': 'archive',
'Site Date': 'date',
'Artifact Materials/Techniques': 'artworkMedium',
'Artifact Dimensions': 'artworkSize',
'Rights': 'rights'
},
'default': {
'Creator': 'creators',
'Title': 'title',
'Date': 'date',
'Material': 'artworkMedium',
'Measurements': 'artworkSize',
'Repository': 'archive',
'Rights': 'rights',
'Description': 'abstractNote',
'Accession Number': 'callNumber'
}
};
var itemAry = objItem.split(':');
var serviceUrl = getServiceUrlRoot(url) + "metadata/" + itemAry[0];
Zotero.Utilities.HTTP.doGet(serviceUrl, function(text) {
var json = JSON.parse(text);
var portal = getPortal(url);
if (!(portal in portalMap)) {
portal = 'default';
}
processPortalData(doc, dataItem, json, portalMap[portal], portal);
getNotesDataItem(url, objItem, dataItem);
});
}
/**
This procedure process the json, and add the json value to the
Zotero item.
**/
function processPortalData(doc, dataItem, json, fieldMap, portal) {
var fieldName;
var fieldValue;
if (portal == 'archaeology') {
var hasSiteName = false;
for (var i = 0; i < json.metaData.length; i++) {
fieldName = json.metaData[i].fieldName;
fieldValue = htmlDecode(doc, json.metaData[i].fieldValue);
if (fieldName in fieldMap) {
var key = fieldMap[fieldName];
if (fieldName == 'Site Name') {
hasSiteName = true;
setItemValue(dataItem, "title", fieldValue);
} else if (fieldName == 'Artifact Title') {
if (hasSiteName) {
setItemLabelValue(doc, dataItem, "extra", fieldName, dataItem.title);
hasSiteName = false;
}
setItemValue(dataItem, "title", fieldValue);
} else {
setItemValue(dataItem, key, fieldValue);
}
} else {
setItemLabelValue(doc, dataItem, "extra", fieldName, fieldValue);
}
}
} else {
for (var i = 0; i < json.metaData.length; i++) {
fieldName = json.metaData[i].fieldName;
fieldValue = htmlDecode(doc, json.metaData[i].fieldValue);
// fieldValue = json.metaData[i].fieldValue;
if (fieldName in fieldMap) {
var key = fieldMap[fieldName];
if (key == 'creators') {
setItemCreator(dataItem, fieldValue);
} else {
setItemValue(dataItem, key, fieldValue);
}
} else {
setItemLabelValue(doc, dataItem, "extra", fieldName, fieldValue);
}
}
}
if (json.SSID !== undefined && json.SSID !== "") {
setItemLabelValue(doc, dataItem, "extra", "SSID", json.SSID);
}
if (dataItem.title == undefined) {
dataItem.title = "Unknown";
}
}
function setItemCreator(dataItem, fieldValue) {
var names = [];
if (fieldValue.indexOf(';') > 0) {
names = fieldValue.split(';');
} else {
names.push(fieldValue);
}
for (var i = 0; i < names.length; i++) {
var str = names[i];
var contributor = "author";
var name = str;
var value = name.replace(/<\/?[^>]+(>|$)/g, " ").replace(/(>)|(<)/g, "");
dataItem.creators.push(ZU.cleanAuthor(value, contributor, false));
}
}
function cleanStringValue(str) {
var cleanValue = str.replace(/\<wbr\/\>/g, "");
cleanValue = cleanValue.replace(/<\/?[^>]+(>|$)/g, " ");
return cleanValue;
}
function setItemLabelValue(doc, dataItem, key, label, value) {
var cleanValue = cleanStringValue(value);
if (!(key in dataItem)) {
dataItem[key] = label + ": " + cleanValue;
} else {
var fieldValue = dataItem[key];
if (fieldValue.indexOf(label) >= 0) {
dataItem[key] += ", " + cleanValue;
} else {
dataItem[key] += "; " + label + ": " + cleanValue;
}
}
}
function setItemValue(dataItem, key, value, override) {
var cleanValue = cleanStringValue(value);
if (!(key in dataItem) || override) {
dataItem[key] = cleanValue;
} else {
dataItem[key] += "; " + cleanValue;
}
}
/**
This procedure makes the extra call to get the notes associated
with the image records and add it to the Zotero data item.
**/
function getNotesDataItem(url, objItem, dataItem) {
var itemAry = objItem.split(':');
var objType = itemAry[1];
var serviceURL = getServiceUrlRoot(url) + "icommentary/" + itemAry[0];
Zotero.Utilities.HTTP.doGet(serviceURL,
function(text) {
var json = JSON.parse(text);
for (var j = 0; j < json.numberOfCommentaries; j = j + 1) {
if (json.ICommentary[j].status == 2) {
//public commentary
var comment = "";
if (json.ICommentary[j].ownerName == "") {
comment = "Note: ";
} else {
comment = "Note by: " + json.ICommentary[j].ownerName + " - ";
}
comment += json.ICommentary[j].commentary;
dataItem.notes.push({
note: comment
});
}
}
getResourceDataItem(url, objItem, dataItem);
}
); //doGet
}
function getResourceDataItem(url, objItem, dataItem) {
var itemAry = objItem.split(':');
var serviceURL = getServiceUrlRoot(url) + "metadata/" + itemAry[0] + "/" + "?_method=FpHtml";
Zotero.Utilities.HTTP.doGet(serviceURL, function(text) {
var service = text.substring(text.indexOf("secure"));
service = service.substring(0, service.indexOf("</td>")).replace(/<wbr\/>/g, "").substring(service.indexOf("?")).trim();
dataItem.url = getServerUrl(url) + "/secure/ViewImages" + service + "&zoomparams=&fs=true";
dataItem.complete();
});
}
function getPortal(url) {
var portal = url.substring(url.indexOf('://') + 3, url.indexOf('.'));
return portal;
}
function getServerUrl(url) {
var serverUrl;
if (url.indexOf('/iv2.') > 0) {
serverUrl = url.substring(0, url.indexOf('iv2.'));
} else if (url.indexOf('/ExternalIV.jsp') > 0) {
serverUrl = url.substring(0, url.indexOf('ExternalIV.jsp'));
} else {
serverUrl = url.substring(0, url.indexOf('#3'));
}
serverUrl = serverUrl.substring(0, serverUrl.lastIndexOf('/'));
return serverUrl;
}
function getServiceUrlRoot(url) {
var serviceRoot = getServerUrl(url) + "/secure/";
return serviceRoot;
}
/** BEGIN TEST CASES **/
var testCases = [
{
"type": "artwork",
"url": "http://www.sscommons.org/openlibrary/ExternalIV.jsp?objectId=4jEkdDElLjUzRkY6fz5%2BRXlDOHkje1x9fg%3D%3D&fs=true",
"items": [
{
"itemType": "artwork",
"title": "Trailer Home; Exterior view",
"creators": [
{
"firstName": "Image by: Barbara",
"lastName": "Lane",
"creatorType": "author"
}
],
"date": "Photographed: 2001",
"extra": "Location: Bradford County, Pennsylvania; Collection: Bryn Mawr College Faculty/Staff/Student Photographs; ID Number: 01-07828; Source: Personal photographs of Professor Barbara Lane, 2001",
"libraryCatalog": "ARTstor",
"rights": "Copyright is owned by the photographer. Questions can be directed to [email protected].; This image has been selected and made available by a user using Artstor's software tools. Artstor has not screened or selected this image or cleared any rights to it and is acting as an online service provider pursuant to 17 U.S.C. §512. Artstor disclaims any liability associated with the use of this image. Should you have any legal objection to the use of this image, please visit http://www.artstor.org/our-organization/o-html/copyright.shtml for contact information and instructions on how to proceed.",
"url": "http://www.sscommons.org/openlibrary/secure/ViewImages?id=4jEkdDElLjUzRkY6fz5%2BRXlDOHkje1x9fg%3D%3D&userId=gDFB&zoomparams=&fs=true",
"attachments": [
{
"title": "Artstor Thumbnails"
}
],
"tags": [],
"notes": [],
"seeAlso": []
}
]
}
]
/** END TEST CASES **/