[interface] Although commented out, code in place to accept URL drags into collections (waiting on an Ingester.scrapeURL function)

[interface] Multi-notes functionality (waiting on data layer)
[docs] Major internal documentation written for itemTreeView.js and collectionTreeView.js (this actually does work ;-))
This commit is contained in:
David Norton 2006-06-15 22:35:48 +00:00
parent f635ee7788
commit e417d8e690
4 changed files with 324 additions and 52 deletions

View file

@ -1,3 +1,14 @@
////////////////////////////////////////////////////////////////////////////////
///
/// CollectionTreeView
/// -- handles the link between an individual tree and the data layer
/// -- displays only collections, in a hierarchy (no items)
///
////////////////////////////////////////////////////////////////////////////////
/*
* Constructor the the CollectionTreeView object
*/
Scholar.CollectionTreeView = function()
{
this._treebox = null;
@ -6,6 +17,9 @@ Scholar.CollectionTreeView = function()
this._unregisterID = Scholar.Notifier.registerColumnTree(this);
}
/*
* Called by the tree itself
*/
Scholar.CollectionTreeView.prototype.setTree = function(treebox)
{
if(this._treebox)
@ -13,6 +27,10 @@ Scholar.CollectionTreeView.prototype.setTree = function(treebox)
this._treebox = treebox;
}
/*
* Reload the rows from the data access methods
* (doesn't call the tree.invalidate methods, etc.)
*/
Scholar.CollectionTreeView.prototype.refresh = function()
{
this._dataItems = new Array();
@ -27,7 +45,7 @@ Scholar.CollectionTreeView.prototype.refresh = function()
}
/*
* Is called by Scholar.Notifier on any changes to the data layer
* Called by Scholar.Notifier on any changes to collections in the data layer
*/
Scholar.CollectionTreeView.prototype.notify = function(action, type, ids)
{
@ -102,13 +120,20 @@ Scholar.CollectionTreeView.prototype.notify = function(action, type, ids)
}
/*
* Unregisters itself from Scholar.Notifier (called on window close)
* Unregisters view from Scholar.Notifier (called on window close)
*/
Scholar.CollectionTreeView.prototype.unregister = function()
{
Scholar.Notifier.unregisterColumnTree(this._unregisterID);
}
////////////////////////////////////////////////////////////////////////////////
///
/// nsITreeView functions
/// http://www.xulplanet.com/references/xpcomref/ifaces/nsITreeView.html
///
////////////////////////////////////////////////////////////////////////////////
Scholar.CollectionTreeView.prototype.getCellText = function(row, column)
{
var obj = this._getItemAtRow(row);
@ -137,6 +162,8 @@ Scholar.CollectionTreeView.prototype.isContainerOpen = function(row)
Scholar.CollectionTreeView.prototype.isContainerEmpty = function(row)
{
//NOTE: this returns true if the collection has no child collections
var itemGroup = this._getItemAtRow(row);
if(itemGroup.isCollection())
return !itemGroup.ref.hasChildCollections();
@ -170,6 +197,9 @@ Scholar.CollectionTreeView.prototype.hasNextSibling = function(row, afterIndex)
}
}
/*
* Opens/closes the specified row
*/
Scholar.CollectionTreeView.prototype.toggleOpenState = function(row)
{
var count = 0; //used to tell the tree how many rows were added/removed
@ -202,6 +232,15 @@ Scholar.CollectionTreeView.prototype.toggleOpenState = function(row)
this._refreshHashMap();
}
////////////////////////////////////////////////////////////////////////////////
///
/// Additional functions for managing data in the tree
///
////////////////////////////////////////////////////////////////////////////////
/*
* Delete the selection
*/
Scholar.CollectionTreeView.prototype.deleteSelection = function()
{
if(this.selection.count == 0)
@ -240,23 +279,37 @@ Scholar.CollectionTreeView.prototype.deleteSelection = function()
this.selection.select(this.rowCount-1);
}
Scholar.CollectionTreeView.prototype._showItem = function(item, level, beforeRow)
/*
* Called by various view functions to show a row
*
* itemGroup: reference to the ItemGroup
* level: the indent level of the row
* beforeRow: row index to insert new row before
*/
Scholar.CollectionTreeView.prototype._showItem = function(itemGroup, level, beforeRow)
{
this._dataItems.splice(beforeRow, 0, [item, false, level]); this.rowCount++;
this._dataItems.splice(beforeRow, 0, [itemGroup, false, level]); this.rowCount++;
}
/*
* Called by view to hide specified row
*/
Scholar.CollectionTreeView.prototype._hideItem = function(row)
{
this._dataItems.splice(row,1); this.rowCount--;
}
/*
* Returns a reference to the collection at row (see Scholar.Collection in data_access.js)
*/
Scholar.CollectionTreeView.prototype._getItemAtRow = function(row)
{
return this._dataItems[row][0];
}
/*
* Create hash map of collection ids to row indexes
* Creates hash map of collection ids to row indexes
* e.g., var rowForID = this._collectionRowMap[]
*/
Scholar.CollectionTreeView.prototype._refreshHashMap = function()
{
@ -268,8 +321,17 @@ Scholar.CollectionTreeView.prototype._refreshHashMap = function()
}
/* DRAG AND DROP FUNCTIONS */
////////////////////////////////////////////////////////////////////////////////
///
/// Drag-and-drop functions:
/// canDrop() and drop() are for nsITreeView
/// onDragStart(), getSupportedFlavours(), and onDrop() for nsDragAndDrop.js + nsTransferable.js
///
////////////////////////////////////////////////////////////////////////////////
/*
* Called while a drag is over the tree.
*/
Scholar.CollectionTreeView.prototype.canDrop = function(row, orient)
{
if(typeof row == 'object') //workaround... two different services call canDrop (nsDragAndDrop, and the tree)
@ -288,23 +350,28 @@ Scholar.CollectionTreeView.prototype.canDrop = function(row, orient)
}
var data = dataSet.first.first;
var dataType = data.flavour.contentType;
var rowCollection = this._getItemAtRow(row).ref;
//Check to make sure that the highlighting is done right
if(orient == 1 && row == 0 && dataType == 'scholar/collection')
//Highlight the rows correctly on drag:
if(orient == 1 && row == 0 && dataType == 'scholar/collection') //for dropping collections into root level
{
return true;
}
else if(orient == 0)
else if(orient == 0) //directly on a row...
{
var rowCollection = this._getItemAtRow(row).ref; //the collection we are dragging over
if(dataType == 'scholar/item' || dataType == "text/x-moz-url")
return true;
return true; //items can be dropped on anything
else if(dataType='scholar/collection' && data.data != rowCollection.getID() && !Scholar.Collections.get(data.data).hasDescendent('collection',rowCollection.getID()) )
return true;
return true; //collections cannot be dropped on themselves, nor in their children
}
return false;
}
/*
* Called when something's been dropped on or next to a row
*/
Scholar.CollectionTreeView.prototype.drop = function(row, orient)
{
var dataSet = nsTransferable.get(this.getSupportedFlavours(),nsDragAndDrop.getDragData, true);
@ -340,19 +407,31 @@ Scholar.CollectionTreeView.prototype.drop = function(row, orient)
}
else if(dataType == 'text/x-moz-url' && this.canDrop(row, orient))
{
alert(data.data);
var targetCollection = this._getItemAtRow(row).ref;
/*for(var i = 0; i<ids.length; i++)
targetCollection.addItem(ids[i]); */
var url = data.data.split("\n")[0];
/* WAITING FOR INGESTER SUPPORT
var newItem = Scholar.Ingester.scrapeURL(url);
if(newItem)
this._getItemAtRow(row).ref.addItem(newItem.getID());
*/
}
}
/*
* Begin a drag
*/
Scholar.CollectionTreeView.prototype.onDragStart = function(evt,transferData,action)
{
transferData.data=new TransferData();
//attach ID
transferData.data.addDataForFlavour("scholar/collection",this._getItemAtRow(this.selection.currentIndex).ref.getID());
}
/*
* Returns the supported drag flavors
*/
Scholar.CollectionTreeView.prototype.getSupportedFlavours = function ()
{
var flavors = new FlavourSet();
@ -362,9 +441,16 @@ Scholar.CollectionTreeView.prototype.getSupportedFlavours = function ()
return flavors;
}
/*
* Called by nsDragAndDrop.js for any sort of drop on the tree
*/
Scholar.CollectionTreeView.prototype.onDrop = function (evt,dropdata,session) { }
/* MORE TREEVIEW FUNCTIONS THAT HAVE TO BE HERE */
////////////////////////////////////////////////////////////////////////////////
///
/// Functions for nsITreeView that we have to stub out.
///
////////////////////////////////////////////////////////////////////////////////
Scholar.CollectionTreeView.prototype.isSorted = function() { return false; }
Scholar.CollectionTreeView.prototype.isSeparator = function(row) { return false; }
@ -377,9 +463,12 @@ Scholar.CollectionTreeView.prototype.performActionOnCell = function(action, row,
Scholar.CollectionTreeView.prototype.getProgressMode = function(row, col) { }
Scholar.CollectionTreeView.prototype.cycleHeader = function(column) { }
//
// SCHOLAR ITEMGROUP
//
////////////////////////////////////////////////////////////////////////////////
///
/// Scholar ItemGroup -- a sort of "super class" for Collection, library,
/// and eventually smartSearch
///
////////////////////////////////////////////////////////////////////////////////
Scholar.ItemGroup = function(type, ref)
{

View file

@ -3,7 +3,9 @@ ScholarItemPane = new function()
var _dynamicFields;
var _creatorTypeMenu;
var _beforeRow;
var _notesPane;
var _notesMenu;
var _notesField;
var _notesLabel;
var _creatorCount;
@ -17,12 +19,18 @@ ScholarItemPane = new function()
this.hideEditor = hideEditor;
this.modifyField = modifyField;
this.modifyCreator = modifyCreator;
this.modifySelectedNote = modifySelectedNote;
this.removeSelectedNote = removeSelectedNote;
this.addNote = addNote;
this.onNoteSelected = onNoteSelected;
function onLoad()
{
_dynamicFields = document.getElementById('editpane-dynamic-fields');
_creatorTypeMenu = document.getElementById('creatorTypeMenu');
_notesPane = document.getElementById('scholar-notes');
_notesMenu = document.getElementById('scholar-notes-menu');
_notesField = document.getElementById('scholar-notes-field');
_notesLabel = document.getElementById('scholar-notes-label');
var creatorTypes = Scholar.CreatorTypes.getTypes();
for(var i = 0; i < creatorTypes.length; i++)
@ -60,24 +68,18 @@ ScholarItemPane = new function()
for(var i = 0; i<fieldNames.length; i++)
{
if(fieldNames[i] != 'notes')
{
var editable = (!_itemBeingEdited.isPrimaryField(fieldNames[i]) || _itemBeingEdited.isEditableField(fieldNames[i]));
var valueElement = createValueElement(_itemBeingEdited.getField(fieldNames[i]), editable ? fieldNames[i] : null);
var label = document.createElement("label");
label.setAttribute("value",Scholar.getString("itemFields."+fieldNames[i])+":");
label.setAttribute("onclick","this.nextSibling.blur();");
addDynamicRow(label,valueElement);
}
else
{
_notesPane.value = _itemBeingEdited.getField(fieldNames[i]);
}
var editable = (!_itemBeingEdited.isPrimaryField(fieldNames[i]) || _itemBeingEdited.isEditableField(fieldNames[i]));
var valueElement = createValueElement(_itemBeingEdited.getField(fieldNames[i]), editable ? fieldNames[i] : null);
var label = document.createElement("label");
label.setAttribute("value",Scholar.getString("itemFields."+fieldNames[i])+":");
label.setAttribute("onclick","this.nextSibling.blur();");
addDynamicRow(label,valueElement);
}
//CREATORS:
_beforeRow = _dynamicFields.firstChild.nextSibling;
_creatorCount = 0;
if(_itemBeingEdited.numCreators() > 0)
@ -92,6 +94,19 @@ ScholarItemPane = new function()
{
addCreatorRow('', '', 1);
}
//NOTES:
_notesMenu.removeAllItems();
var notes = _itemBeingEdited.getNotes();
if(notes.length)
for(var i = 0; i < notes.length; i++)
_notesMenu.appendItem(_noteToTitle(_itemBeingEdited.getNote(notes[i])),notes[i]);
else
addNote();
_updateNoteCount();
_notesMenu.selectedIndex = 0;
}
function addDynamicRow(label, value, beforeElement)
@ -248,6 +263,80 @@ ScholarItemPane = new function()
_itemBeingEdited.setCreator(index, firstName, lastName, typeID);
_itemBeingEdited.save();
}
function modifySelectedNote()
{
if(_notesMenu.selectedIndex == -1)
return;
var id = _notesMenu.selectedItem.value;
if(id)
{
_itemBeingEdited.updateNote(id,_notesField.value);
}
else //new note
{
id = _itemBeingEdited.addNote(_notesField.value);
_notesMenu.selectedItem.value = id;
}
var label = _notesField.value;
_notesMenu.selectedItem.label = _noteToTitle(_notesField.value);
}
function removeSelectedNote()
{
var id = _notesMenu.selectedItem.value;
if(id)
{
_itemBeingEdited.removeNote(id);
}
_notesMenu.removeitemAt(_notesMenu.selectedIndex);
if(_notesMenu.firstChild.childNodes.length == 0)
addNote();
_updateNoteCount();
}
function addNote()
{
modifySelectedNote();
_notesMenu.appendItem('Untitled Note');
_notesMenu.selectedIndex = _notesMenu.firstChild.childNodes.length-1;
_updateNoteCount();
}
function onNoteSelected()
{
var id = _notesMenu.selectedItem.value;
if(id)
_notesField.value = _itemBeingEdited.getNote(id);
else
_notesField.value = "";
}
function _noteToTitle(text)
{
var t = text.substring(0, Math.min(text.indexOf("\n"), 30) );
if(t == "")
{
return "Untitled Note";
}
else
{
return t;
}
}
function _updateNoteCount()
{
var c = _notesMenu.firstChild.childNodes.length;
_notesLabel.value = c + " note" + (c != 1 ? "s" : "") + ":";
}
}
addEventListener("load", function(e) { ScholarItemPane.onLoad(e); }, false);

View file

@ -12,8 +12,16 @@
</tabs>
<tabpanels flex="1">
<vbox>
<textbox id="scholar-notes"
type="timed" timeout="1000" oncommand="ScholarItemPane.modifyField('notes',this.value);"
<hbox align="center">
<label id="scholar-notes-label"/>
<menulist flex="1" id="scholar-notes-menu" onselect="ScholarItemPane.onNoteSelected();">
<menupopup/>
</menulist>
<toolbarbutton label="-" class="addremove" oncommand="ScholarItemPane.removeSelectedNote();"/>
<toolbarbutton label="+" class="addremove" oncommand="ScholarItemPane.addNote();"/>
</hbox>
<textbox id="scholar-notes-field"
type="timed" timeout="1000" oncommand="ScholarItemPane.modifySelectedNote();"
multiline="true" flex="1"
onblur="ScholarItemPane.modifyField('notes',this.value);"/>
</vbox>

View file

@ -1,3 +1,14 @@
////////////////////////////////////////////////////////////////////////////////
///
/// ItemTreeView
/// -- handles the link between an individual tree and the data layer
/// -- displays only items (no collections, no hierarchy)
///
////////////////////////////////////////////////////////////////////////////////
/*
* Constructor the the ItemTreeView object
*/
Scholar.ItemTreeView = function(itemGroup)
{
this._itemGroup = itemGroup;
@ -9,6 +20,9 @@ Scholar.ItemTreeView = function(itemGroup)
this._unregisterID = Scholar.Notifier.registerItemTree(this);
}
/*
* Called by the tree itself
*/
Scholar.ItemTreeView.prototype.setTree = function(treebox)
{
if(this._treebox)
@ -25,6 +39,10 @@ Scholar.ItemTreeView.prototype.setTree = function(treebox)
}
}
/*
* Reload the rows from the data access methods
* (doesn't call the tree.invalidate methods, etc.)
*/
Scholar.ItemTreeView.prototype.refresh = function()
{
this._dataItems = new Array();
@ -38,6 +56,9 @@ Scholar.ItemTreeView.prototype.refresh = function()
this._refreshHashMap();
}
/*
* Called by Scholar.Notifier on any changes to items in the data layer
*/
Scholar.ItemTreeView.prototype.notify = function(action, type, ids)
{
var madeChanges = false;
@ -112,11 +133,21 @@ Scholar.ItemTreeView.prototype.notify = function(action, type, ids)
this.selection.selectEventsSuppressed = false;
}
/*
* Unregisters view from Scholar.Notifier (called on window close)
*/
Scholar.ItemTreeView.prototype.unregister = function()
{
Scholar.Notifier.unregisterItemTree(this._unregisterID);
}
////////////////////////////////////////////////////////////////////////////////
///
/// nsITreeView functions
/// http://www.xulplanet.com/references/xpcomref/ifaces/nsITreeView.html
///
////////////////////////////////////////////////////////////////////////////////
Scholar.ItemTreeView.prototype.getCellText = function(row, column)
{
var obj = this._getItemAtRow(row);
@ -175,9 +206,12 @@ Scholar.ItemTreeView.prototype.cycleHeader = function(column)
this._treebox.invalidate();
}
/*
* Sort the items by the currently sorted column.
* Simply uses Array.sort() function, and refreshes the hash map.
*/
Scholar.ItemTreeView.prototype.sort = function()
{
var column = this._treebox.columns.getSortedColumn()
var order = column.element.getAttribute('sortDirection') == 'descending';
@ -199,13 +233,13 @@ Scholar.ItemTreeView.prototype.sort = function()
}
}
function oppSort(a,b)
function oppositeSort(a,b)
{
return(columnSort(a,b) * -1);
}
if(order)
this._dataItems.sort(oppSort);
this._dataItems.sort(oppositeSort);
else
this._dataItems.sort(columnSort);
@ -213,6 +247,15 @@ Scholar.ItemTreeView.prototype.sort = function()
}
////////////////////////////////////////////////////////////////////////////////
///
/// Additional functions for managing data in the tree
///
////////////////////////////////////////////////////////////////////////////////
/*
* Delete the selection
*/
Scholar.ItemTreeView.prototype.deleteSelection = function()
{
if(this.selection.count == 0)
@ -246,6 +289,9 @@ Scholar.ItemTreeView.prototype.deleteSelection = function()
this._treebox.endUpdateBatch();
}
/*
* Set the search filter on the view
*/
Scholar.ItemTreeView.prototype.searchText = function(search)
{
this.selection.selectEventsSuppressed = true;
@ -263,23 +309,35 @@ Scholar.ItemTreeView.prototype.searchText = function(search)
this._treebox.invalidate();
}
/*
* Called by various view functions to show a row
*
* item: reference to the Item
* beforeRow: row index to insert new row before
*/
Scholar.ItemTreeView.prototype._showItem = function(item, beforeRow)
{
this._dataItems.splice(beforeRow, 0, item); this.rowCount++;
}
/*
* Called by view to hide specified row
*/
Scholar.ItemTreeView.prototype._hideItem = function(row)
{
this._dataItems.splice(row,1); this.rowCount--;
}
/*
* Returns a reference to the item at row (see Scholar.Item in data_access.js)
*/
Scholar.ItemTreeView.prototype._getItemAtRow = function(row)
{
return this._dataItems[row];
}
/*
* Create hash map of item ids to row indexes
* Create hash map of item ids to row indexes
*/
Scholar.ItemTreeView.prototype._refreshHashMap = function()
{
@ -288,6 +346,9 @@ Scholar.ItemTreeView.prototype._refreshHashMap = function()
this._itemRowMap[this._getItemAtRow(i).getID()] = i;
}
/*
* Saves the ids of currently selected items for later
*/
Scholar.ItemTreeView.prototype.saveSelection = function()
{
this._savedSelection = new Array();
@ -302,6 +363,9 @@ Scholar.ItemTreeView.prototype.saveSelection = function()
}
}
/*
* Sets the selection based on saved selection ids (see above)
*/
Scholar.ItemTreeView.prototype.rememberSelection = function()
{
this.selection.clearSelection();
@ -312,15 +376,26 @@ Scholar.ItemTreeView.prototype.rememberSelection = function()
}
}
/* DRAG AND DROP FUNCTIONS */
////////////////////////////////////////////////////////////////////////////////
///
/// Drag-and-drop functions:
/// for nsDragAndDrop.js + nsTransferable.js
///
////////////////////////////////////////////////////////////////////////////////
/*
* Begin a drag
*/
Scholar.ItemTreeView.prototype.onDragStart = function (evt,transferData,action)
{
transferData.data=new TransferData();
this.saveSelection();
transferData.data.addDataForFlavour("scholar/item",this._savedSelection);
}
/*
* Called by nsDragAndDrop.js for any sort of drop on the tree
*/
Scholar.ItemTreeView.prototype.getSupportedFlavours = function ()
{
var flavors = new FlavourSet();
@ -329,28 +404,39 @@ Scholar.ItemTreeView.prototype.getSupportedFlavours = function ()
return flavors;
}
/*
* Called by nsDragAndDrop.js for any sort of drop on the tree
*/
Scholar.ItemTreeView.prototype.onDrop = function (evt,data,session)
{
var dataType = data.flavour.contentType;
var ids = data.data.split(',');
if(dataType == 'scholar/item')
{
var ids = data.data.split(',');
for(var i = 0; i<ids.length; i++)
this._itemGroup.ref.addItem(ids[i]);
}
else if(dataType == 'text/x-moz-url')
{
alert(data.data);
var targetCollection = this._itemGroup.ref;
/*for(var i = 0; i<ids.length; i++)
targetCollection.addItem(ids[i]); */
var url = data.data.split("\n")[0];
/* WAITING FOR INGESTER SUPPORT
var newItem = Scholar.Ingester.scrapeURL(url);
if(newItem)
this._itemGroup.ref.addItem(newItem.getID());
*/
}
}
Scholar.ItemTreeView.prototype.onDragOver = function (evt,dropdata,session) { }
/* MORE TREEVIEW FUNCTIONS THAT HAVE TO BE HERE */
////////////////////////////////////////////////////////////////////////////////
///
/// Functions for nsITreeView that we have to stub out.
///
////////////////////////////////////////////////////////////////////////////////
Scholar.ItemTreeView.prototype.isSeparator = function(row) { return false; }
Scholar.ItemTreeView.prototype.isContainer = function(row) { return false; }