Skip to content

Commit

Permalink
Project name tagging
Browse files Browse the repository at this point in the history
Adds support for setting a project name in one or more documents
via the integration plugin. Project names are set as special-purpose
tags in the client, with a tag type of 10000. Tagging is performed
automatically whenever the citations in the document are updated.
Updates to tagging are cumulative, to allow multiple documents to
share the same project name.

In the client, project names behave as follows:

* In the tag selector:
    - Project names are displayed immediately
      after colored tags, with distinctive styling.
    - If both project name and an ordinary tag of the same name
      exist, the two are displayed separately.
    - Project names can be deleted in the tag selector; other
      operations (renaming, colorizing) are not available.
    - Deleting a project name or ordinary tag affects only
      the name/tag of that type.
    - Adding or renaming an ordinary tag with the same name
      as a project name has no effect on the project name or
      its dependent items.
    - HOWEVER: selecting a project name will also select
      an ordinary tag of the same time, if one exists.

* In the item tag box:
    - Project names do no appear in the tags box of individual items.
  • Loading branch information
fbennett committed Apr 26, 2014
1 parent 2016e7f commit 37f79e7
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 36 deletions.
20 changes: 19 additions & 1 deletion chrome/content/zotero/bibliography.js
Expand Up @@ -42,7 +42,8 @@ var Zotero_File_Interface_Bibliography = new function() {
this.citationPrimary = citationPrimary;
this.citationSecondary = citationSecondary;
this.citationSetAffixes = citationSetAffixes;
this.setLanguageRoleHighlight = setLanguageRoleHighlight
this.setLanguageRoleHighlight = setLanguageRoleHighlight;
this.editProjectName = editProjectName;

/*
* Initialize some variables and prepare event listeners for when chrome is done
Expand Down Expand Up @@ -157,6 +158,13 @@ var Zotero_File_Interface_Bibliography = new function() {
}
}

// Set project name (integrationDocPrefs.xul only)

var projectName = document.getElementById('project-name');
if (projectName) {
projectName.value = _io.projectName ? _io.projectName : '';
}

// Also ONLY for integrationDocPrefs.xul: update language selections

// initialize options display from provided params
Expand Down Expand Up @@ -574,5 +582,15 @@ var Zotero_File_Interface_Bibliography = new function() {
}
return count;
}

function editProjectName () {
var projectName = document.getElementById('project-name').value;
_io['projectName'] = projectName;
}

function displayProjectName () {
var projectNameNode = document.getElementById('project-name');
projectNameNode.value = _io['projectName'];
}
}

102 changes: 77 additions & 25 deletions chrome/content/zotero/bindings/tagselector.xml
Expand Up @@ -92,7 +92,7 @@
<property name="_types">
<getter>
<![CDATA[
var types = [0];
var types = [0,10000];
if (this.showAutomatic) {
types.push(1);
}
Expand Down Expand Up @@ -205,8 +205,6 @@
this.init();
fetch = true;
}
Zotero.debug('Refreshing tags selector');
var emptyColored = true;
var emptyRegular = true;
var tagsToggleBox = this.id('tags-toggle');
Expand All @@ -230,6 +228,19 @@
return collation.compareString(1, a.name, b.name);
});
var projectNameObjects = Zotero.Tags.getProjectNames(self.libraryID);
var projectNamesById = {};
for (var i=0,ilen=projectNameObjects.length;i<ilen;i+=1) {
var projectNameObject = projectNameObjects[i];
orderedTags.unshift({
id: projectNameObject.tagID,
name: projectNameObject.name,
type: 10000,
hasColor: false
});
projectNamesById[projectNameObject.tagID] = projectNameObjects[i];
}
var tagColorsLowerCase = {};
var colorTags = [];
for (let name in tagColors) {
Expand All @@ -239,22 +250,26 @@
var positions = Object.keys(colorTags);
for (let i=positions.length-1; i>=0; i--) {
let name = colorTags[positions[i]];
let ids = Zotero.Tags.getIDs(name, self.libraryID);
let ids = Zotero.Tags.getIDs(name, self.libraryID, false);
orderedTags.unshift({
id: ids ? ids.join('-') : null,
name: name,
type: 0,
hasColor: true
});
}
var lastTag;
for (let i=0; i<orderedTags.length; i++) {
let tagObj = orderedTags[i];
// Skip colored tags in the regular section,
// since we add them to the beginning above
if (!tagObj.hasColor && tagColorsLowerCase[tagObj.name.toLowerCase()]) {
if (!tagObj.hasColor && tagColorsLowerCase[tagObj.name.toLowerCase()] && tagObj.type != 10000) {
continue;
}
if (tagObj.hasColor !== false && projectNamesById[tagObj.id]) {
continue;
}
Expand All @@ -263,7 +278,7 @@
tagButton.addEventListener('click', function(event) {
self.handleTagClick(event, this);
});
if (self.editable) {
if (self.editable && tagObj.type !== 10000) {
tagButton.addEventListener('dragover', self.dragObserver.onDragOver);
tagButton.addEventListener('dragexit', self.dragObserver.onDragExit);
tagButton.addEventListener('drop', self.dragObserver.onDrop, true);
Expand All @@ -288,11 +303,14 @@
let lcname = name.toLowerCase();
let colorData = tagColors[name];
if (colorData) {
if (colorData && labels[i].getAttribute('tagType') != 10000) {
labels[i].setAttribute(
'style', 'color:' + colorData.color + '; ' + 'font-weight: bold'
);
}
else if (labels[i].getAttribute('tagType') == 10000) {
labels[i].classList.add('project-name');
}
else {
labels[i].removeAttribute('style');
}
Expand Down Expand Up @@ -339,25 +357,25 @@
}
else if (self.filterToScope) {
if (self._hasScope && inScope) {
labels[i].className = 'zotero-clicky';
labels[i].classList.add('zotero-clicky');
labels[i].setAttribute('inScope', true);
labels[i].setAttribute('hidden', false);
emptyRegular = false;
}
else {
labels[i].className = '';
labels[i].classList.remove('zotero-clicky');
labels[i].setAttribute('hidden', true);
labels[i].setAttribute('inScope', false);
}
}
// Display all
else {
if (self._hasScope && inScope) {
labels[i].className = 'zotero-clicky';
labels[i].classList.add('zotero-clicky');
labels[i].setAttribute('inScope', true);
}
else {
labels[i].className = '';
labels[i].classList.remove('zotero-clicky');
labels[i].setAttribute('inScope', false);
}
Expand All @@ -372,6 +390,11 @@
labels[i].setAttribute('hasColor', true);
emptyColored = false;
}
else if (labels[i].getAttribute('tagType') == 10000 && (!self._search || inSearch)) {
// zzz
labels[i].setAttribute('hidden', false);
labels[i].setAttribute('hasColor',false);
}
else {
labels[i].removeAttribute('hasColor');
}
Expand Down Expand Up @@ -711,7 +734,7 @@
}
// Get current tagIDs with the old name
var tagIDs = Zotero.Tags.getIDs(oldName, this.libraryID) || [];
var tagIDs = Zotero.Tags.getIDs(oldName, this.libraryID, false) || [];
if (tagIDs.length) {
if (this.selection[oldName]) {
var wasSelected = true;
Expand Down Expand Up @@ -771,9 +794,12 @@


<method name="delete">
<parameter name="name"/>
<parameter name="node"/>
<body>
<![CDATA[
var name = node.getAttribute('value');
var tagType = node.getAttribute('tagType');
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
Expand All @@ -784,8 +810,11 @@
if (confirmed) {
Zotero.DB.beginTransaction();
// Add other ids with same tag
var ids = Zotero.Tags.getIDs(name, this.libraryID);
// Add other ids with same tag, distinguishing
// between project names and ordinary tags
var isProjectName = tagType == 10000 ? true : false;
Zotero.debug('MLZ: isProjectName: '+isProjectName);
var ids = Zotero.Tags.getIDs(name, this.libraryID, isProjectName);
var tagIDs = [];
for each(var id in ids) {
if (tagIDs.indexOf(id) == -1) {
Expand Down Expand Up @@ -833,12 +862,12 @@
<![CDATA[
var tagID = tagObj.id, tagName = tagObj.name, tagType = tagObj.type;
// If the last tag was the same, add this tagID and tagType to it
if(lastTag && lastTag.value === tagName) {
if(lastTag && lastTag.value === tagName && tagType != 10000 && lastTag.getAttribute('10000') != 10000) {
lastTag.setAttribute('tagID', lastTag.getAttribute('tagID') + '-' + tagID);
lastTag.setAttribute('tagType', lastTag.getAttribute('tagType') + '-' + tagType);
return false;
}
var label = document.createElement('label');
label.setAttribute('value', tagName);
Expand Down Expand Up @@ -885,7 +914,7 @@
if (typeof io.color == 'undefined') {
return;
}
return Zotero.Tags.setColor(self.libraryID, io.name, io.color, io.position);
})
.done();
Expand All @@ -903,6 +932,24 @@
</method>


<method name="twiddleTagMenu">
<parameter name="menuPopup"/>
<parameter name="tagType"/>
<body>
<![CDATA[
var colorizeTag = document.getElementById('tag-selector-colorize-tag');
var renameTag = document.getElementById('tag-selector-rename-tag');
if (tagType == 10000) {
colorizeTag.setAttribute('hidden','true');
renameTag.setAttribute('hidden','true');
} else {
colorizeTag.setAttribute('hidden','false');
renameTag.setAttribute('hidden','false');
}
]]>
</body>
</method>

<property name="dragObserver"/>
<method name="_dragObserverConstructor">
<body>
Expand Down Expand Up @@ -995,13 +1042,18 @@
<content>
<groupbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" flex="1">
<menupopup id="tag-menu"
onpopupshowing="document.getBindingParent(this)._triggerNode = event.target.triggerNode;">
<menuitem label="&zotero.tagSelector.assignColor;"
oncommand="_openColorPickerWindow(document.getBindingParent(this)._triggerNode.getAttribute('value')); event.stopPropagation()"/>
<menuitem label="&zotero.tagSelector.renameTag;"
onpopupshowing="var triggerNode = event.target.triggerNode;
document.getBindingParent(this)._triggerNode = triggerNode;
document.getBindingParent(this).twiddleTagMenu(this,triggerNode.getAttribute('tagType'));">
<menuitem id="tag-selector-colorize-tag" label="&zotero.tagSelector.assignColor;"
oncommand="_openColorPickerWindow(
document.getBindingParent(this)._triggerNode.getAttribute('value'),
document.getBindingParent(this)._triggerNode.getAttribute('tagType')
); event.stopPropagation()"/>
<menuitem id="tag-selector-rename-tag" label="&zotero.tagSelector.renameTag;"
oncommand="document.getBindingParent(this).rename(document.getBindingParent(this)._triggerNode.getAttribute('value')); event.stopPropagation()"/>
<menuitem label="&zotero.tagSelector.deleteTag;"
oncommand="document.getBindingParent(this).delete(document.getBindingParent(this)._triggerNode.getAttribute('value')); event.stopPropagation()"/>
oncommand="document.getBindingParent(this).delete(document.getBindingParent(this)._triggerNode); event.stopPropagation()"/>
</menupopup>

<vbox id="no-tags-box" align="center" pack="center" flex="1">
Expand Down
24 changes: 24 additions & 0 deletions chrome/content/zotero/integration/integrationDocPrefs.xul
Expand Up @@ -48,6 +48,7 @@
<tabs id="doc-prefs-tabs">
<tab>&zotero.integration.prefs.lang.styleAndFormat;</tab>
<tab>&zotero.integration.prefs.lang.languages;</tab>
<tab>Project Name</tab>
</tabs>
<tabpanels id="doc-prefs-tabpanels">
<tabpanel>
Expand Down Expand Up @@ -625,6 +626,29 @@
</grid>
</groupbox>
</tabpanel>
<tabpanel>
<groupbox>
<grid flex="1">
<columns>
<column flex="1"/>
</columns>
<rows>
<row>
<hbox flex="1">
<caption label="Apply a tag to sources cited in this document"/>
<hbox flex="2"/>
</hbox>
</row>
<row>
<hbox>
<textbox id="project-name" size="20"/>
<button id="project-name-button" label="Apply" oncommand="Zotero_File_Interface_Bibliography.editProjectName();"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>
</tabpanel>
</tabpanels>
</tabbox>
</dialog>
2 changes: 1 addition & 1 deletion chrome/content/zotero/xpcom/data/item.js
Expand Up @@ -4459,7 +4459,7 @@ Zotero.Item.prototype.getTags = function() {
return [];
}
var sql = "SELECT tagID, name FROM tags WHERE tagID IN "
+ "(SELECT tagID FROM itemTags WHERE itemID=?)";
+ "(SELECT tagID FROM itemTags WHERE itemID=? AND type IS NOT 10000)";
var tags = Zotero.DB.query(sql, this.id);
if (!tags) {
return [];
Expand Down
2 changes: 1 addition & 1 deletion chrome/content/zotero/xpcom/data/tag.js
Expand Up @@ -283,7 +283,7 @@ Zotero.Tag.prototype.save = function (full) {
this.type = 0;
}

if (this.type != 0 && this.type != 1) {
if (this.type != 0 && this.type != 1 && this.type != 10000) {
Zotero.debug(this);
throw ('Invalid tag type ' + this.type + ' for tag ' + this.id + ' in Zotero.Tag.save()');
}
Expand Down

0 comments on commit 37f79e7

Please sign in to comment.