commit 3ac311e85aaa8af7f126d74d422ec7159cc20654
parent b79937d13428c9d092ce96377d33230345ae893b
Author: Dan Stillman <dstillman@zotero.org>
Date: Mon, 21 Aug 2006 05:08:11 +0000
Search improvements:
Conditions can now offer drop-down menus rather than freeform text fields -- implemented for collections/saved searches and item types
Special handling to combine collections and saved searches into a single "Collection" menu (can we get away with calling them "Smart Collections"?) -- internally, values are stored as C1234 or S5678 in the interface and converted to/from regular collectionID and savedSearchID conditions for search.js
Use localized strings for conditions (tries searchConditions.* first, then itemFields.*)
Alphabetize condition list
Operator menu now fixed length for all conditions
Diffstat:
4 files changed, 175 insertions(+), 13 deletions(-)
diff --git a/chrome/chromeFiles/content/scholar/bindings/scholarsearch.xml b/chrome/chromeFiles/content/scholar/bindings/scholarsearch.xml
@@ -110,7 +110,9 @@
if(conditionsBox.hasChildNodes())
for(var i = 0, len=conditionsBox.childNodes.length; i < len; i++)
+ {
conditionsBox.childNodes[i].updateSearch();
+ }
return this.search.save();
]]>
@@ -133,8 +135,8 @@
<xul:label value="Match"/>
<xul:menulist id="joinModeMenu" oncommand="this.parentNode.parentNode.parentNode.updateJoinMode();">
<xul:menupopup>
- <xul:menuitem label="Any" value="any"/>
- <xul:menuitem label="All" value="all" selected="true"/>
+ <xul:menuitem label="any" value="any"/>
+ <xul:menuitem label="all" value="all" selected="true"/>
</xul:menupopup>
</xul:menulist>
<xul:label value="of the following:"/>
@@ -160,18 +162,28 @@
var conditions = Scholar.SearchConditions.getStandardConditions();
for(var i=0, len=conditions.length; i<len; i++)
- conditionsList.appendItem(conditions[i]['name'], conditions[i]['name']);
+ {
+ conditionsList.appendItem(conditions[i]['localized'], conditions[i]['name']);
+ }
conditionsList.selectedIndex = 0;
]]>
</constructor>
+ <field name="selectedCondition"/>
<method name="onConditionSelected">
<body>
<![CDATA[
+ // Skip if already selected
+ if (this.id('conditionsmenu').value==this.selectedCondition){
+ return;
+ }
+ this.selectedCondition = this.id('conditionsmenu').value;
+
var operatorsList = this.id('operatorsmenu');
var condition = Scholar.SearchConditions.get(this.id('conditionsmenu').value);
var operators = condition['operators'];
+ // Display appropriate operators for condition
var selectThis;
for(var i = 0, len = operatorsList.firstChild.childNodes.length; i < len; i++)
{
@@ -182,12 +194,79 @@
}
operatorsList.selectedIndex = selectThis;
+
+ // Generate drop-down menus for certain conditions
+ switch (this.id('conditionsmenu').value){
+ case 'collectionID':
+ var merged = [];
+ var searches = Scholar.Searches.getAll();
+ var cols = Scholar.getCollections();
+ for (var i in cols)
+ {
+ merged.push([cols[i].getName(), 'C' + cols[i].getID()]);
+ }
+ for (var i in searches)
+ {
+ merged.push([searches[i]['name'], 'S' + searches[i]['id']]);
+ }
+
+ this.createValueMenu(merged);
+ break;
+
+ case 'itemTypeID':
+ var types = Scholar.ItemTypes.getTypes();
+ for (var i in types)
+ {
+ types[i][0] = Scholar.getString('itemTypes.' + types[i]['name']);
+ types[i][1] = types[i]['id'];
+ delete types[i]['name'];
+ delete types[i]['id'];
+ }
+ this.createValueMenu(types);
+ break;
+
+ default:
+ // If switching between menu and textbox, clear value
+ if (this.id('valuefield').hidden){
+ this.value = '';
+ this.id('valuefield').value = '';
+ }
+ else {
+ this.id('valuefield').value = this.value;
+ }
+
+ this.id('valuefield').hidden = false;
+ this.id('valuemenu').hidden = true;
+ break;
+ }
+ ]]>
+ </body>
+ </method>
+ <method name="createValueMenu">
+ <parameter name="values"/>
+ <body>
+ <![CDATA[
+ while (this.id('valuemenu').hasChildNodes()){
+ this.id('valuemenu').removeChild(this.id('valuemenu').firstChild);
+ }
+
+ if (values.length){
+ for (var i in values){
+ this.id('valuemenu').appendItem(values[i][0], values[i][1]);
+ }
+ this.id('valuemenu').selectedIndex = 0;
+ }
+
+ this.id('valuemenu').value = this.value;
+ this.id('valuefield').hidden = true;
+ this.id('valuemenu').hidden = false;
]]>
</body>
</method>
<field name="dontupdate"/>
<field name="parent"/>
<field name="conditionID"/>
+ <field name="value"/>
<method name="initWithParentAndCondition">
<parameter name="parent"/>
<parameter name="condition"/>
@@ -200,10 +279,28 @@
{
this.dontupdate = true; //so that the search doesn't get updated while we are creating controls.
- this.id('conditionsmenu').value = condition['condition'];
+ // Handle collectionID/savedSearchID
+ switch (condition['condition'])
+ {
+ case 'savedSearchID':
+ this.id('conditionsmenu').value = 'collectionID';
+ var prefix = 'S';
+ break;
+
+ case 'collectionID':
+ this.id('conditionsmenu').value = 'collectionID';
+ var prefix = 'C';
+
+ // fall through
+
+ default:
+ this.id('conditionsmenu').value = condition['condition'];
+ var prefix = '';
+ }
+
this.id('operatorsmenu').value = condition['operator'];
- this.id('valuefield').value = condition['value'];
-
+ this.value = prefix + condition['value'];
+
this.dontupdate = false;
}
@@ -218,7 +315,35 @@
{
var condition = this.id('conditionsmenu').value;
var operator = this.id('operatorsmenu').value;
- var value = this.id('valuefield').value;
+
+ // Regular text field
+ if (!this.id('valuefield').hidden)
+ {
+ var value = this.id('valuefield').value;
+ }
+
+ // Handle special C1234 and S5678 form for
+ // collections and searches
+ else if (this.id('conditionsmenu').value=='collectionID')
+ {
+ var letter = this.id('valuemenu').value.substr(0,1);
+ if (letter=='C')
+ {
+ condition = 'collectionID';
+ }
+ else if (letter=='S')
+ {
+ condition = 'savedSearchID';
+ }
+ var value = this.id('valuemenu').value.substr(1);
+ }
+
+ // Regular drop-down menu
+ else
+ {
+ var value = this.id('valuemenu').value;
+ }
+
this.parent.search.updateCondition(this.conditionID, condition, operator, value);
}
]]>
@@ -258,6 +383,9 @@
<xul:menupopup/>
</xul:menulist>
<xul:textbox id="valuefield" flex="1"/>
+ <xul:menulist id="valuemenu" flex="1" hidden="true">
+ <xul:menupopup/>
+ </xul:menulist>
<xul:toolbarbutton id="remove" class="clicky" label="-" oncommand="this.parentNode.parentNode.onRemoveClicked();"/>
<xul:toolbarbutton id="add" class="clicky" label="+" oncommand="this.parentNode.parentNode.onAddClicked();"/>
</xul:hbox>
diff --git a/chrome/chromeFiles/content/scholar/xpcom/search.js b/chrome/chromeFiles/content/scholar/xpcom/search.js
@@ -563,7 +563,8 @@ Scholar.SearchConditions = new function(){
isNot: true
},
table: 'savedSearches',
- field: 'savedSearchID'
+ field: 'savedSearchID',
+ special: true
},
{
@@ -577,7 +578,7 @@ Scholar.SearchConditions = new function(){
},
{
- name: 'itemType',
+ name: 'itemTypeID',
operators: {
is: true,
isNot: true
@@ -593,7 +594,8 @@ Scholar.SearchConditions = new function(){
isNot: true
},
table: 'itemTags',
- field: 'tagID'
+ field: 'tagID',
+ special: true
},
{
@@ -657,19 +659,38 @@ Scholar.SearchConditions = new function(){
delete _conditions[i];
}
+ var sortKeys = [];
+ var sortValues = [];
+
// Separate standard conditions for menu display
for (var i in _conditions){
// Standard conditions a have associated tables
- if (_conditions[i]['table'] &&
+ if (_conditions[i]['table'] && !_conditions[i]['special'] &&
// If a template condition, not the original (e.g. 'field')
(!_conditions[i]['template'] || i!=_conditions[i]['name'])){
- _standardConditions.push({
+
+ try {
+ var localized = Scholar.getString('searchConditions.' + i)
+ }
+ catch (e){
+ var localized = Scholar.getString('itemFields.' + i);
+ }
+
+ sortKeys.push(localized);
+ sortValues[localized] = {
name: i,
+ localized: localized,
operators: _conditions[i]['operators']
- });
+ };
}
}
+ // Alphabetize by localized name
+ sortKeys = sortKeys.sort();
+ for each(var i in sortKeys){
+ _standardConditions.push(sortValues[i]);
+ }
+
_initialized = true;
}
diff --git a/chrome/chromeFiles/locale/en-US/scholar/scholar.properties b/chrome/chromeFiles/locale/en-US/scholar/scholar.properties
@@ -106,5 +106,12 @@ searchOperator.greaterThan = is greater than
searchOperator.isBefore = is before
searchOperator.isAfter = is after
+searchConditions.collectionID = Collection
+searchConditions.itemTypeID = Item Type
+searchConditions.tag = Tag
+searchConditions.note = Note
+searchConditions.creator = Creator
+searchConditions.thesisType = Thesis Type
+
exportOptions.exportNotes = Export Notes
exportOptions.exportFileData = Export Files
\ No newline at end of file
diff --git a/chrome/chromeFiles/skin/default/scholar/scholar.css b/chrome/chromeFiles/skin/default/scholar/scholar.css
@@ -66,6 +66,7 @@ seealsobox
scholarsearch
{
-moz-binding: url('chrome://scholar/content/bindings/scholarsearch.xml#search-box');
+ width:60em;
}
searchcondition
@@ -73,6 +74,11 @@ searchcondition
-moz-binding: url('chrome://scholar/content/bindings/scholarsearch.xml#search-condition');
}
+searchcondition menulist[id="operatorsmenu"]
+{
+ width:15em;
+}
+
.clicky, .unclicky
{
-moz-border-radius: 6px;