Closes #654, reports need to export child items independently from parent items

Two options currently only available via about:config, combineChildItems and includeAllChildItems (which really means "Include All Child Items If Only Parent Items Are Selected")

Other changes:

- Moved Zotero.Utilities.cleanString() functionality to ZU.trimInternal() and created a regular trim() too that doesn't consolidate internal whitespace.
- Removed Zotero.getAll(), replaced with Zotero.Collection.getChildItems() and a new onlyTopLevel flag to Zotero.Items.getAll(). Also removed unused Zotero.getAttachments.
- Fixed XML parsing error during report generation when a long URL contained a trailing space
This commit is contained in:
Dan Stillman 2007-09-12 08:59:34 +00:00
parent dc73c66d96
commit 97d810fc22
10 changed files with 524 additions and 284 deletions

View File

@ -58,7 +58,7 @@ var Zotero_Report_Interface = new function() {
/*
* Load a report for the currently selected collection
* Load a report for the currently selected items
*/
function loadItemReport() {
var items = ZoteroPane.getSelectedItems(true);

View File

@ -1624,7 +1624,8 @@ Zotero.Item.prototype.getAttachmentCharset = function(){
/**
* Returns an array of attachment itemIDs that have this item as a source
* Returns an array of attachment itemIDs that have this item as a source,
* or FALSE if none
**/
Zotero.Item.prototype.getAttachments = function(){
if (this.isAttachment()){
@ -2490,10 +2491,16 @@ Zotero.Items = new function(){
/*
* Returns all items in the database
*
* If |onlyTopLevel|, don't include child items
*/
function getAll(){
function getAll(onlyTopLevel) {
var sql = 'SELECT itemID FROM items';
// DEBUG: default order?
if (onlyTopLevel) {
sql += ' A LEFT JOIN itemNotes B USING (itemID) '
+ 'LEFT JOIN itemAttachments C ON (C.itemID=A.itemID) '
+ 'WHERE B.sourceItemID IS NULL AND C.sourceItemID IS NULL';
}
var ids = Zotero.DB.columnQuery(sql);
return this.get(ids);
@ -3202,6 +3209,29 @@ Zotero.Collection.prototype.removeItems = function(itemIDs) {
Zotero.DB.commitTransaction();
}
/*
* Returns an array of child items of this collecetion as Zotero.Item instances,
* or FALSE if none
*/
Zotero.Collection.prototype.getChildItems = function () {
if (!this._childItemsLoaded){
this._loadChildItems();
}
if (this._childItems.length == 0) {
return false;
}
var toLoad = [];
for (var id in this._childItems.items) {
toLoad.push(id);
}
return Zotero.Items.get(toLoad);
}
/**
* Check if an item belongs to the collection
**/
@ -4742,50 +4772,3 @@ Zotero.getCollections = function(parent, recursive){
return toReturn;
}
/*
* Zotero.getItems(parent)
*
* Returns an array of all items that are children of a collection--or all
* items if no parent provided--as Zotero.Item instances
*/
Zotero.getItems = function(parent){
var toReturn = new Array();
if (!parent){
// Not child items
var sql = "SELECT A.itemID FROM items A LEFT JOIN itemNotes B USING (itemID) "
+ "LEFT JOIN itemAttachments C ON (C.itemID=A.itemID) WHERE B.sourceItemID IS NULL"
+ " AND C.sourceItemID IS NULL";
}
else {
var sql = 'SELECT itemID FROM collectionItems '
+ 'WHERE collectionID=' + parent;
}
var children = Zotero.DB.columnQuery(sql);
if (!children){
if (!parent){
Zotero.debug('No items in library', 5);
}
else {
Zotero.debug('No child items of collection ' + parent, 5);
}
return toReturn;
}
return Zotero.Items.get(children);
}
Zotero.getAttachments = function(){
var toReturn = [];
var sql = "SELECT A.itemID FROM items A JOIN itemAttachments B ON "
+ "(B.itemID=A.itemID) WHERE B.sourceItemID IS NULL";
var items = Zotero.DB.query(itemAttachments);
return Zotero.Items.get(items);
}

View File

@ -31,7 +31,8 @@ Zotero.Report = new function() {
/^http:\/\/([^\.]*\.)?nytimes\.com/
];
function generateHTMLDetails(items) {
function generateHTMLDetails(items, combineChildItems) {
var ZU = new Zotero.Utilities();
var escapeXML = ZU.htmlSpecialChars;
@ -43,214 +44,63 @@ Zotero.Report = new function() {
content += '<link rel="stylesheet" type="text/css" href="chrome://zotero/skin/report/detail.css"/>\n';
content += '<link rel="stylesheet" type="text/css" media="screen,projection" href="chrome://zotero/skin/report/detail_screen.css"/>\n';
content += '<link rel="stylesheet" type="text/css" media="print" href="chrome://zotero/skin/report/detail_print.css"/>\n';
content += '</head>\n<body>\n';
content += '</head>\n\n<body>\n';
content += '<ul class="report">\n';
content += '<ul class="report' + (combineChildItems ? ' combineChildItems' : '') + '">\n';
for each(var arr in items) {
//Zotero.debug(arr);
content += '\n<li id="i' + arr.itemID + '" class="item ' + arr.itemType + '">\n';
content += '<li id="i' + arr.itemID + '" class="item ' + arr.itemType + '">\n';
// Title
if (arr.title) {
content += '<h2>' + escapeXML(arr.title) + '</h2>\n';
}
// Metadata table
var table = false;
var tableContent = '<table>\n';
// Item type
tableContent += '<tr>\n';
tableContent += '<th>'
+ escapeXML(Zotero.getString('itemFields.itemType'))
+ '</th>\n';
tableContent += '<td>' + escapeXML(Zotero.getString('itemTypes.' + arr['itemType'])) + '</td>\n';
tableContent += '</tr>\n';
// Creators
if (arr['creators']) {
table = true;
var displayText;
for each(var creator in arr['creators']) {
// Two fields
if (creator['fieldMode']==0) {
displayText = creator['firstName'] + ' ' + creator['lastName'];
}
// Single field
else if (creator['fieldMode']==1) {
displayText = creator['lastName'];
}
else {
// TODO
}
tableContent += '<tr>\n';
tableContent += '<th class="' + creator.creatorType + '">'
+ escapeXML(Zotero.getString('creatorTypes.' + creator.creatorType))
+ '</th>\n';
tableContent += '<td>' + escapeXML(displayText) + '</td>\n';
tableContent += '</tr>\n';
}
}
// Move dateAdded and dateModified to the end of the array
var da = arr['dateAdded'];
var dm = arr['dateModified'];
delete arr['dateAdded'];
delete arr['dateModified'];
arr['dateAdded'] = da;
arr['dateModified'] = dm;
for (var i in arr) {
// Skip certain fields
switch (i) {
case 'itemType':
case 'itemID':
case 'sourceItemID':
case 'title':
case 'firstCreator':
case 'creators':
case 'tags':
case 'seeAlso':
case 'notes':
case 'note':
case 'attachments':
continue;
}
try {
var localizedFieldName = Zotero.getString('itemFields.' + i);
}
// Skip fields we don't have a localized string for
catch (e) {
Zotero.debug('Localized string not available for ' + 'itemFields.' + i, 2);
continue;
}
// Skip empty fields
if (!arr[i]) {
continue;
}
table = true;
var fieldText;
// Shorten long URLs manually until Firefox wraps at ?
// (like Safari) or supports the CSS3 word-wrap property
var firstSpace = arr[i].indexOf(' ');
if (arr[i].indexOf('http://') === 0 &&
((firstSpace == -1 && arr[i].length > 29) || firstSpace > 29)) {
var stripped = false;
// Strip query string for sites we know don't need it
for each(var re in _noQueryStringSites) {
if (re.test(arr[i])){
var pos = arr[i].indexOf('?');
if (pos != -1) {
fieldText = arr[i].substr(0, pos);
stripped = true;
}
break;
}
}
if (!stripped) {
// Add a line-break after the ? of long URLs,
fieldText = arr[i].replace('?', "?<ZOTEROBREAK/>");
// Strip query string variables from the end while the
// query string is longer than the main part
var pos = fieldText.indexOf('?');
if (pos != -1) {
while (pos < (fieldText.length / 2)) {
var lastAmp = fieldText.lastIndexOf('&');
if (lastAmp == -1) {
break;
}
fieldText = fieldText.substr(0, lastAmp);
var shortened = true;
}
// Append '&...' to the end
if (shortened) {
fieldText += "&<ZOTEROHELLIP/>";
}
}
}
if (i == 'url' && firstSpace == -1) {
fieldText = '<a href="' + escapeXML(arr[i]) + '">'
+ escapeXML(fieldText) + '</a>';
}
}
// Remove SQL date from multipart dates
// (e.g. '2006-00-00 Summer 2006' becomes 'Summer 2006')
else if (i=='date') {
fieldText = escapeXML(Zotero.Date.multipartToStr(arr[i]));
}
// Convert dates to local format
else if (i=='accessDate' || i=='dateAdded' || i=='dateModified') {
var date = Zotero.Date.sqlToDate(arr[i], true)
fieldText = escapeXML(date.toLocaleString());
// Top-level item matched search, so display title
if (arr.reportSearchMatch) {
content += '<h2>' + escapeXML(arr.title) + '</h2>\n';
}
// Non-matching parent, so display "Parent Item: [Title]"
else {
fieldText = escapeXML(arr[i]);
content += '<h2 class="parentItem">' + escapeXML(Zotero.getString('report.parentItem'))
+ ' <span class="title">' + escapeXML(arr.title) + '</span></h2>';
}
}
// If parent matches search, display parent item metadata table and tags
if (arr.reportSearchMatch) {
content += _generateMetadataTable(arr);
tableContent += '<tr>\n<th>' + escapeXML(localizedFieldName)
+ '</th>\n<td>' + fieldText + '</td>\n</tr>\n';
}
if (table) {
content += tableContent + '</table>\n';
}
// Tags
if (arr['tags'] && arr['tags'].length) {
// TODO: localize
content += '<h3 class="tags">' + escapeXML('Tags') + '</h3>\n';
content += '<ul class="tags">\n';
for each(var tag in arr.tags) {
content += '<li>' + escapeXML(tag.tag) + '</li>\n';
content += _generateTagsList(arr);
// Independent note
if (arr['note']) {
content += '<p>' + escapeXML(arr['note']) + '</p>\n';
}
content += '</ul>\n';
}
// Child notes
if (arr['notes'] && arr['notes'].length) {
// TODO: localize
content += '<h3 class="notes">' + escapeXML(Zotero.getString('itemFields.notes')) + '</h3>\n';
content += '<ul class="notes">\n';
for each(var note in arr['notes']) {
content += '<li id="i' + note.itemID + '">\n';
content += '<p>' + escapeXML(note.note) + '</p>\n';
content += '</li>\n';
// Children
if (arr.reportChildren) {
// Child notes
if (arr.reportChildren.notes.length) {
// Only display "Notes:" header if parent matches search
if (arr.reportSearchMatch) {
content += '<h3 class="notes">' + escapeXML(Zotero.getString('report.notes')) + '</h3>\n';
}
content += '<ul class="notes">\n';
for each(var note in arr.reportChildren.notes) {
content += '<li id="i' + note.itemID + '">\n';
content += '<p>' + escapeXML(note.note) + '</p>\n';
// Child note tags
content += _generateTagsList(note);
content += '</li>\n';
}
content += '</ul>\n';
}
content += '</ul>\n';
// Chid attachments
content += _generateAttachmentsList(arr.reportChildren);
}
// Independent note
if (arr['note']) {
content += '<p>' + escapeXML(arr['note']) + '</p>\n';
}
// Attachments
if (arr['attachments'] && arr['attachments'].length) {
content += '<h3 class="attachments">' + escapeXML(Zotero.getString('itemFields.attachments')) + '</h3>\n';
content += '<ul class="attachments">\n';
for each(var attachment in arr['attachments']) {
content += '<li id="i' + attachment.itemID + '">';
content += escapeXML(attachment.title);
content += '</li>\n';
}
content += '</ul>\n';
}
// Attachments
if (arr['seeAlso'] && arr['seeAlso'].length) {
// Related
if (arr.reportSearchMatch && arr['seeAlso'] && arr['seeAlso'].length) {
content += '<h3 class="related">' + escapeXML(Zotero.getString('itemFields.related')) + '</h3>\n';
content += '<ul class="related">\n';
var relateds = Zotero.Items.get(arr['seeAlso']);
@ -263,7 +113,7 @@ Zotero.Report = new function() {
}
content += '</li>\n';
content += '</li>\n\n';
}
content += '</ul>\n';
content += '</body>\n</html>';
@ -275,4 +125,206 @@ Zotero.Report = new function() {
function generateHTMLList(items) {
}
function _generateMetadataTable(arr) {
var ZU = new Zotero.Utilities();
var escapeXML = ZU.htmlSpecialChars;
var table = false;
var content = '<table>\n';
// Item type
content += '<tr>\n';
content += '<th>'
+ escapeXML(Zotero.getString('itemFields.itemType'))
+ '</th>\n';
content += '<td>' + escapeXML(Zotero.getString('itemTypes.' + arr['itemType'])) + '</td>\n';
content += '</tr>\n';
// Creators
if (arr['creators']) {
table = true;
var displayText;
for each(var creator in arr['creators']) {
// Two fields
if (creator['fieldMode']==0) {
displayText = creator['firstName'] + ' ' + creator['lastName'];
}
// Single field
else if (creator['fieldMode']==1) {
displayText = creator['lastName'];
}
else {
// TODO
}
content += '<tr>\n';
content += '<th class="' + creator.creatorType + '">'
+ escapeXML(Zotero.getString('creatorTypes.' + creator.creatorType))
+ '</th>\n';
content += '<td>' + escapeXML(displayText) + '</td>\n';
content += '</tr>\n';
}
}
// Move dateAdded and dateModified to the end of the array
var da = arr['dateAdded'];
var dm = arr['dateModified'];
delete arr['dateAdded'];
delete arr['dateModified'];
arr['dateAdded'] = da;
arr['dateModified'] = dm;
for (var i in arr) {
// Skip certain fields
switch (i) {
case 'reportSearchMatch':
case 'reportChildren':
case 'itemType':
case 'itemID':
case 'sourceItemID':
case 'title':
case 'firstCreator':
case 'creators':
case 'tags':
case 'seeAlso':
case 'notes':
case 'note':
case 'attachments':
continue;
}
try {
var localizedFieldName = Zotero.getString('itemFields.' + i);
}
// Skip fields we don't have a localized string for
catch (e) {
Zotero.debug('Localized string not available for ' + 'itemFields.' + i, 2);
continue;
}
arr[i] = ZU.trim(arr[i] + '');
// Skip empty fields
if (!arr[i]) {
continue;
}
table = true;
var fieldText;
// Shorten long URLs manually until Firefox wraps at ?
// (like Safari) or supports the CSS3 word-wrap property
var firstSpace = arr[i].indexOf(' ');
if (arr[i].indexOf('http://') === 0 &&
((firstSpace == -1 && arr[i].length > 29) || firstSpace > 29)) {
var stripped = false;
// Strip query string for sites we know don't need it
for each(var re in _noQueryStringSites) {
if (re.test(arr[i])){
var pos = arr[i].indexOf('?');
if (pos != -1) {
fieldText = arr[i].substr(0, pos);
stripped = true;
}
break;
}
}
if (!stripped) {
// Add a line-break after the ? of long URLs
fieldText = arr[i].replace('?', "?<ZOTEROBREAK/>");
// Strip query string variables from the end while the
// query string is longer than the main part
var pos = fieldText.indexOf('?');
if (pos != -1) {
while (pos < (fieldText.length / 2)) {
var lastAmp = fieldText.lastIndexOf('&');
if (lastAmp == -1) {
break;
}
fieldText = fieldText.substr(0, lastAmp);
var shortened = true;
}
// Append '&...' to the end
if (shortened) {
fieldText += "&<ZOTEROHELLIP/>";
}
}
}
if (i == 'url' && firstSpace == -1) {
fieldText = '<a href="' + escapeXML(arr[i]) + '">'
+ escapeXML(fieldText) + '</a>';
}
}
// Remove SQL date from multipart dates
// (e.g. '2006-00-00 Summer 2006' becomes 'Summer 2006')
else if (i=='date') {
fieldText = escapeXML(Zotero.Date.multipartToStr(arr[i]));
}
// Convert dates to local format
else if (i=='accessDate' || i=='dateAdded' || i=='dateModified') {
var date = Zotero.Date.sqlToDate(arr[i], true)
fieldText = escapeXML(date.toLocaleString());
}
else {
fieldText = escapeXML(arr[i]);
}
content += '<tr>\n<th>' + escapeXML(localizedFieldName)
+ '</th>\n<td>' + fieldText + '</td>\n</tr>\n';
}
content += '</table>';
return table ? content : '';
}
function _generateTagsList(arr) {
var ZU = new Zotero.Utilities();
var escapeXML = ZU.htmlSpecialChars;
var content = '';
if (arr['tags'] && arr['tags'].length) {
var str = Zotero.getString('report.tags');
content += '<h3 class="tags">' + escapeXML(str) + '</h3>\n';
content += '<ul class="tags">\n';
for each(var tag in arr.tags) {
content += '<li>' + escapeXML(tag.tag) + '</li>\n';
}
content += '</ul>\n';
}
return content;
}
function _generateAttachmentsList(arr) {
var ZU = new Zotero.Utilities();
var escapeXML = ZU.htmlSpecialChars;
var content = '';
if (arr.attachments && arr.attachments.length) {
content += '<h3 class="attachments">' + escapeXML(Zotero.getString('itemFields.attachments')) + '</h3>\n';
content += '<ul class="attachments">\n';
for each(var attachment in arr.attachments) {
content += '<li id="i' + attachment.itemID + '">';
content += escapeXML(attachment.title);
// Attachment tags
content += _generateTagsList(attachment);
content += '</li>\n';
}
content += '</ul>\n';
}
return content;
}
}

View File

@ -1690,19 +1690,19 @@ Zotero.Translate.prototype._export = function() {
this._itemsLeft = this.items;
} else if(this.collection) {
// get items in this collection
this._itemsLeft = Zotero.getItems(this.collection.getID());
this._itemsLeft = this.collection.getChildItems();
if(this.configOptions.getCollections) {
// get child collections
this._collectionsLeft = Zotero.getCollections(this.collection.getID(), true);
// get items in child collections
for each(var collection in this._collectionsLeft) {
this._itemsLeft = this._itemsLeft.concat(Zotero.getItems(collection.getID()));
this._itemsLeft = this._itemsLeft.concat(collection.getChildItems());
}
}
} else {
// get all items
this._itemsLeft = Zotero.getItems();
// get all top-level items
this._itemsLeft = Zotero.Items.getAll(true);
if(this.configOptions.getCollections) {
// get all collections

View File

@ -85,17 +85,42 @@ Zotero.Utilities.prototype.cleanAuthor = function(author, type, useComma) {
return {firstName:firstName, lastName:lastName, creatorType:type};
}
/*
* Removes leading and trailing whitespace from a string
*/
Zotero.Utilities.prototype.trim = function(s) {
if (typeof(s) != "string") {
throw "trim: argument must be a string";
}
s = s.replace(/^\s+/, "");
return s.replace(/\s+$/, "");
}
/*
* Cleans whitespace off a string and replaces multiple spaces with one
*/
Zotero.Utilities.prototype.cleanString = function(s) {
if(typeof(s) != "string") {
throw "cleanString: argument must be a string";
Zotero.Utilities.prototype.trimInternal = function(s) {
if (typeof(s) != "string") {
throw "trimInternal: argument must be a string";
}
s = s.replace(/[\xA0\r\n\s]+/g, " ");
s = s.replace(/^\s+/, "");
return s.replace(/\s+$/, "");
return this.trim(s);
}
/*
* Cleans whitespace off a string and replaces multiple spaces with one
*
* DEPRECATED: use trimInternal()
*/
Zotero.Utilities.prototype.cleanString = function(s) {
Zotero.debug("cleanString() is deprecated; use trimInternal() instead", 2);
return this.trimInternal(s);
}
/*

View File

@ -470,7 +470,8 @@ var Zotero = new function(){
"No chrome package registered for chrome://communicator",
'[JavaScript Error: "Components is not defined" {file: "chrome://nightly/content/talkback/talkback.js',
'[JavaScript Error: "document.getElementById("sanitizeItem")',
'chrome://webclipper'
'chrome://webclipper',
'No chrome package registered for chrome://piggy-bank'
];
for (var i=0; i<blacklist.length; i++) {
@ -1007,7 +1008,7 @@ Zotero.Keys = new function() {
**/
Zotero.Hash = function(){
this.length = 0;
this.items = new Array();
this.items = {};
// Public methods defined on prototype below

View File

@ -439,6 +439,9 @@ citation.showEditor = Show Editor...
citation.hideEditor = Hide Editor...
report.title.default = Zotero Report
report.parentItem = Parent Item:
report.notes = Notes:
report.tags = Tags:
annotations.confirmClose.title = Are you sure you want to close this annotation?
annotations.confirmClose.body = All text will be lost.

View File

@ -15,13 +15,29 @@ h1, h2, h3, h4, h5, h6 {
}
h2 {
margin: 0 0 .75em;
padding: 0 0 0.25em;
margin: 0 0 .5em;
}
h2.parentItem {
font-weight: bold;
font-size: 1em;
padding: 0 0 .5em;
border-bottom: 1px solid #ccc;
}
/* If combining children, display parent slightly larger */
ul.report.combineChildItems h2.parentItem {
font-size: 1.1em;
padding-bottom: .75em;
margin-bottom: .4em;
}
h2.parentItem .title {
font-weight: normal;
}
h3 {
margin-bottom: .5em;
margin-bottom: .6em;
font-weight: bold !important;
font-size: 1em;
display: block;
@ -46,7 +62,11 @@ ul {
padding-left: 0;
}
/* Display tags as comma-separated lists */
/* Tags */
h3.tags {
font-size: 1.1em;
}
ul.tags {
line-height: 1.75em;
list-style: none;
@ -62,14 +82,33 @@ ul.tags li:not(:last-child):after {
/* Child notes */
h3.notes {
font-size: 1.1em;
}
ul.notes {
margin-bottom: 1.2em;
}
ul.notes li {
ul.notes > li:first-child p {
margin-top: 0;
}
ul.notes > li {
padding: .7em 0;
}
ul.notes > li:not(:last-child) {
border-bottom: 1px #ccc solid;
}
ul.notes li:last-child {
border-bottom: none;
ul.notes > li p:first-child {
margin-top: 0;
}
ul.notes > li p:last-child {
margin-bottom: 0;
}
@ -81,3 +120,21 @@ ul.notes li p, li.note p {
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
/* Display tags within child notes inline */
ul.notes h3.tags {
display: inline;
font-size: 1em;
}
ul.notes h3.tags:after {
content: ' ';
}
ul.notes ul.tags {
display: inline;
}
ul.notes ul.tags li:not(:last-child):after {
content: ', ';
}

View File

@ -102,7 +102,8 @@ function ChromeExtensionHandler() {
switch (type){
case 'collection':
var results = Zotero.getItems(ids);
var col = Zotero.Collections.get(ids);
var results = col.getChildItems();
break;
case 'search':
@ -124,21 +125,133 @@ function ChromeExtensionHandler() {
if (!results) {
var results = Zotero.Items.get(ids);
}
var items = [];
// Only include parent items
for (var i=0; i<results.length; i++) {
if (!results[i].getSource()) {
items.push(results[i]);
if (!results) {
mimeType = 'text/html';
content = 'Invalid ID';
break generateContent;
}
}
if (!items){
mimeType = 'text/html';
content = 'Invalid ID';
break generateContent;
var items = [];
var itemsHash = {}; // key = itemID, val = position in |items|
var searchItemIDs = {}; // hash of all selected items
var searchParentIDs = {}; // hash of parents of selected child items
var searchChildIDs = {}; // hash of selected chlid items
var includeAllChildItems = Zotero.Prefs.get('report.includeAllChildItems');
var combineChildItems = Zotero.Prefs.get('report.combineChildItems');
for (var i=0; i<results.length; i++) {
// Don't add child items directly
// (instead mark their parents for inclusion below)
var sourceItemID = results[i].getSource();
if (sourceItemID) {
searchParentIDs[sourceItemID] = true;
searchChildIDs[results[i].getID()] = true;
// Don't include all child items if any child
// items were selected
includeAllChildItems = false;
}
// If combining children, add matching parents
else if (combineChildItems) {
itemsHash[results[i].getID()] = items.length;
items.push(results[i].toArray());
// Flag item as a search match
items[items.length - 1].reportSearchMatch = true;
}
searchItemIDs[results[i].getID()] = true;
}
// If including all child items, add children of all matched
// parents to the child array
if (includeAllChildItems) {
for (var id in searchItemIDs) {
if (!searchChildIDs[id]) {
var children = [];
var item = Zotero.Items.get(id);
var func = function (ids) {
if (ids) {
for (var i=0; i<ids.length; i++) {
searchChildIDs[ids[i]] = true;
}
}
};
func(item.getNotes());
func(item.getAttachments());
}
}
}
if (combineChildItems) {
// Add parents of matches if not parents aren't matches themselves
for (var id in searchParentIDs) {
if (!searchItemIDs[id]) {
var item = Zotero.Items.get(id);
itemsHash[id] = items.length;
items.push(item.toArray());
}
}
// Add children to reportChildren property of parents
for (var id in searchChildIDs) {
var item = Zotero.Items.get(id);
var parentItemID = item.getSource();
if (!items[itemsHash[parentItemID]].reportChildren) {
items[itemsHash[parentItemID]].reportChildren = {
notes: [],
attachments: []
};
}
if (item.isNote()) {
items[itemsHash[parentItemID]].reportChildren.notes.push(item.toArray());
}
if (item.isAttachment()) {
items[itemsHash[parentItemID]].reportChildren.attachments.push(item.toArray());
}
}
}
// If not combining children, add a parent/child pair
// for each matching child
else {
for (var id in searchChildIDs) {
var item = Zotero.Items.get(id);
var parentID = item.getSource();
var parentItem = Zotero.Items.get(parentID);
if (!itemsHash[parentID]) {
// If parent is a search match and not yet added,
// add on its own
if (searchItemIDs[parentID]) {
itemsHash[parentID] = [items.length];
items.push(parentItem.toArray());
items[items.length - 1].reportSearchMatch = true;
}
else {
itemsHash[parentID] = [];
}
}
// Now add parent and child
itemsHash[parentID].push(items.length);
items.push(parentItem.toArray());
if (item.isNote()) {
items[items.length - 1].reportChildren = {
notes: [item.toArray()],
attachments: []
};
}
else if (item.isAttachment()) {
items[items.length - 1].reportChildren = {
notes: [],
attachments: [item.toArray()]
};
}
}
}
// Sort items
if (!sortBy) {
sortBy = 'title';
@ -171,8 +284,8 @@ function ChromeExtensionHandler() {
// Multidimensional sort
do {
var cmp = collation.compareString(0,
a.getField(sorts[index].field),
b.getField(sorts[index].field)
a[sorts[index].field],
b[sorts[index].field]
);
if (cmp == 0) {
@ -188,10 +301,11 @@ function ChromeExtensionHandler() {
};
items.sort(compareFunction);
// Convert item objects to export arrays
for (var i=0; i<items.length; i++) {
items[i] = items[i].toArray();
for (var i in items) {
if (items[i].reportChildren) {
items[i].reportChildren.notes.sort(compareFunction);
items[i].reportChildren.attachments.sort(compareFunction);
}
}
// Pass off to the appropriate handler
@ -207,7 +321,7 @@ function ChromeExtensionHandler() {
default:
format = 'html';
mimeType = 'application/xhtml+xml';
content = Zotero.Report.generateHTMLDetails(items);
content = Zotero.Report.generateHTMLDetails(items, combineChildItems);
}
}
catch (e){
@ -362,7 +476,8 @@ function ChromeExtensionHandler() {
switch (type){
case 'collection':
var results = Zotero.getItems(ids);
var col = Zotero.Collections.get(ids);
var results = col.getChildItems();
break;
case 'search':

View File

@ -47,6 +47,10 @@ pref("extensions.zotero.fulltext.textMaxLength", 500000);
pref("extensions.zotero.fulltext.pdfMaxPages", 100);
pref("extensions.zotero.search.useLeftBound", true);
// Reports
pref("extensions.zotero.report.includeAllChildItems", true);
pref("extensions.zotero.report.combineChildItems", true);
// Export and citation settings
pref("extensions.zotero.export.lastTranslator", '14763d24-8ba0-45df-8f52-b8d1108e7ac9');
pref("extensions.zotero.export.translatorSettings", 'true,false');