forked from ka1/zot2indd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
importZotero.jsx
1707 lines (1512 loc) · 70.2 KB
/
importZotero.jsx
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
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//Citation Import for Zotero (modified MOD export) to Indesign CS6 or later
//(c) 2013 Kai Kasugai
app.scriptPreferences.version = 8; //Indesign CS6 and later. Use 7.5 to use CS5.5 features
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL; //INTERACT_WITH_ALL is the default anyway. just in case you want to change that.
app.scriptPreferences.enableRedraw = true;
//$.level = 2;
//global vars
var myDocument, myXML;
//styles, tags, layer
var parsedReferenceStyle, parsedReferenceTag, noReferenceStyle;
var referenceParagraphStyle;
var styleAuthor, styleYear, styleTitle, styleBacklink;
var hoverObjectLayer; //the layer for hover objects
var hoverObjectStyle; //the style for hover objects (the hidden ones)
var hoverTriggerStyle; //the style for the objects (rectangles) that mask the text and trigger the hover object
var hoverTextFrameStyle; //the style for the textframe that contains the bibliography info
//text frame with bibliography
var myRefTextFrame;
//arrays
var myCitekeyInfo = new CiteKeyInfo();
//error arrays
var error_publishtypes = new Array();
var error_general = new Array();
var notice_general = new Array();
var notice_ambiguities = new Array();
var foundNew = 0;
var foundTotal = 0;
var removedOld = 0;
//settings
var showStatistics, showWarnings, checkForAmbiguousCitekeys, redrawMode, safeBeforeStart;
var createHoveringReferences;
var createBacklinksToPages;
var backlinksIgnoreRedundantPages;
var backlinksIgnoreOverflowText;
var defaultDirectory = false;
var useDefaultDirectory = false;
var langBibliographyName = "References";
var langAuthorConnector = "and";
var langEditorString = "Edt.";
var langOnlineAsOfString = "online as of";
var xmlSettingsTag = 'zoteroImportSettings';
var neutralCharacterStyleBetweenPageUsages = false;
var referenceParagraphStyleHead;
var referenceParagraphStyleHeadString = "Level \\ Level X"; //paragraph style of the page header
var intextRefCharStart = "[";
var intextRefCharEnd = "]";
//progress bar und timer
var individualReferenceProgressBarSpace = 50;
var individualBibliographyItemProgressBarSpace = 20;
var individualBacklinksProgressBarSpace = 20;
var myMaximumValue = 32;
var myProgressBarWidth = 400;
var myReferenceTooltipIndexCounter = 0;
var timeStart, timeEnd;
var stime;
//Locate and run the glue code.jsx file.
var myFilePath = app.filePath + "/Scripts/xml rules/glue code.jsx";
if(File(myFilePath).exists == false){
myFilePath = File.openDialog("Locate the file: glue code.jsx");
}
if(myFilePath != null){
var myFile = File(myFilePath); app.doScript(myFile);
main();
} else {
alert('unable to locate glue code.jsc');
}
function main(){
myDocument = app.documents.item(0);
//define styles and tag vars
parsedReferenceStyle = returnCharacterStyleOrCreatenew("parsedReference","References");
noReferenceStyle = myDocument.characterStyles[0]; //[0] should always be equal to [None], but as the name for [none] is internationalised, we cannot use myDocument.characterStyles.item("[None]"), but have to use the first object in the document character styles array
styleAuthor = returnCharacterStyleOrCreatenew("REF-Autor","References");
styleYear = returnCharacterStyleOrCreatenew("REF-Jahr","References");
styleBacklink= returnCharacterStyleOrCreatenew("REF-Backlink","References",{pointSize:8});
styleTitle = returnCharacterStyleOrCreatenew("REF-Titel","References");
referenceParagraphStyle = returnParagraphStyleOrCreatenew("References", "References", {
leftIndent: 6,
firstLineIndent: -6,
spaceAfter: 3,
pointSize:10,
appliedFont: "Minion Pro",
fontStyle: "Regular"
});
referenceHoverParagraphStyle = returnParagraphStyleOrCreatenew("References Hover", "References", {
basedOn: referenceParagraphStyle,
firstLineIndent: 0,
leftIndent: 0
});
hoverObjectLayer = returnLayerOrCreatenew("Hover Objects");
hoverTriggerStyle = returnObjectStyleOrCreatenew("Hover Object Trigger (hidden)",{
enableFill: true,
fillColor: myDocument.swatches[0],
//~ objectEffectsEnablingSettings: {
//~ enableTransparency: true },
//~ transparencySettings: {
//~ blendingSettings: {
//~ blendMode: BlendMode.MULTIPLY, opacity: 30}},
enableStroke: true,
strokeColor: myDocument.swatches[0],
enableTextWrapAndOthers: true,
textWrapPreferences: {
textWrapMode: TextWrapModes.NONE}
});
hoverTextFrameStyle = returnObjectStyleOrCreatenew("Hover Textframe",{
enableFill: true,
fillColor: myDocument.swatches[2],
fillTint: 100,
objectEffectsEnablingSettings: {
enableTransparency: false },
enableStroke: true,
strokeColor: myDocument.swatches[3],
strokeWeight: .1,
enableTextWrapAndOthers: true,
textWrapPreferences: {
textWrapMode: TextWrapModes.NONE},
enableTextFrameGeneralOptions: true,
enableTextFrameAutoSizingOptions: true,
textFramePreferences :{
ignoreWrap: true,
textColumnCount: 1,
autoSizingType: AutoSizingTypeEnum.HEIGHT_ONLY,
autoSizingReferencePoint: AutoSizingReferenceEnum.TOP_CENTER_POINT,
insetSpacing:4}
});
//set tag or create new
try{
parsedReferenceTag = myDocument.xmlTags.item('referencetag');
name = parsedReferenceTag.name;
} catch(e) {
parsedReferenceTag = myDocument.xmlTags.add('referencetag');
}
//ask for options
if (!userSettingsDialog()){
return false;
}
if (safeBeforeStart){
myDocument.save();
}
//set refresh mode
if (redrawMode == false){
app.scriptPreferences.enableRedraw = false;
} else {
app.scriptPreferences.enableRedraw = true;
}
//zeitmessung starten
timeStart = new Date().getTime();
//progress bar
myCreateProgressPanel(myMaximumValue + individualReferenceProgressBarSpace + (createBacklinksToPages ? individualBacklinksProgressBarSpace : 0), myProgressBarWidth);
myProgressPanel.show();
myProgressPanel.myProgressBar.value = 0;
myProgressPanel.myText.text = "Starting Import";
//import XML file
if (!myImportXMLFileUsingDefaults()) {
return false;
}
//show unknown genres so that we can improve the script when a new genre comes up
if (error_publishtypes.length > 0){
alert("Following genres where unknown:\n" + error_publishtypes);
}
//show errors
if (error_general.length > 0){
alert("There where following errors:\n" + error_general.join("\n"));
}
//show warnings (if activated)
if (notice_general.length > 0 && showWarnings){
alert("There where following warnings:\n" + notice_general.join("\n\n"));
}
//show warnings (if activated)
if (notice_ambiguities.length > 0 && checkForAmbiguousCitekeys){
alert("Following citekeys where ambiguous:\n" + notice_ambiguities.join("\n"));
}
}
//asks for a xml file and imports it using set defaults
function myImportXMLFileUsingDefaults(){
myProgressPanel.myText.text = "Loading XML File";
myProgressPanel.myProgressBar.value = 1;
//xml file pre-read
var myXMLFile;
if (useDefaultDirectory){
myXMLFile = new File(defaultDirectory);
}
else {
myXMLFile = File.openDialog("Please select the Zotero XML file", "*.xml");
if (myXMLFile == null) {
alert('You cancelled. Aborting script.');
return false;
}
//write default directory setting
checkOrWriteSetting("defaultDirectory",myXMLFile);
}
if (!myXMLFile.exists){
checkOrWriteSetting("defaultDirectory","");
alert('error reading file');
exit();
}
myXMLFile.open('r');
myProgressPanel.myText.text = "Reading XML File";
var myXMLStr = myXMLFile.read(); //read XML file into variable
myXMLFile.close(); //close XML file
var root = new XML(myXMLStr); //convert variable into XML object
var xc = root.xpath("//mods"); //all elements in the XML File
if (xc.length() < 1){
checkOrWriteSetting("defaultDirectory","");
alert("no valid Items found in file");
return false;
}
//$.writeln('Number of references in XML found: ' + xc .length());
myProgressPanel.myText.text = "Finding new citations";
//USING FIND
// Clear the find/change grep preferences
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;
// Set the find options
app.findChangeGrepOptions.includeFootnotes = true;
app.findChangeGrepOptions.includeHiddenLayers = false;
app.findChangeGrepOptions.includeLockedLayersForFind = false;
app.findChangeGrepOptions.includeLockedStoriesForFind = false;
app.findChangeGrepOptions.includeMasterPages = false;
app.findGrepPreferences.findWhat = '\\\\cite[rayt]?\\{[^{}]*\\}';
var myFindings = myDocument.findGrep();
// Clear the find/change grep preferences again
app.findGrepPreferences = NothingEnum.NOTHING;
app.changeGrepPreferences = NothingEnum.NOTHING;
myProgressPanel.myText.text = "Parsing new citations";
for (var i = myFindings.length - 1; i >= 0; i--){
myProgressPanel.myText.text = "Parsing new citations (" + (myFindings.length - i) + "/" + myFindings.length + ")";
var myRawCitekey = myFindings[i].texts[0];
var myCitekeyMatchArray = myRawCitekey.contents.match(/\\(cite[rayt]?)\{([^{}]*)\}/);
var myCiteType = myCitekeyMatchArray[1];
var myCitekey = myCitekeyMatchArray[2];
//continue and alert if no proper citekey was found (shouldnt ever happen, because this is part of a grep find with exactyly the same regex)
if (!myCitekey || myCitekey == ''){
error_general.push("Error when parsing citekey " + myRawCitekey.contents);
continue;
}
//create xml element and add attributes
var myNewXMLElement;
try{
//first create a new xml element in the associated xml element
myNewXMLElement = myRawCitekey.associatedXMLElements[0].xmlElements.add(parsedReferenceTag);
} catch(e){
myDocument.xmlElements[0].xmlElements.add('storyelement',myRawCitekey.parentStory);
myNewXMLElement = myRawCitekey.associatedXMLElements[0].xmlElements.add(parsedReferenceTag);
}
//apply an attribute
myNewXMLElement.xmlAttributes.add('citekey',myCitekey.replace(/^\s+|\s+$/g, '')); //safe attribute using trimming
//add attribute describing the citekey type
switch(myCiteType){
case 'citea':
myNewXMLElement.xmlAttributes.add('citetype','authorOnly');
break;
case 'citey':
myNewXMLElement.xmlAttributes.add('citetype','yearOnly');
break;
case 'cite':
myNewXMLElement.xmlAttributes.add('citetype','default');
break;
case 'citer':
myNewXMLElement.xmlAttributes.add('citetype','noBrackets');
break;
case 'citet':
myNewXMLElement.xmlAttributes.add('citetype','titleOnly');
break;
default:
//to extend, add the new cite command and make sure that you add it to the 2 regular expressions (find settings and also in this for loop)
myNewXMLElement.xmlAttributes.add('citetype','unknown type');
error_general.push("cannot determine cite type for" + myCitekey);
break;
}
//link the xmlelment (which was, until now, at the end of the structure) to the text (the xml element then moves to the right point in the structure, according to the occurence of the text)
if (myRawCitekey.parent.constructor.name == 'Footnote'){
notice_general.push('References cannot be in footnotes, ignoring key ' + myCitekey + ' (type ' + myNewXMLElement.xmlAttributes.itemByName('citetype').value + ').');
} else {
myRawCitekey.markup(myNewXMLElement);
foundNew++;
}
}
myProgressPanel.myText.text = "Parsing document structure";
myProgressPanel.myProgressBar.value = 2;
myXML= myDocument.xmlElements[0];
var allReferenceTags = myXML.evaluateXPathExpression("//referencetag");
myProgressPanel.myText.text = "Deleting empty elements";
myProgressPanel.myProgressBar.value = 3;
//now, all new citekeys have been tagged. we can parse the document xml and collect unique citekeys. go backwards, because we want to delete empty elements
for (var r = allReferenceTags.length - 1; r >=0 ; r--){
//see if the element content was empty and delete the tag and the item in the array if so
if (allReferenceTags[r].contents.replace(/^\s+|\s+$/g, '') == ''){
allReferenceTags[r].remove(); //removes the tag
allReferenceTags.splice(r,1); //removes the item in the array
removedOld++;
continue;
}
//add citetype attribute if not already done (for compatibility reasons with older documents)
try{
allReferenceTags[r].xmlAttributes.itemByName('citetype').value;
}
catch(e) {
notice_general.push(allReferenceTags[r].xmlAttributes.item('citekey').value + ' did not have citetype attribute. adding default attribute.');
allReferenceTags[r].xmlAttributes.add('citetype','default');
}
//store citekey in an array to be sorted and processed later
myCitekeyInfo.getKey(allReferenceTags[r].xmlAttributes.item('citekey').value);
foundTotal++;
}
myProgressPanel.myText.text = "Sorting references";
myProgressPanel.myProgressBar.value = 4;
//sort references in bibliography by citekey
myCitekeyInfo.sortKeys();
myProgressPanel.myText.text = "Deleting old hyperlink sources";
myProgressPanel.myProgressBar.value = 5;
//CLEAN UP
//delete existing hyperlink sources (text anchors within the xmlelement.content)
if (myDocument.hyperlinkTextSources.length > 0){
for(var i = myDocument.hyperlinkTextSources.length -1; i >= 0; i--){
//$.writeln("checking hyperlink source " + i + " (" + myDocument.hyperlinkTextSources[i].name + ")");
//do not remove the contents of the comment around the OR condition. this might be needed to clean older files, that did not use labels but used names starting with ZotRefSrc (as they do now, but regex match is slow...)
//somehow, the second "or" condition seems to be necessary, even though the label should identify all links.
//TODO: check why the regex is necessary
if (myDocument.hyperlinkTextSources[i].label == 'zotrefLinksrc' || myDocument.hyperlinkTextSources[i].label == 'zotRefBacklinkSource' || myDocument.hyperlinkTextSources[i].name.match(/ZotRefSrc[0-9]+/i)){
//$.writeln("deleted source: " + allHyperlinkSources[i].name + ", label: " + allHyperlinkSources[i].label);
myDocument.hyperlinkTextSources[i].remove();
}
}
}
myProgressPanel.myText.text = "Deleting old hyperlink destinations";
myProgressPanel.myProgressBar.value = 6;
//delete all hyperlink destinations
if (myDocument.hyperlinkTextDestinations.length > 0){
for (var i = myDocument.hyperlinkTextDestinations.length - 1; i >= 0; i--){
//$.writeln("checking hyperlink destination " + i + " (" + myDocument.hyperlinkTextDestinations[i].label + ")");
if (myDocument.hyperlinkTextDestinations[i].label == 'zotrefLinkDest' || myDocument.hyperlinkTextDestinations[i].label == 'zotrefBackLinkDest') {
myDocument.hyperlinkTextDestinations[i].remove();
}
}
}
myProgressPanel.myText.text = "Preparing deletion of old hyperlinks";
myProgressPanel.myProgressBar.value = 7;
//~ $.writeln('hyperlink deletion start');
//delete all hyperlinks (seems to be unnecessary as hyperlinks (src - dest)) are automatically deleted when the hyperlink source is deleted)
//hyperlink destinations need not to be deleted as they are deleted with the emptying of the reference frame
if (myDocument.hyperlinks.length > 0){
var hyperlinksToBeDeleted = Array();
for (var i = myDocument.hyperlinks.length - 1; i >= 0; i--){
//$.writeln("checking hyperlink " + i + " (" + myDocument.hyperlinks[i].label + ")");
if (myDocument.hyperlinks[i].label == 'zotrefHyperlink'){
hyperlinksToBeDeleted.push(myDocument.hyperlinks[i]);
//myDocument.hyperlinks[i].remove();
//$.writeln('marked hyperlink ' + i);
}
}
myProgressPanel.myText.text = "Deleting " + hyperlinksToBeDeleted.length + " old hyperlinks that where in collection";
for (var c = hyperlinksToBeDeleted.length - 1; c >= 0; c--){
hyperlinksToBeDeleted[c].remove();
}
}
myProgressPanel.myText.text = "Deleting old tooltip buttons and trigger buttons";
myProgressPanel.myProgressBar.value = 8;
//remove all old hover and trigger buttons
for(var i = myDocument.buttons.length - 1; i >=0; i--){
if (myDocument.buttons.item(i).label == 'zotRefHoverButton' || myDocument.buttons.item(i).label == 'zotRefTriggerButton'){
myDocument.buttons.item(i).remove();
}
}
myProgressPanel.myText.text = "Looking for bibliography textframe";
myProgressPanel.myProgressBar.value = 9;
//CREATE REFERENCE TEXT FRAME
//find reference text frame
for (var i = 0; i < myDocument.pages.count(); i++){
for (var j = 0; j < myDocument.pages[i].textFrames.count(); j++){
if (myDocument.pages[i].textFrames[j].label == 'references'){
myRefTextFrame = myDocument.pages[i].textFrames[j];
myRefTextFrame.parentStory.contents = "";
if (langBibliographyName != '[NONE]'){
addFormattedTextToStory(myRefTextFrame,false,(langBibliographyName == '' ? " " : langBibliographyName),referenceParagraphStyleHead);
}
}
}
}
//create new page with textframe for references if none was found
if (!myRefTextFrame){
var newPage = myDocument.pages.add();
myRefTextFrame = newPage.textFrames.add();
myRefTextFrame.label = 'references';
//move and scale the text frame to the right dimensions, according on the side the page is placed
if (newPage.side == PageSideOptions.RIGHT_HAND){
myRefTextFrame.geometricBounds = [newPage.marginPreferences.top,newPage.bounds[1] + newPage.marginPreferences.left,newPage.bounds[2] - newPage.marginPreferences.bottom,newPage.bounds[3] - newPage.marginPreferences.right];
} else {
myRefTextFrame.geometricBounds = [newPage.marginPreferences.top,newPage.bounds[1] + newPage.marginPreferences.right,newPage.bounds[2] - newPage.marginPreferences.bottom,newPage.bounds[3] - newPage.marginPreferences.left];
}
if (langBibliographyName != '[NONE]'){
addFormattedTextToStory(myRefTextFrame,false,(langBibliographyName == '' ? " " : langBibliographyName),referenceParagraphStyleHead);
}
notice_general.push("Page " + (newPage.documentOffset+1) + " was created with the textframe for the references. If you want to define your own reference textframe, please create a textframe with the script-label \"references\". This textframe (and the parent story) will be emptied and filled with references.");
}
myProgressPanel.myText.text = "Building bibliography";
myProgressPanel.myProgressBar.value = 10; //the loop will add 20 to that (=individualBibliographyItemProgressBarSpace)
//search for citekey in the xml file and add to the references textframe
findings:
for(var i = 0; i < myCitekeyInfo.citeKeyArray.length; i++){
myProgressPanel.myText.text = "Building bibliography " + (i+1) + "/" + myCitekeyInfo.citeKeyArray.length + ": " + myCitekeyInfo.citeKeyArray[i].citeKey;
myProgressPanel.myProgressBar.value += individualBibliographyItemProgressBarSpace / myCitekeyInfo.citeKeyArray.length;
//search for citekey in the xml document
xmlcontents:
for(var c = 0; c < xc .length(); c++){
if (xc[c].citeKey == myCitekeyInfo.citeKeyArray[i].citeKey){
myCitekeyInfo.citeKeyArray[i].found = true;
//add a linebreak, if a bibliography title was set, or ignore the first line if none was set
if (i != 0 || langBibliographyName != '[NONE]'){
addFormattedTextToStory(myRefTextFrame,false, "\r",false);
}
myCitekeyInfo.citeKeyArray[i].hyperlinkTextDestination = myDocument.hyperlinkTextDestinations.add(myRefTextFrame.parentStory.insertionPoints[-1],{name:"ref-" + xc[c].citeKey, label: 'zotrefLinkDest'}); //create a hyperlink text destination and safe it in the meta data of the citation
addFormattedTextToStory(myRefTextFrame,styleAuthor, getAuthorNames(xc[c]),referenceParagraphStyle);
addFormattedTextToStory(myRefTextFrame,styleTitle, getTitle(xc[c]));
addFormattedTextToStory(myRefTextFrame,styleYear, getPublishedIn(xc[c]));
addFormattedTextToStory(myRefTextFrame,styleYear, getYearAndPublisher(xc[c]));
//safe an insertion point in the paragraph in metadata to later be able to adress the paragraph (ie. for duplication of the paragraph into a button)
myCitekeyInfo.citeKeyArray[i].bibParagraphInsertionPoint = myRefTextFrame.parentStory.insertionPoints[-2].index; //use -2, to not get the last insertionpoint, which moves as new content is added
continue findings;
}
}
error_general.push("CITEKEY NOT FOUND: " + myCitekeyInfo.citeKeyArray[i].citeKey);
}
myProgressPanel.myText.text = "Adding bibliography to textframe";
myProgressPanel.myProgressBar.value = 31;
//add a final linebreak to story. otherwise, we cannot insert things after the last paragraph
addFormattedTextToStory(myRefTextFrame,false, "\r",false);
myProgressPanel.myText.text = "Parsing tags in document";
myProgressPanel.myProgressBar.value = 32; //the loop will add 50 to that (=individualReferenceProgressBarSpace)
stime = new splittime();
stime.addtime('until loop');
//now, all citekeys where searched and all citekeys in the text have a tag. we can parse the tags and replace the contents by the reference. alternatively, we could make a text search
//for all the citekeys and replace one citekey at a time - maybe better performace, but this would make updating impossible!
var buttonNumber = 0;
for (var r = 0; r < allReferenceTags.length; r++){
stime.addtime("loop " + r + " start");
var currentRefTagXMLElement = allReferenceTags[r];
var currentKey = currentRefTagXMLElement.xmlAttributes.item('citekey').value;
var currentCitetype = currentRefTagXMLElement.xmlAttributes.item('citetype').value;
var currentCitekeyItem = myCitekeyInfo.getItemByKey(currentKey);
stime.addtime("loop " + r + " vars (" + currentKey + ")");
//detailled progress bar for tooltips
myProgressPanel.myText.text = "Reference " + (createHoveringReferences ? "and tooltip " : "") + (r+1) + "/" + allReferenceTags.length + ": " + currentKey;
myProgressPanel.myProgressBar.value += individualReferenceProgressBarSpace / allReferenceTags.length;
//write NOT FOUND tag into reference keys that where not found in the parsed xml file. parse a file where they exist and the text will be replaced by the valid reference info
if (currentCitekeyItem.found == false){
currentRefTagXMLElement.contents = "[??NOTFOUND??]";
continue;
}
//to see the title in the indesign structure view, add the title as an attribute to the indesign-xml-element. this is especially helpful for ambiguous tags (ie. smith2010 vs. smith2010-1)
try{
currentRefTagXMLElement.xmlAttributes.itemByName('title').value = currentCitekeyItem.title;
}
catch(e) {
currentRefTagXMLElement.xmlAttributes.add('title', currentCitekeyItem.title)
}
stime.addtime("loop " + r + " progress bar and error output");
switch(currentCitetype){
case 'default':
currentRefTagXMLElement.contents = intextRefCharStart + myCitekeyInfo.getReference(currentKey) + intextRefCharEnd;
currentRefTagXMLElement.applyCharacterStyle(parsedReferenceStyle);
break;
case 'noBrackets':
currentRefTagXMLElement.contents = myCitekeyInfo.getReference(currentKey);
currentRefTagXMLElement.applyCharacterStyle(parsedReferenceStyle);
break;
case 'authorOnly':
currentRefTagXMLElement.contents = currentCitekeyItem.author;
currentRefTagXMLElement.applyCharacterStyle(noReferenceStyle);
break;
case 'yearOnly':
currentRefTagXMLElement.contents = currentCitekeyItem.year.toString();
currentRefTagXMLElement.applyCharacterStyle(noReferenceStyle);
break;
case 'titleOnly':
currentRefTagXMLElement.contents = currentCitekeyItem.title.toString();
currentRefTagXMLElement.applyCharacterStyle(noReferenceStyle);
break;
}
stime.addtime("loop " + r + " contents and style");
//add hyperlinks to the reference in the text. for this, select the text first
var myReferenceTagText = currentRefTagXMLElement.characters.itemByRange(currentRefTagXMLElement.insertionPoints.firstItem(),currentRefTagXMLElement.insertionPoints.lastItem());
//check if the selection or anything in the paragraph is already a hyperlink
var foundHyperlinks = myReferenceTagText.findHyperlinks();
if (foundHyperlinks[0].length < 1){
//if the following line causes an error, maybe there are old textsources in the document. remove them by removing the comment tags around allHyperlinkSources[i].name.match(/ZotRefSrc[0-9]+/i)
//if the error is something about an existing hyperlink, check this if condition, because this _should_ find already existing hyperlinks and skip the creation. however, the found object is a bit strange and is only distinguishable by "length"
var myReferenceSource = myDocument.hyperlinkTextSources.add(myReferenceTagText,{name:"ZotRefSrc" + r, label: "zotrefLinksrc"});
myDocument.hyperlinks.add(myReferenceSource,currentCitekeyItem.hyperlinkTextDestination,{name: r + "_" + currentKey,label:"zotrefHyperlink"});
}
else {
//activate the following line if you want to be notified about skipped links
//find out page number
var errorPageNumber;
if (currentRefTagXMLElement.texts[0].parentTextFrames[0] == undefined){
errorPageNumber = "[OVERFLOW TEXT]";
} else {
errorPageNumber = currentRefTagXMLElement.texts[0].parentTextFrames[0].parentPage.name;
}
notice_general.push("Already a link: skipping Hyperlink creation for reference " + myReferenceTagText.contents + " on page " + errorPageNumber);
}
stime.addtime("loop " + r + " hyperlinks");
//add hover effects
//create new
if (createHoveringReferences == true){
switch(currentCitetype){
case 'default':
case 'noBrackets':
createReferenceButton(currentRefTagXMLElement, currentCitekeyItem, buttonNumber);
buttonNumber++;
break;
}
}
stime.addtime("loop " + r + " hover effects");
//create an anchor (hyperlink destination) to link back to this citation
//only create the anchor if it is a 'real' reference
switch(currentCitetype){
case 'default':
case 'noBrackets':
try{
var thisHyperlinkDestination = myDocument.hyperlinkTextDestinations.add(currentRefTagXMLElement.insertionPoints.firstItem(),{name:"back-" + currentKey + "-to-" + r, label: 'zotrefBackLinkDest'}); //create a linkdestination to the reference in the text. this will be linked in the bibliography (with the small page numbers)
} catch(e) {
if (e.number == 79110) {
//remove the old Hyperlink with the same name. These hyperlinks seem to remain when you copy paste contents via the clipboard - probably because the label is not copied, which is why they are not deleted upon the beginning of this script
myDocument.hyperlinkTextDestinations.itemByName("back-" + currentKey + "-to-" + r).remove();
//warn about this
alert("Deleted old hyperlink \"" + "back-" + currentKey + "-to-" + r + "\". The hyperlink was probably left over after copy-paste actions. No need to worry, however, this error should not occur often and only after copy-paste actions. The script will continue now.");
//try again after deleting old link
thisHyperlinkDestination = myDocument.hyperlinkTextDestinations.add(currentRefTagXMLElement.insertionPoints.firstItem(),{name:"back-" + currentKey + "-to-" + r, label: 'zotrefBackLinkDest'}); //create a linkdestination to the reference in the text. this will be linked in the bibliography (with the small page numbers)
} else {
alert("Unknown Error: " + e.message + "\n\nExiting.");
exit();
}
}
currentCitekeyItem.usages.push(thisHyperlinkDestination);
break;
}
}
myProgressPanel.myText.text = "Adding backlinks"; //individualBacklinksProgressBarSpace
myProgressPanel.myProgressBar.value = 83; //the following loop, if backlinks are activated, will add 20 to that (=individualBacklinksProgressBarSpace)
stime.addtime("done with loop");
//now, add the page usages to the bibliography, that has already been created
if (createBacklinksToPages){
//first, create a link format
//which reference format to use
var crossRefFormatBuildingBlocks =
[ //this array should be containing all parameters (3) needed for buildingBlocks.add
[BuildingBlockTypes.CUSTOM_STRING_BUILDING_BLOCK,null,"["],
[BuildingBlockTypes.PAGE_NUMBER_BUILDING_BLOCK,null,null],
[BuildingBlockTypes.CUSTOM_STRING_BUILDING_BLOCK,null,"]"]
];
var crossRefFormat = returnCrossrefFormatOrCreatenew('Backlink',null,crossRefFormatBuildingBlocks); //myDocument.crossReferenceFormats.itemByName('Backlink'); //TODO: i8n
//now parse all references (safed in the myCitekeyInfo Array)
for(var i = myCitekeyInfo.citeKeyArray.length - 1; i >= 0; i--){
myProgressPanel.myText.text = "Adding backlinks - " + (myCitekeyInfo.citeKeyArray.length - i)+ "/" + myCitekeyInfo.citeKeyArray.length;
myProgressPanel.myProgressBar.value += individualBacklinksProgressBarSpace / myCitekeyInfo.citeKeyArray.length;
var currentCitekeyItem = myCitekeyInfo.citeKeyArray[i];
//save previous page number to remove redundant page links
var previousLinkDestinationPage = 0;
if (currentCitekeyItem.usages.length > 0){
//sort array by page number
currentCitekeyItem.usages.sort(sortLinkDestinationArrayByPage);
//parse all usages
for(var u = 0; u < currentCitekeyItem.usages.length; u++){
//the usage (linkdestination) of that loop
var currentUsage = currentCitekeyItem.usages[u];
//check the integrity of the document. see if the link destination is a correct story, or an XML-Story element that was left over after copy paste actions
if (currentUsage.destinationText.parentStory.constructor.name == "XmlStory"){
error_general.push("Link to " + currentCitekeyItem.citeKey + " (" + u + ") is in an xmlStory Element. Please check your document structure and delete unlinked xmlStories.");
continue;
}
//ignore overflow text
var currentLinkIsOverflow = !checkLinkdestinationForOverflow(currentUsage);
if (currentLinkIsOverflow == true){
//if overflow text should not be linked
if (backlinksIgnoreOverflowText !== true){
continue;
}
//otherwise safe a warning and include the overflow text
notice_general.push("Link to " + currentCitekeyItem.citeKey + " (" + u + ") is in overflow section");
}
//ignore redundant page links
var currentLinkDestinationPage = (currentLinkIsOverflow ? -1 : parseInt(currentUsage.destinationText.parentTextFrames[0].parentPage.name));
//compare to previous run
if (backlinksIgnoreRedundantPages !== true && currentLinkDestinationPage == previousLinkDestinationPage){
continue;
}
//save for later
previousLinkDestinationPage = currentLinkDestinationPage;
//add a space and comma
var currentParagraphLastInsertionPoint = myRefTextFrame.parentStory.insertionPoints[currentCitekeyItem.bibParagraphInsertionPoint].paragraphs[0].insertionPoints[-2];
//reset character style between page usages if set
if (neutralCharacterStyleBetweenPageUsages){
currentParagraphLastInsertionPoint.appliedCharacterStyle = myDocument.characterStyles[0]; //no character style for things between the page numbers
}
//add separation after first or space before first
currentParagraphLastInsertionPoint.contents += (u > 0 ? ", " : " ");
//the end of the current paragraph
var crossTextEndIns = myRefTextFrame.parentStory.insertionPoints[currentCitekeyItem.bibParagraphInsertionPoint].paragraphs[0].insertionPoints[-2];
//create a new cross refrence source
//the source is the text that you click in order to get to the destination
var myCrossReferenceSource = myDocument.crossReferenceSources.add(crossTextEndIns,crossRefFormat,{
name: "ZotRefBacklinkSource_" + currentCitekeyItem.citeKey + "-" + u,
label: "zotRefBacklinkSource",
appliedCharacterStyle: styleBacklink});
//create the link back to the usage of the reference
myDocument.hyperlinks.add(myCrossReferenceSource,currentUsage,{name: i + "_" + " _" + u + "_" + currentCitekeyItem.citeKey,label:"zotrefHyperlink"});
}
} else {
//warn if there are no usages
notice_general.push("No usages (link destinations) found for " + currentCitekeyItem.citeKey);
}
}
}
stime.addtime("backlinks");
//check for ambiguities
if (checkForAmbiguousCitekeys){
myProgressPanel.myText.text = "Checking for ambiguous citekeys";
//parse all citekeys in XML file
for(var c = 0; c < xc.length(); c++){
//found some -1 citekeys?
if (xc[c].citeKey.substr(-2,2) == '-1'){
var ambiCiteKeyRootLength = xc[c].citeKey.toString().length - 2;
var ambiCiteKeyRoot = xc[c].citeKey.substr(0,ambiCiteKeyRootLength);
//is the citekey(or the root) used at all?
var ambiCiteKeyUsedList = new Array();
for(var i = 0; i < myCitekeyInfo.citeKeyArray.length; i++){
//compare all used citekeys with the rootname of the citekey in question
if (myCitekeyInfo.citeKeyArray[i].citeKey.substr(0,ambiCiteKeyRootLength) == ambiCiteKeyRoot){
ambiCiteKeyUsedList.push(myCitekeyInfo.citeKeyArray[i].citeKey);
}
}
//count occurences in XML file
var ambiCiteKeyXmlOccurrences = 0;
for(var o = 0; o < xc.length(); o++){
//compare with citekey root
if (xc[o].citeKey.substr(0,ambiCiteKeyRootLength) == ambiCiteKeyRoot){
ambiCiteKeyXmlOccurrences++;
}
}
//if the citekey is used
if (ambiCiteKeyUsedList.length > 0) {
notice_ambiguities.push(ambiCiteKeyRoot + ", used: " + ambiCiteKeyUsedList.length + " times, " + ambiCiteKeyXmlOccurrences + " duplicates in XML\n" +
"> used as:\n - " +
ambiCiteKeyUsedList.join("\n - "));
}
}
}
}
stime.addtime("ambiguous citekeys");
myProgressPanel.myText.text = "Done";
myProgressPanel.myProgressBar.value = myProgressPanel.myProgressBar.maxvalue;
myProgressPanel.hide();
if (showStatistics){
timeEnd = new Date().getTime();
alert(
"Done\nNew citations: " + foundNew +
"\nExisting citations: " + (foundTotal - foundNew) +
"\nRemoved existing: " + removedOld +
"\nNumber of unique references: " + myCitekeyInfo.citeKeyArray.length +
"\n\nin " + Math.ceil((timeEnd - timeStart) / 1000.0) + " seconds"
);
}
//$.writeln(stime.stoptimer());
return true;
}
function createReferenceButton(referenceTextXMLElement, citekeyItem, buttonNumber){
stime.addtime("- start hover effects");
var firstInsertionpoint = referenceTextXMLElement.insertionPoints.firstItem();
stime.addtime("- get first point");
//return if the reference is not within a textframe
if (firstInsertionpoint.parentTextFrames[0] == undefined || firstInsertionpoint.parentTextFrames[0].isValid == false){
stime.addtime("- exitting");
return false;
}
stime.addtime("- checking parent textframes");
var refPage;
var theReferenceText = referenceTextXMLElement.texts[0];
var currentKey = citekeyItem.citeKey;
var hoverElementDistance = 2; //distance to text
var maskOffset = 1; //how much bigger than the text
var hoverWidth = 70; //width of the hovering element
stime.addtime("- vars");
//first, create all maskrectangles and collect them in an array
var maskRectangles = Array();
//if it is a single line
if (theReferenceText.lines.length == 1){
refPage = referenceTextXMLElement.insertionPoints.firstItem().parentTextFrames[0].parentPage;
var ry1 = theReferenceText.insertionPoints.item(0).baseline + maskOffset;
var ry2 = theReferenceText.insertionPoints.item(0).baseline - theReferenceText.texts[0].ascent - maskOffset;
var rx1 = theReferenceText.insertionPoints.item(0).horizontalOffset - maskOffset;
var rx2 = theReferenceText.insertionPoints.item(-1).endHorizontalOffset + maskOffset;
maskRectangles.push(refPage.rectangles.add({geometricBounds:[ry1,rx1,ry2,rx2], label: "zotRefHoverTrigger",itemLayer: hoverObjectLayer, appliedObjectStyle: hoverTriggerStyle}));
stime.addtime("- rects (single line)");
}
//if the text spans over more than one line
else {
//prepare array with parameters for rectangles. if refPage.rectangles.add is called in this loop, indesign crashes...
var maskRectanglesPreparation = Array();
for(var l = 0; l < theReferenceText.lines.length; l++){
var currentLine = theReferenceText.lines.item(l);
//break if the line is not within a text frame
if (currentLine.parentTextFrames.length == 0){
break;
}
//page of the line
refPage = currentLine.parentTextFrames[0].parentPage;
var ry1 = currentLine.baseline + maskOffset;
var ry2 = currentLine.baseline - currentLine.ascent - maskOffset;
var rx1 = currentLine.horizontalOffset - maskOffset;
var rx2 = currentLine.endHorizontalOffset + maskOffset;
if (l == 0){
//exception first line:
rx1 = theReferenceText.insertionPoints.item(0).horizontalOffset - maskOffset;
} else if (l == theReferenceText.lines.length - 1) {
//exception last line
rx2 = theReferenceText.insertionPoints.item(-1).endHorizontalOffset + maskOffset;
}
//neues array und folgende zeile in eine weitere for schleife setzen!
maskRectanglesPreparation.push([ry1,rx1,ry2,rx2]);
}
//now add the rectangles
for(var rec = 0; rec < maskRectanglesPreparation.length; rec++){
maskRectangles.push(refPage.rectangles.add({geometricBounds: maskRectanglesPreparation[rec], label: "zotRefHoverTrigger", itemLayer: hoverObjectLayer, appliedObjectStyle: hoverTriggerStyle}));
}
stime.addtime("- rects (multiple lines)");
}
//then, create the tooltip geometry
var firstRectPage = maskRectangles[0].parentPage;
var hovergBounds = [maskRectangles[0].geometricBounds[2] + hoverElementDistance - maskOffset,maskRectangles[0].geometricBounds[1] + maskOffset, maskRectangles[0].geometricBounds[2] + 5 + hoverElementDistance - maskOffset, maskRectangles[0].geometricBounds[1] + hoverWidth];
var hoverTextFrame = firstRectPage.textFrames.add({itemLayer: hoverObjectLayer, geometricBounds: hovergBounds, label: 'zotRefHoverTextframe', appliedObjectStyle: hoverTextFrameStyle});
stime.addtime("- text frame");
//duplicate the reference paragraph into the text frame
myRefTextFrame.parentStory.insertionPoints[citekeyItem.bibParagraphInsertionPoint].paragraphs[0].duplicate(LocationOptions.AT_BEGINNING,hoverTextFrame.insertionPoints.firstItem()).appliedParagraphStyle = referenceHoverParagraphStyle;
hoverTextFrame.characters[-1].remove(); //removing the linebreak at the end of the paragraph
stime.addtime("- paragraph duplication");
//check position
var pos = hoverTextFrame.geometricBounds;
var pageBounds = hoverTextFrame.parentPage.bounds;
var pagePadding = 5; //distance to keep from page boundaries
//left point out left?
if (pos[1] < pageBounds[1] + pagePadding){
hoverTextFrame.move(undefined,[pageBounds[1] - pos[1] + pagePadding, 0]);
}
//right point our right
else if (pos[3] > pageBounds[3] - pagePadding){
hoverTextFrame.move(undefined,[pageBounds[3] - pos[3] - pagePadding, 0]);
}
//top point out top
if (pos[0] < pageBounds[0] + pagePadding){
hoverTextFrame.move(undefined,[0, pageBounds[0] - pos[0] + pagePadding]);
}
//bottom point out bottom
else if (pos[2] > pageBounds[2] - pagePadding){
hoverTextFrame.move(undefined,[0, pageBounds[2] - pos[2] - pagePadding]);
}
stime.addtime("- position check");
//create the hover button
var hoverButton = firstRectPage.buttons.add({itemLayer: hoverObjectLayer, geometricBounds: hoverTextFrame.geometricBounds, label: 'zotRefHoverButton'});
hoverButton.states.item(0).addItemsToState(hoverTextFrame);
hoverButton.hiddenUntilTriggered = true;
hoverButton.name = 'zotRefHover' + buttonNumber + "_" + referenceTextXMLElement.xmlAttributes.item('citekey').value;
hoverButton.bringToFront();
stime.addtime("- hover button");
//now that the hovering text is created, we can trigger the tooltip with our line masks
for (var i = 0; i < maskRectangles.length; i++){
var currentLineRect = maskRectangles[i];
var triggerButton = firstRectPage.buttons.add({itemLayer: hoverObjectLayer, geometricBounds: currentLineRect.geometricBounds, label: 'zotRefTriggerButton'});
triggerButton.states.item(0).addItemsToState(currentLineRect);
triggerButton.name = 'zotRefTrigger' + buttonNumber + "." + i + "_" + referenceTextXMLElement.xmlAttributes.item('citekey').value;
triggerButton.showHideFieldsBehaviors.add({behaviorEvent:BehaviorEvents.MOUSE_ENTER, fieldsToShow: hoverButton});
triggerButton.showHideFieldsBehaviors.add({behaviorEvent:BehaviorEvents.MOUSE_EXIT, fieldsToHide: hoverButton});
triggerButton.showHideFieldsBehaviors.add({behaviorEvent:BehaviorEvents.MOUSE_DOWN, fieldsToHide: hoverButton}); //necessary, because otherwise the hover will stay visible when clicked (page jumps to reference and no MOUSE_EXIT is triggered)
triggerButton.gotoAnchorBehaviors.add({behaviorEvent:BehaviorEvents.MOUSE_UP, anchorItem: citekeyItem.hyperlinkTextDestination});
triggerButton.sendToBack();
}
stime.addtime("- behaviours and now done hover effects");
}
function addFormattedTextToStory(myTextframe,myFormat,myContent,myParagraphFormat){
if (!myContent) return false;
//safe insertion point index
var firstInsertionPoint = myTextframe.parentStory.insertionPoints[-1].index;
//add text
myTextframe.parentStory.insertionPoints[-1].contents += myContent;
var myAdditions = myTextframe.parentStory.characters.itemByRange(myTextframe.parentStory.insertionPoints[firstInsertionPoint],myTextframe.parentStory.insertionPoints[-1]);
//add formatting
if (myFormat) {
myAdditions.appliedCharacterStyle = myFormat;
}
if (myParagraphFormat) {
myAdditions.appliedParagraphStyle = myParagraphFormat;
}
return true;
}
function getPublishedIn(modPart){
var publishedIn;
//return if book (books are not published in anything
var genre = modPart.xpath("genre[@authority='local']");
if (genre.toString() == 'book' || genre.toString() == 'thesis') {
if (modPart.xpath("relatedItem[@type='host']/titleInfo[not(@type = 'abbreviated')]/title") != '') {
notice_general.push(modPart.citeKey + ' seems to have a related published medium, but the genre is ' + genre.toString() + '. please check this item');
}
//check thesis type and return that if found
if (genre.toString() == 'thesis'){
//see if there is a genre tag without authority attribute (in fact, no attribute, but [not(@*)] causes errors) - this will contain the thesis type
var thesisType = modPart.xpath("genre[not(@authority)]");
if (thesisType.toString() != '') {
publishedIn = ", " + thesisType.toString();
//$.writeln("thesis type of " + modPart.citeKey + ": " + thesisType.toString());
return publishedIn;
}
}
return false;
}
publishedIn = modPart.xpath("relatedItem[@type='host']/titleInfo[not(@type = 'abbreviated')]/title");
if (!publishedIn || publishedIn.toString() == "") {
//genres that do not necessarily need a published medium
if (genre.toString() == 'report'){
return false;
}
notice_general.push("could not find the published medium for " + modPart.citeKey);
return false;
}
//get editors
var editorArray = getNameArray(modPart.xpath("relatedItem[@type='host']/name[@type='personal' or @type='corporate']"), ['edt']);
var editors = "";
if (editorArray.length > 0){
for (var n = 0; n < editorArray.length; n++){
editors += (n > 0 && n != editorArray.length-1 ? ", " : (n == editorArray.length-1 && editorArray.length != 1 ? " " + langAuthorConnector + " " : "")) + editorArray[n].fullName;
}
editors += " (" + langEditorString + "), ";
}
//combine texts
switch(modPart.xpath("relatedItem[@type='host']/genre[@authority='marcgt']").toString()) {
case 'book':
case 'journal':
case 'conference publication':
publishedIn = ", in: " + editors + publishedIn;
break;
default:
publishedIn = ", " + publishedIn;
break;
}
return publishedIn;
}
function getNameArray(names, roleArray){
if (names.length() == 0) return false;
var allNames = new Array();
//parse names
for(var n = 0; n < names.length(); n++){
var role = names[n].xpath("role/roleTerm").toString().replace(/^\s+|\s+$/g, '');
if (findObjInArray(roleArray,role)) {
var thisName;
var lastName = names[n].xpath("namePart[@type='family']").toString();
var firstName = names[n].xpath("namePart[@type='given']").toString().substr(0,1) + ".";
if (!lastName || lastName == '') {
thisName = names[n].xpath("namePart[not(@type)]'"); //take namepart that does not have any attributes, if given and family name where not specified
if (!thisName){
continue;
}
}
else {
thisName = lastName + (firstName ? ", " + firstName : "");
}
allNames.push({'fullName': thisName, 'firstName': firstName, 'lastName': (lastName && lastName != '' ? lastName : thisName)});
}
}
return allNames;
}
function getAuthorNames(modPart,depth){