2006-10-04 17:16:56 +00:00
|
|
|
|
/*
|
|
|
|
|
***** BEGIN LICENSE BLOCK *****
|
|
|
|
|
|
2009-12-28 09:47:49 +00:00
|
|
|
|
Copyright © 2009 Center for History and New Media
|
|
|
|
|
George Mason University, Fairfax, Virginia, USA
|
|
|
|
|
http://zotero.org
|
2006-10-04 17:16:56 +00:00
|
|
|
|
|
2009-12-28 09:47:49 +00:00
|
|
|
|
This file is part of Zotero.
|
2006-10-04 17:16:56 +00:00
|
|
|
|
|
2009-12-28 09:47:49 +00:00
|
|
|
|
Zotero is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
2006-10-04 17:16:56 +00:00
|
|
|
|
|
2009-12-28 09:47:49 +00:00
|
|
|
|
Zotero is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
2006-10-04 17:16:56 +00:00
|
|
|
|
|
|
|
|
|
***** END LICENSE BLOCK *****
|
|
|
|
|
*/
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
const ZOTERO_CONFIG = {
|
2006-08-30 07:05:57 +00:00
|
|
|
|
GUID: 'zotero@chnm.gmu.edu',
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
DB_REBUILD: false, // erase DB and recreate from schema
|
2009-11-09 05:13:10 +00:00
|
|
|
|
REPOSITORY_URL: 'https://api.zotero.org/repo',
|
2006-07-31 03:38:02 +00:00
|
|
|
|
REPOSITORY_CHECK_INTERVAL: 86400, // 24 hours
|
2008-06-17 20:41:31 +00:00
|
|
|
|
REPOSITORY_RETRY_INTERVAL: 3600, // 1 hour
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
BASE_URI: 'http://zotero.org/',
|
|
|
|
|
WWW_BASE_URL: 'http://www.zotero.org/',
|
Zotero File Storage megacommit
- Group file sync via Zotero File Storage
- Split file syncing into separate modules for ZFS and WebDAV
- Dragging items between libraries copies child notes, snapshots/files, and links based on checkboxes for each (enabled by default) in the Zotero preferences
- Sync errors now trigger an exclamation/error icon separate from the sync icon, with a popup window displaying the error and an option to report it
- Various errors that could cause perpetual sync icon spinning now stop the sync properly
- Zotero.Utilities.md5(str) is now md5(strOrFile, base64)
- doPost(), doHead(), and retrieveSource() now takes a headers parameter instead of requestContentType
- doHead() can now accept an nsIURI (with login credentials), is a background request, and isn't cached
- When library access or file writing access is denied during sync, display a warning and then reset local group to server version
- Perform additional steps (e.g., removing local groups) when switching sync users to prevent errors
- Compare hash as well as mod time when checking for modified local files
- Don't trigger notifications when removing groups from the client
- Clear relation links to items in removed groups
- Zotero.Item.attachmentHash property to get file MD5
- importFromFile() now takes libraryID as a third parameter
- Zotero.Attachments.getNumFiles() returns the number of files in the attachment directory
- Zotero.Attachments.copyAttachmentToLibrary() copies an attachment item, including files, to another library
- Removed Zotero.File.getFileHash() in favor of updated Zotero.Utilities.md5()
- Zotero.File.copyDirectory(dir, newDir) copies all files from dir into newDir
- Preferences shuffling: OpenURL to Advanced, import/export character set options to Export, "Include URLs of paper articles in references" to Styles
- Other stuff I don't remember
Suffice it to say, this could use testing.
2009-09-13 07:23:29 +00:00
|
|
|
|
SYNC_URL: 'https://sync.zotero.org/',
|
|
|
|
|
API_URL: 'https://api.zotero.org/'
|
2006-02-21 17:01:06 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Core functions
|
|
|
|
|
*/
|
2006-10-02 23:15:27 +00:00
|
|
|
|
var Zotero = new function(){
|
2006-05-27 00:20:27 +00:00
|
|
|
|
// Privileged (public) methods
|
2006-03-20 21:47:22 +00:00
|
|
|
|
this.init = init;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.stateCheck = stateCheck;
|
2006-07-27 08:45:48 +00:00
|
|
|
|
this.getProfileDirectory = getProfileDirectory;
|
Merged revisions 3080-3081,3084,3087-3088,3090,3092,3099-3103,3113-3114,3132,3134-3143,3145,3148-3151,3154-3159,3165,3174,3194,3234-3235,3239-3240,3244,3246-3254,3258-3262,3268,3270,3274,3279,3286-3288,3294-3295 from 1.0 branch via svnmerge
2008-09-01 01:54:00 +00:00
|
|
|
|
this.getInstallDirectory = getInstallDirectory;
|
2006-10-02 23:15:27 +00:00
|
|
|
|
this.getZoteroDirectory = getZoteroDirectory;
|
2006-07-27 08:45:48 +00:00
|
|
|
|
this.getStorageDirectory = getStorageDirectory;
|
2006-10-02 23:15:27 +00:00
|
|
|
|
this.getZoteroDatabase = getZoteroDatabase;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.chooseZoteroDirectory = chooseZoteroDirectory;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
this.debug = debug;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.log = log;
|
|
|
|
|
this.getErrors = getErrors;
|
|
|
|
|
this.getSystemInfo = getSystemInfo;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
this.varDump = varDump;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.safeDebug = safeDebug;
|
2006-05-27 00:20:27 +00:00
|
|
|
|
this.getString = getString;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.localeJoin = localeJoin;
|
|
|
|
|
this.getLocaleCollation = getLocaleCollation;
|
|
|
|
|
this.setFontSize = setFontSize;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
this.flattenArguments = flattenArguments;
|
Closes #259, auto-complete of tags
Addresses #260, Add auto-complete to search window
- New XPCOM autocomplete component for Zotero data -- can be used by setting the autocompletesearch attribute of a textbox to 'zotero' and passing a search scope with the autocompletesearchparam attribute. Additional parameters can be passed by appending them to the autocompletesearchparam value with a '/', e.g. 'tag/2732' (to exclude tags that show up in item 2732)
- Tag entry now uses more or less the same interface as metadata -- no more popup window -- note that tab isn't working properly yet, and there's no way to quickly enter multiple tags (though it's now considerably quicker than it was before)
- Autocomplete for tags, excluding any tags already set for the current item
- Standalone note windows now register with the Notifier (since tags needed item modification notifications to work properly), which will help with #282, "Notes opened in separate windows need item notification"
- Tags are now retrieved in alphabetical order
- Scholar.Item.replaceTag(oldTagID, newTag), with a single notify
- Scholar.getAncestorByTagName(elem, tagName) -- walk up the DOM tree from an element until an element with the specified tag name is found (also checks with 'xul:' prefix, for use in XBL), or false if not found -- probably shouldn't be used too widely, since it's doing string comparisons, but better than specifying, say, nine '.parentNode' properties, and makes for more resilient code
A few notes:
- Autocomplete in Minefield seems to self-destruct after using it in the same field a few times, taking down saving of the field with it -- this may or may not be my fault, but it makes Zotero more or less unusable in 3.0 at the moment. Sorry. (I use 3.0 myself for development, so I'll work on it.)
- This would have been much, much easier if having an autocomplete textbox (which uses an XBL-generated popup for the suggestions) within a popup (as it is in the independent note edit panes) didn't introduce all sorts of crazy bugs that had to be defeated with annoying hackery -- one side effect of this is that at the moment you can't close the tags popup with the Escape key
- Independent note windows now need to pull in itemPane.js to function properly, which is a bit messy and not ideal, but less messy and more ideal than duplicating all the dual-state editor and tabindex logic would be
- Hitting tab in a tag field not only doesn't work but also breaks things until the next window refresh.
- There are undoubtedly other bugs.
2006-09-07 08:07:48 +00:00
|
|
|
|
this.getAncestorByTagName = getAncestorByTagName;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
this.join = join;
|
2006-06-20 17:32:40 +00:00
|
|
|
|
this.inArray = inArray;
|
|
|
|
|
this.arraySearch = arraySearch;
|
Fulltext search support
There are currently two types of fulltext searching: an SQL-based word index and a file scanner. They each have their advantages and drawbacks.
The word index is very fast to search and is currently used for the find-as-you-type quicksearch. However, indexing files takes some time, so we should probably offer a preference to turn it off ("Index attachment content for quicksearch" or something). There's also an issue with Chinese characters (which are indexed by character rather than word, since there are no spaces to go by, so a search for a word with common characters could produce erroneous results). The quicksearch doesn't use a left-bound index (since that would probably upset German speakers searching for "musik" in "nachtmusik," though I don't know for sure how they think of words) but still seems pretty fast.
* Note: There will be a potentially long delay when you start Firefox with this revision as it builds a fulltext word index of your existing items. We obviously need a notification/option for this. *
The file scanner, used in the Attachment Content condition of the search dialog, offers phrase searching as well as regex support (both case-sensitive and not, and defaulting to multiline). It doesn't require an index, though it should probably be optimized to use the word index, if available, for narrowing the results when not in regex mode. (It does only scan files that pass all the other search conditions, which speeds it up considerably for multi-condition searches, and skips non-text files unless instructed otherwise, but it's still relatively slow.)
Both convert HTML to text before searching (with the exception of the binary file scanning mode).
There are some issues with which files get indexed and which don't that we can't do much about and that will probably confuse users immensely. Dan C. suggested some sort of indicator (say, a green dot) to show which files are indexed.
Also added (very ugly) charset detection (anybody want to figure out getCharsetFromString(str)?), a setTimeout() replacement in the XPCOM service, an arrayToHash() method, and a new header to timedtextarea.xml, since it's really not copyright CHNM (it's really just a few lines off from the toolkit timed-textbox binding--I tried to change it to extend timed-textbox and just ignore Return keypress events so that we didn't need to duplicate the Mozilla code, but timed-textbox's reliance on html:input instead of html:textarea made things rather difficult).
To do:
- Pref/buttons to disable/clear/rebuild fulltext index
- Hidden prefs to set maximum file size to index/scan
- Don't index words of fewer than 3 non-Asian characters
- MRU cache for saved searches
- Use word index if available to narrow search scope of fulltext scanner
- Cache attachment info methods
- Show content excerpt in search results (at least in advanced search window, when it exists)
- Notification window (a la scraping) to show when indexing
- Indicator of indexed status
- Context menu option to index
- Indicator that a file scanning search is in progress, if possible
- Find other ways to make it index the NYT front page in under 10 seconds
- Probably fix lots of bugs, which you will likely start telling me about...now.
2006-09-21 00:10:29 +00:00
|
|
|
|
this.arrayToHash = arrayToHash;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.hasValues = hasValues;
|
2006-06-01 19:46:57 +00:00
|
|
|
|
this.randomString = randomString;
|
2006-08-01 23:10:31 +00:00
|
|
|
|
this.moveToUnique = moveToUnique;
|
2006-05-27 00:20:27 +00:00
|
|
|
|
|
2006-06-15 06:13:02 +00:00
|
|
|
|
// Public properties
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.initialized = false;
|
|
|
|
|
this.skipLoading = false;
|
2009-12-29 22:21:54 +00:00
|
|
|
|
this.startupError;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.__defineGetter__("startupErrorHandler", function() { return _startupErrorHandler; });
|
2006-06-15 06:13:02 +00:00
|
|
|
|
this.version;
|
2006-08-30 19:18:43 +00:00
|
|
|
|
this.platform;
|
2006-09-06 07:04:02 +00:00
|
|
|
|
this.locale;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.dir; // locale direction: 'ltr' or 'rtl'
|
2006-08-30 21:56:52 +00:00
|
|
|
|
this.isMac;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.isWin;
|
|
|
|
|
this.initialURL; // used by Schema to show the changelog on upgrades
|
|
|
|
|
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
|
|
|
|
|
this.__defineGetter__('userID', function () {
|
|
|
|
|
var sql = "SELECT value FROM settings WHERE "
|
|
|
|
|
+ "setting='account' AND key='userID'";
|
|
|
|
|
return Zotero.DB.valueQuery(sql);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.__defineSetter__('userID', function (val) {
|
|
|
|
|
var sql = "REPLACE INTO settings VALUES ('account', 'userID', ?)";
|
|
|
|
|
Zotero.DB.query(sql, parseInt(val));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.__defineGetter__('libraryID', function () {
|
|
|
|
|
var sql = "SELECT value FROM settings WHERE "
|
|
|
|
|
+ "setting='account' AND key='libraryID'";
|
|
|
|
|
return Zotero.DB.valueQuery(sql);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.__defineSetter__('libraryID', function (val) {
|
|
|
|
|
var sql = "REPLACE INTO settings VALUES ('account', 'libraryID', ?)";
|
|
|
|
|
Zotero.DB.query(sql, parseInt(val));
|
|
|
|
|
});
|
|
|
|
|
|
Zotero File Storage megacommit
- Group file sync via Zotero File Storage
- Split file syncing into separate modules for ZFS and WebDAV
- Dragging items between libraries copies child notes, snapshots/files, and links based on checkboxes for each (enabled by default) in the Zotero preferences
- Sync errors now trigger an exclamation/error icon separate from the sync icon, with a popup window displaying the error and an option to report it
- Various errors that could cause perpetual sync icon spinning now stop the sync properly
- Zotero.Utilities.md5(str) is now md5(strOrFile, base64)
- doPost(), doHead(), and retrieveSource() now takes a headers parameter instead of requestContentType
- doHead() can now accept an nsIURI (with login credentials), is a background request, and isn't cached
- When library access or file writing access is denied during sync, display a warning and then reset local group to server version
- Perform additional steps (e.g., removing local groups) when switching sync users to prevent errors
- Compare hash as well as mod time when checking for modified local files
- Don't trigger notifications when removing groups from the client
- Clear relation links to items in removed groups
- Zotero.Item.attachmentHash property to get file MD5
- importFromFile() now takes libraryID as a third parameter
- Zotero.Attachments.getNumFiles() returns the number of files in the attachment directory
- Zotero.Attachments.copyAttachmentToLibrary() copies an attachment item, including files, to another library
- Removed Zotero.File.getFileHash() in favor of updated Zotero.Utilities.md5()
- Zotero.File.copyDirectory(dir, newDir) copies all files from dir into newDir
- Preferences shuffling: OpenURL to Advanced, import/export character set options to Export, "Include URLs of paper articles in references" to Styles
- Other stuff I don't remember
Suffice it to say, this could use testing.
2009-09-13 07:23:29 +00:00
|
|
|
|
this.__defineGetter__('username', function () {
|
|
|
|
|
var sql = "SELECT value FROM settings WHERE "
|
|
|
|
|
+ "setting='account' AND key='username'";
|
|
|
|
|
return Zotero.DB.valueQuery(sql);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.__defineSetter__('username', function (val) {
|
|
|
|
|
var sql = "REPLACE INTO settings VALUES ('account', 'username', ?)";
|
|
|
|
|
Zotero.DB.query(sql, val);
|
|
|
|
|
});
|
|
|
|
|
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
this.getLocalUserKey = function (generate) {
|
|
|
|
|
if (_localUserKey) {
|
|
|
|
|
return _localUserKey;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var sql = "SELECT value FROM settings WHERE "
|
|
|
|
|
+ "setting='account' AND key='localUserKey'";
|
|
|
|
|
var key = Zotero.DB.valueQuery(sql);
|
|
|
|
|
|
|
|
|
|
// Generate a local user key if we don't have a global library id
|
|
|
|
|
if (!key && generate) {
|
|
|
|
|
key = Zotero.randomString(8);
|
|
|
|
|
var sql = "INSERT INTO settings VALUES ('account', 'localUserKey', ?)";
|
|
|
|
|
Zotero.DB.query(sql, key);
|
|
|
|
|
}
|
|
|
|
|
_localUserKey = key;
|
|
|
|
|
return key;
|
|
|
|
|
};
|
|
|
|
|
|
2009-08-08 07:38:34 +00:00
|
|
|
|
/**
|
|
|
|
|
* @property {Boolean} waiting Whether Zotero is waiting for other
|
|
|
|
|
* main thread events to be processed
|
|
|
|
|
*/
|
|
|
|
|
this.__defineGetter__('waiting', function () _waiting);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @property {Boolean} locked Whether all Zotero panes are locked
|
|
|
|
|
* with an overlay
|
|
|
|
|
*/
|
|
|
|
|
this.__defineGetter__('locked', function () _locked);
|
|
|
|
|
|
2010-03-18 07:06:38 +00:00
|
|
|
|
/**
|
|
|
|
|
* @property {Boolean} suppressUIUpdates Don't update UI on Notifier triggers
|
|
|
|
|
*/
|
|
|
|
|
this.suppressUIUpdates = false;
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var _startupErrorHandler;
|
|
|
|
|
var _zoteroDirectory = false;
|
|
|
|
|
var _localizedStringBundle;
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
var _localUserKey;
|
2009-08-08 07:38:34 +00:00
|
|
|
|
var _waiting;
|
2009-08-09 19:39:32 +00:00
|
|
|
|
|
2009-08-08 07:38:34 +00:00
|
|
|
|
var _locked;
|
2009-09-14 06:13:04 +00:00
|
|
|
|
var _unlockCallbacks = [];
|
2009-08-09 19:39:32 +00:00
|
|
|
|
var _progressMeters;
|
|
|
|
|
var _lastPercentage;
|
2006-06-15 06:13:02 +00:00
|
|
|
|
|
2006-02-21 17:01:06 +00:00
|
|
|
|
/*
|
|
|
|
|
* Initialize the extension
|
|
|
|
|
*/
|
2006-03-20 21:47:22 +00:00
|
|
|
|
function init(){
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (this.initialized || this.skipLoading) {
|
2006-05-27 00:20:27 +00:00
|
|
|
|
return false;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
}
|
2006-05-27 00:20:27 +00:00
|
|
|
|
|
2008-09-11 19:35:53 +00:00
|
|
|
|
var start = (new Date()).getTime()
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
// Register shutdown handler to call Zotero.shutdown()
|
2006-08-01 18:01:56 +00:00
|
|
|
|
var observerService = Components.classes["@mozilla.org/observer-service;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIObserverService);
|
|
|
|
|
observerService.addObserver({
|
2008-11-14 13:43:01 +00:00
|
|
|
|
observe: Zotero.shutdown
|
|
|
|
|
}, "quit-application", false);
|
2006-08-01 18:01:56 +00:00
|
|
|
|
|
2006-06-25 07:31:01 +00:00
|
|
|
|
// Load in the preferences branch for the extension
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Prefs.init();
|
2006-06-25 07:31:01 +00:00
|
|
|
|
|
2009-08-10 16:44:15 +00:00
|
|
|
|
Zotero.Debug.init();
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
2009-08-09 10:51:12 +00:00
|
|
|
|
this.mainThread = Components.classes["@mozilla.org/thread-manager;1"].getService().mainThread;
|
|
|
|
|
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
var appInfo =
|
|
|
|
|
Components.classes["@mozilla.org/xre/app-info;1"].
|
2010-07-06 09:02:35 +00:00
|
|
|
|
getService(Components.interfaces.nsIXULAppInfo);
|
|
|
|
|
this.appName = appInfo.name;
|
|
|
|
|
this.isFx3 = appInfo.platformVersion.indexOf('1.9') === 0;
|
|
|
|
|
this.isFx35 = appInfo.platformVersion.indexOf('1.9.1') === 0;
|
|
|
|
|
this.isFx31 = this.isFx35;
|
|
|
|
|
this.isFx36 = appInfo.platformVersion.indexOf('1.9.2') === 0;
|
|
|
|
|
this.isFx4 = appInfo.platformVersion[0] == 2;
|
|
|
|
|
|
2010-03-28 07:21:17 +00:00
|
|
|
|
this.isStandalone = appInfo.ID == ZOTERO_CONFIG['GUID'];
|
|
|
|
|
if(this.isStandalone) {
|
|
|
|
|
this.version = appInfo.version;
|
|
|
|
|
} else {
|
|
|
|
|
// Load in the extension version from the extension manager
|
2010-07-06 09:02:35 +00:00
|
|
|
|
if(this.isFx4) {
|
|
|
|
|
AddonManager.getAddonByID(ZOTERO_CONFIG['GUID'],
|
2010-07-06 09:25:58 +00:00
|
|
|
|
function(addon) { Zotero.version = addon.version; Zotero.addon = addon; });
|
2010-07-06 09:02:35 +00:00
|
|
|
|
} else {
|
|
|
|
|
var gExtensionManager =
|
|
|
|
|
Components.classes["@mozilla.org/extensions/manager;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIExtensionManager);
|
|
|
|
|
this.version
|
|
|
|
|
= gExtensionManager.getItemForID(ZOTERO_CONFIG['GUID']).version;
|
|
|
|
|
}
|
2010-03-28 07:21:17 +00:00
|
|
|
|
}
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
|
2006-08-30 19:18:43 +00:00
|
|
|
|
// OS platform
|
|
|
|
|
var win = Components.classes["@mozilla.org/appshell/appShellService;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIAppShellService)
|
|
|
|
|
.hiddenDOMWindow;
|
|
|
|
|
this.platform = win.navigator.platform;
|
2006-08-30 19:57:23 +00:00
|
|
|
|
this.isMac = (this.platform.substr(0, 3) == "Mac");
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.isWin = (this.platform.substr(0, 3) == "Win");
|
|
|
|
|
this.isLinux = (this.platform.substr(0, 5) == "Linux");
|
2009-09-22 20:27:26 +00:00
|
|
|
|
this.oscpu = win.navigator.oscpu;
|
2006-07-27 08:45:48 +00:00
|
|
|
|
|
2010-07-06 09:02:35 +00:00
|
|
|
|
// Installed extensions (Fx4 only)
|
|
|
|
|
if(this.isFx4) {
|
|
|
|
|
AddonManager.getAllAddons(function(addonList) {
|
|
|
|
|
Zotero.addons = addonList;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-06 07:04:02 +00:00
|
|
|
|
// Locale
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var ph = Components.classes["@mozilla.org/network/protocol;1?name=http"].
|
|
|
|
|
getService(Components.interfaces.nsIHttpProtocolHandler);
|
|
|
|
|
if (ph.language.length == 2) {
|
|
|
|
|
this.locale = ph.language + '-' + ph.language.toUpperCase();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
this.locale = ph.language;
|
|
|
|
|
}
|
2006-09-06 07:04:02 +00:00
|
|
|
|
|
2006-05-27 00:20:27 +00:00
|
|
|
|
// Load in the localization stringbundle for use by getString(name)
|
2006-10-02 23:15:27 +00:00
|
|
|
|
var src = 'chrome://zotero/locale/zotero.properties';
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var localeService = Components.classes['@mozilla.org/intl/nslocaleservice;1'].
|
|
|
|
|
getService(Components.interfaces.nsILocaleService);
|
2006-05-27 00:20:27 +00:00
|
|
|
|
var appLocale = localeService.getApplicationLocale();
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
2006-05-27 00:20:27 +00:00
|
|
|
|
var stringBundleService =
|
|
|
|
|
Components.classes["@mozilla.org/intl/stringbundle;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIStringBundleService);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
2006-05-27 00:20:27 +00:00
|
|
|
|
_localizedStringBundle = stringBundleService.createBundle(src, appLocale);
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
// Set the locale direction to Zotero.dir
|
|
|
|
|
// DEBUG: is there a better way to get the entity from JS?
|
|
|
|
|
var xmlhttp = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
|
|
|
|
.createInstance();
|
|
|
|
|
xmlhttp.open('GET', 'chrome://global/locale/global.dtd', false);
|
Merged revisions 2190-2192,2194,2196-2199,2202-2205,2209,2212,2214-2215,2227-2228,2230,2232-2243,2245,2247-2256,2263-2272,2276,2278-2279,2281,2284-2286,2292,2296-2297,2299-2302,2304-2305,2309-2310,2314,2317-2323,2325-2329,2331-2337,2339,2341-2342,2344,2347-2366,2370-2371,2373-2377,2379-2391,2393-2402,2405-2410,2413,2415-2416,2418,2420-2421,2423,2427-2429,2431-2433,2437,2440-2441,2443-2450,2453,2455-2459,2461-2467,2471,2475-2480,2482-2490,2493,2495-2499,2501-2506,2511,2513-2519,2521,2525-2536,2540,2543-2553,2555-2559,2561-2576,2578,2580-2603,2606-2609,2611-2616,2618-2620,2624-2630,2632-2633 to trunk via svnmerge from 1.0 branch
2008-05-05 07:19:34 +00:00
|
|
|
|
xmlhttp.overrideMimeType('text/plain');
|
2007-10-23 07:11:59 +00:00
|
|
|
|
xmlhttp.send(null);
|
2008-10-25 07:37:47 +00:00
|
|
|
|
var matches = xmlhttp.responseText.match(/(ltr|rtl)/);
|
|
|
|
|
if (matches && matches[0] == 'rtl') {
|
|
|
|
|
this.dir = 'rtl';
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
this.dir = 'ltr';
|
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
|
|
|
|
try {
|
2009-01-02 00:35:09 +00:00
|
|
|
|
var dataDir = this.getZoteroDirectory();
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
// Zotero dir not found
|
|
|
|
|
if (e.name == 'NS_ERROR_FILE_NOT_FOUND') {
|
2009-12-29 22:21:54 +00:00
|
|
|
|
this.startupError = Zotero.getString('dataDir.notFound');
|
2007-10-23 07:11:59 +00:00
|
|
|
|
_startupErrorHandler = function() {
|
|
|
|
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIWindowMediator);
|
|
|
|
|
var win = wm.getMostRecentWindow('navigator:browser');
|
|
|
|
|
|
|
|
|
|
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
|
|
|
|
|
createInstance(Components.interfaces.nsIPromptService);
|
|
|
|
|
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_OK)
|
|
|
|
|
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_IS_STRING)
|
|
|
|
|
+ (ps.BUTTON_POS_2) * (ps.BUTTON_TITLE_IS_STRING);
|
|
|
|
|
var index = ps.confirmEx(win,
|
|
|
|
|
Zotero.getString('general.error'),
|
2009-12-29 22:21:54 +00:00
|
|
|
|
this.startupError + '\n\n' +
|
2007-10-23 07:11:59 +00:00
|
|
|
|
Zotero.getString('dataDir.previousDir') + ' '
|
|
|
|
|
+ Zotero.Prefs.get('lastDataDir'),
|
|
|
|
|
buttonFlags, null,
|
|
|
|
|
Zotero.getString('dataDir.useProfileDir'),
|
|
|
|
|
Zotero.getString('general.locate'),
|
|
|
|
|
null, {});
|
|
|
|
|
|
|
|
|
|
// Revert to profile directory
|
|
|
|
|
if (index == 1) {
|
|
|
|
|
Zotero.chooseZoteroDirectory(false, true);
|
|
|
|
|
}
|
|
|
|
|
// Locate data directory
|
|
|
|
|
else if (index == 2) {
|
|
|
|
|
Zotero.chooseZoteroDirectory();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// DEBUG: handle more startup errors
|
|
|
|
|
else {
|
|
|
|
|
throw (e);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-16 20:11:27 +00:00
|
|
|
|
Zotero.VersionHeader.init();
|
|
|
|
|
|
2009-01-02 00:35:09 +00:00
|
|
|
|
// Check for DB restore
|
|
|
|
|
var restoreFile = dataDir.clone();
|
|
|
|
|
restoreFile.append('restore-from-server');
|
|
|
|
|
if (restoreFile.exists()) {
|
|
|
|
|
try {
|
|
|
|
|
// TODO: better error handling
|
|
|
|
|
|
|
|
|
|
// TODO: prompt for location
|
|
|
|
|
// TODO: Back up database
|
|
|
|
|
|
|
|
|
|
restoreFile.remove(false);
|
|
|
|
|
|
|
|
|
|
var dbfile = Zotero.getZoteroDatabase();
|
|
|
|
|
dbfile.remove(false);
|
|
|
|
|
|
|
|
|
|
// Recreate database with no quick start guide
|
|
|
|
|
Zotero.Schema.skipDefaultData = true;
|
|
|
|
|
Zotero.Schema.updateSchema();
|
|
|
|
|
|
|
|
|
|
this.restoreFromServer = true;
|
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
// Restore from backup?
|
|
|
|
|
alert(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
|
try {
|
|
|
|
|
Zotero.DB.test();
|
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
2009-07-23 10:52:28 +00:00
|
|
|
|
if (e.name == 'NS_ERROR_FILE_ACCESS_DENIED') {
|
|
|
|
|
var msg = Zotero.localeJoin([
|
|
|
|
|
Zotero.getString('startupError.databaseCannotBeOpened'),
|
|
|
|
|
Zotero.getString('startupError.checkPermissions')
|
|
|
|
|
]);
|
2009-12-29 22:21:54 +00:00
|
|
|
|
this.startupError = msg;
|
2009-07-23 10:52:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
Components.utils.reportError(e);
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
|
this.skipLoading = true;
|
|
|
|
|
Zotero.DB.skipBackup = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
// Add notifier queue callbacks to the DB layer
|
|
|
|
|
Zotero.DB.addCallback('begin', Zotero.Notifier.begin);
|
|
|
|
|
Zotero.DB.addCallback('commit', Zotero.Notifier.commit);
|
|
|
|
|
Zotero.DB.addCallback('rollback', Zotero.Notifier.reset);
|
|
|
|
|
|
|
|
|
|
Zotero.Fulltext.init();
|
|
|
|
|
|
2006-06-15 06:13:02 +00:00
|
|
|
|
// Trigger updating of schema and scrapers
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (Zotero.Schema.userDataUpgradeRequired()) {
|
|
|
|
|
var upgraded = Zotero.Schema.showUpgradeWizard();
|
|
|
|
|
if (!upgraded) {
|
|
|
|
|
this.skipLoading = true;
|
|
|
|
|
Zotero.DB.skipBackup = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If no userdata upgrade, still might need to process system/scrapers
|
|
|
|
|
else {
|
|
|
|
|
try {
|
2010-01-15 21:55:25 +00:00
|
|
|
|
var updated = Zotero.Schema.updateSchema();
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
if (typeof e == 'string' && e.match('newer than SQL file')) {
|
2010-07-09 05:10:48 +00:00
|
|
|
|
var kbURL = "http://zotero.org/support/kb/newer_db_version";
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var msg = Zotero.localeJoin([
|
|
|
|
|
Zotero.getString('startupError.zoteroVersionIsOlder'),
|
|
|
|
|
Zotero.getString('startupError.zoteroVersionIsOlder.upgrade')
|
|
|
|
|
]) + "\n\n"
|
2010-07-09 05:16:13 +00:00
|
|
|
|
+ Zotero.getString('startupError.zoteroVersionIsOlder.current', Zotero.version) + "\n\n"
|
2009-12-30 07:22:53 +00:00
|
|
|
|
+ Zotero.getString('general.seeForMoreInformation', kbURL);
|
2009-12-29 22:21:54 +00:00
|
|
|
|
this.startupError = msg;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
2008-08-31 23:36:01 +00:00
|
|
|
|
else {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
this.startupError = Zotero.getString('startupError.databaseUpgradeError');
|
2008-08-31 23:36:01 +00:00
|
|
|
|
}
|
2008-09-11 23:19:23 +00:00
|
|
|
|
Components.utils.reportError(e);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Zotero.DB.startDummyStatement();
|
2008-09-12 22:09:54 +00:00
|
|
|
|
Zotero.Schema.updateFromRepository();
|
2006-06-15 06:13:02 +00:00
|
|
|
|
|
2010-01-15 21:55:25 +00:00
|
|
|
|
// Populate combined tables for custom types and fields -- this is likely temporary
|
|
|
|
|
if (!upgraded && !updated) {
|
|
|
|
|
Zotero.Schema.updateCustomTables();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-06 09:02:35 +00:00
|
|
|
|
// Initialize various services
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Integration.init();
|
2010-07-06 17:39:13 +00:00
|
|
|
|
//Zotero.Connector.init();
|
2006-08-30 00:16:07 +00:00
|
|
|
|
|
2008-06-03 05:26:30 +00:00
|
|
|
|
Zotero.Zeroconf.init();
|
|
|
|
|
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
Zotero.Sync.init();
|
2008-08-31 23:36:01 +00:00
|
|
|
|
Zotero.Sync.Runner.init();
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
|
2008-09-16 19:14:52 +00:00
|
|
|
|
Zotero.MIMETypeHandler.init();
|
2008-09-11 19:35:53 +00:00
|
|
|
|
Zotero.Proxies.init();
|
|
|
|
|
|
2009-01-02 00:35:09 +00:00
|
|
|
|
// Initialize keyboard shortcuts
|
|
|
|
|
Zotero.Keys.init();
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.initialized = true;
|
2008-09-11 19:35:53 +00:00
|
|
|
|
Zotero.debug("Initialized in "+((new Date()).getTime() - start)+" ms");
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check if a DB transaction is open and, if so, disable Zotero
|
|
|
|
|
*/
|
|
|
|
|
function stateCheck() {
|
|
|
|
|
if (Zotero.DB.transactionInProgress()) {
|
|
|
|
|
this.initialized = false;
|
|
|
|
|
this.skipLoading = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2006-05-27 00:20:27 +00:00
|
|
|
|
return true;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
}
|
2006-02-21 17:01:06 +00:00
|
|
|
|
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
|
2008-11-14 13:43:01 +00:00
|
|
|
|
this.shutdown = function (subject, topic, data) {
|
|
|
|
|
Zotero.debug("Shutting down Zotero");
|
|
|
|
|
Zotero.removeTempDirectory();
|
2006-08-01 23:10:31 +00:00
|
|
|
|
return true;
|
2006-08-01 18:01:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-07-27 08:45:48 +00:00
|
|
|
|
function getProfileDirectory(){
|
|
|
|
|
return Components.classes["@mozilla.org/file/directory_service;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIProperties)
|
|
|
|
|
.get("ProfD", Components.interfaces.nsIFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Merged revisions 3080-3081,3084,3087-3088,3090,3092,3099-3103,3113-3114,3132,3134-3143,3145,3148-3151,3154-3159,3165,3174,3194,3234-3235,3239-3240,3244,3246-3254,3258-3262,3268,3270,3274,3279,3286-3288,3294-3295 from 1.0 branch via svnmerge
2008-09-01 01:54:00 +00:00
|
|
|
|
function getInstallDirectory() {
|
2010-03-28 07:21:17 +00:00
|
|
|
|
if(this.isStandalone) {
|
|
|
|
|
var dir = Components.classes["@mozilla.org/file/directory_service;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIProperties)
|
|
|
|
|
.get("CurProcD", Components.interfaces.nsILocalFile);
|
|
|
|
|
return dir;
|
|
|
|
|
} else {
|
2010-07-06 09:02:35 +00:00
|
|
|
|
if(this.isFx4) {
|
2010-07-06 10:11:25 +00:00
|
|
|
|
while(!Zotero.addon) Zotero.mainThread.processNextEvent(true);
|
2010-07-06 09:25:58 +00:00
|
|
|
|
var resourceURI = Zotero.addon.getResourceURI();
|
|
|
|
|
return resourceURI.QueryInterface(Components.interfaces.nsIFileURL).file;
|
2010-07-06 09:02:35 +00:00
|
|
|
|
} else {
|
|
|
|
|
var id = ZOTERO_CONFIG.GUID;
|
|
|
|
|
var em = Components.classes["@mozilla.org/extensions/manager;1"].
|
|
|
|
|
getService(Components.interfaces.nsIExtensionManager);
|
|
|
|
|
return em.getInstallLocation(id).getItemLocation(id);
|
|
|
|
|
}
|
2010-03-28 07:21:17 +00:00
|
|
|
|
}
|
Merged revisions 3080-3081,3084,3087-3088,3090,3092,3099-3103,3113-3114,3132,3134-3143,3145,3148-3151,3154-3159,3165,3174,3194,3234-3235,3239-3240,3244,3246-3254,3258-3262,3268,3270,3274,3279,3286-3288,3294-3295 from 1.0 branch via svnmerge
2008-09-01 01:54:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
function getZoteroDirectory(){
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (_zoteroDirectory != false) {
|
|
|
|
|
// Return a clone of the file pointer so that callers can modify it
|
|
|
|
|
return _zoteroDirectory.clone();
|
|
|
|
|
}
|
2006-07-27 08:45:48 +00:00
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (Zotero.Prefs.get('useDataDir')) {
|
|
|
|
|
var file = Components.classes["@mozilla.org/file/local;1"].
|
|
|
|
|
createInstance(Components.interfaces.nsILocalFile);
|
Merged revisions 3080-3081,3084,3087-3088,3090,3092,3099-3103,3113-3114,3132,3134-3143,3145,3148-3151,3154-3159,3165,3174,3194,3234-3235,3239-3240,3244,3246-3254,3258-3262,3268,3270,3274,3279,3286-3288,3294-3295 from 1.0 branch via svnmerge
2008-09-01 01:54:00 +00:00
|
|
|
|
try {
|
|
|
|
|
file.persistentDescriptor = Zotero.Prefs.get('dataDir');
|
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
Zotero.debug("Persistent descriptor in extensions.zotero.dataDir did not resolve", 1);
|
|
|
|
|
e = { name: "NS_ERROR_FILE_NOT_FOUND" };
|
|
|
|
|
throw (e);
|
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (!file.exists()) {
|
|
|
|
|
var e = { name: "NS_ERROR_FILE_NOT_FOUND" };
|
|
|
|
|
throw (e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var file = Zotero.getProfileDirectory();
|
|
|
|
|
file.append('zotero');
|
2008-09-11 17:20:09 +00:00
|
|
|
|
Zotero.File.createDirectoryIfMissing(file);
|
2006-07-27 08:45:48 +00:00
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
Zotero.debug("Using data directory " + file.path);
|
|
|
|
|
|
|
|
|
|
_zoteroDirectory = file;
|
2008-09-11 17:20:09 +00:00
|
|
|
|
return file.clone();
|
2006-07-27 08:45:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getStorageDirectory(){
|
2006-10-02 23:15:27 +00:00
|
|
|
|
var file = Zotero.getZoteroDirectory();
|
2006-07-27 08:45:48 +00:00
|
|
|
|
|
|
|
|
|
file.append('storage');
|
2008-09-11 17:20:09 +00:00
|
|
|
|
Zotero.File.createDirectoryIfMissing(file);
|
2006-07-27 08:45:48 +00:00
|
|
|
|
return file;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
function getZoteroDatabase(name, ext){
|
|
|
|
|
name = name ? name + '.sqlite' : 'zotero.sqlite';
|
2006-08-01 23:10:31 +00:00
|
|
|
|
ext = ext ? '.' + ext : '';
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
var file = Zotero.getZoteroDirectory();
|
2007-10-23 07:11:59 +00:00
|
|
|
|
file.append(name + ext);
|
2006-08-01 23:10:31 +00:00
|
|
|
|
return file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-08-31 23:36:01 +00:00
|
|
|
|
/**
|
|
|
|
|
* @return {nsIFile}
|
|
|
|
|
*/
|
2008-11-14 13:43:01 +00:00
|
|
|
|
this.getTempDirectory = function () {
|
2008-08-31 23:36:01 +00:00
|
|
|
|
var tmp = this.getZoteroDirectory();
|
|
|
|
|
tmp.append('tmp');
|
2008-09-11 17:20:09 +00:00
|
|
|
|
Zotero.File.createDirectoryIfMissing(tmp);
|
2008-08-31 23:36:01 +00:00
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-11-14 13:43:01 +00:00
|
|
|
|
this.removeTempDirectory = function () {
|
|
|
|
|
var tmp = this.getZoteroDirectory();
|
|
|
|
|
tmp.append('tmp');
|
|
|
|
|
if (tmp.exists()) {
|
|
|
|
|
try {
|
|
|
|
|
tmp.remove(true);
|
|
|
|
|
}
|
|
|
|
|
catch (e) {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-09-11 17:20:09 +00:00
|
|
|
|
this.getStylesDirectory = function () {
|
|
|
|
|
var dir = this.getZoteroDirectory();
|
|
|
|
|
dir.append('styles');
|
|
|
|
|
Zotero.File.createDirectoryIfMissing(dir);
|
|
|
|
|
return dir;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.getTranslatorsDirectory = function () {
|
|
|
|
|
var dir = this.getZoteroDirectory();
|
|
|
|
|
dir.append('translators');
|
|
|
|
|
Zotero.File.createDirectoryIfMissing(dir);
|
|
|
|
|
return dir;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
function chooseZoteroDirectory(forceRestartNow, useProfileDir) {
|
|
|
|
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIWindowMediator);
|
|
|
|
|
var win = wm.getMostRecentWindow('navigator:browser');
|
2006-08-01 23:10:31 +00:00
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIPromptService);
|
2006-08-01 23:10:31 +00:00
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (useProfileDir) {
|
|
|
|
|
Zotero.Prefs.set('useDataDir', false);
|
2006-08-01 23:10:31 +00:00
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
else {
|
|
|
|
|
var nsIFilePicker = Components.interfaces.nsIFilePicker;
|
|
|
|
|
while (true) {
|
|
|
|
|
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
|
|
|
|
.createInstance(nsIFilePicker);
|
|
|
|
|
fp.init(win, Zotero.getString('dataDir.selectDir'), nsIFilePicker.modeGetFolder);
|
|
|
|
|
fp.appendFilters(nsIFilePicker.filterAll);
|
|
|
|
|
if (fp.show() == nsIFilePicker.returnOK) {
|
|
|
|
|
var file = fp.file;
|
|
|
|
|
|
|
|
|
|
if (file.directoryEntries.hasMoreElements()) {
|
|
|
|
|
var dbfile = file.clone();
|
|
|
|
|
dbfile.append('zotero.sqlite');
|
2009-11-20 20:25:09 +00:00
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
// Warn if non-empty and no zotero.sqlite
|
|
|
|
|
if (!dbfile.exists()) {
|
|
|
|
|
var buttonFlags = ps.STD_YES_NO_BUTTONS;
|
|
|
|
|
var index = ps.confirmEx(win,
|
|
|
|
|
Zotero.getString('dataDir.selectedDirNonEmpty.title'),
|
|
|
|
|
Zotero.getString('dataDir.selectedDirNonEmpty.text'),
|
|
|
|
|
buttonFlags, null, null, null, null, {});
|
|
|
|
|
|
|
|
|
|
// Not OK -- return to file picker
|
|
|
|
|
if (index == 1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-11-20 20:25:09 +00:00
|
|
|
|
else {
|
|
|
|
|
var buttonFlags = ps.STD_YES_NO_BUTTONS;
|
|
|
|
|
var index = ps.confirmEx(win,
|
|
|
|
|
//Zotero.getString('dataDir.selectedDirEmpty.title'),
|
|
|
|
|
//Zotero.getString('dataDir.selectedDirEmpty.text'),
|
|
|
|
|
'Directory Empty',
|
|
|
|
|
'The directory you selected is empty. To move an existing Zotero data directory, '
|
|
|
|
|
+ 'you will need to manually copy files from the existing data directory to the new location. '
|
|
|
|
|
+ 'See http://zotero.org/support/zotero_data for more information.\n\nUse the new directory?',
|
|
|
|
|
|
|
|
|
|
buttonFlags, null, null, null, null, {});
|
|
|
|
|
|
|
|
|
|
// Not OK -- return to file picker
|
|
|
|
|
if (index == 1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
|
|
|
|
// Set new data directory
|
|
|
|
|
Zotero.Prefs.set('dataDir', file.persistentDescriptor);
|
|
|
|
|
Zotero.Prefs.set('lastDataDir', file.path);
|
|
|
|
|
Zotero.Prefs.set('useDataDir', true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-08-01 23:10:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING);
|
|
|
|
|
if (!forceRestartNow) {
|
|
|
|
|
buttonFlags += (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_IS_STRING);
|
2006-08-01 23:10:31 +00:00
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var index = ps.confirmEx(win,
|
|
|
|
|
Zotero.getString('general.restartRequired'),
|
|
|
|
|
Zotero.getString('general.restartRequiredForChange'),
|
|
|
|
|
buttonFlags,
|
|
|
|
|
Zotero.getString('general.restartNow'),
|
|
|
|
|
forceRestartNow ? null : Zotero.getString('general.restartLater'),
|
|
|
|
|
null, null, {});
|
2006-08-01 23:10:31 +00:00
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (index == 0) {
|
|
|
|
|
var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIAppStartup);
|
2010-03-12 22:05:18 +00:00
|
|
|
|
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit
|
|
|
|
|
| Components.interfaces.nsIAppStartup.eRestart);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
2006-08-01 23:10:31 +00:00
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
return useProfileDir ? true : file;
|
2006-08-01 23:10:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-07-27 08:45:48 +00:00
|
|
|
|
|
2006-02-21 17:01:06 +00:00
|
|
|
|
/*
|
|
|
|
|
* Debug logging function
|
|
|
|
|
*
|
2007-10-23 07:11:59 +00:00
|
|
|
|
* Uses prefs e.z.debug.log and e.z.debug.level (restart required)
|
2006-02-21 17:01:06 +00:00
|
|
|
|
*
|
|
|
|
|
* Defaults to log level 3 if level not provided
|
|
|
|
|
*/
|
2006-03-20 21:47:22 +00:00
|
|
|
|
function debug(message, level) {
|
2009-08-10 16:44:15 +00:00
|
|
|
|
Zotero.Debug.log(message, level);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Log a message to the Mozilla JS error console
|
|
|
|
|
*
|
|
|
|
|
* |type| is a string with one of the flag types in nsIScriptError:
|
|
|
|
|
* 'error', 'warning', 'exception', 'strict'
|
|
|
|
|
*/
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
function log(message, type, sourceName, sourceLine, lineNumber, columnNumber) {
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIConsoleService);
|
|
|
|
|
var scriptError = Components.classes["@mozilla.org/scripterror;1"]
|
|
|
|
|
.createInstance(Components.interfaces.nsIScriptError);
|
|
|
|
|
|
|
|
|
|
if (!type) {
|
|
|
|
|
type = 'warning';
|
2006-02-21 17:01:06 +00:00
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var flags = scriptError[type + 'Flag'];
|
|
|
|
|
|
|
|
|
|
scriptError.init(
|
|
|
|
|
message,
|
|
|
|
|
sourceName ? sourceName : null,
|
|
|
|
|
sourceLine != undefined ? sourceLine : null,
|
|
|
|
|
lineNumber != undefined ? lineNumber : null,
|
|
|
|
|
columnNumber != undefined ? columnNumber : null,
|
|
|
|
|
flags,
|
2010-08-24 21:08:04 +00:00
|
|
|
|
'component javascript'
|
2007-10-23 07:11:59 +00:00
|
|
|
|
);
|
|
|
|
|
consoleService.logMessage(scriptError);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getErrors(asStrings) {
|
|
|
|
|
var errors = [];
|
|
|
|
|
var cs = Components.classes["@mozilla.org/consoleservice;1"].
|
|
|
|
|
getService(Components.interfaces.nsIConsoleService);
|
|
|
|
|
var messages = {};
|
|
|
|
|
cs.getMessageArray(messages, {})
|
|
|
|
|
|
|
|
|
|
var skip = ['CSS Parser', 'content javascript'];
|
2006-02-21 17:01:06 +00:00
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
msgblock:
|
|
|
|
|
for each(var msg in messages.value) {
|
|
|
|
|
//Zotero.debug(msg);
|
|
|
|
|
try {
|
|
|
|
|
msg.QueryInterface(Components.interfaces.nsIScriptError);
|
|
|
|
|
//Zotero.debug(msg);
|
|
|
|
|
if (skip.indexOf(msg.category) != -1 || msg.flags & msg.warningFlag) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (e) { }
|
|
|
|
|
|
|
|
|
|
var blacklist = [
|
|
|
|
|
"No chrome package registered for chrome://communicator",
|
|
|
|
|
'[JavaScript Error: "Components is not defined" {file: "chrome://nightly/content/talkback/talkback.js',
|
|
|
|
|
'[JavaScript Error: "document.getElementById("sanitizeItem")',
|
|
|
|
|
'No chrome package registered for chrome://piggy-bank',
|
Merged revisions 2190-2192,2194,2196-2199,2202-2205,2209,2212,2214-2215,2227-2228,2230,2232-2243,2245,2247-2256,2263-2272,2276,2278-2279,2281,2284-2286,2292,2296-2297,2299-2302,2304-2305,2309-2310,2314,2317-2323,2325-2329,2331-2337,2339,2341-2342,2344,2347-2366,2370-2371,2373-2377,2379-2391,2393-2402,2405-2410,2413,2415-2416,2418,2420-2421,2423,2427-2429,2431-2433,2437,2440-2441,2443-2450,2453,2455-2459,2461-2467,2471,2475-2480,2482-2490,2493,2495-2499,2501-2506,2511,2513-2519,2521,2525-2536,2540,2543-2553,2555-2559,2561-2576,2578,2580-2603,2606-2609,2611-2616,2618-2620,2624-2630,2632-2633 to trunk via svnmerge from 1.0 branch
2008-05-05 07:19:34 +00:00
|
|
|
|
'[JavaScript Error: "[Exception... "\'Component is not available\' when calling method: [nsIHandlerService::getTypeFromExtension',
|
|
|
|
|
'[JavaScript Error: "this._uiElement is null',
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
'Error: a._updateVisibleText is not a function',
|
2008-10-30 20:53:47 +00:00
|
|
|
|
'[JavaScript Error: "Warning: unrecognized command line flag ',
|
2008-12-29 07:57:20 +00:00
|
|
|
|
'[JavaScript Error: "Warning: unrecognized command line flag -foreground',
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
'LibX:',
|
|
|
|
|
'function skype_',
|
2010-05-05 16:07:34 +00:00
|
|
|
|
'[JavaScript Error: "uncaught exception: Permission denied to call method Location.toString"]',
|
2010-08-06 17:52:33 +00:00
|
|
|
|
'CVE-2009-3555'
|
2007-10-23 07:11:59 +00:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
for (var i=0; i<blacklist.length; i++) {
|
|
|
|
|
if (msg.message.indexOf(blacklist[i]) != -1) {
|
Merged revisions 2190-2192,2194,2196-2199,2202-2205,2209,2212,2214-2215,2227-2228,2230,2232-2243,2245,2247-2256,2263-2272,2276,2278-2279,2281,2284-2286,2292,2296-2297,2299-2302,2304-2305,2309-2310,2314,2317-2323,2325-2329,2331-2337,2339,2341-2342,2344,2347-2366,2370-2371,2373-2377,2379-2391,2393-2402,2405-2410,2413,2415-2416,2418,2420-2421,2423,2427-2429,2431-2433,2437,2440-2441,2443-2450,2453,2455-2459,2461-2467,2471,2475-2480,2482-2490,2493,2495-2499,2501-2506,2511,2513-2519,2521,2525-2536,2540,2543-2553,2555-2559,2561-2576,2578,2580-2603,2606-2609,2611-2616,2618-2620,2624-2630,2632-2633 to trunk via svnmerge from 1.0 branch
2008-05-05 07:19:34 +00:00
|
|
|
|
//Zotero.debug("Skipping blacklisted error: " + msg.message);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
continue msgblock;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-15 09:48:27 +00:00
|
|
|
|
// Remove password in malformed XML messages
|
|
|
|
|
if (msg.category == 'malformed-xml') {
|
|
|
|
|
try {
|
|
|
|
|
// msg.message is read-only, so store separately
|
|
|
|
|
var altMessage = msg.message.replace(/(file: "https?:\/\/[^:]+:)([^@]+)(@[^"]+")/, "$1********$3");
|
|
|
|
|
}
|
|
|
|
|
catch (e) {}
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (asStrings) {
|
2008-09-15 09:48:27 +00:00
|
|
|
|
errors.push(altMessage ? altMessage : msg.message)
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
errors.push(msg);
|
|
|
|
|
}
|
2006-02-21 17:01:06 +00:00
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
return errors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getSystemInfo() {
|
|
|
|
|
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
|
|
|
|
|
getService(Components.interfaces.nsIXULAppInfo);
|
|
|
|
|
|
|
|
|
|
var info = {
|
|
|
|
|
version: Zotero.version,
|
|
|
|
|
platform: Zotero.platform,
|
2009-09-22 20:27:26 +00:00
|
|
|
|
oscpu: Zotero.oscpu,
|
2007-10-23 07:11:59 +00:00
|
|
|
|
locale: Zotero.locale,
|
|
|
|
|
appName: appInfo.name,
|
Merged revisions 3080-3081,3084,3087-3088,3090,3092,3099-3103,3113-3114,3132,3134-3143,3145,3148-3151,3154-3159,3165,3174,3194,3234-3235,3239-3240,3244,3246-3254,3258-3262,3268,3270,3274,3279,3286-3288,3294-3295 from 1.0 branch via svnmerge
2008-09-01 01:54:00 +00:00
|
|
|
|
appVersion: appInfo.version,
|
|
|
|
|
extensions: this.getInstalledExtensions().join(', ')
|
2007-10-23 07:11:59 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var str = '';
|
|
|
|
|
for (var key in info) {
|
|
|
|
|
str += key + ' => ' + info[key] + ', ';
|
2006-02-21 17:01:06 +00:00
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
str = str.substr(0, str.length - 2);
|
|
|
|
|
return str;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
}
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
|
|
|
|
|
|
Merged revisions 3080-3081,3084,3087-3088,3090,3092,3099-3103,3113-3114,3132,3134-3143,3145,3148-3151,3154-3159,3165,3174,3194,3234-3235,3239-3240,3244,3246-3254,3258-3262,3268,3270,3274,3279,3286-3288,3294-3295 from 1.0 branch via svnmerge
2008-09-01 01:54:00 +00:00
|
|
|
|
/**
|
|
|
|
|
* @return {String[]} Array of extension names and versions
|
|
|
|
|
*/
|
|
|
|
|
this.getInstalledExtensions = function () {
|
2010-07-06 09:02:35 +00:00
|
|
|
|
if(this.isFx4) {
|
2010-07-06 10:11:25 +00:00
|
|
|
|
while(!Zotero.addons) Zotero.mainThread.processNextEvent(true);
|
2010-07-06 09:02:35 +00:00
|
|
|
|
var installed = Zotero.addons;
|
|
|
|
|
} else {
|
|
|
|
|
var em = Components.classes["@mozilla.org/extensions/manager;1"].
|
|
|
|
|
getService(Components.interfaces.nsIExtensionManager);
|
|
|
|
|
var installed = em.getItemList(
|
|
|
|
|
Components.interfaces.nsIUpdateItem.TYPE_ANY, {}
|
|
|
|
|
);
|
|
|
|
|
}
|
Merged revisions 3080-3081,3084,3087-3088,3090,3092,3099-3103,3113-3114,3132,3134-3143,3145,3148-3151,3154-3159,3165,3174,3194,3234-3235,3239-3240,3244,3246-3254,3258-3262,3268,3270,3274,3279,3286-3288,3294-3295 from 1.0 branch via svnmerge
2008-09-01 01:54:00 +00:00
|
|
|
|
|
|
|
|
|
var addons = [];
|
|
|
|
|
for each(var addon in installed) {
|
|
|
|
|
switch (addon.id) {
|
|
|
|
|
case "zotero@chnm.gmu.edu":
|
|
|
|
|
case "{972ce4c6-7e08-4474-a285-3208198ce6fd}": // Default theme
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addons.push(addon.name + " (" + addon.version
|
|
|
|
|
+ (addon.type != 2 ? ", " + addon.type : "") + ")");
|
|
|
|
|
}
|
|
|
|
|
return addons;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* PHP var_dump equivalent for JS
|
|
|
|
|
*
|
|
|
|
|
* Adapted from http://binnyva.blogspot.com/2005/10/dump-function-javascript-equivalent-of.html
|
|
|
|
|
*/
|
2006-03-20 21:47:22 +00:00
|
|
|
|
function varDump(arr,level) {
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
var dumped_text = "";
|
|
|
|
|
if (!level){
|
|
|
|
|
level = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The padding given at the beginning of the line.
|
|
|
|
|
var level_padding = "";
|
|
|
|
|
for (var j=0;j<level+1;j++){
|
|
|
|
|
level_padding += " ";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeof(arr) == 'object') { // Array/Hashes/Objects
|
|
|
|
|
for (var item in arr) {
|
|
|
|
|
var value = arr[item];
|
|
|
|
|
|
|
|
|
|
if (typeof(value) == 'object') { // If it is an array,
|
|
|
|
|
dumped_text += level_padding + "'" + item + "' ...\n";
|
|
|
|
|
dumped_text += arguments.callee(value,level+1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (typeof value == 'function'){
|
|
|
|
|
dumped_text += level_padding + "'" + item + "' => function(...){...} \n";
|
|
|
|
|
}
|
2008-06-25 01:07:35 +00:00
|
|
|
|
else if (typeof value == 'number') {
|
|
|
|
|
dumped_text += level_padding + "'" + item + "' => " + value + "\n";
|
|
|
|
|
}
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
else {
|
|
|
|
|
dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { // Stings/Chars/Numbers etc.
|
|
|
|
|
dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
|
|
|
|
|
}
|
|
|
|
|
return dumped_text;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
}
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
function safeDebug(obj){
|
|
|
|
|
for (var i in obj){
|
|
|
|
|
try {
|
|
|
|
|
Zotero.debug(i + ': ' + obj[i]);
|
|
|
|
|
}
|
|
|
|
|
catch (e){
|
|
|
|
|
try {
|
|
|
|
|
Zotero.debug(i + ': ERROR');
|
|
|
|
|
}
|
|
|
|
|
catch (e){}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getString(name, params){
|
2006-06-26 20:41:09 +00:00
|
|
|
|
try {
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (params != undefined){
|
|
|
|
|
if (typeof params != 'object'){
|
|
|
|
|
params = [params];
|
|
|
|
|
}
|
|
|
|
|
var l10n = _localizedStringBundle.formatStringFromName(name, params, params.length);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var l10n = _localizedStringBundle.GetStringFromName(name);
|
|
|
|
|
}
|
2006-06-26 20:41:09 +00:00
|
|
|
|
}
|
|
|
|
|
catch (e){
|
|
|
|
|
throw ('Localized string not available for ' + name);
|
|
|
|
|
}
|
|
|
|
|
return l10n;
|
2006-05-27 00:20:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
/*
|
|
|
|
|
* Join the elements of an array into a string using the appropriate
|
|
|
|
|
* locale direction
|
|
|
|
|
*
|
|
|
|
|
* |separator| defaults to a space (not a comma like Array.join()) if
|
|
|
|
|
* not specified
|
|
|
|
|
*
|
|
|
|
|
* TODO: Substitute localized characters (e.g. Arabic comma and semicolon)
|
|
|
|
|
*/
|
|
|
|
|
function localeJoin(arr, separator) {
|
|
|
|
|
if (typeof separator == 'undefined') {
|
|
|
|
|
separator = ' ';
|
|
|
|
|
}
|
|
|
|
|
if (this.dir == 'rtl') {
|
|
|
|
|
arr.reverse();
|
|
|
|
|
separator.split('').reverse().join('');
|
|
|
|
|
}
|
|
|
|
|
return arr.join(separator);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getLocaleCollation() {
|
|
|
|
|
var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
|
|
|
|
|
.getService(Components.interfaces.nsILocaleService);
|
|
|
|
|
var collationFactory = Components.classes["@mozilla.org/intl/collation-factory;1"]
|
|
|
|
|
.getService(Components.interfaces.nsICollationFactory);
|
|
|
|
|
return collationFactory.CreateCollation(localeService.getApplicationLocale());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Sets font size based on prefs -- intended for use on root element
|
|
|
|
|
* (zotero-pane, note window, etc.)
|
|
|
|
|
*/
|
|
|
|
|
function setFontSize(rootElement) {
|
|
|
|
|
var size = Zotero.Prefs.get('fontSize');
|
|
|
|
|
rootElement.style.fontSize = size + 'em';
|
|
|
|
|
if (size <= 1) {
|
|
|
|
|
size = 'small';
|
|
|
|
|
}
|
|
|
|
|
else if (size <= 1.25) {
|
|
|
|
|
size = 'medium';
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
size = 'large';
|
|
|
|
|
}
|
|
|
|
|
// Custom attribute -- allows for additional customizations in zotero.css
|
|
|
|
|
rootElement.setAttribute('zoteroFontSize', size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
/*
|
|
|
|
|
* Flattens mixed arrays/values in a passed _arguments_ object and returns
|
|
|
|
|
* an array of values -- allows for functions to accept both arrays of
|
|
|
|
|
* values and/or an arbitrary number of individual values
|
|
|
|
|
*/
|
2006-03-20 21:47:22 +00:00
|
|
|
|
function flattenArguments(args){
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
var isArguments = args.callee && args.length;
|
|
|
|
|
|
2006-06-02 20:51:34 +00:00
|
|
|
|
// Put passed scalar values into an array
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
if (args === null || (args.constructor.name != 'Array' && !isArguments)) {
|
2006-06-02 20:51:34 +00:00
|
|
|
|
args = [args];
|
|
|
|
|
}
|
|
|
|
|
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
var returns = [];
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
for (var i=0; i<args.length; i++){
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
if (!args[i]) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (args[i].constructor.name == 'Array') {
|
|
|
|
|
for (var j=0; j<args[i].length; j++){
|
|
|
|
|
returns.push(args[i][j]);
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
returns.push(args[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return returns;
|
2006-03-20 21:47:22 +00:00
|
|
|
|
}
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
|
|
|
|
|
|
Closes #259, auto-complete of tags
Addresses #260, Add auto-complete to search window
- New XPCOM autocomplete component for Zotero data -- can be used by setting the autocompletesearch attribute of a textbox to 'zotero' and passing a search scope with the autocompletesearchparam attribute. Additional parameters can be passed by appending them to the autocompletesearchparam value with a '/', e.g. 'tag/2732' (to exclude tags that show up in item 2732)
- Tag entry now uses more or less the same interface as metadata -- no more popup window -- note that tab isn't working properly yet, and there's no way to quickly enter multiple tags (though it's now considerably quicker than it was before)
- Autocomplete for tags, excluding any tags already set for the current item
- Standalone note windows now register with the Notifier (since tags needed item modification notifications to work properly), which will help with #282, "Notes opened in separate windows need item notification"
- Tags are now retrieved in alphabetical order
- Scholar.Item.replaceTag(oldTagID, newTag), with a single notify
- Scholar.getAncestorByTagName(elem, tagName) -- walk up the DOM tree from an element until an element with the specified tag name is found (also checks with 'xul:' prefix, for use in XBL), or false if not found -- probably shouldn't be used too widely, since it's doing string comparisons, but better than specifying, say, nine '.parentNode' properties, and makes for more resilient code
A few notes:
- Autocomplete in Minefield seems to self-destruct after using it in the same field a few times, taking down saving of the field with it -- this may or may not be my fault, but it makes Zotero more or less unusable in 3.0 at the moment. Sorry. (I use 3.0 myself for development, so I'll work on it.)
- This would have been much, much easier if having an autocomplete textbox (which uses an XBL-generated popup for the suggestions) within a popup (as it is in the independent note edit panes) didn't introduce all sorts of crazy bugs that had to be defeated with annoying hackery -- one side effect of this is that at the moment you can't close the tags popup with the Escape key
- Independent note windows now need to pull in itemPane.js to function properly, which is a bit messy and not ideal, but less messy and more ideal than duplicating all the dual-state editor and tabindex logic would be
- Hitting tab in a tag field not only doesn't work but also breaks things until the next window refresh.
- There are undoubtedly other bugs.
2006-09-07 08:07:48 +00:00
|
|
|
|
function getAncestorByTagName(elem, tagName){
|
|
|
|
|
while (elem.parentNode){
|
|
|
|
|
elem = elem.parentNode;
|
2008-12-29 09:35:11 +00:00
|
|
|
|
if (elem.localName == tagName) {
|
Closes #259, auto-complete of tags
Addresses #260, Add auto-complete to search window
- New XPCOM autocomplete component for Zotero data -- can be used by setting the autocompletesearch attribute of a textbox to 'zotero' and passing a search scope with the autocompletesearchparam attribute. Additional parameters can be passed by appending them to the autocompletesearchparam value with a '/', e.g. 'tag/2732' (to exclude tags that show up in item 2732)
- Tag entry now uses more or less the same interface as metadata -- no more popup window -- note that tab isn't working properly yet, and there's no way to quickly enter multiple tags (though it's now considerably quicker than it was before)
- Autocomplete for tags, excluding any tags already set for the current item
- Standalone note windows now register with the Notifier (since tags needed item modification notifications to work properly), which will help with #282, "Notes opened in separate windows need item notification"
- Tags are now retrieved in alphabetical order
- Scholar.Item.replaceTag(oldTagID, newTag), with a single notify
- Scholar.getAncestorByTagName(elem, tagName) -- walk up the DOM tree from an element until an element with the specified tag name is found (also checks with 'xul:' prefix, for use in XBL), or false if not found -- probably shouldn't be used too widely, since it's doing string comparisons, but better than specifying, say, nine '.parentNode' properties, and makes for more resilient code
A few notes:
- Autocomplete in Minefield seems to self-destruct after using it in the same field a few times, taking down saving of the field with it -- this may or may not be my fault, but it makes Zotero more or less unusable in 3.0 at the moment. Sorry. (I use 3.0 myself for development, so I'll work on it.)
- This would have been much, much easier if having an autocomplete textbox (which uses an XBL-generated popup for the suggestions) within a popup (as it is in the independent note edit panes) didn't introduce all sorts of crazy bugs that had to be defeated with annoying hackery -- one side effect of this is that at the moment you can't close the tags popup with the Escape key
- Independent note windows now need to pull in itemPane.js to function properly, which is a bit messy and not ideal, but less messy and more ideal than duplicating all the dual-state editor and tabindex logic would be
- Hitting tab in a tag field not only doesn't work but also breaks things until the next window refresh.
- There are undoubtedly other bugs.
2006-09-07 08:07:48 +00:00
|
|
|
|
return elem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
/*
|
|
|
|
|
* A version of join() that operates externally for use on objects other
|
|
|
|
|
* than arrays (e.g. _arguments_)
|
|
|
|
|
*
|
|
|
|
|
* Note that this is safer than extending Object()
|
|
|
|
|
*/
|
2006-03-20 21:47:22 +00:00
|
|
|
|
function join(obj, delim){
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
var a = [];
|
|
|
|
|
for (var i=0, len=obj.length; i<len; i++){
|
|
|
|
|
a.push(obj[i]);
|
|
|
|
|
}
|
|
|
|
|
return a.join(delim);
|
2006-03-20 21:47:22 +00:00
|
|
|
|
}
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
|
|
|
|
|
|
2006-06-20 17:32:40 +00:00
|
|
|
|
/*
|
|
|
|
|
* PHP's in_array() for JS -- returns true if a value is contained in
|
|
|
|
|
* an array, false otherwise
|
|
|
|
|
*/
|
|
|
|
|
function inArray(needle, haystack){
|
|
|
|
|
for (var i in haystack){
|
|
|
|
|
if (haystack[i]==needle){
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* PHP's array_search() for JS -- searches an array for a value and
|
|
|
|
|
* returns the key if found, false otherwise
|
|
|
|
|
*/
|
|
|
|
|
function arraySearch(needle, haystack){
|
|
|
|
|
for (var i in haystack){
|
|
|
|
|
if (haystack[i]==needle){
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Fulltext search support
There are currently two types of fulltext searching: an SQL-based word index and a file scanner. They each have their advantages and drawbacks.
The word index is very fast to search and is currently used for the find-as-you-type quicksearch. However, indexing files takes some time, so we should probably offer a preference to turn it off ("Index attachment content for quicksearch" or something). There's also an issue with Chinese characters (which are indexed by character rather than word, since there are no spaces to go by, so a search for a word with common characters could produce erroneous results). The quicksearch doesn't use a left-bound index (since that would probably upset German speakers searching for "musik" in "nachtmusik," though I don't know for sure how they think of words) but still seems pretty fast.
* Note: There will be a potentially long delay when you start Firefox with this revision as it builds a fulltext word index of your existing items. We obviously need a notification/option for this. *
The file scanner, used in the Attachment Content condition of the search dialog, offers phrase searching as well as regex support (both case-sensitive and not, and defaulting to multiline). It doesn't require an index, though it should probably be optimized to use the word index, if available, for narrowing the results when not in regex mode. (It does only scan files that pass all the other search conditions, which speeds it up considerably for multi-condition searches, and skips non-text files unless instructed otherwise, but it's still relatively slow.)
Both convert HTML to text before searching (with the exception of the binary file scanning mode).
There are some issues with which files get indexed and which don't that we can't do much about and that will probably confuse users immensely. Dan C. suggested some sort of indicator (say, a green dot) to show which files are indexed.
Also added (very ugly) charset detection (anybody want to figure out getCharsetFromString(str)?), a setTimeout() replacement in the XPCOM service, an arrayToHash() method, and a new header to timedtextarea.xml, since it's really not copyright CHNM (it's really just a few lines off from the toolkit timed-textbox binding--I tried to change it to extend timed-textbox and just ignore Return keypress events so that we didn't need to duplicate the Mozilla code, but timed-textbox's reliance on html:input instead of html:textarea made things rather difficult).
To do:
- Pref/buttons to disable/clear/rebuild fulltext index
- Hidden prefs to set maximum file size to index/scan
- Don't index words of fewer than 3 non-Asian characters
- MRU cache for saved searches
- Use word index if available to narrow search scope of fulltext scanner
- Cache attachment info methods
- Show content excerpt in search results (at least in advanced search window, when it exists)
- Notification window (a la scraping) to show when indexing
- Indicator of indexed status
- Context menu option to index
- Indicator that a file scanning search is in progress, if possible
- Find other ways to make it index the NYT front page in under 10 seconds
- Probably fix lots of bugs, which you will likely start telling me about...now.
2006-09-21 00:10:29 +00:00
|
|
|
|
function arrayToHash(array){
|
|
|
|
|
var hash = {};
|
|
|
|
|
|
|
|
|
|
for each(var val in array){
|
|
|
|
|
hash[val] = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
/*
|
|
|
|
|
* Returns true if an object (or associative array) has at least one value
|
|
|
|
|
*/
|
|
|
|
|
function hasValues(obj) {
|
2010-04-27 08:03:08 +00:00
|
|
|
|
Zotero.debug("WARNING: Zotero.isEmpty() is deprecated! Use Zotero.Utilities.isEmpty(obj)", 2);
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
for (var i in obj) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-06-01 19:46:57 +00:00
|
|
|
|
/**
|
|
|
|
|
* Generate a random string of length 'len' (defaults to 8)
|
|
|
|
|
**/
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
function randomString(len, chars) {
|
|
|
|
|
if (!chars) {
|
|
|
|
|
chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
|
|
|
|
|
}
|
|
|
|
|
if (!len) {
|
2006-06-01 19:46:57 +00:00
|
|
|
|
len = 8;
|
|
|
|
|
}
|
|
|
|
|
var randomstring = '';
|
|
|
|
|
for (var i=0; i<len; i++) {
|
|
|
|
|
var rnum = Math.floor(Math.random() * chars.length);
|
|
|
|
|
randomstring += chars.substring(rnum,rnum+1);
|
|
|
|
|
}
|
|
|
|
|
return randomstring;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-08-01 23:10:31 +00:00
|
|
|
|
function moveToUnique(file, newFile){
|
|
|
|
|
newFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0644);
|
|
|
|
|
var newName = newFile.leafName;
|
|
|
|
|
newFile.remove(null);
|
|
|
|
|
|
|
|
|
|
// Move file to unique name
|
|
|
|
|
file.moveTo(newFile.parent, newName);
|
|
|
|
|
return file;
|
|
|
|
|
}
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
|
|
|
|
|
|
2009-08-08 07:38:34 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sleep for a given amount of time, allowing other events on main thread to be processed
|
|
|
|
|
*
|
2009-08-09 10:51:12 +00:00
|
|
|
|
* @param {Integer} ms Milliseconds to wait
|
2009-08-08 07:38:34 +00:00
|
|
|
|
*/
|
|
|
|
|
this.sleep = function (ms) {
|
2009-08-09 10:51:12 +00:00
|
|
|
|
var mainThread = Zotero.mainThread;
|
2009-08-08 07:38:34 +00:00
|
|
|
|
var endTime = Date.now() + ms;
|
|
|
|
|
do {
|
|
|
|
|
mainThread.processNextEvent(false);
|
|
|
|
|
} while (Date.now() < endTime);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Allow other events (e.g., UI updates) on main thread to be processed if necessary
|
|
|
|
|
*
|
2009-08-08 09:03:55 +00:00
|
|
|
|
* @param {Integer} [timeout=50] Maximum number of milliseconds to wait
|
2009-08-08 07:38:34 +00:00
|
|
|
|
*/
|
|
|
|
|
this.wait = function (timeout) {
|
2009-08-08 09:03:55 +00:00
|
|
|
|
if (!timeout) {
|
|
|
|
|
timeout = 50;
|
|
|
|
|
}
|
2009-08-09 10:51:12 +00:00
|
|
|
|
var mainThread = Zotero.mainThread;
|
2009-08-08 07:38:34 +00:00
|
|
|
|
var endTime = Date.now() + timeout;
|
2009-08-09 10:51:12 +00:00
|
|
|
|
var more;
|
|
|
|
|
//var cycles = 0;
|
2009-08-08 07:38:34 +00:00
|
|
|
|
|
|
|
|
|
_waiting = true;
|
|
|
|
|
|
|
|
|
|
do {
|
2009-08-09 10:51:12 +00:00
|
|
|
|
more = mainThread.processNextEvent(false);
|
|
|
|
|
//cycles++;
|
|
|
|
|
} while (more && Date.now() < endTime);
|
2009-08-08 07:38:34 +00:00
|
|
|
|
|
|
|
|
|
_waiting = false;
|
|
|
|
|
|
|
|
|
|
//Zotero.debug("Waited " + cycles + " cycles");
|
2009-08-09 10:51:12 +00:00
|
|
|
|
return;
|
2009-08-08 07:38:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Show Zotero pane overlay and progress bar in all windows
|
|
|
|
|
*
|
|
|
|
|
* @param {String} msg
|
|
|
|
|
* @param {Boolean} [determinate=false]
|
2009-08-09 19:39:32 +00:00
|
|
|
|
* @return void
|
2009-08-08 07:38:34 +00:00
|
|
|
|
*/
|
2009-08-09 19:39:32 +00:00
|
|
|
|
this.showZoteroPaneProgressMeter = function (msg, determinate) {
|
2009-08-08 07:38:34 +00:00
|
|
|
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIWindowMediator);
|
|
|
|
|
var enumerator = wm.getEnumerator("navigator:browser");
|
|
|
|
|
var progressMeters = [];
|
|
|
|
|
while (enumerator.hasMoreElements()) {
|
|
|
|
|
var win = enumerator.getNext();
|
|
|
|
|
|
|
|
|
|
win.document.getElementById('zotero-pane-progress-label').value = msg;
|
|
|
|
|
var progressMeter = win.document.getElementById('zotero-pane-progressmeter')
|
|
|
|
|
if (determinate) {
|
|
|
|
|
progressMeter.mode = 'determined';
|
|
|
|
|
progressMeter.value = 0;
|
2009-08-09 19:39:32 +00:00
|
|
|
|
progressMeter.max = 1000;
|
2009-08-08 07:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
progressMeter.mode = 'undetermined';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_showWindowZoteroPaneOverlay(win);
|
|
|
|
|
win.document.getElementById('zotero-pane-overlay-deck').selectedIndex = 0;
|
|
|
|
|
|
|
|
|
|
progressMeters.push(progressMeter);
|
|
|
|
|
}
|
|
|
|
|
_locked = true;
|
2009-08-09 19:39:32 +00:00
|
|
|
|
_progressMeters = progressMeters;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Number} percentage Percentage complete as integer or float
|
|
|
|
|
*/
|
|
|
|
|
this.updateZoteroPaneProgressMeter = function (percentage) {
|
|
|
|
|
if (percentage < 0 || percentage > 100) {
|
|
|
|
|
Zotero.debug("Invalid percentage value '" + percentage + "' in Zotero.updateZoteroPaneProgressMeter()");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
percentage = Math.round(percentage * 10);
|
|
|
|
|
if (percentage == _lastPercentage) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for each(var pm in _progressMeters) {
|
|
|
|
|
if (pm.mode == 'undetermined') {
|
|
|
|
|
pm.max = 1000;
|
|
|
|
|
pm.mode = 'determined';
|
|
|
|
|
}
|
|
|
|
|
pm.value = percentage;
|
|
|
|
|
}
|
|
|
|
|
_lastPercentage = percentage;
|
2009-08-08 07:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Hide Zotero pane overlay in all windows
|
|
|
|
|
*/
|
|
|
|
|
this.hideZoteroPaneOverlay = function () {
|
2009-09-14 06:13:04 +00:00
|
|
|
|
// Run any queued callbacks
|
|
|
|
|
if (_unlockCallbacks.length) {
|
|
|
|
|
var func;
|
|
|
|
|
while (func = _unlockCallbacks.shift()) {
|
|
|
|
|
func();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-08 07:38:34 +00:00
|
|
|
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIWindowMediator);
|
|
|
|
|
var enumerator = wm.getEnumerator("navigator:browser");
|
|
|
|
|
while (enumerator.hasMoreElements()) {
|
|
|
|
|
var win = enumerator.getNext();
|
|
|
|
|
_hideWindowZoteroPaneOverlay(win);
|
|
|
|
|
}
|
|
|
|
|
_locked = false;
|
2009-08-09 19:39:32 +00:00
|
|
|
|
_progressMeters = [];
|
|
|
|
|
_lastPercentage = null;
|
2009-08-08 07:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-09-14 06:13:04 +00:00
|
|
|
|
/**
|
|
|
|
|
* Adds a callback to be called when the Zotero pane overlay closes
|
|
|
|
|
*
|
|
|
|
|
* @param {Boolean} TRUE if added, FALSE if not locked
|
|
|
|
|
*/
|
|
|
|
|
this.addUnlockCallback = function (callback) {
|
|
|
|
|
if (!_locked) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
_unlockCallbacks.push(callback);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-08-08 07:38:34 +00:00
|
|
|
|
function _showWindowZoteroPaneOverlay(win) {
|
|
|
|
|
win.document.getElementById('zotero-collections-tree').disabled = true;
|
|
|
|
|
win.document.getElementById('zotero-items-tree').disabled = true;
|
|
|
|
|
win.document.getElementById('zotero-pane-tab-catcher-top').hidden = false;
|
|
|
|
|
win.document.getElementById('zotero-pane-tab-catcher-bottom').hidden = false;
|
|
|
|
|
win.document.getElementById('zotero-pane-overlay').hidden = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function _hideWindowZoteroPaneOverlay(win) {
|
|
|
|
|
win.document.getElementById('zotero-collections-tree').disabled = false;
|
|
|
|
|
win.document.getElementById('zotero-items-tree').disabled = false;
|
|
|
|
|
win.document.getElementById('zotero-pane-tab-catcher-top').hidden = true;
|
|
|
|
|
win.document.getElementById('zotero-pane-tab-catcher-bottom').hidden = true;
|
|
|
|
|
win.document.getElementById('zotero-pane-overlay').hidden = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-02-18 03:09:39 +00:00
|
|
|
|
/*
|
|
|
|
|
* Clear entries that no longer exist from various tables
|
|
|
|
|
*/
|
2009-04-24 06:16:19 +00:00
|
|
|
|
this.purgeDataObjects = function (skipStoragePurge) {
|
2009-02-18 03:09:39 +00:00
|
|
|
|
Zotero.Creators.purge();
|
|
|
|
|
Zotero.Tags.purge();
|
|
|
|
|
Zotero.Fulltext.purgeUnusedWords();
|
|
|
|
|
Zotero.Items.purge();
|
2010-04-27 08:03:08 +00:00
|
|
|
|
// DEBUG: this might not need to be permanent
|
|
|
|
|
Zotero.Relations.purge();
|
2009-02-18 03:09:39 +00:00
|
|
|
|
|
Zotero File Storage megacommit
- Group file sync via Zotero File Storage
- Split file syncing into separate modules for ZFS and WebDAV
- Dragging items between libraries copies child notes, snapshots/files, and links based on checkboxes for each (enabled by default) in the Zotero preferences
- Sync errors now trigger an exclamation/error icon separate from the sync icon, with a popup window displaying the error and an option to report it
- Various errors that could cause perpetual sync icon spinning now stop the sync properly
- Zotero.Utilities.md5(str) is now md5(strOrFile, base64)
- doPost(), doHead(), and retrieveSource() now takes a headers parameter instead of requestContentType
- doHead() can now accept an nsIURI (with login credentials), is a background request, and isn't cached
- When library access or file writing access is denied during sync, display a warning and then reset local group to server version
- Perform additional steps (e.g., removing local groups) when switching sync users to prevent errors
- Compare hash as well as mod time when checking for modified local files
- Don't trigger notifications when removing groups from the client
- Clear relation links to items in removed groups
- Zotero.Item.attachmentHash property to get file MD5
- importFromFile() now takes libraryID as a third parameter
- Zotero.Attachments.getNumFiles() returns the number of files in the attachment directory
- Zotero.Attachments.copyAttachmentToLibrary() copies an attachment item, including files, to another library
- Removed Zotero.File.getFileHash() in favor of updated Zotero.Utilities.md5()
- Zotero.File.copyDirectory(dir, newDir) copies all files from dir into newDir
- Preferences shuffling: OpenURL to Advanced, import/export character set options to Export, "Include URLs of paper articles in references" to Styles
- Other stuff I don't remember
Suffice it to say, this could use testing.
2009-09-13 07:23:29 +00:00
|
|
|
|
if (!skipStoragePurge && Zotero.Utilities.prototype.probability(10)) {
|
|
|
|
|
Zotero.Sync.Storage.purgeDeletedStorageFiles('zfs');
|
|
|
|
|
Zotero.Sync.Storage.purgeDeletedStorageFiles('webdav');
|
2009-02-18 03:09:39 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2.0b3 megacommit
- Support for group libraries
- General support for multiple libraries of different types
- Streamlined sync support
- Using solely libraryID and key rather than itemID, and removed all itemID-changing code
- Combined two requests for increased performance and decreased server load
- Added warning on user account change
- Provide explicit error message on SSL failure
- Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots
- Closes #786, Add numPages field
- Fixes #1063, Duplicate item with tags broken in Sync Preview
- Added better purging of deleted tags
- Added local user key before first sync
- Add clientDateModified to all objects for more flexibility in syncing
- Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries
- Updated zotero.org translator for groups
- Additional trigger-based consistency checks
- Fixed broken URL drag in Firefox 3.5
- Disabled zeroconf menu option (no longer functional)
Developer-specific changes:
- Overhauled data layer
- Data object constructors no longer take arguments (return to 1.0-like API)
- Existing objects can be retrieved by setting id or library/key properties
- id/library/key must be set for new objects before other fields
- New methods:
- ZoteroPane.getSelectedLibraryID()
- ZoteroPane.getSelectedGroup(asID)
- ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot)
- ZoteroPane.addItemFromURL(url, itemType)
- ZoteroPane.canEdit()
- Zotero.CollectionTreeView.selectLibrary(libraryID)
- New Zotero.URI methods
- Changed methods
- Many data object methods now take a libraryID
- ZoteroPane.addAttachmentFromPage(link, itemID)
- Removed saveItem and saveAttachments parameters from Zotero.Translate constructor
- translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor)
- saveAttachments is now a translate() parameter
- Zotero.flattenArguments() better handles passed objects
- Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
|
|
|
|
this.reloadDataObjects = function () {
|
2008-10-10 01:48:19 +00:00
|
|
|
|
Zotero.Tags.reloadAll();
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
Zotero.Collections.reloadAll();
|
2008-10-10 01:48:19 +00:00
|
|
|
|
Zotero.Creators.reloadAll();
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
Zotero.Items.reloadAll();
|
|
|
|
|
}
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2006-06-13 15:14:22 +00:00
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Prefs = new function(){
|
2006-06-25 07:31:01 +00:00
|
|
|
|
// Privileged methods
|
|
|
|
|
this.init = init;
|
|
|
|
|
this.get = get;
|
|
|
|
|
this.set = set;
|
|
|
|
|
|
|
|
|
|
this.register = register;
|
|
|
|
|
this.unregister = unregister;
|
|
|
|
|
this.observe = observe;
|
|
|
|
|
|
|
|
|
|
// Public properties
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.prefBranch;
|
2006-06-25 07:31:01 +00:00
|
|
|
|
|
|
|
|
|
function init(){
|
|
|
|
|
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIPrefService);
|
2006-10-02 23:15:27 +00:00
|
|
|
|
this.prefBranch = prefs.getBranch("extensions.zotero.");
|
2006-06-25 07:31:01 +00:00
|
|
|
|
|
|
|
|
|
// Register observer to handle pref changes
|
|
|
|
|
this.register();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Retrieve a preference
|
|
|
|
|
**/
|
2007-10-23 07:11:59 +00:00
|
|
|
|
function get(pref, global){
|
2006-06-25 07:31:01 +00:00
|
|
|
|
try {
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if (global) {
|
|
|
|
|
var service = Components.classes["@mozilla.org/preferences-service;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIPrefService);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var service = this.prefBranch;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-25 07:31:01 +00:00
|
|
|
|
switch (this.prefBranch.getPrefType(pref)){
|
|
|
|
|
case this.prefBranch.PREF_BOOL:
|
|
|
|
|
return this.prefBranch.getBoolPref(pref);
|
|
|
|
|
case this.prefBranch.PREF_STRING:
|
|
|
|
|
return this.prefBranch.getCharPref(pref);
|
|
|
|
|
case this.prefBranch.PREF_INT:
|
|
|
|
|
return this.prefBranch.getIntPref(pref);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (e){
|
|
|
|
|
throw ("Invalid preference '" + pref + "'");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set a preference
|
|
|
|
|
**/
|
|
|
|
|
function set(pref, value){
|
|
|
|
|
try {
|
|
|
|
|
switch (this.prefBranch.getPrefType(pref)){
|
|
|
|
|
case this.prefBranch.PREF_BOOL:
|
|
|
|
|
return this.prefBranch.setBoolPref(pref, value);
|
|
|
|
|
case this.prefBranch.PREF_STRING:
|
|
|
|
|
return this.prefBranch.setCharPref(pref, value);
|
|
|
|
|
case this.prefBranch.PREF_INT:
|
|
|
|
|
return this.prefBranch.setIntPref(pref, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (e){
|
|
|
|
|
throw ("Invalid preference '" + pref + "'");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-02-24 21:07:23 +00:00
|
|
|
|
this.clear = function (pref) {
|
|
|
|
|
try {
|
|
|
|
|
this.prefBranch.clearUserPref(pref);
|
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
throw ("Invalid preference '" + pref + "'");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-08-29 04:14:05 +00:00
|
|
|
|
// Import settings bundles
|
|
|
|
|
this.importSettings = function (str, uri) {
|
|
|
|
|
var prompt = Components.classes["@mozilla.org/network/default-prompt;1"]
|
|
|
|
|
.createInstance(Components.interfaces.nsIPrompt);
|
|
|
|
|
|
|
|
|
|
if (!uri.match(/https:\/\/([^\.]+\.)?zotero.org\//)) {
|
|
|
|
|
Zotero.debug("Ignoring settings file not from https://zotero.org");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-30 18:28:52 +00:00
|
|
|
|
str = Zotero.Utilities.prototype.trim(str.replace(/<\?xml.*\?>\s*/, ''));
|
2010-08-29 04:14:05 +00:00
|
|
|
|
Zotero.debug(str);
|
|
|
|
|
|
2010-08-30 18:28:52 +00:00
|
|
|
|
var confirm = prompt.confirm(
|
2010-08-29 04:14:05 +00:00
|
|
|
|
"",
|
|
|
|
|
"Apply settings from zotero.org?"
|
|
|
|
|
);
|
|
|
|
|
|
2010-08-30 18:28:52 +00:00
|
|
|
|
if (!confirm) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-08-29 04:14:05 +00:00
|
|
|
|
|
2010-08-30 18:28:52 +00:00
|
|
|
|
var xml = new XML(str);
|
2010-08-29 04:14:05 +00:00
|
|
|
|
|
2010-08-30 18:28:52 +00:00
|
|
|
|
var commonsEnable = xml.setting.(@id == 'commons-enable');
|
|
|
|
|
if (commonsEnable == 'true') {
|
2010-08-29 04:14:05 +00:00
|
|
|
|
Zotero.Commons.enabled = true;
|
2010-08-30 18:28:52 +00:00
|
|
|
|
Zotero.Commons.accessKey = xml.setting.(@id == 'commons-accessKey').toString();
|
|
|
|
|
Zotero.Commons.secretKey = xml.setting.(@id == 'commons-secretKey').toString();
|
2010-08-29 04:14:05 +00:00
|
|
|
|
ZoteroPane.collectionsView.refresh();
|
|
|
|
|
}
|
|
|
|
|
else if (commonsEnable == 'false') {
|
|
|
|
|
Zotero.Commons.enabled = false;
|
2010-08-30 18:38:32 +00:00
|
|
|
|
Zotero.Commons.accessKey = '';
|
2010-08-30 18:39:04 +00:00
|
|
|
|
Zotero.Commons.secretKey = '';
|
2010-08-29 04:14:05 +00:00
|
|
|
|
ZoteroPane.collectionsView.refresh();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-06-25 07:31:01 +00:00
|
|
|
|
//
|
|
|
|
|
// Methods to register a preferences observer
|
|
|
|
|
//
|
|
|
|
|
function register(){
|
|
|
|
|
this.prefBranch.QueryInterface(Components.interfaces.nsIPrefBranch2);
|
|
|
|
|
this.prefBranch.addObserver("", this, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function unregister(){
|
|
|
|
|
if (!this.prefBranch){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.prefBranch.removeObserver("", this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function observe(subject, topic, data){
|
|
|
|
|
if(topic!="nsPref:changed"){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// subject is the nsIPrefBranch we're observing (after appropriate QI)
|
|
|
|
|
// data is the name of the pref that's been changed (relative to subject)
|
|
|
|
|
switch (data){
|
2006-06-25 07:34:03 +00:00
|
|
|
|
case "automaticScraperUpdates":
|
|
|
|
|
if (this.get('automaticScraperUpdates')){
|
2008-09-12 22:09:54 +00:00
|
|
|
|
Zotero.Schema.updateFromRepository();
|
2006-06-25 07:34:03 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Schema.stopRepositoryTimer();
|
2006-06-25 07:34:03 +00:00
|
|
|
|
}
|
2006-06-25 07:31:01 +00:00
|
|
|
|
break;
|
2008-09-16 20:11:27 +00:00
|
|
|
|
|
|
|
|
|
case "zoteroDotOrgVersionHeader":
|
|
|
|
|
if (this.get("zoteroDotOrgVersionHeader")) {
|
|
|
|
|
Zotero.VersionHeader.register();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Zotero.VersionHeader.unregister();
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-19 05:26:48 +00:00
|
|
|
|
|
|
|
|
|
case "sync.autoSync":
|
|
|
|
|
if (this.get("sync.autoSync")) {
|
|
|
|
|
Zotero.Sync.Runner.IdleListener.register();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Zotero.Sync.Runner.IdleListener.unregister();
|
|
|
|
|
}
|
|
|
|
|
break;
|
2006-06-25 07:31:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
/*
|
|
|
|
|
* Handles keyboard shortcut initialization from preferences, optionally
|
|
|
|
|
* overriding existing global shortcuts
|
|
|
|
|
*
|
|
|
|
|
* Actions are configured in ZoteroPane.handleKeyPress()
|
|
|
|
|
*/
|
|
|
|
|
Zotero.Keys = new function() {
|
|
|
|
|
this.init = init;
|
|
|
|
|
this.windowInit = windowInit;
|
|
|
|
|
this.getCommand = getCommand;
|
|
|
|
|
|
Merged revisions 2640-2647,2651,2653-2654,2656-2658,2660-2667,2670-2672,2674-2677,2680,2683-2684,2687-2704,2707 to trunk via svnmerge from 1.0 branch
2008-05-16 09:14:11 +00:00
|
|
|
|
var _keys = {};
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Called by Zotero.init()
|
|
|
|
|
*/
|
|
|
|
|
function init() {
|
|
|
|
|
var actions = Zotero.Prefs.prefBranch.getChildList('keys', {}, {});
|
|
|
|
|
|
|
|
|
|
// Get the key=>command mappings from the prefs
|
|
|
|
|
for each(var action in actions) {
|
|
|
|
|
var action = action.substr(5); // strips 'keys.'
|
|
|
|
|
if (action == 'overrideGlobal') {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
_keys[Zotero.Prefs.get('keys.' + action)] = action;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Called by ZoteroPane.onLoad()
|
|
|
|
|
*/
|
|
|
|
|
function windowInit(document) {
|
|
|
|
|
var useShift = Zotero.isMac;
|
|
|
|
|
|
|
|
|
|
// Zotero pane shortcut
|
|
|
|
|
var zKey = Zotero.Prefs.get('keys.openZotero');
|
|
|
|
|
var keyElem = document.getElementById('key_openZotero');
|
|
|
|
|
// Only override the default with the pref if the <key> hasn't been manually changed
|
|
|
|
|
// and the pref has been
|
|
|
|
|
if (keyElem.getAttribute('key') == 'Z' && keyElem.getAttribute('modifiers') == 'accel alt'
|
Merged revisions 2640-2647,2651,2653-2654,2656-2658,2660-2667,2670-2672,2674-2677,2680,2683-2684,2687-2704,2707 to trunk via svnmerge from 1.0 branch
2008-05-16 09:14:11 +00:00
|
|
|
|
&& (zKey != 'Z' || useShift)) {
|
2007-10-23 07:11:59 +00:00
|
|
|
|
keyElem.setAttribute('key', zKey);
|
|
|
|
|
if (useShift) {
|
|
|
|
|
keyElem.setAttribute('modifiers', 'accel shift');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Zotero.Prefs.get('keys.overrideGlobal')) {
|
|
|
|
|
var keys = document.getElementsByTagName('key');
|
|
|
|
|
for each(var key in keys) {
|
|
|
|
|
try {
|
|
|
|
|
var id = key.getAttribute('id');
|
|
|
|
|
}
|
|
|
|
|
// A couple keys are always invalid
|
|
|
|
|
catch (e) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (id == 'key_openZotero') {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var mods = key.getAttribute('modifiers').split(/[\,\s]/);
|
|
|
|
|
var second = useShift ? 'shift' : 'alt';
|
|
|
|
|
// Key doesn't match a Zotero shortcut
|
|
|
|
|
if (mods.length != 2 || !((mods[0] == 'accel' && mods[1] == second) ||
|
|
|
|
|
(mods[0] == second && mods[1] == 'accel'))) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_keys[key.getAttribute('key')] || key.getAttribute('key') == zKey) {
|
Merged revisions 2640-2647,2651,2653-2654,2656-2658,2660-2667,2670-2672,2674-2677,2680,2683-2684,2687-2704,2707 to trunk via svnmerge from 1.0 branch
2008-05-16 09:14:11 +00:00
|
|
|
|
// Don't override Redo on Fx3 Mac, since Redo and Zotero can coexist
|
|
|
|
|
if (zKey == 'Z' && key.getAttribute('key') == 'Z'
|
|
|
|
|
&& id == 'key_redo' && Zotero.isFx3 && Zotero.isMac) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
Zotero.debug('Removing key ' + id + ' with accesskey ' + key.getAttribute('key'));
|
|
|
|
|
key.parentNode.removeChild(key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getCommand(key) {
|
|
|
|
|
return _keys[key] ? _keys[key] : false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-13 15:14:22 +00:00
|
|
|
|
|
2008-09-16 20:11:27 +00:00
|
|
|
|
/**
|
|
|
|
|
* Add X-Zotero-Version header to HTTP requests to zotero.org
|
|
|
|
|
*
|
|
|
|
|
* @namespace
|
|
|
|
|
*/
|
|
|
|
|
Zotero.VersionHeader = {
|
|
|
|
|
init: function () {
|
|
|
|
|
if (Zotero.Prefs.get("zoteroDotOrgVersionHeader")) {
|
|
|
|
|
this.register();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Called from this.init() and Zotero.Prefs.observe()
|
|
|
|
|
register: function () {
|
|
|
|
|
var observerService = Components.classes["@mozilla.org/observer-service;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIObserverService);
|
|
|
|
|
observerService.addObserver(this, "http-on-modify-request", false);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
observe: function (subject, topic, data) {
|
|
|
|
|
try {
|
|
|
|
|
var channel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
|
|
|
|
|
if (channel.URI.host.match(/zotero\.org$/)) {
|
|
|
|
|
channel.setRequestHeader("X-Zotero-Version", Zotero.version, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
Zotero.debug(e);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
unregister: function () {
|
|
|
|
|
var observerService = Components.classes["@mozilla.org/observer-service;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIObserverService);
|
|
|
|
|
observerService.removeObserver(this, "http-on-modify-request");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-06-13 15:14:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Class for creating hash arrays that behave a bit more sanely
|
|
|
|
|
*
|
|
|
|
|
* Hashes can be created in the constructor by alternating key and val:
|
|
|
|
|
*
|
2006-10-02 23:15:27 +00:00
|
|
|
|
* var hasharray = new Zotero.Hash('foo','foovalue','bar','barvalue');
|
2006-06-13 15:14:22 +00:00
|
|
|
|
*
|
|
|
|
|
* Or using hasharray.set(key, val)
|
|
|
|
|
*
|
|
|
|
|
* _val_ defaults to true if not provided
|
|
|
|
|
*
|
|
|
|
|
* If using foreach-style looping, be sure to use _for (i in arr.items)_
|
|
|
|
|
* rather than just _for (i in arr)_, or else you'll end up with the
|
|
|
|
|
* methods and members instead of the hash items
|
|
|
|
|
*
|
|
|
|
|
* Most importantly, hasharray.length will work as expected, even with
|
|
|
|
|
* non-numeric keys
|
|
|
|
|
*
|
|
|
|
|
* Adapated from http://www.mojavelinux.com/articles/javascript_hashes.html
|
|
|
|
|
* (c) Mojavelinux, Inc.
|
|
|
|
|
* License: Creative Commons
|
|
|
|
|
**/
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Hash = function(){
|
2006-06-13 15:14:22 +00:00
|
|
|
|
this.length = 0;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.items = {};
|
2006-06-13 15:14:22 +00:00
|
|
|
|
|
|
|
|
|
// Public methods defined on prototype below
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < arguments.length; i += 2) {
|
|
|
|
|
if (typeof(arguments[i + 1]) != 'undefined') {
|
|
|
|
|
this.items[arguments[i]] = arguments[i + 1];
|
|
|
|
|
this.length++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Hash.prototype.get = function(in_key){
|
2006-08-26 05:33:44 +00:00
|
|
|
|
return this.items[in_key] ? this.items[in_key] : false;
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Hash.prototype.set = function(in_key, in_value){
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
// Default to a boolean hash if value not provided
|
|
|
|
|
if (typeof(in_value) == 'undefined'){
|
|
|
|
|
in_value = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeof(this.items[in_key]) == 'undefined') {
|
|
|
|
|
this.length++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.items[in_key] = in_value;
|
|
|
|
|
|
|
|
|
|
return in_value;
|
|
|
|
|
}
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Hash.prototype.remove = function(in_key){
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
var tmp_value;
|
|
|
|
|
if (typeof(this.items[in_key]) != 'undefined') {
|
|
|
|
|
this.length--;
|
|
|
|
|
var tmp_value = this.items[in_key];
|
|
|
|
|
delete this.items[in_key];
|
2006-02-21 17:01:06 +00:00
|
|
|
|
}
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
|
|
|
|
|
return tmp_value;
|
2006-02-21 17:01:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Hash.prototype.has = function(in_key){
|
Renamed DB to scholar.sqlite, since that seems to be the current fashion
Added some new core functions:
- Scholar.varDump(), after PHP's var_dump()
- Scholar.flattenArguments(), to flatten mixed array/literal argument lists into a single array
- Scholar.join() -- a version of join() that operates externally, for use on, for example, the arguments object (safer than extending Object)
- Scholar.Hash, a slightly smarter associative array -- not perfect, but brings a proper length property and a few convenience methods (and allows for other additions) -- should probably be limited to places where the length property or other additional additions are needed, since its use is a little non-standard (e.g. you have to remember to do _for (i in arr.items)_ rather than just _for (i in arr)_, to use set(), etc.)
2006-03-14 11:45:19 +00:00
|
|
|
|
return typeof(this.items[in_key]) != 'undefined';
|
2006-06-13 14:53:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-12-02 05:45:07 +00:00
|
|
|
|
/**
|
|
|
|
|
* Singleton for common text formatting routines
|
|
|
|
|
**/
|
|
|
|
|
Zotero.Text = new function() {
|
|
|
|
|
this.titleCase = titleCase;
|
|
|
|
|
|
|
|
|
|
var skipWords = ["but", "or", "yet", "so", "for", "and", "nor", "a", "an",
|
|
|
|
|
"the", "at", "by", "from", "in", "into", "of", "on", "to", "with", "up",
|
|
|
|
|
"down", "as"];
|
|
|
|
|
// this may only match a single character
|
|
|
|
|
var delimiterRegexp = /([ \/\-–—])/;
|
|
|
|
|
|
|
|
|
|
function titleCase(string) {
|
|
|
|
|
if (!string) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// split words
|
|
|
|
|
var words = string.split(delimiterRegexp);
|
|
|
|
|
var isUpperCase = string.toUpperCase() == string;
|
|
|
|
|
|
|
|
|
|
var newString = "";
|
|
|
|
|
var delimiterOffset = words[0].length;
|
|
|
|
|
var lastWordIndex = words.length-1;
|
|
|
|
|
var previousWordIndex = -1;
|
|
|
|
|
for(var i=0; i<=lastWordIndex; i++) {
|
|
|
|
|
// only do manipulation if not a delimiter character
|
|
|
|
|
if(words[i].length != 0 && (words[i].length != 1 || !delimiterRegexp.test(words[i]))) {
|
|
|
|
|
var upperCaseVariant = words[i].toUpperCase();
|
|
|
|
|
var lowerCaseVariant = words[i].toLowerCase();
|
|
|
|
|
|
|
|
|
|
// only use if word does not already possess some capitalization
|
|
|
|
|
if(isUpperCase || words[i] == lowerCaseVariant) {
|
|
|
|
|
if(
|
|
|
|
|
// a skip word
|
|
|
|
|
skipWords.indexOf(lowerCaseVariant.replace(/[^a-zA-Z]+/, "")) != -1
|
|
|
|
|
// not first or last word
|
|
|
|
|
&& i != 0 && i != lastWordIndex
|
|
|
|
|
// does not follow a colon
|
|
|
|
|
&& (previousWordIndex == -1 || words[previousWordIndex][words[previousWordIndex].length-1] != ":")
|
|
|
|
|
) {
|
|
|
|
|
words[i] = lowerCaseVariant;
|
|
|
|
|
} else {
|
|
|
|
|
// this is not a skip word or comes after a colon;
|
|
|
|
|
// we must capitalize
|
|
|
|
|
words[i] = upperCaseVariant[0] + lowerCaseVariant.substr(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
previousWordIndex = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newString += words[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return newString;
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-06-13 14:53:38 +00:00
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Date = new function(){
|
2006-06-13 15:07:08 +00:00
|
|
|
|
this.sqlToDate = sqlToDate;
|
2006-10-04 00:47:55 +00:00
|
|
|
|
this.dateToSQL = dateToSQL;
|
2006-08-30 23:21:49 +00:00
|
|
|
|
this.strToDate = strToDate;
|
2006-08-31 00:04:11 +00:00
|
|
|
|
this.formatDate = formatDate;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.strToISO = strToISO;
|
|
|
|
|
this.strToMultipart = strToMultipart;
|
|
|
|
|
this.isMultipart = isMultipart;
|
|
|
|
|
this.multipartToSQL = multipartToSQL;
|
|
|
|
|
this.multipartToStr = multipartToStr;
|
|
|
|
|
this.isSQLDate = isSQLDate;
|
|
|
|
|
this.isSQLDateTime = isSQLDateTime;
|
|
|
|
|
this.sqlHasYear = sqlHasYear;
|
|
|
|
|
this.sqlHasMonth = sqlHasMonth;
|
|
|
|
|
this.sqlHasDay = sqlHasDay;
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
this.getUnixTimestamp = getUnixTimestamp;
|
|
|
|
|
this.toUnixTimestamp = toUnixTimestamp;
|
2006-08-01 23:10:31 +00:00
|
|
|
|
this.getFileDateString = getFileDateString;
|
|
|
|
|
this.getFileTimeString = getFileTimeString;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
this.getLocaleDateOrder = getLocaleDateOrder;
|
|
|
|
|
|
|
|
|
|
var _localeDateOrder = null;
|
|
|
|
|
|
2006-06-13 15:07:08 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert an SQL date in the form '2006-06-13 11:03:05' into a JS Date object
|
|
|
|
|
*
|
|
|
|
|
* Can also accept just the date part (e.g. '2006-06-13')
|
|
|
|
|
**/
|
2006-08-14 03:19:01 +00:00
|
|
|
|
function sqlToDate(sqldate, isUTC){
|
2006-06-13 15:07:08 +00:00
|
|
|
|
try {
|
|
|
|
|
var datetime = sqldate.split(' ');
|
|
|
|
|
var dateparts = datetime[0].split('-');
|
|
|
|
|
if (datetime[1]){
|
|
|
|
|
var timeparts = datetime[1].split(':');
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
timeparts = [false, false, false];
|
|
|
|
|
}
|
2006-08-14 03:19:01 +00:00
|
|
|
|
|
Cross-posting to BC for discussion: http://chnm.grouphub.com/projects/310105/msg/cat/2114872/3538662/comments
Changes as per my discussions with Dan:
- Separated snapshot functionality into two individual buttons, Create New Item From Current Page and Take Snapshot of Current page
- Updated schema to support primary, secondary and hidden item types (and future user customizations)
- Reorganized New Item menu, moving secondary items into sub-menu
- Removed ability to create link attachments, since it never really made much sense -- will simply use the webpage item type instead. Underlying functionality still exists for the time being, as people have existing links in their libraries--I think we're gonna have to just warn beta testers and delete them in a transition step, as converting nested links really wouldn't be worth the effort.
- Moved file link/add functions into new item menu and removed attachment drop-down
- Large, prominent View and Locate buttons in edit pane for going to an associated URL and looking up in OpenURL, respectively -- buttons gray out as appropriate
- New Item from Page stores the URL and access date (Item.save() checks for the string "CURRENT_TIMESTAMP" for accessDate and doesn't bind it as a string)
- "Website" to "Web Page" (do we prefer "Webpage"? they both look a bit funky in uppercase)
More coming.
Bugs/Known Issues:
- Since snapshots from the toolbar are now top-level in the current collection, there needs to be a way to drag them into items
- The camera icon for adding snapshots, despite being a famfamfam icon, really doesn't read too well (or perhaps just clashes with the rest of our icons). Anybody have a better one? (It also may be able to just be lightened up a bit.)
- Trying the large View/Locate buttons after discussions with Dan, but this approach may not work -- 1) a large View button for the URL makes a lot less sense when you have a parent item with a child snapshot, since people will end up clicking it all the time when they really want to view the snapshot, and 2) the Locate button is awfully big for something that only applies to certain types of items, may not get used very often when it does, and probably won't work when it is
- The access date is stored in UTC and displayed with toLocaleString() like Date Added and Date Modified, but, unlike those two, it's also user-editable. This is clearly a problem. Probably need to parse to Date on blur() with strToDate() and insert as UTC, discarding anything left over.
- Item type itself is still "website" -- should probably change that while we still can
Closes #253, OpenURL arrow should provide visual feedback on mouseover and/or look more button-like
Addresses #304, change references to "website" to "web page"
Addresses #207, openurl arrow functionality
2006-09-27 08:12:09 +00:00
|
|
|
|
// Invalid date part
|
|
|
|
|
if (dateparts.length==1){
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-14 03:19:01 +00:00
|
|
|
|
if (isUTC){
|
|
|
|
|
return new Date(Date.UTC(dateparts[0], dateparts[1]-1, dateparts[2],
|
|
|
|
|
timeparts[0], timeparts[1], timeparts[2]));
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-14 16:59:29 +00:00
|
|
|
|
return new Date(dateparts[0], dateparts[1]-1, dateparts[2],
|
2006-06-13 15:07:08 +00:00
|
|
|
|
timeparts[0], timeparts[1], timeparts[2]);
|
|
|
|
|
}
|
|
|
|
|
catch (e){
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.debug(sqldate + ' is not a valid SQL date', 2)
|
2006-06-13 15:07:08 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-08-01 23:10:31 +00:00
|
|
|
|
|
2006-10-04 00:47:55 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert a JS Date object to an SQL date in the form '2006-06-13 11:03:05'
|
|
|
|
|
*
|
|
|
|
|
* If _toUTC_ is true, creates a UTC date
|
|
|
|
|
**/
|
|
|
|
|
function dateToSQL(date, toUTC)
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
if (toUTC){
|
|
|
|
|
var year = date.getUTCFullYear();
|
|
|
|
|
var month = date.getUTCMonth();
|
|
|
|
|
var day = date.getUTCDate();
|
|
|
|
|
var hours = date.getUTCHours();
|
|
|
|
|
var minutes = date.getUTCMinutes();
|
|
|
|
|
var seconds = date.getUTCSeconds();
|
|
|
|
|
}
|
|
|
|
|
else {
|
2010-01-22 05:49:49 +00:00
|
|
|
|
return date.toLocaleFormat('%Y-%m-%d %H:%M:%S');
|
2006-10-04 00:47:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var utils = new Zotero.Utilities();
|
|
|
|
|
year = utils.lpad(year, '0', 4);
|
|
|
|
|
month = utils.lpad(month + 1, '0', 2);
|
|
|
|
|
day = utils.lpad(day, '0', 2);
|
|
|
|
|
hours = utils.lpad(hours, '0', 2);
|
|
|
|
|
minutes = utils.lpad(minutes, '0', 2);
|
|
|
|
|
seconds = utils.lpad(seconds, '0', 2);
|
|
|
|
|
|
|
|
|
|
return year + '-' + month + '-' + day + ' '
|
|
|
|
|
+ hours + ':' + minutes + ':' + seconds;
|
|
|
|
|
}
|
|
|
|
|
catch (e){
|
|
|
|
|
Zotero.debug(date + ' is not a valid JS date', 2);
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-08-31 23:36:01 +00:00
|
|
|
|
/**
|
|
|
|
|
* Convert a JS Date object to an ISO 8601 UTC date/time
|
|
|
|
|
*
|
|
|
|
|
* @param {Date} date JS Date object
|
|
|
|
|
* @return {String} ISO 8601 UTC date/time
|
|
|
|
|
* e.g. 2008-08-15T20:00:00Z
|
|
|
|
|
*/
|
|
|
|
|
this.dateToISO = function (date) {
|
|
|
|
|
var year = date.getUTCFullYear();
|
|
|
|
|
var month = date.getUTCMonth();
|
|
|
|
|
var day = date.getUTCDate();
|
|
|
|
|
var hours = date.getUTCHours();
|
|
|
|
|
var minutes = date.getUTCMinutes();
|
|
|
|
|
var seconds = date.getUTCSeconds();
|
|
|
|
|
|
|
|
|
|
var utils = new Zotero.Utilities();
|
|
|
|
|
year = utils.lpad(year, '0', 4);
|
|
|
|
|
month = utils.lpad(month + 1, '0', 2);
|
|
|
|
|
day = utils.lpad(day, '0', 2);
|
|
|
|
|
hours = utils.lpad(hours, '0', 2);
|
|
|
|
|
minutes = utils.lpad(minutes, '0', 2);
|
|
|
|
|
seconds = utils.lpad(seconds, '0', 2);
|
|
|
|
|
|
|
|
|
|
return year + '-' + month + '-' + day + 'T'
|
|
|
|
|
+ hours + ':' + minutes + ':' + seconds + 'Z';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert an ISO 8601–formatted UTC date/time to a JS Date
|
|
|
|
|
*
|
|
|
|
|
* Adapted from http://delete.me.uk/2005/03/iso8601.html (AFL-licensed)
|
|
|
|
|
*
|
|
|
|
|
* @param {String} isoDate ISO 8601 date
|
|
|
|
|
* @return {Date} JS Date
|
|
|
|
|
*/
|
|
|
|
|
this.isoToDate = function (isoDate) {
|
|
|
|
|
var re8601 = /([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?/;
|
|
|
|
|
var d = isoDate.match(re8601);
|
|
|
|
|
|
|
|
|
|
var offset = 0;
|
|
|
|
|
var date = new Date(d[1], 0, 1);
|
|
|
|
|
|
|
|
|
|
if (d[3]) { date.setMonth(d[3] - 1); }
|
|
|
|
|
if (d[5]) { date.setDate(d[5]); }
|
|
|
|
|
if (d[7]) { date.setHours(d[7]); }
|
|
|
|
|
if (d[8]) { date.setMinutes(d[8]); }
|
|
|
|
|
if (d[10]) { date.setSeconds(d[10]); }
|
|
|
|
|
if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
|
|
|
|
|
if (d[14]) {
|
|
|
|
|
offset = (Number(d[16]) * 60) + Number(d[17]);
|
|
|
|
|
offset *= ((d[15] == '-') ? 1 : -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
offset -= date.getTimezoneOffset();
|
|
|
|
|
var time = (Number(date) + (offset * 60 * 1000));
|
|
|
|
|
return new Date(time);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-08-30 23:21:49 +00:00
|
|
|
|
/*
|
|
|
|
|
* converts a string to an object containing:
|
|
|
|
|
* day: integer form of the day
|
|
|
|
|
* month: integer form of the month (indexed from 0, not 1)
|
|
|
|
|
* year: 4 digit year (or, year + BC/AD/etc.)
|
|
|
|
|
* part: anything that does not fall under any of the above categories
|
|
|
|
|
* (e.g., "Summer," etc.)
|
2007-10-23 07:11:59 +00:00
|
|
|
|
*
|
|
|
|
|
* Note: the returned object is *not* a JS Date object
|
2006-08-30 23:21:49 +00:00
|
|
|
|
*/
|
2010-07-21 19:52:28 +00:00
|
|
|
|
var _slashRe = /^(.*?)\b([0-9]{1,4})(?:([\-\/\.\u5e74])([0-9]{1,2}))?(?:([\-\/\.\u6708])([0-9]{1,4}))?((?:\b|[^0-9]).*?)$/
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var _yearRe = /^(.*?)\b((?:circa |around |about |c\.? ?)?[0-9]{1,4}(?: ?B\.? ?C\.?(?: ?E\.?)?| ?C\.? ?E\.?| ?A\.? ?D\.?)|[0-9]{3,4})\b(.*?)$/i;
|
2006-09-06 07:04:02 +00:00
|
|
|
|
var _monthRe = null;
|
|
|
|
|
var _dayRe = null;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
2006-08-30 23:21:49 +00:00
|
|
|
|
function strToDate(string) {
|
2010-01-15 21:55:25 +00:00
|
|
|
|
// Parse 'yesterday'/'today'/'tomorrow'
|
|
|
|
|
var lc = (string + '').toLowerCase();
|
|
|
|
|
if (lc == 'yesterday' || lc == Zotero.getString('date.yesterday')) {
|
|
|
|
|
string = Zotero.Date.dateToSQL(new Date(new Date().getTime() - 86400000)).substr(0, 10);
|
|
|
|
|
}
|
|
|
|
|
else if (lc == 'today' || lc == Zotero.getString('date.today')) {
|
|
|
|
|
string = Zotero.Date.dateToSQL(new Date()).substr(0, 10);
|
|
|
|
|
}
|
|
|
|
|
else if (lc == 'tomorrow' || lc == Zotero.getString('date.tomorrow')) {
|
|
|
|
|
string = Zotero.Date.dateToSQL(new Date(new Date().getTime() + 86400000)).substr(0, 10);
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-30 23:21:49 +00:00
|
|
|
|
var date = new Object();
|
|
|
|
|
|
|
|
|
|
// skip empty things
|
|
|
|
|
if(!string) {
|
|
|
|
|
return date;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-31 01:49:46 +00:00
|
|
|
|
string = string.toString().replace(/^\s+/, "").replace(/\s+$/, "").replace(/\s+/, " ");
|
2006-08-30 23:21:49 +00:00
|
|
|
|
|
2006-09-06 07:04:02 +00:00
|
|
|
|
// first, directly inspect the string
|
|
|
|
|
var m = _slashRe.exec(string);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if(m &&
|
|
|
|
|
(!m[5] || m[3] == m[5] || (m[3] == "\u5e74" && m[5] == "\u6708")) && // require sane separators
|
|
|
|
|
((m[2] && m[4] && m[6]) || (!m[1] && !m[7]))) { // require that either all parts are found,
|
|
|
|
|
// or else this is the entire date field
|
2006-09-06 07:04:02 +00:00
|
|
|
|
// figure out date based on parts
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if(m[2].length == 3 || m[2].length == 4 || m[3] == "\u5e74") {
|
2006-09-06 07:04:02 +00:00
|
|
|
|
// ISO 8601 style date (big endian)
|
2007-10-23 07:11:59 +00:00
|
|
|
|
date.year = m[2];
|
|
|
|
|
date.month = m[4];
|
|
|
|
|
date.day = m[6];
|
2006-09-06 07:04:02 +00:00
|
|
|
|
} else {
|
|
|
|
|
// local style date (middle or little endian)
|
2007-10-23 07:11:59 +00:00
|
|
|
|
date.year = m[6];
|
2006-10-02 23:15:27 +00:00
|
|
|
|
var country = Zotero.locale.substr(3);
|
2006-09-06 07:04:02 +00:00
|
|
|
|
if(country == "US" || // The United States
|
|
|
|
|
country == "FM" || // The Federated States of Micronesia
|
|
|
|
|
country == "PW" || // Palau
|
|
|
|
|
country == "PH") { // The Philippines
|
2007-10-23 07:11:59 +00:00
|
|
|
|
date.month = m[2];
|
|
|
|
|
date.day = m[4];
|
2006-09-06 07:04:02 +00:00
|
|
|
|
} else {
|
2007-10-23 07:11:59 +00:00
|
|
|
|
date.month = m[4];
|
|
|
|
|
date.day = m[2];
|
2006-09-06 07:04:02 +00:00
|
|
|
|
}
|
2006-08-30 23:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if(date.year) date.year = parseInt(date.year, 10);
|
|
|
|
|
if(date.day) date.day = parseInt(date.day, 10);
|
|
|
|
|
if(date.month) {
|
|
|
|
|
date.month = parseInt(date.month, 10);
|
|
|
|
|
|
|
|
|
|
if(date.month > 12) {
|
|
|
|
|
// swap day and month
|
|
|
|
|
var tmp = date.day;
|
|
|
|
|
date.day = date.month
|
|
|
|
|
date.month = tmp;
|
|
|
|
|
}
|
2006-09-06 07:04:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if((!date.month || date.month <= 12) && (!date.day || date.day <= 31)) {
|
|
|
|
|
if(date.year && date.year < 100) { // for two digit years, determine proper
|
|
|
|
|
// four digit year
|
2006-09-06 07:04:02 +00:00
|
|
|
|
var today = new Date();
|
|
|
|
|
var year = today.getFullYear();
|
|
|
|
|
var twoDigitYear = year % 100;
|
|
|
|
|
var century = year - twoDigitYear;
|
|
|
|
|
|
|
|
|
|
if(date.year <= twoDigitYear) {
|
|
|
|
|
// assume this date is from our century
|
|
|
|
|
date.year = century + date.year;
|
|
|
|
|
} else {
|
|
|
|
|
// assume this date is from the previous century
|
|
|
|
|
date.year = century - 100 + date.year;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
if(date.month) date.month--; // subtract one for JS style
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.debug("DATE: retrieved with algorithms: "+date.toSource());
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
|
|
|
|
date.part = m[1]+m[7];
|
|
|
|
|
} else {
|
|
|
|
|
// give up; we failed the sanity check
|
|
|
|
|
Zotero.debug("DATE: algorithms failed sanity check");
|
|
|
|
|
date = {"part":string};
|
2006-09-06 07:04:02 +00:00
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
} else {
|
|
|
|
|
Zotero.debug("DATE: could not apply algorithms");
|
|
|
|
|
date.part = string;
|
2006-08-30 23:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
// couldn't find something with the algorithms; use regexp
|
|
|
|
|
// YEAR
|
|
|
|
|
if(!date.year) {
|
|
|
|
|
var m = _yearRe.exec(date.part);
|
|
|
|
|
if(m) {
|
|
|
|
|
date.year = m[2];
|
|
|
|
|
date.part = m[1]+m[3];
|
|
|
|
|
Zotero.debug("DATE: got year ("+date.year+", "+date.part+")");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MONTH
|
|
|
|
|
if(!date.month) {
|
|
|
|
|
// compile month regular expression
|
|
|
|
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
|
Merged revisions 1986,1988-1990,1996,1998,2000-2004,2006,2008-2010,2013,2020-2028,2032-2034,2037,2039,2044-2049,2052-2056,2059,2065-2066,2068-2072,2075,2077-2079,2081,2083-2084,2086,2088-2094,2096,2099,2101,2103-2104,2107-2110,2115,2118,2120-2122,2126-2128,2131,2140,2142-2145,2149-2153,2155-2159,2165,2167-2168,2170-2171,2173-2176,2179-2183,2185-2186 via svnmerge from
https://www.zotero.org/svn/extension/branches/1.0
2008-01-30 09:53:19 +00:00
|
|
|
|
'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
2007-10-23 07:11:59 +00:00
|
|
|
|
// If using a non-English bibliography locale, try those too
|
2010-05-30 11:25:25 +00:00
|
|
|
|
if (Zotero.locale != 'en-US') {
|
|
|
|
|
months = months.concat(Zotero.Cite.getMonthStrings("short"));
|
2006-09-08 22:26:59 +00:00
|
|
|
|
}
|
2006-09-06 07:04:02 +00:00
|
|
|
|
if(!_monthRe) {
|
2007-10-23 07:11:59 +00:00
|
|
|
|
_monthRe = new RegExp("^(.*)\\b("+months.join("|")+")[^ ]*(?: (.*)$|$)", "i");
|
2006-09-06 07:04:02 +00:00
|
|
|
|
}
|
2006-08-31 00:04:11 +00:00
|
|
|
|
|
2006-09-06 07:04:02 +00:00
|
|
|
|
var m = _monthRe.exec(date.part);
|
2006-08-30 23:21:49 +00:00
|
|
|
|
if(m) {
|
2007-10-23 07:11:59 +00:00
|
|
|
|
// Modulo 12 in case we have multiple languages
|
|
|
|
|
date.month = months.indexOf(m[2][0].toUpperCase()+m[2].substr(1).toLowerCase()) % 12;
|
2006-08-30 23:21:49 +00:00
|
|
|
|
date.part = m[1]+m[3];
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.debug("DATE: got month ("+date.month+", "+date.part+")");
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DAY
|
|
|
|
|
if(!date.day) {
|
|
|
|
|
// compile day regular expression
|
|
|
|
|
if(!_dayRe) {
|
|
|
|
|
var daySuffixes = Zotero.getString("date.daySuffixes").replace(/, ?/g, "|");
|
|
|
|
|
_dayRe = new RegExp("\\b([0-9]{1,2})(?:"+daySuffixes+")?\\b(.*)", "i");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var m = _dayRe.exec(date.part);
|
|
|
|
|
if(m) {
|
|
|
|
|
var day = parseInt(m[1], 10);
|
|
|
|
|
// Sanity check
|
|
|
|
|
if (day <= 31) {
|
|
|
|
|
date.day = day;
|
2006-09-11 01:05:26 +00:00
|
|
|
|
if(m.index > 0) {
|
|
|
|
|
date.part = date.part.substr(0, m.index);
|
|
|
|
|
if(m[2]) {
|
|
|
|
|
date.part += " "+m[2];;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
date.part = m[2];
|
|
|
|
|
}
|
|
|
|
|
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.debug("DATE: got day ("+date.day+", "+date.part+")");
|
2006-08-30 23:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
// clean up date part
|
2006-08-30 23:21:49 +00:00
|
|
|
|
if(date.part) {
|
|
|
|
|
date.part = date.part.replace(/^[^A-Za-z0-9]+/, "").replace(/[^A-Za-z0-9]+$/, "");
|
2006-09-06 04:45:19 +00:00
|
|
|
|
if(!date.part.length) {
|
|
|
|
|
date.part = undefined;
|
|
|
|
|
}
|
2006-08-30 23:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return date;
|
|
|
|
|
}
|
2006-08-01 23:10:31 +00:00
|
|
|
|
|
2008-06-20 06:40:05 +00:00
|
|
|
|
/**
|
2006-08-31 00:04:11 +00:00
|
|
|
|
* does pretty formatting of a date object returned by strToDate()
|
2007-10-23 07:11:59 +00:00
|
|
|
|
*
|
2008-06-20 06:40:05 +00:00
|
|
|
|
* @param {Object} date A date object, as returned from strToDate()
|
|
|
|
|
* @param {Boolean} shortFormat Whether to return a short (12/1/95) date
|
|
|
|
|
* @return A formatted date string
|
|
|
|
|
* @type String
|
|
|
|
|
**/
|
|
|
|
|
function formatDate(date, shortFormat) {
|
|
|
|
|
if(shortFormat) {
|
|
|
|
|
var localeDateOrder = getLocaleDateOrder();
|
|
|
|
|
var string = localeDateOrder[0]+"/"+localeDateOrder[1]+"/"+localeDateOrder[2];
|
|
|
|
|
return string.replace("y", (date.year !== undefined ? date.year : "00"))
|
|
|
|
|
.replace("m", (date.month !== undefined ? 1+date.month : "0"))
|
|
|
|
|
.replace("d", (date.day !== undefined ? date.day : "0"));
|
|
|
|
|
} else {
|
|
|
|
|
var string = "";
|
|
|
|
|
|
|
|
|
|
if(date.part) {
|
|
|
|
|
string += date.part+" ";
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-30 11:25:25 +00:00
|
|
|
|
var months = Zotero.Cite.getMonthStrings("long");
|
2008-06-20 06:40:05 +00:00
|
|
|
|
if(date.month != undefined && months[date.month]) {
|
|
|
|
|
// get short month strings from CSL interpreter
|
|
|
|
|
string += months[date.month];
|
|
|
|
|
if(date.day) {
|
|
|
|
|
string += " "+date.day+", ";
|
|
|
|
|
} else {
|
|
|
|
|
string += " ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(date.year) {
|
|
|
|
|
string += date.year;
|
2006-08-31 00:04:11 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-31 23:36:01 +00:00
|
|
|
|
function strToISO(str) {
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var date = Zotero.Date.strToDate(str);
|
|
|
|
|
|
|
|
|
|
if(date.year) {
|
|
|
|
|
var dateString = Zotero.Utilities.prototype.lpad(date.year, "0", 4);
|
|
|
|
|
if(date.month) {
|
|
|
|
|
dateString += "-"+Zotero.Utilities.prototype.lpad(date.month+1, "0", 2);
|
|
|
|
|
if(date.day) {
|
|
|
|
|
dateString += "-"+Zotero.Utilities.prototype.lpad(date.day, "0", 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return dateString;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function strToMultipart(str){
|
|
|
|
|
if (!str){
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var utils = new Zotero.Utilities();
|
|
|
|
|
|
|
|
|
|
var parts = strToDate(str);
|
2009-08-09 18:24:58 +00:00
|
|
|
|
|
|
|
|
|
// FIXME: Until we have a better BCE date solution,
|
|
|
|
|
// remove year value if not between 1 and 9999
|
|
|
|
|
if (parts.year) {
|
|
|
|
|
var year = parts.year + '';
|
|
|
|
|
if (!year.match(/^[0-9]{1,4}$/)) {
|
|
|
|
|
delete parts.year;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
parts.month = typeof parts.month != "undefined" ? parts.month + 1 : '';
|
|
|
|
|
|
|
|
|
|
var multi = (parts.year ? utils.lpad(parts.year, '0', 4) : '0000') + '-'
|
|
|
|
|
+ utils.lpad(parts.month, '0', 2) + '-'
|
|
|
|
|
+ (parts.day ? utils.lpad(parts.day, '0', 2) : '00')
|
|
|
|
|
+ ' '
|
|
|
|
|
+ str;
|
|
|
|
|
return multi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Regexes for multipart and SQL dates
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
// Allow zeroes in multipart dates
|
2008-10-25 07:37:47 +00:00
|
|
|
|
// TODO: Allow negative multipart in DB and here with \-?
|
|
|
|
|
var _multipartRE = /^[0-9]{4}\-(0[0-9]|10|11|12)\-(0[0-9]|[1-2][0-9]|30|31) /;
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
var _sqldateRE = /^\-?[0-9]{4}\-(0[1-9]|10|11|12)\-(0[1-9]|[1-2][0-9]|30|31)$/;
|
2009-08-03 10:50:03 +00:00
|
|
|
|
var _sqldateWithZeroesRE = /^\-?[0-9]{4}\-(0[0-9]|10|11|12)\-(0[0-9]|[1-2][0-9]|30|31)$/;
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
var _sqldatetimeRE = /^\-?[0-9]{4}\-(0[1-9]|10|11|12)\-(0[1-9]|[1-2][0-9]|30|31) ([0-1][0-9]|[2][0-3]):([0-5][0-9]):([0-5][0-9])$/;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests if a string is a multipart date string
|
|
|
|
|
* e.g. '2006-11-03 November 3rd, 2006'
|
|
|
|
|
*/
|
|
|
|
|
function isMultipart(str){
|
2009-07-06 11:42:03 +00:00
|
|
|
|
if (isSQLDateTime(str)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
return _multipartRE.test(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the SQL part of a multipart date string
|
|
|
|
|
* (e.g. '2006-11-03 November 3rd, 2006' returns '2006-11-03')
|
|
|
|
|
*/
|
|
|
|
|
function multipartToSQL(multi){
|
|
|
|
|
if (!multi){
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isMultipart(multi)){
|
|
|
|
|
return '0000-00-00';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return multi.substr(0, 10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the user part of a multipart date string
|
|
|
|
|
* (e.g. '2006-11-03 November 3rd, 2006' returns 'November 3rd, 2006')
|
|
|
|
|
*/
|
|
|
|
|
function multipartToStr(multi){
|
|
|
|
|
if (!multi){
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isMultipart(multi)){
|
|
|
|
|
return multi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return multi.substr(11);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-08-03 10:50:03 +00:00
|
|
|
|
function isSQLDate(str, allowZeroes) {
|
|
|
|
|
if (allowZeroes) {
|
|
|
|
|
return _sqldateWithZeroesRE.test(str);
|
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
return _sqldateRE.test(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function isSQLDateTime(str){
|
|
|
|
|
return _sqldatetimeRE.test(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function sqlHasYear(sqldate){
|
2009-08-03 10:50:03 +00:00
|
|
|
|
return isSQLDate(sqldate, true) && sqldate.substr(0,4)!='0000';
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function sqlHasMonth(sqldate){
|
2009-08-03 10:50:03 +00:00
|
|
|
|
return isSQLDate(sqldate, true) && sqldate.substr(5,2)!='00';
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function sqlHasDay(sqldate){
|
2009-08-03 10:50:03 +00:00
|
|
|
|
return isSQLDate(sqldate, true) && sqldate.substr(8,2)!='00';
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Initial Zotero 1.5 Megacommit
Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog:
- Added server sync functionality (incomplete)
- Overhaul of data layer
- Split data_access.js into separate files (item.js, items.js, creator.js, etc.)
- Made creators and collections first-class objects, similar to items
- Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing
- Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes
- Better handling of unsaved objects
- Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators
- clone() now works on unsaved objects
- Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get()
- Added secondary lookup key to data objects
- Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties
- toArray() deprecated in favor of serialize(), which has a somewhat modified format
- Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer
- Added Item.diff() for comparing item metadata
- Database changes
- Added SQLite triggers to enforce foreign key constraints
- Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction
- Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction
- Properly store 64-bit integers
- Set PRAGMA locking_mode=EXCLUSIVE on database
- Set SQLite page size to 4096 on new databases
- Set SQLite page cache to 8MB
- Do some database cleanup and integrity checking on migration from 1.0 branch
- Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization
- Removed itemNoteTitles table and moved titles into itemNotes
- Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states
- Massive speed-up of item tree view
- Several fixes from 1.0 branch for Fx3 compatibility
- Added Notifier observer to log delete events for syncing
- Zotero.Utilities changes
- New methods getSQLDataType() and md5()
- Removed onError from Zotero.Utilities.HTTP.doGet()
- Don't display more than 1024 characters in doPost() debug output
- Don't display passwords in doPost() debug output
- Added Zotero.Notifier.untrigger() -- currently unused
- Added Zotero.reloadDataObjects() to reset all in-memory objects
- Added |chars| parameter to Zotero.randomString(len, chars)
- Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate)
- Adjusted zotero-service.js to simplify file inclusion
Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
|
|
|
|
function getUnixTimestamp() {
|
|
|
|
|
return Math.round(Date.now() / 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function toUnixTimestamp(date) {
|
|
|
|
|
if (date === null || typeof date != 'object' ||
|
|
|
|
|
date.constructor.name != 'Date') {
|
|
|
|
|
throw ('Not a valid date in Zotero.Date.toUnixTimestamp()');
|
|
|
|
|
}
|
|
|
|
|
return Math.round(date.getTime() / 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-02-22 10:30:01 +00:00
|
|
|
|
/**
|
|
|
|
|
* Convert a JS Date to a relative date (e.g., "5 minutes ago")
|
|
|
|
|
*
|
|
|
|
|
* Adapted from http://snipplr.com/view/10290/javascript-parse-relative-date/
|
|
|
|
|
*
|
|
|
|
|
* @param {Date} date
|
|
|
|
|
* @return {String}
|
|
|
|
|
*/
|
|
|
|
|
this.toRelativeDate = function (date) {
|
|
|
|
|
var str;
|
|
|
|
|
var now = new Date();
|
|
|
|
|
var timeSince = now.getTime() - date;
|
|
|
|
|
var inSeconds = timeSince / 1000;
|
|
|
|
|
var inMinutes = timeSince / 1000 / 60;
|
|
|
|
|
var inHours = timeSince / 1000 / 60 / 60;
|
|
|
|
|
var inDays = timeSince / 1000 / 60 / 60 / 24;
|
|
|
|
|
var inYears = timeSince / 1000 / 60 / 60 / 24 / 365;
|
|
|
|
|
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var n;
|
|
|
|
|
|
2009-02-22 10:30:01 +00:00
|
|
|
|
// in seconds
|
|
|
|
|
if (Math.round(inSeconds) == 1) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "secondsAgo";
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
else if (inMinutes < 1.01) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "secondsAgo";
|
|
|
|
|
n = Math.round(inSeconds);
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// in minutes
|
|
|
|
|
else if (Math.round(inMinutes) == 1) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "minutesAgo";
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
else if (inHours < 1.01) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "minutesAgo";
|
|
|
|
|
n = Math.round(inMinutes);
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// in hours
|
|
|
|
|
else if (Math.round(inHours) == 1) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "hoursAgo";
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
else if (inDays < 1.01) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "hoursAgo";
|
|
|
|
|
n = Math.round(inHours);
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// in days
|
|
|
|
|
else if (Math.round(inDays) == 1) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "daysAgo";
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
else if (inYears < 1.01) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "daysAgo";
|
|
|
|
|
n = Math.round(inDays);
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// in years
|
|
|
|
|
else if (Math.round(inYears) == 1) {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "yearsAgo";
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2009-12-30 07:22:53 +00:00
|
|
|
|
var key = "yearsAgo";
|
|
|
|
|
var n = Math.round(inYears);
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-12-30 07:22:53 +00:00
|
|
|
|
return Zotero.getString("date.relative." + key + "." + (n ? "multiple" : "one"), n);
|
2009-02-22 10:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-08-01 23:10:31 +00:00
|
|
|
|
function getFileDateString(file){
|
|
|
|
|
var date = new Date();
|
|
|
|
|
date.setTime(file.lastModifiedTime);
|
|
|
|
|
return date.toLocaleDateString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getFileTimeString(file){
|
|
|
|
|
var date = new Date();
|
|
|
|
|
date.setTime(file.lastModifiedTime);
|
|
|
|
|
return date.toLocaleTimeString();
|
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Figure out the date order from the output of toLocaleDateString()
|
|
|
|
|
*
|
|
|
|
|
* Returns a string with y, m, and d (e.g. 'ymd', 'mdy')
|
|
|
|
|
*/
|
|
|
|
|
function getLocaleDateOrder(){
|
|
|
|
|
if (_localeDateOrder) {
|
|
|
|
|
return _localeDateOrder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var date = new Date("October 5, 2006");
|
|
|
|
|
var parts = date.toLocaleDateString().match(/([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)/);
|
|
|
|
|
|
|
|
|
|
// The above only works on OS X and Linux,
|
|
|
|
|
// where toLocaleDateString() produces "10/05/2006"
|
|
|
|
|
if (!parts) {
|
|
|
|
|
var country = Zotero.locale.substr(3);
|
|
|
|
|
switch (country) {
|
|
|
|
|
// I don't know where this country list came from, but these
|
|
|
|
|
// are little-endian in Zotero.strToDate()
|
|
|
|
|
case 'US': // The United States
|
|
|
|
|
case 'FM': // The Federated States of Micronesia
|
|
|
|
|
case 'PW': // Palau
|
|
|
|
|
case 'PH': // The Philippines
|
|
|
|
|
return 'mdy';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return 'dmy';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (parseInt(parts[1])){
|
|
|
|
|
case 2006:
|
|
|
|
|
var order = 'y';
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
var order = 'm';
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
var order = 'd';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
switch (parseInt(parts[2])){
|
|
|
|
|
case 2006:
|
|
|
|
|
order += 'y';
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
order += 'm';
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
order += 'd';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
switch (parseInt(parts[3])){
|
|
|
|
|
case 2006:
|
|
|
|
|
order += 'y';
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
order += 'm';
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
order += 'd';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_localeDateOrder = order;
|
|
|
|
|
|
|
|
|
|
return order;
|
|
|
|
|
}
|
2006-07-27 23:01:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-30 20:18:48 +00:00
|
|
|
|
|
|
|
|
|
Zotero.DragDrop = {
|
|
|
|
|
currentDataTransfer: null,
|
|
|
|
|
|
|
|
|
|
getDragData: function (element, firstOnly) {
|
|
|
|
|
var dragData = {
|
|
|
|
|
dataType: '',
|
|
|
|
|
data: []
|
|
|
|
|
};
|
|
|
|
|
|
2010-07-09 20:10:43 +00:00
|
|
|
|
var dt = this.currentDataTransfer;
|
|
|
|
|
if (!dt) {
|
|
|
|
|
Zotero.debug("Drag data not available");
|
|
|
|
|
return false;
|
2008-11-30 20:18:48 +00:00
|
|
|
|
}
|
2010-07-09 20:10:43 +00:00
|
|
|
|
|
|
|
|
|
var len = firstOnly ? 1 : dt.mozItemCount;
|
|
|
|
|
|
|
|
|
|
if (dt.types.contains('zotero/collection')) {
|
|
|
|
|
dragData.dataType = 'zotero/collection';
|
|
|
|
|
var ids = dt.getData('zotero/collection').split(",");
|
|
|
|
|
dragData.data = ids;
|
|
|
|
|
}
|
|
|
|
|
else if (dt.types.contains('zotero/item')) {
|
|
|
|
|
dragData.dataType = 'zotero/item';
|
|
|
|
|
var ids = dt.getData('zotero/item').split(",");
|
|
|
|
|
dragData.data = ids;
|
|
|
|
|
}
|
|
|
|
|
else if (dt.types.contains('application/x-moz-file')) {
|
|
|
|
|
dragData.dataType = 'application/x-moz-file';
|
|
|
|
|
var files = [];
|
|
|
|
|
for (var i=0; i<len; i++) {
|
|
|
|
|
var file = dt.mozGetDataAt("application/x-moz-file", i);
|
|
|
|
|
file.QueryInterface(Components.interfaces.nsIFile);
|
|
|
|
|
// Don't allow folder drag
|
|
|
|
|
if (file.isDirectory()) {
|
|
|
|
|
continue;
|
2008-11-30 20:18:48 +00:00
|
|
|
|
}
|
2010-07-09 20:10:43 +00:00
|
|
|
|
files.push(file);
|
|
|
|
|
}
|
|
|
|
|
dragData.data = files;
|
|
|
|
|
}
|
|
|
|
|
else if (dt.types.contains('text/x-moz-url')) {
|
|
|
|
|
dragData.dataType = 'text/x-moz-url';
|
|
|
|
|
var urls = [];
|
|
|
|
|
for (var i=0; i<len; i++) {
|
|
|
|
|
var url = dt.getData("text/x-moz-url").split("\n")[0];
|
|
|
|
|
urls.push(url);
|
2008-11-30 20:18:48 +00:00
|
|
|
|
}
|
2010-07-09 20:10:43 +00:00
|
|
|
|
dragData.data = urls;
|
2008-11-30 20:18:48 +00:00
|
|
|
|
}
|
2010-07-09 20:10:43 +00:00
|
|
|
|
|
2008-11-30 20:18:48 +00:00
|
|
|
|
return dragData;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
/**
|
|
|
|
|
* Functions for creating and destroying hidden browser objects
|
|
|
|
|
**/
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.Browser = new function() {
|
2006-07-27 23:01:55 +00:00
|
|
|
|
this.createHiddenBrowser = createHiddenBrowser;
|
|
|
|
|
this.deleteHiddenBrowser = deleteHiddenBrowser;
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
function createHiddenBrowser(win) {
|
|
|
|
|
if (!win) {
|
|
|
|
|
var win = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
|
|
|
|
.getService(Components.interfaces.nsIWindowMediator)
|
|
|
|
|
.getMostRecentWindow("navigator:browser");
|
2006-07-27 23:01:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
Fulltext search support
There are currently two types of fulltext searching: an SQL-based word index and a file scanner. They each have their advantages and drawbacks.
The word index is very fast to search and is currently used for the find-as-you-type quicksearch. However, indexing files takes some time, so we should probably offer a preference to turn it off ("Index attachment content for quicksearch" or something). There's also an issue with Chinese characters (which are indexed by character rather than word, since there are no spaces to go by, so a search for a word with common characters could produce erroneous results). The quicksearch doesn't use a left-bound index (since that would probably upset German speakers searching for "musik" in "nachtmusik," though I don't know for sure how they think of words) but still seems pretty fast.
* Note: There will be a potentially long delay when you start Firefox with this revision as it builds a fulltext word index of your existing items. We obviously need a notification/option for this. *
The file scanner, used in the Attachment Content condition of the search dialog, offers phrase searching as well as regex support (both case-sensitive and not, and defaulting to multiline). It doesn't require an index, though it should probably be optimized to use the word index, if available, for narrowing the results when not in regex mode. (It does only scan files that pass all the other search conditions, which speeds it up considerably for multi-condition searches, and skips non-text files unless instructed otherwise, but it's still relatively slow.)
Both convert HTML to text before searching (with the exception of the binary file scanning mode).
There are some issues with which files get indexed and which don't that we can't do much about and that will probably confuse users immensely. Dan C. suggested some sort of indicator (say, a green dot) to show which files are indexed.
Also added (very ugly) charset detection (anybody want to figure out getCharsetFromString(str)?), a setTimeout() replacement in the XPCOM service, an arrayToHash() method, and a new header to timedtextarea.xml, since it's really not copyright CHNM (it's really just a few lines off from the toolkit timed-textbox binding--I tried to change it to extend timed-textbox and just ignore Return keypress events so that we didn't need to duplicate the Mozilla code, but timed-textbox's reliance on html:input instead of html:textarea made things rather difficult).
To do:
- Pref/buttons to disable/clear/rebuild fulltext index
- Hidden prefs to set maximum file size to index/scan
- Don't index words of fewer than 3 non-Asian characters
- MRU cache for saved searches
- Use word index if available to narrow search scope of fulltext scanner
- Cache attachment info methods
- Show content excerpt in search results (at least in advanced search window, when it exists)
- Notification window (a la scraping) to show when indexing
- Indicator of indexed status
- Context menu option to index
- Indicator that a file scanning search is in progress, if possible
- Find other ways to make it index the NYT front page in under 10 seconds
- Probably fix lots of bugs, which you will likely start telling me about...now.
2006-09-21 00:10:29 +00:00
|
|
|
|
// Create a hidden browser
|
2007-10-23 07:11:59 +00:00
|
|
|
|
var hiddenBrowser = win.document.createElement("browser");
|
Merged revisions 2890,2895-2896,2898,2900-2901,2905,2909-2911,2913,2916-2917,2919,2922,2936-2937,2953-2954,2957,2959,2962-2965,2969-2970,2973-2975,2979-2980,2983 via svnmerge from 1.0 branch
2008-07-07 15:18:49 +00:00
|
|
|
|
hiddenBrowser.setAttribute('type', 'content');
|
Merged revisions 2710-2712,2714-2716,2718-2728,2730-2731,2734,2736-2738,2740-2750,2752-2753,2755,2758-2768,2770-2779,2782,2789-2790,2794,2797-2802,2804,2808-2810,2812,2814-2824,2826-2832,2834-2835 via svnmerge from 1.0 branch
2008-06-11 08:55:59 +00:00
|
|
|
|
hiddenBrowser.setAttribute('disablehistory', 'true');
|
2007-10-23 07:11:59 +00:00
|
|
|
|
win.document.documentElement.appendChild(hiddenBrowser);
|
Merged revisions 3080-3081,3084,3087-3088,3090,3092,3099-3103,3113-3114,3132,3134-3143,3145,3148-3151,3154-3159,3165,3174,3194,3234-3235,3239-3240,3244,3246-3254,3258-3262,3268,3270,3274,3279,3286-3288,3294-3295 from 1.0 branch via svnmerge
2008-09-01 01:54:00 +00:00
|
|
|
|
// Disable some features
|
|
|
|
|
hiddenBrowser.docShell.allowImages = false;
|
|
|
|
|
hiddenBrowser.docShell.allowJavascript = false;
|
|
|
|
|
hiddenBrowser.docShell.allowMetaRedirects = false;
|
|
|
|
|
hiddenBrowser.docShell.allowPlugins = false;
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.debug("created hidden browser ("
|
2009-08-09 08:31:21 +00:00
|
|
|
|
+ (win.document.getElementsByTagName('browser').length - 1) + ")");
|
2007-10-23 07:11:59 +00:00
|
|
|
|
return hiddenBrowser;
|
2006-07-27 23:01:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-10-23 07:11:59 +00:00
|
|
|
|
function deleteHiddenBrowser(myBrowser) {
|
|
|
|
|
myBrowser.stop();
|
2006-07-27 23:01:55 +00:00
|
|
|
|
myBrowser.parentNode.removeChild(myBrowser);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
myBrowser = null;
|
2006-10-02 23:15:27 +00:00
|
|
|
|
Zotero.debug("deleted hidden browser");
|
2006-07-27 23:01:55 +00:00
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Functions for disabling and enabling the unresponsive script indicator
|
|
|
|
|
**/
|
|
|
|
|
Zotero.UnresponsiveScriptIndicator = new function() {
|
|
|
|
|
this.disable = disable;
|
|
|
|
|
this.enable = enable;
|
|
|
|
|
|
|
|
|
|
// stores the state of the unresponsive script preference prior to disabling
|
|
|
|
|
var _unresponsiveScriptPreference, _isDisabled;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* disables the "unresponsive script" warning; necessary for import and
|
|
|
|
|
* export, which can take quite a while to execute
|
|
|
|
|
**/
|
|
|
|
|
function disable() {
|
|
|
|
|
// don't do anything if already disabled
|
2009-02-18 03:09:39 +00:00
|
|
|
|
if (_isDisabled) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
|
|
|
|
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
|
|
|
|
|
getService(Components.interfaces.nsIPrefBranch);
|
|
|
|
|
_unresponsiveScriptPreference = prefService.getIntPref("dom.max_chrome_script_run_time");
|
|
|
|
|
prefService.setIntPref("dom.max_chrome_script_run_time", 0);
|
|
|
|
|
|
|
|
|
|
_isDisabled = true;
|
2009-02-18 03:09:39 +00:00
|
|
|
|
return true;
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* restores the "unresponsive script" warning
|
|
|
|
|
**/
|
|
|
|
|
function enable() {
|
|
|
|
|
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
|
|
|
|
|
getService(Components.interfaces.nsIPrefBranch);
|
|
|
|
|
prefService.setIntPref("dom.max_chrome_script_run_time", _unresponsiveScriptPreference);
|
|
|
|
|
|
|
|
|
|
_isDisabled = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Implements nsIWebProgressListener
|
|
|
|
|
*/
|
|
|
|
|
Zotero.WebProgressFinishListener = function(onFinish) {
|
|
|
|
|
this.onStateChange = function(wp, req, stateFlags, status) {
|
|
|
|
|
//Zotero.debug('onStageChange: ' + stateFlags);
|
|
|
|
|
if ((stateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
|
|
|
|
|
&& (stateFlags & Components.interfaces.nsIWebProgressListener.STATE_IS_NETWORK)) {
|
|
|
|
|
onFinish();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.onProgressChange = function(wp, req, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) {
|
|
|
|
|
//Zotero.debug('onProgressChange');
|
|
|
|
|
//Zotero.debug('Current: ' + curTotalProgress);
|
|
|
|
|
//Zotero.debug('Max: ' + maxTotalProgress);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.onLocationChange = function(wp, req, location) {}
|
|
|
|
|
this.onSecurityChange = function(wp, req, stateFlags, status) {}
|
|
|
|
|
this.onStatusChange = function(wp, req, status, msg) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2010-06-05 17:49:04 +00:00
|
|
|
|
* Saves or loads JSON objects.
|
2007-10-23 07:11:59 +00:00
|
|
|
|
*/
|
|
|
|
|
Zotero.JSON = new function() {
|
2010-06-05 17:49:04 +00:00
|
|
|
|
var nativeJSON = Components.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
|
2010-06-05 17:49:04 +00:00
|
|
|
|
this.serialize = function(arg) {
|
|
|
|
|
return nativeJSON.encode(arg);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-06-05 17:49:04 +00:00
|
|
|
|
this.unserialize = function(arg) {
|
|
|
|
|
return nativeJSON.decode(arg);
|
2007-10-23 07:11:59 +00:00
|
|
|
|
}
|
2006-06-06 19:53:27 +00:00
|
|
|
|
}
|