2006-03-14 11:48:36 +00:00
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Constructor for Item object
|
2006-03-14 11:48:36 +00:00
|
|
|
*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Generally should be called through Scholar.Items rather than directly
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item = function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
this._init();
|
|
|
|
|
2006-06-01 06:35:33 +00:00
|
|
|
// Accept itemTypeID in constructor
|
2006-03-14 11:48:36 +00:00
|
|
|
if (arguments.length){
|
|
|
|
this.setType(arguments[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype._init = function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
//
|
|
|
|
// Public members for access by public methods -- do not access directly
|
|
|
|
//
|
|
|
|
this._data = new Array();
|
|
|
|
this._creators = new Scholar.Hash();
|
2006-05-18 11:25:10 +00:00
|
|
|
this._itemData = new Array();
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
this._creatorsLoaded = false;
|
2006-05-18 11:25:10 +00:00
|
|
|
this._itemDataLoaded = false;
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
this._changed = new Scholar.Hash();
|
|
|
|
this._changedCreators = new Scholar.Hash();
|
2006-05-18 11:25:10 +00:00
|
|
|
this._changedItemData = new Scholar.Hash();
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-03-17 05:11:03 +00:00
|
|
|
|
2006-05-15 19:30:18 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2006-05-18 11:25:10 +00:00
|
|
|
// Public Scholar.Item methods
|
2006-05-15 19:30:18 +00:00
|
|
|
//
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Check if the specified field is a primary field from the items table
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.isPrimaryField = function(field){
|
2006-06-01 00:22:18 +00:00
|
|
|
// Create primaryFields hash array if not yet created
|
2006-05-18 11:25:10 +00:00
|
|
|
if (!Scholar.Item.primaryFields){
|
|
|
|
Scholar.Item.primaryFields = Scholar.DB.getColumnHash('items');
|
|
|
|
Scholar.Item.primaryFields['firstCreator'] = true;
|
2006-06-25 05:43:00 +00:00
|
|
|
Scholar.Item.primaryFields['numNotes'] = true;
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
Scholar.Item.primaryFields['numFiles'] = true;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
return !!Scholar.Item.primaryFields[field];
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.editableFields = {
|
2006-06-01 00:22:18 +00:00
|
|
|
title: true
|
2006-03-14 11:48:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if the specified primary field can be changed with setField()
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.isEditableField = function(field){
|
|
|
|
return !!Scholar.Item.editableFields[field];
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Build object from database
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.loadFromID = function(id){
|
2006-06-25 05:43:00 +00:00
|
|
|
// Should be the same as query in Scholar.Items.loadFromID, just
|
|
|
|
// without itemID clause
|
2006-06-06 17:37:52 +00:00
|
|
|
var sql = 'SELECT I.*, lastName || '
|
|
|
|
+ 'CASE ((SELECT COUNT(*) FROM itemCreators WHERE itemID=' + id + ')>1) '
|
2006-06-25 05:43:00 +00:00
|
|
|
+ "WHEN 0 THEN '' ELSE ' et al.' END AS firstCreator, "
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
+ "(SELECT COUNT(*) FROM itemNotes WHERE sourceItemID=I.itemID) AS numNotes, "
|
|
|
|
+ "(SELECT COUNT(*) FROM itemFiles WHERE sourceItemID=I.itemID) AS numFiles "
|
2006-05-18 11:25:10 +00:00
|
|
|
+ 'FROM items I '
|
|
|
|
+ 'LEFT JOIN itemCreators IC ON (I.itemID=IC.itemID) '
|
|
|
|
+ 'LEFT JOIN creators C ON (IC.creatorID=C.creatorID) '
|
2006-05-18 21:55:43 +00:00
|
|
|
+ 'WHERE itemID=' + id
|
2006-06-01 00:22:18 +00:00
|
|
|
+ ' AND (IC.orderIndex=0 OR IC.orderIndex IS NULL)'; // first creator
|
2006-03-20 21:47:22 +00:00
|
|
|
var row = Scholar.DB.rowQuery(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
this.loadFromRow(row);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Populate basic item data from a database row
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.loadFromRow = function(row){
|
2006-03-14 11:48:36 +00:00
|
|
|
this._init();
|
|
|
|
for (col in row){
|
2006-06-01 00:22:18 +00:00
|
|
|
// Only accept primary field data through loadFromRow()
|
|
|
|
if (this.isPrimaryField(col)){
|
2006-03-14 11:48:36 +00:00
|
|
|
this._data[col] = row[col];
|
|
|
|
}
|
2006-06-01 00:22:18 +00:00
|
|
|
else {
|
|
|
|
Scholar.debug(col + ' is not a valid primary field');
|
|
|
|
}
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if any data fields have changed since last save
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.hasChanged = function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
return (this._changed.length || this._changedCreators.length ||
|
2006-05-18 11:25:10 +00:00
|
|
|
this._changedItemData.length);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.getID = function(){
|
|
|
|
return this._data['itemID'] ? this._data['itemID'] : false;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.getType = function(){
|
|
|
|
return this._data['itemTypeID'] ? this._data['itemTypeID'] : false;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Set or change the item's type
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.setType = function(itemTypeID){
|
|
|
|
if (itemTypeID==this.getType()){
|
2006-03-14 11:48:36 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If existing type, clear fields from old type that aren't in new one
|
|
|
|
if (this.getType()){
|
2006-05-18 11:25:10 +00:00
|
|
|
var sql = 'SELECT fieldID FROM itemTypeFields '
|
|
|
|
+ 'WHERE itemTypeID=' + this.getType() + ' AND fieldID NOT IN '
|
|
|
|
+ '(SELECT fieldID FROM itemTypeFields WHERE itemTypeID='
|
|
|
|
+ itemTypeID + ')';
|
2006-03-20 21:47:22 +00:00
|
|
|
var obsoleteFields = Scholar.DB.columnQuery(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (obsoleteFields){
|
|
|
|
for (var i=0; i<obsoleteFields.length; i++){
|
|
|
|
this.setField(obsoleteFields[i],false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
this._data['itemTypeID'] = itemTypeID;
|
|
|
|
this._changed.set('itemTypeID');
|
2006-03-14 11:48:36 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
/**
|
|
|
|
* Return an array of collectionIDs for all collections the item belongs to
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.getCollections = function(){
|
|
|
|
return Scholar.DB.columnQuery("SELECT collectionID FROM collectionItems "
|
|
|
|
+ "WHERE itemID=" + this.getID());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-01 20:03:53 +00:00
|
|
|
/**
|
|
|
|
* Determine whether the item belongs to a given collectionID
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.inCollection = function(collectionID){
|
|
|
|
return !!parseInt(Scholar.DB.valueQuery("SELECT COUNT(*) collectionID "
|
|
|
|
+ "FROM collectionItems WHERE collectionID=" + collectionID + " AND "
|
|
|
|
+ "itemID=" + this.getID()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Returns the number of creators for this item
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.numCreators = function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (this.getID() && !this._creatorsLoaded){
|
|
|
|
this._loadCreators();
|
|
|
|
}
|
|
|
|
return this._creators.length;
|
|
|
|
}
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
|
|
|
* Returns an array of the creator data at the given position, or false if none
|
2006-06-29 03:56:22 +00:00
|
|
|
*
|
|
|
|
* Note: Creator data array is returned by reference
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.getCreator = function(pos){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (this.getID() && !this._creatorsLoaded){
|
|
|
|
this._loadCreators();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this._creators.items[pos]){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return this._creators.items[pos];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-27 20:26:44 +00:00
|
|
|
/*
|
|
|
|
* Returns a multidimensional array of creators, or an empty array if none
|
2006-06-29 03:56:22 +00:00
|
|
|
*
|
|
|
|
* Note: Creator data array is returned by reference
|
2006-06-27 20:26:44 +00:00
|
|
|
*/
|
|
|
|
Scholar.Item.prototype.getCreators = function(){
|
|
|
|
var creators = [];
|
|
|
|
for (var i=0, len=this.numCreators(); i<len; i++){
|
|
|
|
creators.push(this.getCreator(i));
|
|
|
|
}
|
|
|
|
return creators;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
|
|
|
* Set or update the creator at the specified position
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.setCreator = function(orderIndex, firstName, lastName, creatorTypeID){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (this.getID() && !this._creatorsLoaded){
|
|
|
|
this._loadCreators();
|
|
|
|
}
|
|
|
|
|
2006-05-20 15:18:36 +00:00
|
|
|
if (!firstName){
|
|
|
|
firstName = '';
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-20 15:18:36 +00:00
|
|
|
if (!lastName){
|
|
|
|
lastName = '';
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-08 00:16:35 +00:00
|
|
|
// If creator at this position hasn't changed, cancel
|
2006-03-14 11:48:36 +00:00
|
|
|
if (this._creators.has(orderIndex) &&
|
|
|
|
this._creators.get(orderIndex)['firstName']==firstName &&
|
|
|
|
this._creators.get(orderIndex)['lastName']==lastName &&
|
|
|
|
this._creators.get(orderIndex)['creatorTypeID']==creatorTypeID){
|
2006-06-08 00:16:35 +00:00
|
|
|
return false;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-20 15:18:36 +00:00
|
|
|
if (!creatorTypeID){
|
|
|
|
creatorTypeID = 1;
|
|
|
|
}
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
var creator = new Array();
|
|
|
|
creator['firstName'] = firstName;
|
|
|
|
creator['lastName'] = lastName;
|
|
|
|
creator['creatorTypeID'] = creatorTypeID;
|
|
|
|
|
|
|
|
this._creators.set(orderIndex, creator);
|
|
|
|
this._changedCreators.set(orderIndex);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove a creator and shift others down
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.removeCreator = function(orderIndex){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (this.getID() && !this._creatorsLoaded){
|
|
|
|
this._loadCreators();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this._creators.has(orderIndex)){
|
|
|
|
throw ('No creator exists at position ' + orderIndex);
|
|
|
|
}
|
|
|
|
this._creators.remove(orderIndex);
|
|
|
|
|
2006-05-20 15:18:36 +00:00
|
|
|
// Go to length+1 so we clear the last one
|
|
|
|
for (var i=orderIndex, max=this._creators.length+1; i<max; i++){
|
2006-03-14 11:48:36 +00:00
|
|
|
var next =
|
|
|
|
this._creators.items[i+1] ? this._creators.items[i+1] : false;
|
|
|
|
this._creators.set(i, next);
|
|
|
|
this._changedCreators.set(i);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-08 00:16:35 +00:00
|
|
|
Scholar.Item.prototype.creatorExists = function(firstName, lastName, creatorTypeID, skipIndex){
|
|
|
|
for (var j=0, len=this.numCreators(); j<len; j++){
|
|
|
|
if (typeof skipIndex!='undefined' && skipIndex==j){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
var creator2 = this.getCreator(j);
|
|
|
|
|
|
|
|
if (firstName==creator2['firstName'] &&
|
|
|
|
lastName==creator2['lastName'] &&
|
|
|
|
creatorTypeID==creator2['creatorTypeID']){
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Retrieves (and loads from DB, if necessary) an itemData field value
|
2006-03-14 11:48:36 +00:00
|
|
|
*
|
|
|
|
* Field can be passed as fieldID or fieldName
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.getField = function(field){
|
|
|
|
//Scholar.debug('Requesting field ' + field + ' for item ' + this.getID(), 4);
|
2006-03-14 11:48:36 +00:00
|
|
|
if (this.isPrimaryField(field)){
|
2006-03-17 05:11:03 +00:00
|
|
|
return this._data[field] ? this._data[field] : '';
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
else {
|
2006-05-18 11:25:10 +00:00
|
|
|
if (this.getID() && !this._itemDataLoaded){
|
|
|
|
this._loadItemData();
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
var fieldID = Scholar.ItemFields.getID(field);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
return this._itemData[fieldID] ? this._itemData[fieldID] : '';
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Set a field value, loading existing itemData first if necessary
|
2006-03-14 11:48:36 +00:00
|
|
|
*
|
|
|
|
* Field can be passed as fieldID or fieldName
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.setField = function(field, value, loadIn){
|
2006-03-14 11:48:36 +00:00
|
|
|
// Primary field
|
|
|
|
if (this.isPrimaryField(field)){
|
2006-03-22 18:16:29 +00:00
|
|
|
if (!this.isEditableField(field)){
|
2006-03-14 11:48:36 +00:00
|
|
|
throw ('Primary field ' + field + ' cannot be changed through ' +
|
|
|
|
'setField');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._data[field] && this._data[field]==value){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this._data[field] = value;
|
|
|
|
this._changed.set(field);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Type-specific field
|
|
|
|
else {
|
|
|
|
if (!this.getType()){
|
2006-05-18 11:25:10 +00:00
|
|
|
throw ('Item type must be set before setting field data.');
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
// If existing item, load field data first unless we're already in
|
2006-03-14 11:48:36 +00:00
|
|
|
// the middle of a load
|
2006-05-18 11:25:10 +00:00
|
|
|
if (this.getID() && !loadIn && !this._itemDataLoaded){
|
|
|
|
this._loadItemData();
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
var fieldID = Scholar.ItemFields.getID(field);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (!fieldID){
|
2006-05-18 11:25:10 +00:00
|
|
|
throw (field + ' is not a valid itemData field.');
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
if (!Scholar.ItemFields.isValidForType(fieldID, this.getType())){
|
2006-03-14 11:48:36 +00:00
|
|
|
throw (field + ' is not a valid field for this type.');
|
|
|
|
}
|
|
|
|
|
|
|
|
// If existing value, make sure it's actually changing
|
2006-06-08 21:08:50 +00:00
|
|
|
if ((!this._itemData[fieldID] && !value) ||
|
|
|
|
(this._itemData[fieldID] && this._itemData[fieldID]==value)){
|
2006-03-14 11:48:36 +00:00
|
|
|
return false;
|
|
|
|
}
|
2006-05-18 11:25:10 +00:00
|
|
|
this._itemData[fieldID] = value;
|
2006-03-14 11:48:36 +00:00
|
|
|
if (!loadIn){
|
2006-05-18 11:25:10 +00:00
|
|
|
this._changedItemData.set(fieldID);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-01 22:19:21 +00:00
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
|
|
|
* Save changes back to database
|
2006-06-28 15:47:58 +00:00
|
|
|
*
|
|
|
|
* Note: Does not call notify() if transaction is in progress
|
|
|
|
*
|
|
|
|
* Returns true on item update or itemID of new item
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.save = function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (!this.hasChanged()){
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.debug('Item ' + this.getID() + ' has not changed', 4);
|
2006-03-14 11:48:36 +00:00
|
|
|
return !!this.getID();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2006-05-18 11:25:10 +00:00
|
|
|
// Existing item, update
|
2006-03-14 11:48:36 +00:00
|
|
|
//
|
|
|
|
if (this.getID()){
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.debug('Updating database with new item data', 4);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
var itemID = this.getID();
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
try {
|
2006-03-20 21:47:22 +00:00
|
|
|
Scholar.DB.beginTransaction();
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
// Begin history transaction
|
|
|
|
Scholar.History.begin('modify-item', this.getID());
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
//
|
|
|
|
// Primary fields
|
|
|
|
//
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.modify('items', 'itemID', this.getID());
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
var sql = "UPDATE items SET ";
|
2006-03-14 11:48:36 +00:00
|
|
|
var sql2;
|
2006-06-02 07:03:24 +00:00
|
|
|
var sqlValues = [];
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
if (this._changed.has('itemTypeID')){
|
2006-06-02 07:03:24 +00:00
|
|
|
sql += "itemTypeID=?, ";
|
|
|
|
sqlValues.push({'int':this.getField('itemTypeID')});
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
if (this._changed.has('title')){
|
2006-06-02 07:03:24 +00:00
|
|
|
sql += "title=?, ";
|
|
|
|
sqlValues.push({'string':this.getField('title')});
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Always update modified time
|
|
|
|
sql += "dateModified=CURRENT_TIMESTAMP ";
|
2006-06-08 00:16:35 +00:00
|
|
|
sql += "WHERE itemID=?";
|
2006-06-02 07:03:24 +00:00
|
|
|
sqlValues.push({'int':this.getID()});
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-06-02 07:03:24 +00:00
|
|
|
Scholar.DB.query(sql, sqlValues);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Creators
|
|
|
|
//
|
|
|
|
if (this._changedCreators.length){
|
2006-06-08 00:16:35 +00:00
|
|
|
for (var i=0, len=this.numCreators(); i<len; i++){
|
|
|
|
var creator = this.getCreator(i);
|
|
|
|
if (this.creatorExists(creator['firstName'],
|
|
|
|
creator['lastName'], creator['creatorTypeID'], i)){
|
|
|
|
throw('Cannot add duplicate creator/creatorType '
|
|
|
|
+ 'to item ' + this.getID());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
for (orderIndex in this._changedCreators.items){
|
|
|
|
Scholar.debug('Creator ' + orderIndex + ' has changed', 4);
|
|
|
|
|
|
|
|
var creator = this.getCreator(orderIndex);
|
|
|
|
|
2006-06-08 00:16:35 +00:00
|
|
|
// Delete at position
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.remove('itemCreators', 'itemID-orderIndex',
|
|
|
|
[this.getID(), orderIndex]);
|
|
|
|
|
2006-06-08 00:16:35 +00:00
|
|
|
sql2 = 'DELETE FROM itemCreators'
|
|
|
|
+ ' WHERE itemID=' + this.getID()
|
|
|
|
+ ' AND orderIndex=' + orderIndex;
|
|
|
|
Scholar.DB.query(sql2);
|
|
|
|
|
|
|
|
// If empty, move on
|
2006-03-14 11:48:36 +00:00
|
|
|
if (!creator['firstName'] && !creator['lastName']){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if this is an existing creator
|
2006-03-21 15:19:11 +00:00
|
|
|
var creatorID = Scholar.Creators.getID(
|
2006-03-14 11:48:36 +00:00
|
|
|
creator['firstName'],
|
2006-05-20 15:18:36 +00:00
|
|
|
creator['lastName']
|
2006-03-14 11:48:36 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
// If not, add it
|
|
|
|
if (!creatorID){
|
2006-03-21 15:19:11 +00:00
|
|
|
creatorID = Scholar.Creators.add(
|
2006-03-14 11:48:36 +00:00
|
|
|
creator['firstName'],
|
2006-05-20 15:18:36 +00:00
|
|
|
creator['lastName']
|
2006-03-14 11:48:36 +00:00
|
|
|
);
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.add('creators', 'creatorID', creatorID);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
sql2 = 'SELECT COUNT(*) FROM itemCreators'
|
|
|
|
+ ' WHERE itemID=' + this.getID()
|
2006-06-08 00:16:35 +00:00
|
|
|
+ ' AND creatorID=' + creatorID
|
|
|
|
+ ' AND creatorTypeID=' + creator['creatorTypeID'];
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
// If this creator and creatorType exists elsewhere, move it
|
2006-03-20 21:47:22 +00:00
|
|
|
if (Scholar.DB.valueQuery(sql2)){
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.modify('itemCreators',
|
|
|
|
'itemID-creatorID-creatorTypeID',
|
|
|
|
[this.getID(), creatorID, creator['creatorTypeID']]);
|
|
|
|
|
2006-06-08 00:16:35 +00:00
|
|
|
sql = 'UPDATE itemCreators SET orderIndex=? '
|
|
|
|
+ "WHERE itemID=? AND creatorID=? AND "
|
|
|
|
+ "creatorTypeID=?";
|
2006-06-02 07:03:24 +00:00
|
|
|
|
|
|
|
sqlValues = [
|
2006-06-08 00:16:35 +00:00
|
|
|
{'int':orderIndex},
|
2006-06-02 07:03:24 +00:00
|
|
|
{'int':this.getID()},
|
2006-06-08 00:16:35 +00:00
|
|
|
{'int':creatorID},
|
|
|
|
{'int':creator['creatorTypeID']}
|
2006-06-02 07:03:24 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
Scholar.DB.query(sql, sqlValues);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
2006-06-25 04:11:19 +00:00
|
|
|
|
2006-05-20 15:18:36 +00:00
|
|
|
// Otherwise insert
|
2006-03-14 11:48:36 +00:00
|
|
|
else {
|
2006-06-02 16:37:17 +00:00
|
|
|
sql = "INSERT INTO itemCreators VALUES (?,?,?,?)";
|
2006-06-02 07:03:24 +00:00
|
|
|
|
|
|
|
sqlValues = [
|
|
|
|
{'int':itemID},
|
|
|
|
{'int':creatorID},
|
|
|
|
{'int':creator['creatorTypeID']},
|
|
|
|
{'int':orderIndex}
|
|
|
|
];
|
|
|
|
|
|
|
|
Scholar.DB.query(sql, sqlValues);
|
2006-06-25 04:11:19 +00:00
|
|
|
|
|
|
|
Scholar.History.add('itemCreators',
|
|
|
|
'itemID-creatorID-creatorTypeID',
|
|
|
|
[this.getID(), creatorID, creator['creatorTypeID']]);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-23 22:00:39 +00:00
|
|
|
// Delete obsolete creators
|
2006-06-25 04:11:19 +00:00
|
|
|
var deleted;
|
|
|
|
if (deleted = Scholar.Creators.purge()){
|
|
|
|
for (var i in deleted){
|
|
|
|
// Add purged creators to history
|
|
|
|
Scholar.History.remove('creators', 'creatorID', i);
|
|
|
|
}
|
|
|
|
}
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2006-05-18 11:25:10 +00:00
|
|
|
// ItemData
|
2006-03-14 11:48:36 +00:00
|
|
|
//
|
2006-05-18 11:25:10 +00:00
|
|
|
if (this._changedItemData.length){
|
2006-03-14 11:48:36 +00:00
|
|
|
var del = new Array();
|
2006-05-18 11:25:10 +00:00
|
|
|
for (fieldID in this._changedItemData.items){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (this.getField(fieldID)){
|
|
|
|
// Oh, for an INSERT...ON DUPLICATE KEY UPDATE
|
2006-05-18 11:25:10 +00:00
|
|
|
sql2 = 'SELECT COUNT(*) FROM itemData '
|
|
|
|
+ 'WHERE itemID=' + this.getID()
|
2006-03-14 11:48:36 +00:00
|
|
|
+ ' AND fieldID=' + fieldID;
|
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
// Update
|
2006-03-20 21:47:22 +00:00
|
|
|
if (Scholar.DB.valueQuery(sql2)){
|
2006-06-02 07:03:24 +00:00
|
|
|
sqlValues = [];
|
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.modify('itemData', 'itemID-fieldID',
|
|
|
|
[this.getID(), fieldID]);
|
|
|
|
|
2006-06-02 07:03:24 +00:00
|
|
|
sql = "UPDATE itemData SET value=?";
|
2006-03-14 11:48:36 +00:00
|
|
|
// Take advantage of SQLite's manifest typing
|
2006-05-18 11:25:10 +00:00
|
|
|
if (Scholar.ItemFields.isInteger(fieldID)){
|
2006-06-02 07:03:24 +00:00
|
|
|
sqlValues.push({'int':this.getField(fieldID)});
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
else {
|
2006-06-02 07:03:24 +00:00
|
|
|
sqlValues.push({'string':this.getField(fieldID)});
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
2006-06-02 16:37:17 +00:00
|
|
|
sql += " WHERE itemID=? AND fieldID=?";
|
2006-06-02 07:03:24 +00:00
|
|
|
|
|
|
|
sqlValues.push(
|
|
|
|
{'int':this.getID()},
|
|
|
|
{'int':fieldID}
|
|
|
|
);
|
|
|
|
|
|
|
|
Scholar.DB.query(sql, sqlValues);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
2006-06-25 04:11:19 +00:00
|
|
|
|
|
|
|
// Insert
|
2006-03-14 11:48:36 +00:00
|
|
|
else {
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.add('itemData', 'itemID-fieldID',
|
|
|
|
[this.getID(), fieldID]);
|
|
|
|
|
2006-06-02 16:37:17 +00:00
|
|
|
sql = "INSERT INTO itemData VALUES (?,?,?)";
|
|
|
|
|
2006-06-02 07:03:24 +00:00
|
|
|
sqlValues = [
|
|
|
|
{'int':this.getID()},
|
|
|
|
{'int':fieldID},
|
|
|
|
];
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
if (Scholar.ItemFields.isInteger(fieldID)){
|
2006-06-02 07:03:24 +00:00
|
|
|
sqlValues.push({'int':this.getField(fieldID)});
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
else {
|
2006-06-02 07:03:24 +00:00
|
|
|
sqlValues.push({'string':this.getField(fieldID)});
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
2006-06-02 07:03:24 +00:00
|
|
|
|
|
|
|
Scholar.DB.query(sql, sqlValues);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
2006-06-25 04:11:19 +00:00
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
// If field changed and is empty, mark row for deletion
|
|
|
|
else {
|
|
|
|
del.push(fieldID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete blank fields
|
|
|
|
if (del.length){
|
2006-06-25 04:11:19 +00:00
|
|
|
// Add to history
|
|
|
|
for (var i in del){
|
|
|
|
Scholar.History.remove('itemData', 'itemID-fieldID',
|
|
|
|
[this.getID(), del[i]]);
|
|
|
|
}
|
|
|
|
|
2006-06-02 07:03:24 +00:00
|
|
|
sql = 'DELETE from itemData '
|
2006-05-18 11:25:10 +00:00
|
|
|
+ 'WHERE itemID=' + this.getID() + ' '
|
2006-06-02 16:37:17 +00:00
|
|
|
+ 'AND fieldID IN (' + del.join() + ")";
|
2006-06-02 07:03:24 +00:00
|
|
|
Scholar.DB.query(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.commit();
|
2006-03-20 21:47:22 +00:00
|
|
|
Scholar.DB.commitTransaction();
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
catch (e){
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.cancel();
|
2006-03-20 21:47:22 +00:00
|
|
|
Scholar.DB.rollbackTransaction();
|
2006-05-18 21:55:43 +00:00
|
|
|
throw(e);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2006-05-18 11:25:10 +00:00
|
|
|
// New item, insert and return id
|
2006-03-14 11:48:36 +00:00
|
|
|
//
|
|
|
|
else {
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.debug('Saving data for new item to database');
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
var isNew = true;
|
|
|
|
var sqlColumns = new Array();
|
|
|
|
var sqlValues = new Array();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Primary fields
|
|
|
|
//
|
2006-06-29 06:28:50 +00:00
|
|
|
sqlColumns.push('itemID');
|
|
|
|
var itemID = Scholar.getRandomID('items', 'itemID');
|
|
|
|
sqlValues.push(itemID);
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
sqlColumns.push('itemTypeID');
|
|
|
|
sqlValues.push({'int':this.getField('itemTypeID')});
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (this._changed.has('title')){
|
|
|
|
sqlColumns.push('title');
|
|
|
|
sqlValues.push({'string':this.getField('title')});
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2006-03-20 21:47:22 +00:00
|
|
|
Scholar.DB.beginTransaction();
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
// Begin history transaction
|
|
|
|
// No associated id yet, so we use false
|
|
|
|
Scholar.History.begin('add-item', false);
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
//
|
2006-06-25 04:11:19 +00:00
|
|
|
// Primary fields
|
2006-03-14 11:48:36 +00:00
|
|
|
//
|
2006-05-18 11:25:10 +00:00
|
|
|
var sql = "INSERT INTO items (" + sqlColumns.join() + ')'
|
2006-03-14 11:48:36 +00:00
|
|
|
+ ' VALUES (';
|
|
|
|
// Insert placeholders for bind parameters
|
|
|
|
for (var i=0; i<sqlValues.length; i++){
|
|
|
|
sql += '?,';
|
|
|
|
}
|
2006-06-08 00:16:35 +00:00
|
|
|
sql = sql.substring(0,sql.length-1) + ")";
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-06-29 06:28:50 +00:00
|
|
|
// Save basic data to items table
|
|
|
|
Scholar.DB.query(sql, sqlValues);
|
2006-05-18 21:55:43 +00:00
|
|
|
this._data['itemID'] = itemID;
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.setAssociatedID(itemID);
|
|
|
|
Scholar.History.add('items', 'itemID', itemID);
|
|
|
|
|
|
|
|
//
|
|
|
|
// ItemData
|
|
|
|
//
|
2006-05-18 11:25:10 +00:00
|
|
|
if (this._changedItemData.length){
|
|
|
|
for (fieldID in this._changedItemData.items){
|
2006-05-18 21:55:43 +00:00
|
|
|
if (!this.getField(fieldID)){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-06-02 07:03:24 +00:00
|
|
|
// TODO: update DB methods so that this can be
|
|
|
|
// implemented as a prepared statement that gets
|
|
|
|
// called multiple times
|
2006-06-02 16:37:17 +00:00
|
|
|
sql = "INSERT INTO itemData VALUES (?,?,?)";
|
2006-06-02 07:03:24 +00:00
|
|
|
|
2006-06-02 16:37:17 +00:00
|
|
|
sqlValues = [
|
2006-06-02 07:03:24 +00:00
|
|
|
{'int':itemID},
|
|
|
|
{'int':fieldID}
|
2006-06-02 16:37:17 +00:00
|
|
|
];
|
2006-06-02 07:03:24 +00:00
|
|
|
|
|
|
|
if (Scholar.ItemFields.isInteger(fieldID)){
|
|
|
|
sqlValues.push({'int':this.getField(fieldID)});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sqlValues.push({'string':this.getField(fieldID)});
|
|
|
|
}
|
2006-06-02 16:37:17 +00:00
|
|
|
|
2006-06-02 07:03:24 +00:00
|
|
|
Scholar.DB.query(sql, sqlValues);
|
2006-06-25 04:11:19 +00:00
|
|
|
|
|
|
|
Scholar.History.add('itemData', 'itemID-fieldID',
|
2006-06-25 05:26:53 +00:00
|
|
|
[itemID, fieldID]);
|
2006-05-18 21:55:43 +00:00
|
|
|
}
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-01 07:29:39 +00:00
|
|
|
//
|
|
|
|
// Creators
|
|
|
|
//
|
|
|
|
if (this._changedCreators.length){
|
|
|
|
for (orderIndex in this._changedCreators.items){
|
|
|
|
var creator = this.getCreator(orderIndex);
|
|
|
|
|
|
|
|
// If empty, skip
|
|
|
|
if (!creator['firstName'] && !creator['lastName']){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if this is an existing creator
|
|
|
|
var creatorID = Scholar.Creators.getID(
|
|
|
|
creator['firstName'],
|
|
|
|
creator['lastName']
|
|
|
|
);
|
|
|
|
|
|
|
|
// If not, add it
|
|
|
|
if (!creatorID){
|
|
|
|
creatorID = Scholar.Creators.add(
|
|
|
|
creator['firstName'],
|
|
|
|
creator['lastName']
|
|
|
|
);
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.add('creators', 'creatorID', creatorID);
|
2006-06-01 07:29:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sql = 'INSERT INTO itemCreators VALUES ('
|
|
|
|
+ itemID + ',' + creatorID + ','
|
|
|
|
+ creator['creatorTypeID'] + ', ' + orderIndex
|
2006-06-08 00:16:35 +00:00
|
|
|
+ ")";
|
2006-06-01 07:29:39 +00:00
|
|
|
Scholar.DB.query(sql);
|
2006-06-25 04:11:19 +00:00
|
|
|
|
|
|
|
Scholar.History.add('itemCreators',
|
|
|
|
'itemID-creatorID-creatorTypeID',
|
|
|
|
[this.getID(), creatorID, creator['creatorTypeID']]);
|
2006-06-01 07:29:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.commit();
|
2006-03-20 21:47:22 +00:00
|
|
|
Scholar.DB.commitTransaction();
|
2006-05-18 21:55:43 +00:00
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
// Reload collection to update isEmpty,
|
|
|
|
// in case this was the first item in a collection
|
|
|
|
Scholar.Collections.reloadAll();
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
catch (e){
|
2006-06-25 04:11:19 +00:00
|
|
|
Scholar.History.cancel();
|
2006-03-20 21:47:22 +00:00
|
|
|
Scholar.DB.rollbackTransaction();
|
2006-05-18 21:55:43 +00:00
|
|
|
throw(e);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Items.reload(this.getID());
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-06-02 01:17:44 +00:00
|
|
|
if (isNew){
|
2006-06-28 15:47:58 +00:00
|
|
|
if (!Scholar.DB.transactionInProgress()){
|
|
|
|
Scholar.Notifier.trigger('add', 'item', this.getID());
|
|
|
|
}
|
2006-06-02 01:17:44 +00:00
|
|
|
return this.getID();
|
|
|
|
}
|
|
|
|
else {
|
2006-06-28 15:47:58 +00:00
|
|
|
if (!Scholar.DB.transactionInProgress()){
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', this.getID());
|
|
|
|
}
|
2006-06-02 01:17:44 +00:00
|
|
|
return true;
|
|
|
|
}
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-16 15:57:52 +00:00
|
|
|
Scholar.Item.prototype.updateDateModified = function(){
|
|
|
|
Scholar.DB.query("UPDATE items SET dateModified=CURRENT_TIMESTAMP "
|
|
|
|
+ "WHERE itemID=" + this.getID());
|
|
|
|
var date = Scholar.DB.valueQuery("SELECT dateModified FROM items "
|
|
|
|
+ "WHERE itemID=" + this.getID());
|
|
|
|
this._data['dateModified'] = date;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
////////////////////////////////////////////////////////
|
2006-06-16 07:32:48 +00:00
|
|
|
//
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
// Methods dealing with note items
|
2006-06-16 07:32:48 +00:00
|
|
|
//
|
|
|
|
// save() is not required for note functions
|
|
|
|
//
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
////////////////////////////////////////////////////////
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
Scholar.Item.prototype.incrementNoteCount = function(){
|
2006-06-25 05:43:00 +00:00
|
|
|
this._data['numNotes']++;
|
2006-06-16 07:32:48 +00:00
|
|
|
}
|
|
|
|
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
|
|
|
|
Scholar.Item.prototype.decrementNoteCount = function(){
|
|
|
|
this._data['numNotes']--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-16 07:32:48 +00:00
|
|
|
/**
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
* Determine if an item is a note
|
2006-06-16 07:32:48 +00:00
|
|
|
**/
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
Scholar.Item.prototype.isNote = function(){
|
|
|
|
return Scholar.ItemTypes.getName(this.getType())=='note';
|
2006-06-16 07:32:48 +00:00
|
|
|
}
|
|
|
|
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
|
2006-06-16 07:32:48 +00:00
|
|
|
/**
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
* Update an item note
|
|
|
|
*
|
|
|
|
* Note: This can only be called on note items.
|
2006-06-16 07:32:48 +00:00
|
|
|
**/
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
Scholar.Item.prototype.updateNote = function(text){
|
|
|
|
if (!this.isNote()){
|
|
|
|
throw ("updateNote() can only be called on items of type 'note'");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.getID()){
|
|
|
|
throw ("Cannot call updateNote() on unsaved note");
|
|
|
|
}
|
|
|
|
|
2006-06-16 15:57:52 +00:00
|
|
|
Scholar.DB.beginTransaction();
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
|
|
|
|
var sql = "UPDATE itemNotes SET note=? WHERE itemID=?";
|
|
|
|
bindParams = [{string:text}, this.getID()];
|
|
|
|
var updated = Scholar.DB.query(sql, bindParams);
|
|
|
|
if (updated){
|
2006-06-25 05:43:00 +00:00
|
|
|
this.updateDateModified();
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', this.getID());
|
2006-06-25 05:43:00 +00:00
|
|
|
}
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
else {
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
Scholar.Item.prototype.setSource = function(sourceItemID){
|
|
|
|
if (this.isNote()){
|
|
|
|
var type = 'note';
|
|
|
|
var Type = 'Note';
|
|
|
|
}
|
|
|
|
else if (this.isFile()){
|
|
|
|
var type = 'file';
|
|
|
|
var Type = 'file';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw ("setSource() can only be called on items of type 'note' or 'file'");
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.getID()){
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
throw ("Cannot call setSource() on unsaved " + type);
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
var newItem = Scholar.Items.get(sourceItemID);
|
|
|
|
// FK check
|
|
|
|
if (sourceItemID && !newItem){
|
|
|
|
Scholar.DB.rollbackTransaction();
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
throw ("Cannot set " + type + " source to invalid item " + sourceItemID);
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get previous source item id
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
var sql = "SELECT sourceItemID FROM item" + Type + "s WHERE item=" + this.getID();
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
var oldSourceItemID = Scholar.DB.valueQuery(sql);
|
|
|
|
|
|
|
|
if (oldSourceItemID==sourceItemID){
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
Scholar.debug(Type + " source hasn't changed", 4);
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var oldItem = Scholar.Items.get(oldSourceItemID);
|
|
|
|
if (oldSourceItemID && !oldItem){
|
|
|
|
Scholar.debug("Old source item " + oldSourceItemID
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
+ "didn't exist in setSource()", 2);
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
var sql = "UPDATE item" + Type + "s SET sourceItemID=? WHERE itemID=?";
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
var bindParams = [sourceItemID ? {int:sourceItemID} : null, this.getID()];
|
|
|
|
Scholar.DB.query(sql, bindParams);
|
|
|
|
this.updateDateModified();
|
2006-06-16 15:57:52 +00:00
|
|
|
Scholar.DB.commitTransaction();
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
|
2006-06-27 19:42:02 +00:00
|
|
|
Scholar.Notifier.trigger('modify', 'item', this.getID());
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
// Update the counts of the previous and new sources
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
if (oldItem){
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
switch (type){
|
|
|
|
case 'note':
|
|
|
|
oldItem.decrementNoteCount();
|
|
|
|
break;
|
|
|
|
case 'file':
|
|
|
|
oldItem.decrementFileCount();
|
|
|
|
break;
|
|
|
|
}
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
Scholar.Notifier.trigger('modify', 'item', oldSourceItemID);
|
|
|
|
}
|
|
|
|
if (newItem){
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
switch (type){
|
|
|
|
case 'note':
|
|
|
|
newItem.incrementNoteCount();
|
|
|
|
break;
|
|
|
|
case 'file':
|
|
|
|
newItem.incrementFileCount();
|
|
|
|
break;
|
|
|
|
}
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
Scholar.Notifier.trigger('modify', 'item', sourceItemID);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2006-06-16 07:32:48 +00:00
|
|
|
}
|
|
|
|
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
|
2006-06-16 15:18:01 +00:00
|
|
|
/**
|
|
|
|
* Returns number of notes in item
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.numNotes = function(){
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
if (this.isNote()){
|
|
|
|
throw ("numNotes() cannot be called on items of type 'note'");
|
|
|
|
}
|
|
|
|
|
2006-06-16 21:33:03 +00:00
|
|
|
if (!this.getID()){
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-06-25 05:43:00 +00:00
|
|
|
return this._data['numNotes'];
|
2006-06-16 15:18:01 +00:00
|
|
|
}
|
|
|
|
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
|
2006-06-16 07:32:48 +00:00
|
|
|
/**
|
|
|
|
* Get the text of an item note
|
|
|
|
**/
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
Scholar.Item.prototype.getNote = function(){
|
|
|
|
if (!this.isNote()){
|
|
|
|
throw ("getNote() can only be called on items of type 'note'");
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "SELECT note FROM itemNotes WHERE itemID=" + this.getID();
|
2006-06-27 22:55:43 +00:00
|
|
|
var note = Scholar.DB.valueQuery(sql);
|
|
|
|
return note ? note : '';
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
* Get the itemID of the source item for a note or file
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
**/
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
Scholar.Item.prototype.getSource = function(){
|
|
|
|
if (this.isNote()){
|
|
|
|
var Type = 'Note';
|
|
|
|
}
|
|
|
|
else if (this.isFile()){
|
|
|
|
var Type = 'File';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw ("getSource() can only be called on items of type 'note' or 'file'");
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
var sql = "SELECT sourceItemID FROM item" + Type + "s WHERE itemID=" + this.getID();
|
2006-06-16 07:32:48 +00:00
|
|
|
return Scholar.DB.valueQuery(sql);
|
|
|
|
}
|
|
|
|
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
|
2006-06-16 07:32:48 +00:00
|
|
|
/**
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
* Returns an array of note itemIDs for this item
|
2006-06-16 07:32:48 +00:00
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.getNotes = function(){
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
if (this.isNote()){
|
|
|
|
Scholar.debug('here');
|
|
|
|
throw ("getNotes() cannot be called on items of type 'note'");
|
|
|
|
}
|
|
|
|
|
2006-06-16 21:33:03 +00:00
|
|
|
if (!this.getID()){
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
var sql = "SELECT itemID FROM itemNotes NATURAL JOIN items "
|
|
|
|
+ "WHERE sourceItemID=" + this.getID() + " ORDER BY dateAdded";
|
2006-06-16 07:32:48 +00:00
|
|
|
return Scholar.DB.columnQuery(sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Methods dealing with file items
|
|
|
|
//
|
|
|
|
// save() is not required for file functions
|
|
|
|
//
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
Scholar.Item.prototype.incrementFileCount = function(){
|
|
|
|
this._data['numFiles']++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Scholar.Item.prototype.decrementFileCount = function(){
|
|
|
|
this._data['numFiles']--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if an item is a file
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.isFile = function(){
|
|
|
|
return Scholar.ItemTypes.getName(this.getType())=='file';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns number of files in item
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.numFiles = function(){
|
|
|
|
if (this.isFile()){
|
|
|
|
throw ("numFiles() cannot be called on items of type 'file'");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.getID()){
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._data['numFiles'];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get an nsILocalFile for the file item, or false if the associated file doesn't exist
|
|
|
|
*
|
|
|
|
* Note: Always returns false for items with LINK_MODE_LINKED_URL,
|
|
|
|
* since they have no files -- use getFileURL() instead
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.getFile = function(){
|
|
|
|
if (!this.isFile()){
|
|
|
|
throw ("getFile() can only be called on items of type 'file'");
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "SELECT linkMode, path FROM itemFiles WHERE itemID=" + this.getID();
|
|
|
|
var row = Scholar.DB.rowQuery(sql);
|
|
|
|
|
|
|
|
if (!row){
|
|
|
|
throw ('File data not found for item ' + this.getID() + ' in getFile()');
|
|
|
|
}
|
|
|
|
|
|
|
|
// No associated files for linked URLs
|
|
|
|
if (row['linkMode']==Scholar.Files.LINK_MODE_LINKED_URL){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var file = Components.classes["@mozilla.org/file/local;1"].
|
|
|
|
createInstance(Components.interfaces.nsILocalFile);
|
|
|
|
|
|
|
|
var refDir = (linkMode==this.LINK_MODE_LINKED_FILE)
|
|
|
|
? Scholar.getScholarDirectory() : Scholar.getStorageDirectory();
|
|
|
|
file.setRelativeDescriptor(refDir, row['path']);
|
|
|
|
|
|
|
|
if (!file.exists()){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Scholar.Item.prototype.getFileURL = function(){
|
|
|
|
if (!this.isFile()){
|
|
|
|
throw ("getFileURL() can only be called on items of type 'file'");
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "SELECT linkMode, path, originalPath FROM itemFiles "
|
|
|
|
+ "WHERE itemID=" + this.getID();
|
|
|
|
var row = Scholar.DB.rowQuery(sql);
|
|
|
|
|
|
|
|
if (!row){
|
|
|
|
throw ('File data not found for item ' + this.getID() + ' in getFileURL()');
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (row['linkMode']){
|
|
|
|
case Scholar.Files.LINK_MODE_LINKED_URL:
|
|
|
|
return row['path'];
|
|
|
|
case Scholar.Files.LINK_MODE_IMPORTED_URL:
|
|
|
|
return row['originalPath'];
|
|
|
|
default:
|
|
|
|
throw ('getFileURL() cannot be called on files without associated URLs');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the link mode of a file item
|
|
|
|
*
|
|
|
|
* Possible return values specified as constants in Scholar.Files
|
|
|
|
* (e.g. Scholar.Files.LINK_MODE_LINKED_FILE)
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.getFileLinkMode = function(){
|
|
|
|
if (!this.isFile()){
|
|
|
|
throw ("getFileLinkMode() can only be called on items of type 'file'");
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "SELECT linkMode FROM itemFiles WHERE itemID=" + this.getID();
|
|
|
|
return Scholar.DB.valueQuery(sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the mime type of a file item (e.g. text/plain)
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.getFileMimeType = function(){
|
|
|
|
if (!this.isFile()){
|
|
|
|
throw ("getFileData() can only be called on items of type 'file'");
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "SELECT mimeType FROM itemFiles WHERE itemID=" + this.getID();
|
|
|
|
return Scholar.DB.valueQuery(sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the character set id of a file item
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.getFileCharset = function(){
|
|
|
|
if (!this.isFile()){
|
|
|
|
throw ("getFileCharset() can only be called on items of type 'file'");
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "SELECT charsetID FROM itemFiles WHERE itemID=" + this.getID();
|
|
|
|
return Scholar.DB.valueQuery(sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an array of file itemIDs for this item
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.getFiles = function(){
|
|
|
|
if (this.isFile()){
|
|
|
|
throw ("getFiles() cannot be called on items of type 'file'");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.getID()){
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "SELECT itemID FROM itemFiles NATURAL JOIN items "
|
|
|
|
+ "WHERE sourceItemID=" + this.getID() + " ORDER BY dateAdded";
|
|
|
|
return Scholar.DB.columnQuery(sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-06-28 18:06:36 +00:00
|
|
|
//
|
|
|
|
// Methods dealing with item tags
|
|
|
|
//
|
|
|
|
// save() is not required for tag functions
|
|
|
|
//
|
|
|
|
Scholar.Item.prototype.addTag = function(tag){
|
|
|
|
if (!this.getID()){
|
|
|
|
this.save();
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
var tagID = Scholar.Tags.getID(tag);
|
|
|
|
if (!tagID){
|
|
|
|
var tagID = Scholar.Tags.add(tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "INSERT OR IGNORE INTO itemTags VALUES (?,?)";
|
|
|
|
Scholar.DB.query(sql, [this.getID(), tagID]);
|
|
|
|
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', this.getID());
|
2006-06-28 18:12:38 +00:00
|
|
|
|
|
|
|
return tagID;
|
2006-06-28 18:06:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.Item.prototype.getTags = function(){
|
2006-07-06 13:06:32 +00:00
|
|
|
var sql = "SELECT tag FROM tags WHERE tagID IN "
|
|
|
|
+ "(SELECT tagID FROM itemTags WHERE itemID=" + this.getID() + ")";
|
|
|
|
return Scholar.DB.columnQuery(sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.Item.prototype.getTagIDs = function(){
|
2006-06-28 18:06:36 +00:00
|
|
|
var sql = "SELECT tagID FROM itemTags WHERE itemID=" + this.getID();
|
|
|
|
return Scholar.DB.columnQuery(sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.Item.prototype.removeTag = function(tagID){
|
|
|
|
if (!this.getID()){
|
|
|
|
throw ('Cannot remove tag on unsaved item');
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
var sql = "DELETE FROM itemTags WHERE itemID=? AND tagID=?";
|
|
|
|
Scholar.DB.query(sql, [this.getID(), tagID]);
|
|
|
|
Scholar.Tags.purge();
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', this.getID());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-29 01:37:53 +00:00
|
|
|
//
|
|
|
|
// Methods dealing with See Also links
|
|
|
|
//
|
|
|
|
// save() is not required for See Also functions
|
|
|
|
//
|
|
|
|
Scholar.Item.prototype.addSeeAlso = function(itemID){
|
|
|
|
if (itemID==this.getID()){
|
|
|
|
Scholar.debug('Cannot add item as See Also of itself', 2);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
if (!Scholar.Items.get(itemID)){
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
throw ("Cannot add invalid item " + itemID + " as See Also");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check both ways, using a UNION to take advantage of indexes
|
|
|
|
var sql = "SELECT (SELECT COUNT(*) FROM itemSeeAlso WHERE itemID=?1 AND "
|
|
|
|
+ "linkedItemID=?2) + (SELECT COUNT(*) FROM itemSeeAlso WHERE "
|
|
|
|
+ "linkedItemID=?1 AND itemID=?2)";
|
|
|
|
if (Scholar.DB.valueQuery(sql, [this.getID(), itemID])){
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
Scholar.debug("Item " + itemID + " already linked", 2);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "INSERT INTO itemSeeAlso VALUES (?,?)";
|
|
|
|
Scholar.DB.query(sql, [this.getID(), {int:itemID}]);
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', [this.getID(), itemID]);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.Item.prototype.removeSeeAlso = function(itemID){
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
var sql = "DELETE FROM itemSeeAlso WHERE itemID=? AND linkedItemID=?";
|
|
|
|
Scholar.DB.query(sql, [this.getID(), itemID]);
|
|
|
|
var sql = "DELETE FROM itemSeeAlso WHERE itemID=? AND linkedItemID=?";
|
|
|
|
Scholar.DB.query(sql, [itemID, this.getID()]);
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', [this.getID(), itemID]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.Item.prototype.getSeeAlso = function(){
|
|
|
|
// Check both ways, using a UNION to take advantage of indexes
|
|
|
|
var sql ="SELECT linkedItemID FROM itemSeeAlso WHERE itemID=?1 UNION "
|
|
|
|
+ "SELECT itemID FROM itemSeeAlso WHERE linkedItemID=?1";
|
|
|
|
return Scholar.DB.columnQuery(sql, this.getID());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-19 11:31:45 +00:00
|
|
|
/**
|
|
|
|
* Delete item from database and clear from Scholar.Items internal array
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.erase = function(){
|
|
|
|
if (!this.getID()){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.debug('Deleting item ' + this.getID());
|
2006-06-29 01:37:53 +00:00
|
|
|
|
|
|
|
var changedItems = [];
|
|
|
|
|
2006-05-19 11:31:45 +00:00
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
// Remove item from parent collections
|
|
|
|
var parentCollectionIDs = this.getCollections();
|
|
|
|
for (var i=0; i<parentCollectionIDs.length; i++){
|
|
|
|
Scholar.Collections.get(parentCollectionIDs[i]).removeItem(this.getID());
|
|
|
|
}
|
2006-05-19 11:31:45 +00:00
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
// Note
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
if (this.isNote()){
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
// Decrement note count of source items
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
var sql = "SELECT sourceItemID FROM itemNotes WHERE itemID=" + this.getID();
|
|
|
|
var sourceItemID = Scholar.DB.valueQuery(sql);
|
|
|
|
if (sourceItemID){
|
|
|
|
var sourceItem = Scholar.Items.get(sourceItemID);
|
|
|
|
sourceItem.decrementNoteCount();
|
2006-06-29 01:37:53 +00:00
|
|
|
changedItems.push(sourceItemID);
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
|
|
|
}
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
// File
|
|
|
|
else if (this.isFile()){
|
|
|
|
// Decrement file count of source items
|
|
|
|
var sql = "SELECT sourceItemID FROM itemFiles WHERE itemID=" + this.getID();
|
|
|
|
var sourceItemID = Scholar.DB.valueQuery(sql);
|
|
|
|
if (sourceItemID){
|
|
|
|
var sourceItem = Scholar.Items.get(sourceItemID);
|
|
|
|
sourceItem.decrementFileCount();
|
|
|
|
changedItems.push(sourceItemID);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete associated files
|
|
|
|
var linkMode = this.getFileLinkMode();
|
|
|
|
switch (linkMode){
|
|
|
|
case Scholar.Files.LINK_MODE_LINKED_FILE:
|
|
|
|
case Scholar.Files.LINK_MODE_LINKED_URL:
|
|
|
|
// Links only -- nothing to delete
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
var file = Scholar.getStorageDirectory();
|
|
|
|
file.append(this.getID());
|
|
|
|
if (file.exists()){
|
|
|
|
file.remove(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If regular item, unassociate any notes or files for which this is a source
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
else {
|
2006-06-27 19:42:02 +00:00
|
|
|
// TODO: option for deleting child notes instead of unlinking
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
// Notes
|
2006-06-27 19:42:02 +00:00
|
|
|
var sql = "SELECT itemID FROM itemNotes WHERE sourceItemID=" + this.getID();
|
|
|
|
var childNotes = Scholar.DB.columnQuery(sql);
|
2006-06-29 01:37:53 +00:00
|
|
|
if (childNotes){
|
|
|
|
changedItems.push(childNotes);
|
|
|
|
}
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
var sql = "UPDATE itemNotes SET sourceItemID=NULL WHERE sourceItemID="
|
|
|
|
+ this.getID();
|
2006-06-27 19:42:02 +00:00
|
|
|
Scholar.DB.query(sql);
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
|
|
|
|
// Files
|
|
|
|
var sql = "SELECT itemID FROM itemFiles WHERE sourceItemID=" + this.getID();
|
|
|
|
var childFiles = Scholar.DB.columnQuery(sql);
|
|
|
|
if (childFiles){
|
|
|
|
changedItems.push(childFiles);
|
|
|
|
}
|
|
|
|
var sql = "UPDATE itemFiles SET sourceItemID=NULL WHERE sourceItemID="
|
|
|
|
+ this.getID();
|
|
|
|
Scholar.DB.query(sql);
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
|
|
|
|
2006-06-29 01:37:53 +00:00
|
|
|
// Flag See Also links for notification
|
|
|
|
var seeAlso = this.getSeeAlso();
|
|
|
|
if (seeAlso){
|
|
|
|
changedItems = changedItems.concat(seeAlso);
|
|
|
|
}
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
|
2006-06-02 21:11:14 +00:00
|
|
|
sql = 'DELETE FROM itemCreators WHERE itemID=' + this.getID() + ";\n";
|
2006-06-16 15:57:52 +00:00
|
|
|
sql += 'DELETE FROM itemNotes WHERE itemID=' + this.getID() + ";\n";
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
sql += 'DELETE FROM itemFiles WHERE itemID=' + this.getID() + ";\n";
|
2006-06-29 01:37:53 +00:00
|
|
|
sql += 'DELETE FROM itemSeeAlso WHERE itemID=' + this.getID() + ";\n";
|
|
|
|
sql += 'DELETE FROM itemSeeAlso WHERE linkedItemID=' + this.getID() + ";\n";
|
2006-06-28 19:12:35 +00:00
|
|
|
sql += 'DELETE FROM itemTags WHERE itemID=' + this.getID() + ";\n";
|
2006-06-02 21:11:14 +00:00
|
|
|
sql += 'DELETE FROM itemData WHERE itemID=' + this.getID() + ";\n";
|
|
|
|
sql += 'DELETE FROM items WHERE itemID=' + this.getID() + ";\n";
|
2006-05-19 11:31:45 +00:00
|
|
|
|
2006-06-02 21:11:14 +00:00
|
|
|
Scholar.DB.query(sql);
|
2006-05-19 11:31:45 +00:00
|
|
|
Scholar.Creators.purge();
|
|
|
|
|
|
|
|
try {
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
}
|
|
|
|
catch (e){
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
// On failure, reset count of source items
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
if (sourceItem){
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
if (this.isNote()){
|
|
|
|
sourceItem.incrementNoteCount();
|
|
|
|
}
|
|
|
|
else if (this.isFile()){
|
|
|
|
sourceItem.incrementFileCount();
|
|
|
|
}
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
}
|
2006-05-19 11:31:45 +00:00
|
|
|
Scholar.DB.rollbackTransaction();
|
|
|
|
throw (e);
|
|
|
|
}
|
|
|
|
|
2006-06-02 01:17:44 +00:00
|
|
|
Scholar.Items.unload(this.getID());
|
|
|
|
|
2006-06-29 01:37:53 +00:00
|
|
|
// Send notification of changed items
|
|
|
|
if (changedItems.length){
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', changedItems);
|
2006-06-27 19:42:02 +00:00
|
|
|
}
|
|
|
|
|
2006-06-01 22:19:21 +00:00
|
|
|
// If we're not in the middle of a larger commit, trigger the notifier now
|
|
|
|
if (!Scholar.DB.transactionInProgress()){
|
2006-06-08 20:41:37 +00:00
|
|
|
Scholar.Notifier.trigger('delete', 'item', this.getID());
|
2006-06-01 22:19:21 +00:00
|
|
|
}
|
2006-05-19 11:31:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-03 20:41:23 +00:00
|
|
|
Scholar.Item.prototype.isCollection = function(){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype.toString = function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
return this.getTitle();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-27 20:45:41 +00:00
|
|
|
/**
|
|
|
|
* Convert the item data into a multidimensional associative array
|
|
|
|
* for use by the export functions
|
|
|
|
**/
|
|
|
|
Scholar.Item.prototype.toArray = function(){
|
|
|
|
if (this.getID() && !this._itemDataLoaded){
|
|
|
|
this._loadItemData();
|
|
|
|
}
|
|
|
|
|
|
|
|
var arr = [];
|
|
|
|
|
|
|
|
// Primary fields
|
|
|
|
for (var i in this._data){
|
|
|
|
switch (i){
|
|
|
|
case 'itemTypeID':
|
|
|
|
arr['itemType'] = Scholar.ItemTypes.getName(this._data[i]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Skip certain fields
|
|
|
|
case 'firstCreator':
|
|
|
|
case 'numNotes':
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
case 'numFiles':
|
2006-06-27 20:45:41 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// For the rest, just copy over
|
|
|
|
default:
|
|
|
|
arr[i] = this._data[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Item metadata
|
|
|
|
for (var i in this._itemData){
|
|
|
|
arr[Scholar.ItemFields.getName(i)] = this._itemData[i];
|
|
|
|
}
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
if (!this.isNote() && !this.isFile()){
|
2006-06-27 20:45:41 +00:00
|
|
|
// Creators
|
2006-06-29 03:56:22 +00:00
|
|
|
arr['creators'] = [];
|
|
|
|
var creators = this.getCreators();
|
|
|
|
for (var i in creators){
|
|
|
|
arr['creators'][i] = [];
|
|
|
|
arr['creators'][i]['firstName'] = creators[i]['firstName'];
|
|
|
|
arr['creators'][i]['lastName'] = creators[i]['lastName'];
|
|
|
|
// Convert creatorTypeIDs to text
|
2006-06-27 20:45:41 +00:00
|
|
|
arr['creators'][i]['creatorType'] =
|
2006-06-29 03:56:22 +00:00
|
|
|
Scholar.CreatorTypes.getName(creators[i]['creatorTypeID']);
|
2006-06-27 20:45:41 +00:00
|
|
|
}
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Notes
|
|
|
|
if (this.isNote()){
|
|
|
|
// Don't need title for notes
|
|
|
|
delete arr['title'];
|
|
|
|
arr['note'] = this.getNote();
|
|
|
|
if (this.getSource()){
|
|
|
|
arr['sourceItemID'] = this.getSource();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If not note, append attached notes
|
|
|
|
else {
|
|
|
|
arr['notes'] = [];
|
2006-06-27 20:45:41 +00:00
|
|
|
var notes = this.getNotes();
|
|
|
|
for (var i in notes){
|
|
|
|
var note = Scholar.Items.get(notes[i]);
|
|
|
|
arr['notes'].push({
|
2006-06-29 03:56:22 +00:00
|
|
|
itemID: note.getID(),
|
2006-06-27 20:45:41 +00:00
|
|
|
note: note.getNote(),
|
2006-06-28 18:06:36 +00:00
|
|
|
tags: note.getTags(),
|
2006-06-29 03:56:22 +00:00
|
|
|
seeAlso: note.getSeeAlso()
|
2006-06-27 20:45:41 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
// Append source files
|
|
|
|
if (this.isFile()){
|
|
|
|
arr['fileName'] = arr['title'];
|
2006-06-27 20:45:41 +00:00
|
|
|
delete arr['title'];
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
|
|
|
|
// TODO: file data
|
|
|
|
|
|
|
|
if (this.getSource()){
|
|
|
|
arr['sourceItemID'] = this.getSource();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If not file, append attached files
|
|
|
|
else {
|
|
|
|
arr['files'] = [];
|
|
|
|
var files = this.getFiles();
|
|
|
|
for (var i in files){
|
|
|
|
var file = Scholar.Items.get(files[i]);
|
|
|
|
arr['files'].push({
|
|
|
|
itemID: file.getID(),
|
|
|
|
// TODO
|
|
|
|
tags: file.getTags(),
|
|
|
|
seeAlso: file.getSeeAlso()
|
|
|
|
});
|
2006-06-27 20:45:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
|
2006-06-28 18:06:36 +00:00
|
|
|
arr['tags'] = this.getTags();
|
2006-06-29 03:56:22 +00:00
|
|
|
arr['seeAlso'] = this.getSeeAlso();
|
2006-06-27 20:45:41 +00:00
|
|
|
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-15 19:30:18 +00:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2006-05-18 11:25:10 +00:00
|
|
|
// Private Scholar.Item methods
|
2006-05-15 19:30:18 +00:00
|
|
|
//
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
|
|
|
* Load in the creators from the database
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype._loadCreators = function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (!this.getID()){
|
2006-05-18 11:25:10 +00:00
|
|
|
throw ('ItemID not set for item before attempting to load creators');
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-20 15:18:36 +00:00
|
|
|
var sql = 'SELECT C.creatorID, C.*, creatorTypeID, orderIndex '
|
|
|
|
+ 'FROM itemCreators IC '
|
2006-03-14 11:48:36 +00:00
|
|
|
+ 'LEFT JOIN creators C USING (creatorID) '
|
2006-05-18 11:25:10 +00:00
|
|
|
+ 'WHERE itemID=' + this.getID() + ' ORDER BY orderIndex';
|
2006-03-20 21:47:22 +00:00
|
|
|
var creators = Scholar.DB.query(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-03-18 23:46:50 +00:00
|
|
|
this._creatorsLoaded = true;
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
if (!creators){
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._creators = new Scholar.Hash();
|
|
|
|
for (var i=0; i<creators.length; i++){
|
|
|
|
var creator = new Array();
|
|
|
|
creator['firstName'] = creators[i]['firstName'];
|
|
|
|
creator['lastName'] = creators[i]['lastName'];
|
|
|
|
creator['creatorTypeID'] = creators[i]['creatorTypeID'];
|
2006-05-20 15:18:36 +00:00
|
|
|
// Save creator data into Hash, indexed by orderIndex
|
2006-03-14 11:48:36 +00:00
|
|
|
this._creators.set(creators[i]['orderIndex'], creator);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load in the field data from the database
|
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Item.prototype._loadItemData = function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (!this.getID()){
|
2006-05-18 11:25:10 +00:00
|
|
|
throw ('ItemID not set for object before attempting to load data');
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
var sql = 'SELECT ID.fieldID, value FROM itemData ID JOIN '
|
|
|
|
+ 'itemTypeFields ITF ON (ITF.itemTypeID=(SELECT itemTypeID FROM '
|
|
|
|
+ 'items WHERE itemID=?1) AND ITF.fieldID=ID.fieldID) '
|
|
|
|
+ 'WHERE itemID=?1 ORDER BY orderIndex';
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
var result = Scholar.DB.query(sql,[{'int':this._data['itemID']}]);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
this._itemDataLoaded = true;
|
2006-03-18 23:46:50 +00:00
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
if (result){
|
|
|
|
for (var i=0,len=result.length; i<len; i++){
|
|
|
|
this.setField(result[i]['fieldID'], result[i]['value'], true);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-06-27 20:26:44 +00:00
|
|
|
|
2006-03-23 08:51:05 +00:00
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Primary interface for accessing Scholar items
|
2006-03-23 08:51:05 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.Items = new function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
// Private members
|
2006-05-18 11:25:10 +00:00
|
|
|
var _items = new Array();
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
// Privileged methods
|
|
|
|
this.get = get;
|
|
|
|
this.getAll = getAll;
|
|
|
|
this.reload = reload;
|
|
|
|
this.reloadAll = reloadAll;
|
2006-05-18 20:09:01 +00:00
|
|
|
this.getNewItemByType = getNewItemByType;
|
2006-06-06 08:02:29 +00:00
|
|
|
this.search = search;
|
2006-05-19 11:31:45 +00:00
|
|
|
this.erase = erase;
|
|
|
|
this.unload = unload;
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Retrieves (and loads, if necessary) an arbitrary number of items
|
2006-03-14 11:48:36 +00:00
|
|
|
*
|
|
|
|
* Can be passed ids as individual parameters or as an array of ids, or both
|
2006-03-23 08:51:05 +00:00
|
|
|
*
|
|
|
|
* If only one argument and it's an id, return object directly;
|
2006-06-06 20:15:50 +00:00
|
|
|
* otherwise, return array
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
|
|
|
function get(){
|
|
|
|
var toLoad = new Array();
|
|
|
|
var loaded = new Array();
|
|
|
|
|
|
|
|
if (!arguments[0]){
|
2006-06-06 19:06:40 +00:00
|
|
|
Scholar.debug('No arguments provided to Items.get()');
|
2006-03-14 11:48:36 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var ids = Scholar.flattenArguments(arguments);
|
2006-03-23 08:51:05 +00:00
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
for (var i=0; i<ids.length; i++){
|
|
|
|
// Check if already loaded
|
2006-05-18 11:25:10 +00:00
|
|
|
if (!_items[ids[i]]){
|
2006-03-14 11:48:36 +00:00
|
|
|
toLoad.push(ids[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
// New items to load
|
2006-03-14 11:48:36 +00:00
|
|
|
if (toLoad.length){
|
|
|
|
_load(toLoad);
|
|
|
|
}
|
|
|
|
|
2006-03-23 08:51:05 +00:00
|
|
|
// If single id, return the object directly
|
2006-06-06 19:06:40 +00:00
|
|
|
if (arguments[0] && typeof arguments[0]!='object'
|
2006-03-23 08:51:05 +00:00
|
|
|
&& typeof arguments[1]=='undefined'){
|
2006-05-18 11:25:10 +00:00
|
|
|
return _items[arguments[0]];
|
2006-03-23 08:51:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, build return array
|
2006-03-14 11:48:36 +00:00
|
|
|
for (i=0; i<ids.length; i++){
|
2006-06-06 20:15:50 +00:00
|
|
|
loaded.push(_items[ids[i]]);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
2006-06-06 19:06:40 +00:00
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
return loaded;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Returns all items in the database
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
|
|
|
function getAll(){
|
2006-06-01 00:22:18 +00:00
|
|
|
var sql = 'SELECT itemID FROM items';
|
|
|
|
// DEBUG: default order?
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-03-20 21:47:22 +00:00
|
|
|
var ids = Scholar.DB.columnQuery(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
return this.get(ids);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Reloads data for specified items into internal array
|
2006-03-14 11:48:36 +00:00
|
|
|
*
|
|
|
|
* Can be passed ids as individual parameters or as an array of ids, or both
|
|
|
|
*/
|
|
|
|
function reload(){
|
|
|
|
if (!arguments[0]){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var ids = Scholar.flattenArguments(arguments);
|
|
|
|
Scholar.debug('Reloading ' + ids);
|
|
|
|
_load(ids);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2006-06-02 19:48:22 +00:00
|
|
|
* Reloads all items
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
|
|
|
function reloadAll(){
|
2006-06-02 19:48:22 +00:00
|
|
|
_items = new Array();
|
|
|
|
_load();
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
function getNewItemByType(itemTypeID){
|
|
|
|
return new Scholar.Item(itemTypeID);
|
2006-05-18 20:09:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
function add(data, itemTypeID){
|
2006-03-14 11:48:36 +00:00
|
|
|
var insert = new Array();
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
var obj = new Scholar.Item(itemTypeID);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
for (field in data){
|
|
|
|
obj.setField(data[field]);
|
|
|
|
}
|
|
|
|
|
|
|
|
var id = obj.save();
|
|
|
|
|
|
|
|
return this.get(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-06 08:02:29 +00:00
|
|
|
/**
|
|
|
|
* Fulltext search on all fields
|
|
|
|
*
|
|
|
|
* TODO: more
|
|
|
|
**/
|
2006-06-06 20:46:08 +00:00
|
|
|
function search(text, parentCollectionID){
|
2006-06-06 08:02:29 +00:00
|
|
|
if (!text){
|
|
|
|
text = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "SELECT itemID FROM items WHERE title LIKE ?1 UNION "
|
|
|
|
+ "SELECT itemID FROM itemData WHERE value LIKE ?1 UNION "
|
|
|
|
+ "SELECT itemID FROM itemCreators WHERE creatorID IN "
|
|
|
|
+ "(SELECT creatorID FROM creators WHERE firstName LIKE ?1 "
|
|
|
|
+ "OR lastName LIKE ?1) UNION "
|
2006-06-28 19:12:35 +00:00
|
|
|
+ "SELECT itemID FROM itemTags WHERE tagID IN "
|
|
|
|
+ "(SELECT tagID FROM tags WHERE tag LIKE ?1) UNION "
|
2006-06-16 08:04:01 +00:00
|
|
|
+ "SELECT itemID FROM itemNotes WHERE note LIKE ?1";
|
2006-06-06 20:46:08 +00:00
|
|
|
|
|
|
|
var sqlParams = [{'string':'%' + text + '%'}];
|
|
|
|
|
|
|
|
if (parentCollectionID){
|
|
|
|
sql = "SELECT itemID FROM (" + sql + ") WHERE itemID IN "
|
|
|
|
+ "(SELECT itemID FROM collectionItems WHERE collectionID=?2)";
|
|
|
|
sqlParams.push({'int':parentCollectionID});
|
|
|
|
}
|
|
|
|
|
|
|
|
return Scholar.DB.columnQuery(sql, sqlParams);
|
2006-06-06 08:02:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-19 11:31:45 +00:00
|
|
|
/**
|
|
|
|
* Delete item from database and clear from internal array
|
|
|
|
**/
|
|
|
|
function erase(id){
|
|
|
|
var obj = this.get(id);
|
|
|
|
obj.erase(); // calls unload()
|
|
|
|
obj = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clear item from internal array (used by Scholar.Item.erase())
|
|
|
|
**/
|
|
|
|
function unload(id){
|
|
|
|
delete _items[id];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
function _load(){
|
2006-05-18 11:25:10 +00:00
|
|
|
// Should be the same as query in Scholar.Item.loadFromID, just
|
|
|
|
// without itemID clause
|
2006-06-06 17:37:52 +00:00
|
|
|
var sql = 'SELECT I.*, lastName || '
|
|
|
|
+ 'CASE ((SELECT COUNT(*) FROM itemCreators WHERE itemID=I.itemID)>1) '
|
2006-06-25 05:43:00 +00:00
|
|
|
+ "WHEN 0 THEN '' ELSE ' et al.' END AS firstCreator, "
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
+ "(SELECT COUNT(*) FROM itemNotes WHERE sourceItemID=I.itemID) AS numNotes, "
|
|
|
|
+ "(SELECT COUNT(*) FROM itemFiles WHERE sourceItemID=I.itemID) AS numFiles "
|
2006-05-18 11:25:10 +00:00
|
|
|
+ 'FROM items I '
|
|
|
|
+ 'LEFT JOIN itemCreators IC ON (I.itemID=IC.itemID) '
|
|
|
|
+ 'LEFT JOIN creators C ON (IC.creatorID=C.creatorID) '
|
2006-06-02 16:37:17 +00:00
|
|
|
+ 'WHERE (IC.orderIndex=0 OR IC.orderIndex IS NULL)';
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-06-02 19:48:22 +00:00
|
|
|
if (arguments[0]){
|
2006-05-18 11:25:10 +00:00
|
|
|
sql += ' AND I.itemID IN (' + Scholar.join(arguments,',') + ')';
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-03-20 21:47:22 +00:00
|
|
|
var result = Scholar.DB.query(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (result){
|
|
|
|
for (var i=0,len=result.length; i<len; i++){
|
2006-06-02 19:48:22 +00:00
|
|
|
// Item doesn't exist -- create new object and stuff in array
|
|
|
|
if (!_items[result[i]['itemID']]){
|
|
|
|
var obj = new Scholar.Item();
|
|
|
|
obj.loadFromRow(result[i]);
|
|
|
|
_items[result[i]['itemID']] = obj;
|
|
|
|
}
|
|
|
|
// Existing item -- reload in place
|
|
|
|
else {
|
|
|
|
_items[result[i]['itemID']].loadFromRow(result[i]);
|
|
|
|
}
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-23 08:51:05 +00:00
|
|
|
|
2006-05-15 19:30:18 +00:00
|
|
|
|
2006-06-28 18:30:20 +00:00
|
|
|
Scholar.Notes = new function(){
|
|
|
|
this.add = add;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new item of type 'note' and add the note text to the itemNotes table
|
|
|
|
*
|
|
|
|
* Returns the itemID of the new note item
|
|
|
|
**/
|
|
|
|
function add(text, sourceItemID){
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
if (sourceItemID){
|
|
|
|
var sourceItem = Scholar.Items.get(sourceItemID);
|
|
|
|
if (!sourceItem){
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
throw ("Cannot set note source to invalid item " + sourceItemID);
|
|
|
|
}
|
|
|
|
if (sourceItem.isNote()){
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
throw ("Cannot set note source to another note (" + sourceItemID + ")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var note = Scholar.Items.getNewItemByType(Scholar.ItemTypes.getID('note'));
|
|
|
|
note.save();
|
|
|
|
|
|
|
|
var sql = "INSERT INTO itemNotes VALUES (?,?,?)";
|
|
|
|
var bindParams = [
|
|
|
|
note.getID(),
|
|
|
|
(sourceItemID ? {int:sourceItemID} : null),
|
|
|
|
{string:text}
|
|
|
|
];
|
|
|
|
Scholar.DB.query(sql, bindParams);
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
|
|
|
|
if (sourceItemID){
|
|
|
|
sourceItem.incrementNoteCount();
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', sourceItemID);
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.Notifier.trigger('add', 'item', note.getID());
|
|
|
|
|
|
|
|
return note.getID();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
Scholar.Files = new function(){
|
|
|
|
this.LINK_MODE_IMPORTED_FILE = 0;
|
|
|
|
this.LINK_MODE_IMPORTED_URL = 1;
|
|
|
|
this.LINK_MODE_LINKED_FILE = 2;
|
|
|
|
this.LINK_MODE_LINKED_URL = 3;
|
|
|
|
|
|
|
|
this.importFromFile = importFromFile;
|
|
|
|
this.linkFromFile = linkFromFile;
|
|
|
|
this.linkFromDocument = linkFromDocument;
|
|
|
|
this.importFromDocument = importFromDocument;
|
|
|
|
|
|
|
|
|
|
|
|
function importFromFile(file, sourceItemID){
|
|
|
|
var title = file.leafName;
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
// Create a new file item
|
|
|
|
var fileItem = Scholar.Items.getNewItemByType(Scholar.ItemTypes.getID('file'));
|
|
|
|
fileItem.setField('title', title);
|
|
|
|
fileItem.save();
|
|
|
|
var itemID = fileItem.getID();
|
|
|
|
|
|
|
|
// Create directory for item files within storage directory
|
|
|
|
var destDir = Scholar.getStorageDirectory();
|
|
|
|
destDir.append(itemID);
|
|
|
|
destDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0644);
|
|
|
|
|
|
|
|
try {
|
|
|
|
file.copyTo(destDir, null);
|
|
|
|
}
|
|
|
|
catch (e){
|
|
|
|
// hmph
|
|
|
|
Scholar.DB.rollbackTransaction();
|
|
|
|
destDir.remove(true);
|
|
|
|
throw (e);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Point to copied file
|
|
|
|
var newFile = Components.classes["@mozilla.org/file/local;1"]
|
|
|
|
.createInstance(Components.interfaces.nsILocalFile);
|
|
|
|
newFile.initWithFile(destDir);
|
|
|
|
newFile.append(title);
|
|
|
|
|
|
|
|
var mimeType = _getMIMETypeFromFile(newFile);
|
|
|
|
var charsetID = _getCharsetIDFromFile(newFile);
|
|
|
|
|
|
|
|
_addToDB(newFile, null, null, this.LINK_MODE_IMPORTED_FILE, mimeType, charsetID, sourceItemID, itemID);
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
return itemID;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function linkFromFile(file, sourceItemID){
|
|
|
|
var title = file.leafName;
|
|
|
|
var mimeType = _getMIMETypeFromFile(file);
|
|
|
|
var charsetID = _getCharsetIDFromFile(file);
|
|
|
|
return _addToDB(file, null, title, this.LINK_MODE_LINKED_FILE, mimeType, charsetID, sourceItemID);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: what if called on file:// document?
|
|
|
|
function linkFromDocument(document, sourceItemID){
|
|
|
|
var url = document.location;
|
|
|
|
var title = document.title; // TODO: don't use Mozilla-generated title for images, etc.
|
|
|
|
var mimeType = document.contentType;
|
|
|
|
var charsetID = Scholar.CharacterSets.getID(document.characterSet);
|
|
|
|
|
|
|
|
return _addToDB(null, url, title, this.LINK_MODE_LINKED_URL, mimeType, charsetID, sourceItemID);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function importFromDocument(document, sourceItemID){
|
|
|
|
var url = document.location;
|
|
|
|
var title = document.title;
|
|
|
|
var mimeType = document.contentType;
|
|
|
|
var charsetID = Scholar.CharacterSets.getID(document.characterSet);
|
|
|
|
|
|
|
|
const nsIWBP = Components.interfaces.nsIWebBrowserPersist;
|
|
|
|
var wbp = Components
|
|
|
|
.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
|
|
|
|
.createInstance(nsIWBP);
|
|
|
|
//wbp.persistFlags = nsIWBP.PERSIST_FLAGS...;
|
|
|
|
var encodingFlags = false;
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
// Create a new file item
|
|
|
|
var fileItem = Scholar.Items.getNewItemByType(Scholar.ItemTypes.getID('file'));
|
|
|
|
fileItem.setField('title', title);
|
|
|
|
fileItem.save();
|
|
|
|
var itemID = fileItem.getID();
|
|
|
|
|
|
|
|
// Create a new folder for this item in the storage directory
|
|
|
|
var destDir = Scholar.getStorageDirectory();
|
|
|
|
destDir.append(itemID);
|
|
|
|
destDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0644);
|
|
|
|
|
|
|
|
var file = Components.classes["@mozilla.org/file/local;1"].
|
|
|
|
createInstance(Components.interfaces.nsILocalFile);
|
|
|
|
file.initWithFile(destDir);
|
|
|
|
file.append(_getFileNameFromURL(url, mimeType));
|
|
|
|
|
|
|
|
wbp.saveDocument(document, file, destDir, mimeType, encodingFlags, false);
|
|
|
|
|
|
|
|
_addToDB(file, url, title, this.LINK_MODE_IMPORTED_URL, mimeType, charsetID, sourceItemID, itemID);
|
|
|
|
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
return itemID;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: currently only uses file extension
|
|
|
|
function _getMIMETypeFromFile(file){
|
|
|
|
var ms = Components
|
|
|
|
.classes['@mozilla.org/uriloader/external-helper-app-service;1']
|
|
|
|
.getService(Components.interfaces.nsIMIMEService);
|
|
|
|
return ms.getTypeFromFile(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function _getCharsetIDFromFile(file){
|
|
|
|
// TODO: Not yet implemented
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function _getFileNameFromURL(url, mimeType){
|
|
|
|
var nsIURL = Components.classes["@mozilla.org/network/standard-url;1"]
|
|
|
|
.createInstance(Components.interfaces.nsIURL);
|
|
|
|
nsIURL.spec = url;
|
|
|
|
|
|
|
|
if (nsIURL.fileName){
|
|
|
|
return nsIURL.fileName;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mimeType){
|
|
|
|
var ext = Components.classes["@mozilla.org/mime;1"]
|
|
|
|
.getService(Components.interfaces.nsIMIMEService)
|
|
|
|
.getPrimaryExtension(mimeType, nsIURL.fileExt ? nsIURL.fileExt : null);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsIURL.host + (ext ? '.' + ext : '');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new item of type 'file' and add the file link to the itemFiles table
|
|
|
|
*
|
|
|
|
* Passing an itemID causes it to skip new item creation and use the specified
|
|
|
|
* item instead -- used when importing files (since we have to know
|
|
|
|
* the itemID before copying in a file and don't want to update the DB before
|
|
|
|
* the file is saved)
|
|
|
|
*
|
|
|
|
* Returns the itemID of the new file item
|
|
|
|
**/
|
|
|
|
function _addToDB(file, url, title, linkMode, mimeType, charsetID, sourceItemID, itemID){
|
|
|
|
if (url){
|
|
|
|
var path = url;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file){
|
|
|
|
if (linkMode==this.LINK_MODE_IMPORTED_URL){
|
|
|
|
var originalPath = path;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Path relative to Scholar directory for external files and relative
|
|
|
|
// to storage directory for imported files
|
|
|
|
var refDir = (linkMode==this.LINK_MODE_LINKED_FILE)
|
|
|
|
? Scholar.getScholarDirectory() : Scholar.getStorageDirectory();
|
|
|
|
var path = file.getRelativeDescriptor(refDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
if (sourceItemID){
|
|
|
|
var sourceItem = Scholar.Items.get(sourceItemID);
|
|
|
|
if (!sourceItem){
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
throw ("Cannot set file source to invalid item " + sourceItemID);
|
|
|
|
}
|
|
|
|
if (sourceItem.isFile()){
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
throw ("Cannot set file source to another file (" + sourceItemID + ")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If an itemID is provided, use that
|
|
|
|
if (itemID){
|
|
|
|
var fileItem = Scholar.Items.get(itemID);
|
|
|
|
if (!fileItem.isFile()){
|
|
|
|
throw ("Item " + itemID + " is not a valid file item in _addToDB()");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Otherwise create a new file item
|
|
|
|
else {
|
|
|
|
var fileItem = Scholar.Items.getNewItemByType(Scholar.ItemTypes.getID('file'));
|
|
|
|
fileItem.setField('title', title);
|
|
|
|
fileItem.save();
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "INSERT INTO itemFiles (itemID, sourceItemID, linkMode, "
|
|
|
|
+ "mimeType, charsetID, path, originalPath) VALUES (?,?,?,?,?,?,?)";
|
|
|
|
var bindParams = [
|
|
|
|
fileItem.getID(),
|
|
|
|
(sourceItemID ? {int:sourceItemID} : null),
|
|
|
|
{int:linkMode},
|
|
|
|
{string:mimeType},
|
|
|
|
(charsetID ? {int:charsetID} : null),
|
|
|
|
{string:path},
|
|
|
|
(originalPath ? {string:originalPath} : null)
|
|
|
|
];
|
|
|
|
Scholar.DB.query(sql, bindParams);
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
|
|
|
|
if (sourceItemID){
|
|
|
|
sourceItem.incrementNoteCount();
|
|
|
|
Scholar.Notifier.trigger('modify', 'item', sourceItemID);
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.Notifier.trigger('add', 'item', fileItem.getID());
|
|
|
|
|
|
|
|
return fileItem.getID();
|
|
|
|
}
|
|
|
|
}
|
2006-05-15 19:30:18 +00:00
|
|
|
|
2006-03-23 08:51:05 +00:00
|
|
|
/*
|
2006-06-01 00:22:18 +00:00
|
|
|
* Constructor for Collection object
|
2006-03-23 08:51:05 +00:00
|
|
|
*
|
2006-06-01 00:22:18 +00:00
|
|
|
* Generally should be called from Scholar.Collection rather than directly
|
2006-03-23 08:51:05 +00:00
|
|
|
*/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection = function(){
|
2006-06-02 19:48:22 +00:00
|
|
|
this._init();
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.Collection.prototype._init = function(){
|
|
|
|
//
|
|
|
|
// Public members for access by public methods -- do not access directly
|
|
|
|
//
|
2006-03-23 08:51:05 +00:00
|
|
|
this._id;
|
|
|
|
this._name;
|
|
|
|
this._parent;
|
2006-06-01 00:22:18 +00:00
|
|
|
this._hasChildCollections;
|
|
|
|
this._hasChildItems;
|
|
|
|
this._childItems = new Scholar.Hash();
|
|
|
|
this._childItemsLoaded;
|
2006-03-23 08:51:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-06-01 00:22:18 +00:00
|
|
|
* Build collection from database
|
2006-03-23 08:51:05 +00:00
|
|
|
*/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.loadFromID = function(id){
|
|
|
|
// Should be same as query in Scholar.Collections, just with collectionID
|
|
|
|
var sql = "SELECT collectionID, collectionName, parentCollectionID, "
|
|
|
|
+ "(SELECT COUNT(*) FROM collections WHERE "
|
|
|
|
+ "parentCollectionID=C.collectionID)!=0 AS hasChildCollections, "
|
|
|
|
+ "(SELECT COUNT(*) FROM collectionItems WHERE "
|
|
|
|
+ "collectionID=C.collectionID)!=0 AS hasChildItems "
|
|
|
|
+ "FROM collections C "
|
|
|
|
+ "WHERE collectionID=" + id;
|
2006-05-16 21:51:09 +00:00
|
|
|
|
2006-03-23 08:51:05 +00:00
|
|
|
var row = Scholar.DB.rowQuery(sql);
|
|
|
|
this.loadFromRow(row);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2006-06-01 00:22:18 +00:00
|
|
|
* Populate collection data from a database row
|
2006-03-23 08:51:05 +00:00
|
|
|
*/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.loadFromRow = function(row){
|
2006-06-02 19:48:22 +00:00
|
|
|
this._init();
|
2006-06-01 00:22:18 +00:00
|
|
|
this._id = row['collectionID'];
|
|
|
|
this._name = row['collectionName'];
|
|
|
|
this._parent = row['parentCollectionID'];
|
|
|
|
this._hasChildCollections = row['hasChildCollections'];
|
2006-05-23 20:53:09 +00:00
|
|
|
this._hasChildItems = row['hasChildItems'];
|
2006-03-23 08:51:05 +00:00
|
|
|
}
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
|
|
|
|
Scholar.Collection.prototype.getID = function(){
|
2006-03-23 08:51:05 +00:00
|
|
|
return this._id;
|
|
|
|
}
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.getName = function(){
|
2006-03-23 08:51:05 +00:00
|
|
|
return this._name;
|
|
|
|
}
|
|
|
|
|
2006-06-02 01:17:44 +00:00
|
|
|
/**
|
2006-06-03 20:41:23 +00:00
|
|
|
* Returns collectionID of the parent collection
|
2006-06-02 01:17:44 +00:00
|
|
|
**/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.getParent = function(){
|
2006-05-15 19:30:18 +00:00
|
|
|
return this._parent;
|
|
|
|
}
|
2006-03-23 08:51:05 +00:00
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
|
|
|
|
Scholar.Collection.prototype.isEmpty = function(){
|
|
|
|
return !(parseInt(this._hasChildCollections)) && !(parseInt(this._hasChildItems));
|
2006-05-23 20:53:09 +00:00
|
|
|
}
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.hasChildCollections = function(){
|
|
|
|
return !!(parseInt(this._hasChildCollections));
|
2006-05-16 21:51:09 +00:00
|
|
|
}
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.hasChildItems = function(){
|
2006-05-23 20:53:09 +00:00
|
|
|
return !!(parseInt(this._hasChildItems));
|
|
|
|
}
|
|
|
|
|
2006-06-03 20:41:23 +00:00
|
|
|
/**
|
|
|
|
* Rename the collection
|
|
|
|
*
|
2006-06-03 20:51:48 +00:00
|
|
|
* _name_ is non-empty string
|
|
|
|
*
|
2006-06-03 20:41:23 +00:00
|
|
|
* Returns true on success, or false on error
|
|
|
|
**/
|
|
|
|
Scholar.Collection.prototype.rename = function(name){
|
|
|
|
if (!name){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "UPDATE collections SET collectionName=? "
|
|
|
|
+ "WHERE collectionID=?";
|
|
|
|
Scholar.DB.query(sql, [{'string':name},{'int':this.getID()}]);
|
|
|
|
this._name = name;
|
|
|
|
|
|
|
|
Scholar.Notifier.trigger('modify', 'collection', this.getID());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-06-05 21:58:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Change the parentCollectionID of a collection
|
|
|
|
*
|
|
|
|
* Returns TRUE on success, FALSE on error
|
|
|
|
**/
|
|
|
|
Scholar.Collection.prototype.changeParent = function(parent){
|
|
|
|
if (!parent){
|
|
|
|
parent = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
var previousParent = this.getParent();
|
|
|
|
|
|
|
|
if (parent==previousParent){
|
|
|
|
Scholar.debug('Collection ' + this.getID() + ' is already in '
|
|
|
|
+ (parent ? 'collection ' + parent : 'root collection'), 2);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent && !Scholar.Collections.get(parent)){
|
|
|
|
throw('Invalid parentCollectionID ' + parent + ' in changeParent()');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent && parent==this.getID()){
|
|
|
|
Scholar.debug('Cannot move collection into itself!', 2);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent){
|
2006-06-08 19:11:10 +00:00
|
|
|
if (this.hasDescendent('collection', parent)){
|
|
|
|
Scholar.debug('Cannot move collection into one of its own '
|
|
|
|
+ 'descendents!', 2);
|
|
|
|
return false;
|
2006-06-05 21:58:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var parentParam = parent ? {'int':parent} : {'null':true};
|
|
|
|
|
|
|
|
var sql = "UPDATE collections SET parentCollectionID=? "
|
|
|
|
+ "WHERE collectionID=?";
|
|
|
|
|
|
|
|
Scholar.DB.query(sql, [parentParam, {'int':this.getID()}]);
|
|
|
|
this._parent = parent;
|
|
|
|
|
2006-06-08 19:58:54 +00:00
|
|
|
var notifyIDs = [
|
|
|
|
this.getID(),
|
|
|
|
(previousParent ? previousParent : null),
|
|
|
|
(parent ? parent : null)
|
|
|
|
];
|
2006-06-05 21:58:01 +00:00
|
|
|
|
2006-06-08 18:53:49 +00:00
|
|
|
// TODO: only reload the necessary ones
|
|
|
|
Scholar.Collections.reloadAll();
|
2006-06-08 19:58:54 +00:00
|
|
|
Scholar.Notifier.trigger('move', 'collection', notifyIDs);
|
2006-06-05 21:58:01 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-03 20:41:23 +00:00
|
|
|
/**
|
|
|
|
* Add an item to the collection
|
|
|
|
**/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.addItem = function(itemID){
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
if (!Scholar.Items.get(itemID)){
|
|
|
|
Scholar.DB.rollbackTransaction();
|
|
|
|
throw(itemID + ' is not a valid item id');
|
|
|
|
}
|
|
|
|
|
|
|
|
var nextOrderIndex = Scholar.DB.valueQuery("SELECT IFNULL(MAX(orderIndex)+1, 0) "
|
|
|
|
+ "FROM collectionItems WHERE collectionID=" + this._id);
|
|
|
|
|
|
|
|
var sql = "INSERT OR IGNORE INTO collectionItems VALUES "
|
|
|
|
+ "(" + this._id + ", " + itemID + ", " + nextOrderIndex + ")";
|
|
|
|
|
|
|
|
Scholar.DB.query(sql);
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
|
|
|
|
this._childItems.set(itemID);
|
2006-06-08 20:41:37 +00:00
|
|
|
|
|
|
|
// If this was previously empty, update and send a notification to the tree
|
|
|
|
if (!this._hasChildItems){
|
|
|
|
this._hasChildItems = true;
|
2006-06-20 15:28:20 +00:00
|
|
|
Scholar.Notifier.trigger('modify', 'collection', this.getID());
|
2006-06-08 20:41:37 +00:00
|
|
|
}
|
2006-06-01 20:03:53 +00:00
|
|
|
|
|
|
|
Scholar.Notifier.trigger('add', 'item', itemID);
|
2006-06-01 00:22:18 +00:00
|
|
|
}
|
|
|
|
|
2006-06-01 20:03:53 +00:00
|
|
|
|
2006-06-03 20:41:23 +00:00
|
|
|
/**
|
|
|
|
* Remove an item from the collection (does not delete item from library)
|
|
|
|
**/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.removeItem = function(itemID){
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
var sql = "SELECT orderIndex FROM collectionItems "
|
|
|
|
+ "WHERE collectionID=" + this._id + " AND itemID=" + itemID;
|
|
|
|
var orderIndex = Scholar.DB.valueQuery(sql);
|
|
|
|
|
|
|
|
if (orderIndex===false){
|
|
|
|
Scholar.debug('Item ' + itemID + ' is not a child of collection '
|
|
|
|
+ this._id);
|
|
|
|
Scholar.DB.rollbackTransaction();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = "DELETE FROM collectionItems WHERE collectionID=" + this._id
|
|
|
|
+ " AND itemID=" + itemID;
|
|
|
|
Scholar.DB.query(sql);
|
|
|
|
|
|
|
|
// Move down items above deleted item in collection
|
|
|
|
sql = 'UPDATE collectionItems SET orderIndex=orderIndex-1 '
|
|
|
|
+ 'WHERE collectionID=' + this._id
|
|
|
|
+ ' AND orderIndex>' + orderIndex;
|
|
|
|
Scholar.DB.query(sql);
|
|
|
|
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
this._childItems.remove(itemID);
|
|
|
|
|
|
|
|
// If this was the last item, set collection to empty
|
|
|
|
if (!this._childItems.length){
|
|
|
|
this._hasChildItems = false;
|
2006-06-09 14:01:07 +00:00
|
|
|
Scholar.Notifier.trigger('modify', 'collection', this.getID());
|
2006-06-01 00:22:18 +00:00
|
|
|
}
|
2006-06-01 20:03:53 +00:00
|
|
|
|
|
|
|
Scholar.Notifier.trigger('remove', 'item', itemID);
|
2006-06-01 00:22:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-03 20:41:23 +00:00
|
|
|
/**
|
|
|
|
* Check if an item belongs to the collection
|
|
|
|
**/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.hasItem = function(itemID){
|
|
|
|
if (!this._childItemsLoaded){
|
|
|
|
this._loadChildItems();
|
|
|
|
}
|
|
|
|
return this._childItems.has(itemID);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-08 19:11:10 +00:00
|
|
|
Scholar.Collection.prototype.hasDescendent = function(type, id){
|
|
|
|
var descendents = this._getDescendents();
|
|
|
|
for (var i=0, len=descendents.length; i<len; i++){
|
2006-06-29 05:18:55 +00:00
|
|
|
if (descendents[i]['type']==type && descendents[i]['id']==id){
|
2006-06-08 19:11:10 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-23 14:54:10 +00:00
|
|
|
/**
|
2006-06-03 20:41:23 +00:00
|
|
|
* Deletes collection and all descendent collections and items
|
2006-05-23 14:54:10 +00:00
|
|
|
**/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype.erase = function(deleteItems){
|
2006-05-23 14:54:10 +00:00
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
var descendents = this._getDescendents();
|
2006-06-20 15:23:44 +00:00
|
|
|
var collections = [this.getID()], items = [];
|
2006-05-23 14:54:10 +00:00
|
|
|
|
|
|
|
for(var i=0, len=descendents.length; i<len; i++){
|
2006-06-01 00:22:18 +00:00
|
|
|
// Descendent collections
|
2006-06-29 05:18:55 +00:00
|
|
|
if (descendents[i]['type']=='collection'){
|
2006-06-01 00:22:18 +00:00
|
|
|
collections.push(descendents[i]['id']);
|
2006-05-23 14:54:10 +00:00
|
|
|
}
|
2006-06-01 00:22:18 +00:00
|
|
|
// Descendent items
|
2006-05-23 14:54:10 +00:00
|
|
|
else {
|
2006-06-01 00:22:18 +00:00
|
|
|
if (deleteItems){
|
|
|
|
// Delete items from DB
|
|
|
|
Scholar.Items.get(descendents[i]['id']).erase();
|
2006-06-08 20:02:26 +00:00
|
|
|
items.push(descendents[i]['id']);
|
2006-06-01 00:22:18 +00:00
|
|
|
}
|
2006-05-23 14:54:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
// Remove item associations for all descendent collections
|
2006-06-01 22:19:21 +00:00
|
|
|
Scholar.DB.query('DELETE FROM collectionItems WHERE collectionID IN ('
|
2006-06-01 00:22:18 +00:00
|
|
|
+ collections.join() + ')');
|
2006-05-23 14:54:10 +00:00
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
// And delete all descendent collections
|
2006-06-01 22:19:21 +00:00
|
|
|
Scholar.DB.query('DELETE FROM collections WHERE collectionID IN ('
|
2006-06-01 00:22:18 +00:00
|
|
|
+ collections.join() + ')');
|
2006-05-23 14:54:10 +00:00
|
|
|
|
2006-06-01 22:19:21 +00:00
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
// Clear deleted collection from internal memory
|
|
|
|
Scholar.Collections.unload(collections);
|
2006-06-02 01:17:44 +00:00
|
|
|
|
|
|
|
Scholar.Notifier.trigger('remove', 'collection', collections);
|
2006-06-08 20:02:26 +00:00
|
|
|
if (items.length){
|
2006-06-08 20:41:37 +00:00
|
|
|
Scholar.Notifier.trigger('delete', 'item', items);
|
2006-06-08 20:02:26 +00:00
|
|
|
}
|
2006-05-23 14:54:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-03 20:41:23 +00:00
|
|
|
Scholar.Collection.prototype.isCollection = function(){
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-29 05:18:55 +00:00
|
|
|
Scholar.Collection.prototype.toArray = function(){
|
|
|
|
return this._getDescendents(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collection.prototype._loadChildItems = function(){
|
|
|
|
this._childItems = new Scholar.Hash();
|
|
|
|
|
|
|
|
var sql = "SELECT itemID FROM collectionItems WHERE collectionID=" + this._id;
|
|
|
|
var itemIDs = Scholar.DB.columnQuery(sql);
|
|
|
|
|
|
|
|
if (!itemIDs){
|
|
|
|
Scholar.debug('Collection ' + this._id + ' has no child items');
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var i=0; i<itemIDs.length; i++){
|
|
|
|
this._childItems.set(itemIDs[i]);
|
|
|
|
}
|
|
|
|
this._childItemsLoaded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-23 14:54:10 +00:00
|
|
|
/**
|
2006-06-29 05:18:55 +00:00
|
|
|
* Returns an array of descendent collections and items
|
|
|
|
* (rows of 'id', 'type' ('item' or 'collection'), and, if collection, 'name')
|
|
|
|
*
|
|
|
|
* nested: Return multidimensional array with 'children' nodes instead of flat array
|
2006-05-23 14:54:10 +00:00
|
|
|
**/
|
2006-06-29 05:18:55 +00:00
|
|
|
Scholar.Collection.prototype._getDescendents = function(nested){
|
2006-05-23 14:54:10 +00:00
|
|
|
var toReturn = new Array();
|
|
|
|
|
2006-06-29 05:18:55 +00:00
|
|
|
// 0 == collection
|
|
|
|
// 1 == item
|
2006-06-01 00:22:18 +00:00
|
|
|
var children = Scholar.DB.query('SELECT collectionID AS id, '
|
2006-06-29 05:18:55 +00:00
|
|
|
+ "0 AS type, collectionName AS collectionName "
|
|
|
|
+ 'FROM collections WHERE parentCollectionID=' + this._id
|
|
|
|
+ ' UNION SELECT itemID AS id, 1 AS type, NULL AS collectionName '
|
|
|
|
+ 'FROM collectionItems WHERE collectionID=' + this._id);
|
2006-05-23 14:54:10 +00:00
|
|
|
|
|
|
|
for(var i=0, len=children.length; i<len; i++){
|
2006-06-29 05:18:55 +00:00
|
|
|
switch (children[i]['type']){
|
|
|
|
case 0:
|
|
|
|
toReturn.push({
|
|
|
|
id: children[i]['id'],
|
|
|
|
name: children[i]['collectionName'],
|
|
|
|
type: 'collection'
|
|
|
|
});
|
|
|
|
|
|
|
|
var descendents =
|
|
|
|
Scholar.Collections.get(children[i]['id'])._getDescendents(nested);
|
|
|
|
|
|
|
|
if (nested){
|
|
|
|
toReturn[toReturn.length-1]['children'] = descendents;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for(var j=0, len2=descendents.length; j<len2; j++){
|
|
|
|
toReturn.push(descendents[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-05-23 14:54:10 +00:00
|
|
|
|
2006-06-29 05:18:55 +00:00
|
|
|
case 1:
|
|
|
|
toReturn.push({
|
|
|
|
id: children[i]['id'],
|
|
|
|
type: 'item'
|
|
|
|
});
|
|
|
|
break;
|
2006-05-23 14:54:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return toReturn;
|
|
|
|
}
|
|
|
|
|
2006-03-23 08:51:05 +00:00
|
|
|
|
2006-06-12 13:08:36 +00:00
|
|
|
|
|
|
|
|
2006-03-23 08:51:05 +00:00
|
|
|
/*
|
2006-06-01 00:22:18 +00:00
|
|
|
* Primary interface for accessing Scholar collection
|
2006-03-23 08:51:05 +00:00
|
|
|
*/
|
2006-06-01 00:22:18 +00:00
|
|
|
Scholar.Collections = new function(){
|
|
|
|
var _collections = new Array();
|
|
|
|
var _collectionsLoaded = false;
|
2006-03-23 08:51:05 +00:00
|
|
|
|
|
|
|
this.get = get;
|
2006-06-03 20:41:23 +00:00
|
|
|
this.add = add;
|
2006-05-18 21:55:43 +00:00
|
|
|
this.reloadAll = reloadAll;
|
2006-05-23 14:54:10 +00:00
|
|
|
this.unload = unload;
|
2006-03-23 08:51:05 +00:00
|
|
|
|
|
|
|
/*
|
2006-06-01 00:22:18 +00:00
|
|
|
* Returns a Scholar.Collection object for a collectionID
|
2006-03-23 08:51:05 +00:00
|
|
|
*/
|
|
|
|
function get(id){
|
2006-06-01 00:22:18 +00:00
|
|
|
if (!_collectionsLoaded){
|
2006-03-23 08:51:05 +00:00
|
|
|
_load();
|
|
|
|
}
|
2006-06-01 00:22:18 +00:00
|
|
|
return (typeof _collections[id]!='undefined') ? _collections[id] : false;
|
2006-03-23 08:51:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-03 20:51:48 +00:00
|
|
|
/**
|
|
|
|
* Add new collection to DB and return Collection object
|
|
|
|
*
|
|
|
|
* _name_ is non-empty string
|
|
|
|
* _parent_ is optional collectionID -- creates root collection by default
|
|
|
|
*
|
|
|
|
* Returns true on success; false on error
|
|
|
|
**/
|
2006-06-03 20:41:23 +00:00
|
|
|
function add(name, parent){
|
|
|
|
if (!name){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
if (parent && !this.get(parent)){
|
|
|
|
Scholar.DB.rollbackTransaction();
|
|
|
|
throw('Cannot add collection to invalid parent ' + parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
var parentParam = parent ? {'int':parent} : {'null':true};
|
|
|
|
|
|
|
|
var rnd = Scholar.getRandomID('collections', 'collectionID');
|
|
|
|
|
|
|
|
var sql = "INSERT INTO collections VALUES (?,?,?)";
|
|
|
|
var sqlValues = [ {'int':rnd}, {'string':name}, parentParam ];
|
|
|
|
Scholar.DB.query(sql, sqlValues);
|
|
|
|
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
|
|
|
|
_load(rnd);
|
|
|
|
Scholar.Notifier.trigger('add', 'collection', rnd);
|
|
|
|
|
|
|
|
return this.get(rnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-23 14:54:10 +00:00
|
|
|
/**
|
2006-06-01 00:22:18 +00:00
|
|
|
* Clears internal cache and reloads collection data from DB
|
2006-05-23 14:54:10 +00:00
|
|
|
**/
|
2006-05-18 21:55:43 +00:00
|
|
|
function reloadAll(){
|
2006-06-01 00:22:18 +00:00
|
|
|
_collections = new Array();
|
2006-05-18 21:55:43 +00:00
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
2006-05-23 14:54:10 +00:00
|
|
|
|
|
|
|
/**
|
2006-06-01 00:22:18 +00:00
|
|
|
* Clear collection from internal cache (used by Scholar.Collection.erase())
|
2006-05-23 14:54:10 +00:00
|
|
|
*
|
|
|
|
* Can be passed ids as individual parameters or as an array of ids, or both
|
|
|
|
**/
|
|
|
|
function unload(){
|
|
|
|
var ids = Scholar.flattenArguments(arguments);
|
|
|
|
|
|
|
|
for(var i=0; i<ids.length; i++){
|
2006-06-01 00:22:18 +00:00
|
|
|
delete _collections[ids[i]];
|
2006-05-23 14:54:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2006-06-01 00:22:18 +00:00
|
|
|
* Loads collection data from DB and adds to internal cache
|
2006-05-23 14:54:10 +00:00
|
|
|
**/
|
2006-03-23 08:51:05 +00:00
|
|
|
function _load(){
|
2006-06-01 00:22:18 +00:00
|
|
|
// This should be the same as the query in Scholar.Collection.loadFromID,
|
|
|
|
// just without a specific collectionID
|
|
|
|
var sql = "SELECT collectionID, collectionName, parentCollectionID, "
|
|
|
|
+ "(SELECT COUNT(*) FROM collections WHERE "
|
|
|
|
+ "parentCollectionID=C.collectionID)!=0 AS hasChildCollections, "
|
|
|
|
+ "(SELECT COUNT(*) FROM collectionItems WHERE "
|
|
|
|
+ "collectionID=C.collectionID)!=0 AS hasChildItems "
|
|
|
|
+ "FROM collections C";
|
|
|
|
|
2006-06-03 20:41:23 +00:00
|
|
|
var ids = Scholar.flattenArguments(arguments)
|
|
|
|
if (ids.length){
|
|
|
|
sql += " WHERE collectionID IN (" + ids.join() + ")";
|
|
|
|
}
|
|
|
|
|
2006-03-23 08:51:05 +00:00
|
|
|
var result = Scholar.DB.query(sql);
|
|
|
|
|
|
|
|
if (!result){
|
2006-06-03 20:41:23 +00:00
|
|
|
throw ('No collections found');
|
2006-03-23 08:51:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (var i=0; i<result.length; i++){
|
2006-06-02 19:48:22 +00:00
|
|
|
var collectionID = result[i]['collectionID'];
|
|
|
|
|
|
|
|
// If collection doesn't exist, create new object and stuff in array
|
|
|
|
if (!_collections[collectionID]){
|
|
|
|
var collection = new Scholar.Collection();
|
|
|
|
collection.loadFromRow(result[i]);
|
|
|
|
_collections[collectionID] = collection;
|
|
|
|
}
|
|
|
|
// If existing collection, reload in place
|
|
|
|
else {
|
|
|
|
_collections[collectionID].loadFromRow(result[i]);
|
|
|
|
}
|
2006-03-23 08:51:05 +00:00
|
|
|
}
|
2006-06-01 00:22:18 +00:00
|
|
|
_collectionsLoaded = true;
|
2006-03-23 08:51:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-12 13:08:36 +00:00
|
|
|
|
2006-06-28 18:06:36 +00:00
|
|
|
/*
|
|
|
|
* Same structure as Scholar.Tags -- make changes in both places if possible
|
|
|
|
*/
|
2006-03-20 21:47:22 +00:00
|
|
|
Scholar.Creators = new function(){
|
2006-05-20 15:18:36 +00:00
|
|
|
var _creators = new Array; // indexed by first%%%last hash
|
2006-03-14 11:48:36 +00:00
|
|
|
var _creatorsByID = new Array; // indexed by creatorID
|
|
|
|
|
|
|
|
this.get = get;
|
|
|
|
this.getID = getID;
|
|
|
|
this.add = add;
|
|
|
|
this.purge = purge;
|
|
|
|
|
2006-05-19 11:31:45 +00:00
|
|
|
var self = this;
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
|
|
|
* Returns an array of creator data for a given creatorID
|
|
|
|
*/
|
|
|
|
function get(creatorID){
|
|
|
|
if (_creatorsByID[creatorID]){
|
|
|
|
return _creatorsByID[creatorID];
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = 'SELECT * FROM creators WHERE creatorID=' + creatorID;
|
2006-03-20 21:47:22 +00:00
|
|
|
var result = Scholar.DB.rowQuery(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (!result){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_creatorsByID[creatorID] = result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns the creatorID matching given name and type
|
|
|
|
*/
|
2006-05-20 15:18:36 +00:00
|
|
|
function getID(firstName, lastName){
|
|
|
|
var hash = firstName + '%%%' + lastName;
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (_creators[hash]){
|
|
|
|
return _creators[hash];
|
|
|
|
}
|
|
|
|
|
2006-05-20 15:18:36 +00:00
|
|
|
var sql = 'SELECT creatorID FROM creators '
|
|
|
|
+ 'WHERE firstName=? AND lastName=?';
|
2006-06-28 18:06:36 +00:00
|
|
|
var params = [{string: firstName}, {string: lastName}];
|
|
|
|
var creatorID = Scholar.DB.valueQuery(sql, params);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (creatorID){
|
|
|
|
_creators[hash] = creatorID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return creatorID;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add a new creator to the database
|
|
|
|
*
|
|
|
|
* Returns new creatorID
|
|
|
|
*/
|
2006-05-20 15:18:36 +00:00
|
|
|
function add(firstName, lastName){
|
2006-03-14 11:48:36 +00:00
|
|
|
Scholar.debug('Adding new creator', 4);
|
|
|
|
|
2006-06-03 20:41:23 +00:00
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
2006-06-28 18:06:36 +00:00
|
|
|
var sql = 'INSERT INTO creators VALUES (?,?,?)';
|
2006-06-03 20:41:23 +00:00
|
|
|
var rnd = Scholar.getRandomID('creators', 'creatorID');
|
2006-06-28 18:06:36 +00:00
|
|
|
var params = [{int: rnd}, {string: firstName}, {string: lastName}];
|
2006-05-20 15:18:36 +00:00
|
|
|
Scholar.DB.query(sql, params);
|
2006-06-03 20:41:23 +00:00
|
|
|
|
|
|
|
Scholar.DB.commitTransaction();
|
2006-05-20 15:18:36 +00:00
|
|
|
return rnd;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete obsolete creators from database and clear internal array entries
|
|
|
|
*
|
2006-06-23 22:00:39 +00:00
|
|
|
* Returns removed creatorIDs on success
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-06-23 22:00:39 +00:00
|
|
|
function purge(){
|
2006-03-14 11:48:36 +00:00
|
|
|
var sql = 'SELECT creatorID FROM creators WHERE creatorID NOT IN '
|
2006-05-18 11:25:10 +00:00
|
|
|
+ '(SELECT creatorID FROM itemCreators);';
|
2006-03-20 21:47:22 +00:00
|
|
|
var toDelete = Scholar.DB.columnQuery(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (!toDelete){
|
2006-06-23 22:00:39 +00:00
|
|
|
return false;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clear creator entries in internal array
|
|
|
|
for (var i=0; i<toDelete.length; i++){
|
|
|
|
var hash = _getHash(toDelete[i]);
|
|
|
|
delete _creators[hash];
|
|
|
|
delete _creatorsByID[toDelete[i]];
|
|
|
|
}
|
|
|
|
|
2006-06-23 22:00:39 +00:00
|
|
|
sql = 'DELETE FROM creators WHERE creatorID NOT IN '
|
|
|
|
+ '(SELECT creatorID FROM itemCreators);';
|
|
|
|
var result = Scholar.DB.query(sql);
|
|
|
|
|
|
|
|
return toDelete;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function _getHash(creatorID){
|
2006-05-19 11:31:45 +00:00
|
|
|
var creator = self.get(creatorID);
|
2006-03-14 11:48:36 +00:00
|
|
|
if (!creator){
|
|
|
|
return false;
|
|
|
|
}
|
2006-05-20 15:18:36 +00:00
|
|
|
return creator['firstName'] + '%%%' + creator['lastName'];
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-28 18:06:36 +00:00
|
|
|
/*
|
|
|
|
* Same structure as Scholar.Creators -- make changes in both places if possible
|
|
|
|
*/
|
|
|
|
Scholar.Tags = new function(){
|
|
|
|
var _tags = new Array; // indexed by tag text
|
|
|
|
var _tagsByID = new Array; // indexed by tagID
|
|
|
|
|
|
|
|
this.getName = getName;
|
|
|
|
this.getID = getID;
|
|
|
|
this.add = add;
|
|
|
|
this.purge = purge;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns a tag for a given tagID
|
|
|
|
*/
|
|
|
|
function getName(tagID){
|
|
|
|
if (_tagsByID[tagID]){
|
|
|
|
return _tagsByID[tagID];
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = 'SELECT tag FROM tags WHERE tagID=' + tagID;
|
|
|
|
var result = Scholar.DB.valueQuery(sql);
|
|
|
|
|
|
|
|
if (!result){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_tagsByID[tagID] = result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns the tagID matching given tag
|
|
|
|
*/
|
|
|
|
function getID(tag){
|
|
|
|
if (_tags[tag]){
|
|
|
|
return _tags[tag];
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = 'SELECT tagID FROM tags WHERE tag=?';
|
|
|
|
var tagID = Scholar.DB.valueQuery(sql, [{string:tag}]);
|
|
|
|
|
|
|
|
if (tagID){
|
|
|
|
_tags[tag] = tagID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return tagID;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add a new tag to the database
|
|
|
|
*
|
|
|
|
* Returns new tagID
|
|
|
|
*/
|
|
|
|
function add(tag){
|
|
|
|
Scholar.debug('Adding new tag', 4);
|
|
|
|
|
|
|
|
Scholar.DB.beginTransaction();
|
|
|
|
|
|
|
|
var sql = 'INSERT INTO tags VALUES (?,?)';
|
|
|
|
var rnd = Scholar.getRandomID('tags', 'tagID');
|
|
|
|
Scholar.DB.query(sql, [{int: rnd}, {string: tag}]);
|
|
|
|
|
|
|
|
Scholar.DB.commitTransaction();
|
|
|
|
return rnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete obsolete tags from database and clear internal array entries
|
|
|
|
*
|
|
|
|
* Returns removed tagIDs on success
|
|
|
|
*/
|
|
|
|
function purge(){
|
|
|
|
var sql = 'SELECT tagID FROM tags WHERE tagID NOT IN '
|
|
|
|
+ '(SELECT tagID FROM itemTags);';
|
|
|
|
var toDelete = Scholar.DB.columnQuery(sql);
|
|
|
|
|
|
|
|
if (!toDelete){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear tag entries in internal array
|
|
|
|
for (var i=0; i<toDelete.length; i++){
|
|
|
|
var tag = this.getName(toDelete[i]);
|
|
|
|
delete _tags[tag];
|
|
|
|
delete _tagsByID[toDelete[i]];
|
|
|
|
}
|
|
|
|
|
|
|
|
sql = 'DELETE FROM tags WHERE tagID NOT IN '
|
|
|
|
+ '(SELECT tagID FROM itemTags);';
|
|
|
|
var result = Scholar.DB.query(sql);
|
|
|
|
|
|
|
|
return toDelete;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-15 19:30:18 +00:00
|
|
|
|
|
|
|
|
2006-06-28 18:06:36 +00:00
|
|
|
/*
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
* Same structure as Scholar.ItemTypes and FileTypes --
|
|
|
|
* make changes in both places if possible
|
2006-06-28 18:06:36 +00:00
|
|
|
*/
|
2006-06-12 13:08:36 +00:00
|
|
|
Scholar.CreatorTypes = new function(){
|
2006-06-25 04:35:11 +00:00
|
|
|
var _types = new Array();
|
|
|
|
var _typesLoaded;
|
2006-06-12 13:08:36 +00:00
|
|
|
var self = this;
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
this.getName = getName;
|
|
|
|
this.getID = getID;
|
2006-06-12 13:08:36 +00:00
|
|
|
this.getTypes = getTypes;
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
|
|
|
|
function getName(idOrName){
|
|
|
|
if (!_typesLoaded){
|
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_types[idOrName]){
|
|
|
|
Scholar.debug('Invalid creator type ' + idOrName, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _types[idOrName]['name'];
|
2006-06-12 13:08:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
|
|
|
|
function getID(idOrName){
|
|
|
|
if (!_typesLoaded){
|
2006-06-12 13:08:36 +00:00
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
if (!_types[idOrName]){
|
|
|
|
Scholar.debug('Invalid creator type ' + idOrName, 1);
|
2006-06-12 13:08:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
return _types[idOrName]['id'];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getTypes(){
|
|
|
|
return Scholar.DB.query('SELECT creatorTypeID AS id, '
|
|
|
|
+ 'creatorType AS name FROM creatorTypes order BY creatorType');
|
2006-06-12 13:08:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
|
2006-06-12 13:08:36 +00:00
|
|
|
function _load(){
|
|
|
|
var types = self.getTypes();
|
|
|
|
|
|
|
|
for (i in types){
|
2006-06-25 04:35:11 +00:00
|
|
|
// Store as both id and name for access by either
|
|
|
|
var typeData = {
|
|
|
|
id: types[i]['id'],
|
|
|
|
name: types[i]['name']
|
|
|
|
}
|
|
|
|
_types[types[i]['id']] = typeData;
|
|
|
|
_types[types[i]['name']] = _types[types[i]['id']];
|
2006-06-12 13:08:36 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
_typesLoaded = true;
|
2006-06-12 13:08:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-06-28 18:06:36 +00:00
|
|
|
/*
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
* Same structure as Scholar.CreatorTypes and FileTypes --
|
|
|
|
* make changes in both places if possible
|
2006-06-28 18:06:36 +00:00
|
|
|
*/
|
2006-05-18 20:39:38 +00:00
|
|
|
Scholar.ItemTypes = new function(){
|
2006-06-25 04:35:11 +00:00
|
|
|
var _types = new Array();
|
|
|
|
var _typesLoaded;
|
2006-06-12 12:59:25 +00:00
|
|
|
var self = this;
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
this.getName = getName;
|
|
|
|
this.getID = getID;
|
2006-05-18 20:39:38 +00:00
|
|
|
this.getTypes = getTypes;
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
|
|
|
|
function getName(idOrName){
|
|
|
|
if (!_typesLoaded){
|
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_types[idOrName]){
|
|
|
|
Scholar.debug('Invalid item type ' + idOrName, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _types[idOrName]['name'];
|
2006-05-18 20:39:38 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
|
|
|
|
function getID(idOrName){
|
|
|
|
if (!_typesLoaded){
|
2006-06-12 12:59:25 +00:00
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
if (!_types[idOrName]){
|
|
|
|
Scholar.debug('Invalid item type ' + idOrName, 1);
|
2006-06-12 12:59:25 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
return _types[idOrName]['id'];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getTypes(){
|
|
|
|
return Scholar.DB.query('SELECT itemTypeID AS id, typeName AS name '
|
|
|
|
+ 'FROM itemTypes order BY typeName');
|
2006-06-12 12:59:25 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
|
2006-06-12 12:59:25 +00:00
|
|
|
function _load(){
|
|
|
|
var types = self.getTypes();
|
|
|
|
|
|
|
|
for (i in types){
|
2006-06-25 04:35:11 +00:00
|
|
|
// Store as both id and name for access by either
|
|
|
|
var typeData = {
|
|
|
|
id: types[i]['id'],
|
|
|
|
name: types[i]['name']
|
|
|
|
}
|
|
|
|
_types[types[i]['id']] = typeData;
|
|
|
|
_types[types[i]['name']] = _types[types[i]['id']];
|
2006-06-12 12:59:25 +00:00
|
|
|
}
|
|
|
|
|
2006-06-25 04:35:11 +00:00
|
|
|
_typesLoaded = true;
|
2006-05-18 20:39:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-15 19:30:18 +00:00
|
|
|
|
|
|
|
|
Addresses #17, add filesystem/ability to store files
Not finished, but enough to give David something to work with
No BLOBs -- just linking/importing of files and loaded documents
New Scholar.Item methods:
incrementFileCount() (used internally)
decrementFileCount() (used internally)
isFile()
numFiles()
getFile() -- returns nsILocalFile or false if associated file doesn't exist (note: always returns false for items with LINK_MODE_LINKED_URL, since they have no files -- use getFileURL() instead)
getFileURL() -- returns URL string
getFileLinkMode() -- compare to Scholar.Files.LINK_MODE_* constants: LINKED_FILE, IMPORTED_FILE, LINKED_URL, IMPORTED_URL
getFileMimeType() -- mime type of file (e.g. text/plain)
getFileCharset() -- charsetID of file
getFiles() -- array of file itemIDs this file is a source for
New Scholar.Files methods:
importFromFile(nsIFile file [, int sourceItemID])
linkFromFile(nsIFile file [, int sourceItemID])
importFromDocument(nsIDOMDocument document [, int sourceItemID])
linkFromDocument(nsIDOMDocument document [, int sourceItemID])
New class Scholar.FileTypes -- partially implemented, not yet used
New class Scholar.CharacterSets -- same as other *Types classes:
getID(idOrName)
getName(idOrName)
getTypes() (aliased to getAll(), which I'll probably change the others to as well)
Charsets table with all official character sets (copied from Mozilla source)
Renamed Item.setNoteSource() to setSource() and Item.getNoteSource() to getSource() and adjusted to handle both notes and files
2006-07-27 09:16:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Same structure as Scholar.ItemTypes and CreatorTypes --
|
|
|
|
* make changes in both places if possible
|
|
|
|
*/
|
|
|
|
Scholar.FileTypes = new function(){
|
|
|
|
var _types = new Array();
|
|
|
|
var _typesLoaded;
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
this.getName = getName;
|
|
|
|
this.getID = getID;
|
|
|
|
this.getIDFromMIMEType = getIDFromMIMEType;
|
|
|
|
this.getTypes = getTypes;
|
|
|
|
|
|
|
|
|
|
|
|
function getName(idOrName){
|
|
|
|
if (!_typesLoaded){
|
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_types[idOrName]){
|
|
|
|
Scholar.debug('Invalid file type ' + idOrName, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _types[idOrName]['name'];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getID(idOrName){
|
|
|
|
if (!_typesLoaded){
|
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_types[idOrName]){
|
|
|
|
Scholar.debug('Invalid file type ' + idOrName, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _types[idOrName]['id'];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getIDFromMIMEType(mimeType){
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getTypes(){
|
|
|
|
return Scholar.DB.query('SELECT fileTypeID AS id, '
|
|
|
|
+ 'fileType AS name FROM fileTypes order BY fileType');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function _load(){
|
|
|
|
var types = self.getTypes();
|
|
|
|
|
|
|
|
for (i in types){
|
|
|
|
// Store as both id and name for access by either
|
|
|
|
var typeData = {
|
|
|
|
id: types[i]['id'],
|
|
|
|
name: types[i]['name']
|
|
|
|
}
|
|
|
|
_types[types[i]['id']] = typeData;
|
|
|
|
_types[types[i]['name']] = _types[types[i]['id']];
|
|
|
|
}
|
|
|
|
|
|
|
|
_typesLoaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Same structure as Scholar.ItemTypes, CreatorTypes, etc. --
|
|
|
|
* make changes in all versions if possible
|
|
|
|
*/
|
|
|
|
Scholar.CharacterSets = new function(){
|
|
|
|
var _types = new Array();
|
|
|
|
var _typesLoaded;
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
var _typeDesc = 'character set';
|
|
|
|
var _idCol = 'charsetID';
|
|
|
|
var _nameCol = 'charset';
|
|
|
|
var _table = 'charsets';
|
|
|
|
var _ignoreCase = true;
|
|
|
|
|
|
|
|
this.getName = getName;
|
|
|
|
this.getID = getID;
|
|
|
|
this.getTypes = getTypes;
|
|
|
|
this.getAll = getAll;
|
|
|
|
|
|
|
|
function getName(idOrName){
|
|
|
|
if (!_typesLoaded){
|
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_ignoreCase){
|
|
|
|
idOrName = idOrName.toLowerCase();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_types[idOrName]){
|
|
|
|
Scholar.debug('Invalid ' + _typeDesc + ' ' + idOrName, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _types[idOrName]['name'];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getID(idOrName){
|
|
|
|
if (!_typesLoaded){
|
|
|
|
_load();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_ignoreCase){
|
|
|
|
idOrName = idOrName.toLowerCase();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_types[idOrName]){
|
|
|
|
Scholar.debug('Invalid ' + _typeDesc + ' ' + idOrName, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _types[idOrName]['id'];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getTypes(){
|
|
|
|
return Scholar.DB.query('SELECT ' + _idCol + ' AS id, '
|
|
|
|
+ _nameCol + ' AS name FROM ' + _table + ' order BY ' + _nameCol);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getAll(){
|
|
|
|
return this.getTypes();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function _load(){
|
|
|
|
var types = self.getTypes();
|
|
|
|
|
|
|
|
for (i in types){
|
|
|
|
// Store as both id and name for access by either
|
|
|
|
var typeData = {
|
|
|
|
id: types[i]['id'],
|
|
|
|
name: _ignoreCase ? types[i]['name'].toLowerCase() : types[i]['name']
|
|
|
|
}
|
|
|
|
_types[types[i]['id']] = typeData;
|
|
|
|
_types[types[i]['name']] = _types[types[i]['id']];
|
|
|
|
}
|
|
|
|
|
|
|
|
_typesLoaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
Scholar.ItemFields = new function(){
|
2006-03-14 11:48:36 +00:00
|
|
|
// Private members
|
|
|
|
var _fields = new Array();
|
|
|
|
var _fieldFormats = new Array();
|
2006-05-18 11:25:10 +00:00
|
|
|
var _itemTypeFields = new Array();
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
// Privileged methods
|
|
|
|
this.getName = getName;
|
|
|
|
this.getID = getID;
|
|
|
|
this.isValidForType = isValidForType;
|
|
|
|
this.isInteger = isInteger;
|
2006-05-18 11:25:10 +00:00
|
|
|
this.getItemTypeFields = getItemTypeFields;
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the fieldName for a passed fieldID or fieldName
|
|
|
|
*/
|
|
|
|
function getName(field){
|
|
|
|
if (!_fields.length){
|
|
|
|
_loadFields();
|
|
|
|
}
|
|
|
|
return _fields[field] ? _fields[field]['name'] : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the fieldID for a passed fieldID or fieldName
|
|
|
|
*/
|
|
|
|
function getID(field){
|
|
|
|
if (!_fields.length){
|
|
|
|
_loadFields();
|
|
|
|
}
|
|
|
|
return _fields[field] ? _fields[field]['id'] : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
function isValidForType(fieldID, itemTypeID){
|
2006-03-14 11:48:36 +00:00
|
|
|
if (!_fields.length){
|
|
|
|
_loadFields();
|
|
|
|
}
|
2006-06-04 19:37:03 +00:00
|
|
|
|
|
|
|
_fieldCheck(fieldID);
|
|
|
|
|
|
|
|
if (!_fields[fieldID]['itemTypes']){
|
|
|
|
throw('No associated itemTypes for fieldID ' + fieldID);
|
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
return !!_fields[fieldID]['itemTypes'][itemTypeID];
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function isInteger(fieldID){
|
|
|
|
if (!_fields.length){
|
|
|
|
_loadFields();
|
|
|
|
}
|
2006-06-04 19:37:03 +00:00
|
|
|
|
|
|
|
_fieldCheck(fieldID);
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
var ffid = _fields[fieldID]['formatID'];
|
|
|
|
return _fieldFormats[ffid] ? _fieldFormats[ffid]['isInteger'] : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Returns an array of fieldIDs for a given item type
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
function getItemTypeFields(itemTypeID){
|
|
|
|
if (_itemTypeFields[itemTypeID]){
|
|
|
|
return _itemTypeFields[itemTypeID];
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
var sql = 'SELECT fieldID FROM itemTypeFields '
|
|
|
|
+ 'WHERE itemTypeID=' + itemTypeID + ' ORDER BY orderIndex';
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
_itemTypeFields[itemTypeID] = Scholar.DB.columnQuery(sql);
|
|
|
|
return _itemTypeFields[itemTypeID];
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-04 19:37:03 +00:00
|
|
|
/**
|
|
|
|
* Check whether a fieldID is valid, throwing an exception if not
|
|
|
|
* (since it should never actually happen)
|
|
|
|
**/
|
|
|
|
function _fieldCheck(fieldID){
|
|
|
|
if (!_fields.length){
|
|
|
|
_loadFields();
|
|
|
|
}
|
|
|
|
if (typeof _fields[fieldID]=='undefined'){
|
|
|
|
throw('Invalid fieldID ' + fieldID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-14 11:48:36 +00:00
|
|
|
/*
|
2006-05-18 11:25:10 +00:00
|
|
|
* Returns hash array of itemTypeIDs for which a given field is valid
|
2006-03-14 11:48:36 +00:00
|
|
|
*/
|
2006-05-18 11:25:10 +00:00
|
|
|
function _getFieldItemTypes(){
|
|
|
|
var sql = 'SELECT fieldID, itemTypeID FROM itemTypeFields';
|
2006-03-14 11:48:36 +00:00
|
|
|
|
2006-03-20 21:47:22 +00:00
|
|
|
var results = Scholar.DB.query(sql);
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (!results){
|
2006-05-18 11:25:10 +00:00
|
|
|
throw ('No fields in itemTypeFields!');
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
var fields = new Array();
|
|
|
|
for (var i=0; i<results.length; i++){
|
|
|
|
if (!fields[results[i]['fieldID']]){
|
|
|
|
fields[results[i]['fieldID']] = new Array();
|
|
|
|
}
|
2006-05-18 11:25:10 +00:00
|
|
|
fields[results[i]['fieldID']][results[i]['itemTypeID']] = true;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
return fields;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load all fields into an internal hash array
|
|
|
|
*/
|
|
|
|
function _loadFields(){
|
|
|
|
var i,len;
|
|
|
|
|
2006-03-20 21:47:22 +00:00
|
|
|
var result = Scholar.DB.query('SELECT * FROM fieldFormats');
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
for (i=0; i<result.length; i++){
|
|
|
|
_fieldFormats[result[i]['fieldFormatID']] = {
|
|
|
|
regex: result[i]['regex'],
|
|
|
|
isInteger: result[i]['isInteger']
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2006-03-20 21:47:22 +00:00
|
|
|
result = Scholar.DB.query('SELECT * FROM fields');
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
if (!result.length){
|
|
|
|
throw ('No fields in database!');
|
|
|
|
}
|
|
|
|
|
2006-05-18 11:25:10 +00:00
|
|
|
var fieldItemTypes = _getFieldItemTypes();
|
2006-03-14 11:48:36 +00:00
|
|
|
|
|
|
|
for (i=0,len=result.length; i<len; i++){
|
|
|
|
_fields[result[i]['fieldID']] = {
|
|
|
|
id: result[i]['fieldID'],
|
|
|
|
name: result[i]['fieldName'],
|
|
|
|
formatID: result[i]['fieldFormatID'],
|
2006-05-18 11:25:10 +00:00
|
|
|
itemTypes: fieldItemTypes[result[i]['fieldID']]
|
2006-03-14 11:48:36 +00:00
|
|
|
};
|
|
|
|
// Store by name as well as id
|
|
|
|
_fields[result[i]['fieldName']] = _fields[result[i]['fieldID']];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-20 15:18:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Scholar.getCollections(parent)
|
|
|
|
*
|
|
|
|
* Returns an array of all collections are children of a collection
|
|
|
|
* as Scholar.Collection instances
|
|
|
|
*
|
|
|
|
* Takes parent collectionID as optional parameter;
|
|
|
|
* by default, returns root collections
|
|
|
|
*/
|
|
|
|
Scholar.getCollections = function(parent){
|
|
|
|
var toReturn = new Array();
|
|
|
|
|
|
|
|
if (!parent){
|
|
|
|
parent = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
var sql = 'SELECT collectionID FROM collections C WHERE parentCollectionID';
|
|
|
|
sql += parent ? '=' + parent : ' IS NULL';
|
|
|
|
|
|
|
|
sql += ' ORDER BY collectionName';
|
|
|
|
|
|
|
|
var children = Scholar.DB.columnQuery(sql);
|
|
|
|
|
|
|
|
if (!children){
|
|
|
|
Scholar.debug('No child collections of collection ' + parent, 5);
|
|
|
|
return toReturn;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var i=0, len=children.length; i<len; i++){
|
|
|
|
var obj = Scholar.Collections.get(children[i]);
|
|
|
|
if (!obj){
|
|
|
|
throw ('Collection ' + children[i] + ' not found');
|
|
|
|
}
|
|
|
|
|
|
|
|
toReturn.push(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
return toReturn;
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-01 00:22:18 +00:00
|
|
|
/*
|
|
|
|
* Scholar.getItems(parent)
|
|
|
|
*
|
|
|
|
* Returns an array of all items that are children of a collection--or all
|
|
|
|
* items if no parent provided--as Scholar.Item instances
|
|
|
|
*/
|
|
|
|
Scholar.getItems = function(parent){
|
|
|
|
var toReturn = new Array();
|
|
|
|
|
|
|
|
if (!parent){
|
Fixes #29, independent notes
- Added 'note' item type
- Updated API to support independent note creation
Notes are, more or less, just regular items, with an item type of 1. They're created through Scholar.Notes.add(text, sourceItemID), which returns the itemID of the new note. sourceItemID is optional--if left out, an independent note will be created. (There's currently nothing stopping you from doing getNewItemByType(1) yourself, but the note would be contentless and broken, so you shouldn't do that.) Note data could've been stuffed into itemData, but I kept it separate in itemNotes to keep metadata searching faster and to keep things cleaner.
Methods calls that can be called on all items:
isNote() (same as testing for itemTypeID 1)
Method calls that can be called on source items only:
numNotes()
getNotes() (array of note itemIDs for a source)
Method calls that can be called on note items only:
updateNote(text)
setNoteSource(sourceItemID) (for changing source--use empty or false to make independent, which is currently what happens when you delete a note--will get option with #91)
getNote() (note content)
getNoteSource() (sourceItemID of a note)
Calling the above methods on the wrong item types will throw an error.
*** This will break note creation/display until David updates interface code. ***
2006-06-27 15:14:07 +00:00
|
|
|
var sql = "SELECT itemID FROM items LEFT JOIN itemNotes USING (itemID) "
|
|
|
|
+ "WHERE sourceItemID IS NULL";
|
2006-06-01 00:22:18 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
var sql = 'SELECT itemID FROM collectionItems '
|
|
|
|
+ 'WHERE collectionID=' + parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
var children = Scholar.DB.columnQuery(sql);
|
|
|
|
|
|
|
|
if (!children){
|
|
|
|
if (!parent){
|
|
|
|
Scholar.debug('No items in library', 5);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Scholar.debug('No child items of collection ' + parent, 5);
|
|
|
|
}
|
|
|
|
return toReturn;
|
|
|
|
}
|
|
|
|
|
2006-06-06 20:46:08 +00:00
|
|
|
return Scholar.Items.get(children);
|
2006-03-14 11:48:36 +00:00
|
|
|
}
|