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:
parent
dc73c66d96
commit
97d810fc22
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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: ', ';
|
||||
}
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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');
|
||||
|
|
Loading…
Reference in New Issue
Block a user