Commit 3a78bf63 authored by Marco Mariani's avatar Marco Mariani

docs: included built files

parent 01ed23c5
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = /home/marco/src/jio/docs/bin/sphinx-build
PAPER =
BUILDDIR = /home/marco/src/jio/docs/sphinx/build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) /home/marco/src/jio/docs/sphinx/source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) /home/marco/src/jio/docs/sphinx/source
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " warnings-html to make standalone HTML files (warnings become errors)"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
warnings-html:
$(SPHINXBUILD) -W -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sphinx.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sphinx.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/sphinx"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sphinx"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 62b07e3d7bc79b55e5f695bf9afeac10
tags: fbb0d17656682115ca4d033fb2f83ba1
Authors
=======
* Francois Billioud
* Tristan Cavelier
* Sven Franck
.. role:: js(code)
:language: javascript
.. _list-of-available-storages:
List of Available Storages
==========================
JIO saves his job queue in a workspace which is localStorage by default.
Provided storage descriptions are also stored, and it can be dangerous to
store passwords.
The best way to create a storage description is to use the (often) provided
tool given by the storage library. The returned description is secured to avoid
clear readable password. (encrypted password for instance)
When building storage trees, there is no limit on the number of storages you
can use. The only thing you have to be aware of is compatability of simple and
revision based storages.
Connectors
----------
LocalStorage
^^^^^^^^^^^^
Three methods are provided:
* :js:`createDescription(username, [application_name], [mode="localStorage"])`
* :js:`createLocalDescription(username, [application_name])`
* :js:`createMemoryDescription(username, [application_name])`
All parameters are strings.
Examples:
.. code-block:: javascript
// to work on browser localStorage
var jio = jIO.createJIO(local_storage.createDescription("me"));
// to work on browser memory
var jio = jIO.createJIO(local_storage.createMemoryDescription("me"));
DavStorage
^^^^^^^^^^
The tool dav_storage.createDescription generates a dav storage description for
*no*, *basic* or *digest* authentication (*digest* is not implemented yet).
.. code-block:: javascript
dav_storage.createDescription(url, auth_type, [realm], [username], [password]);
All parameters are strings.
.. XXX simplify here
Only ``url`` and ``auth_type`` are required. If ``auth_type`` is equal to "none",
then ``realm``, ``username`` and ``password`` are useless. ``username`` and ``password`` become
required if ``auth_type`` is equal to "basic". And ``realm`` also becomes required if
``auth_type`` is equal to "digest".
digest **is not implemented yet**
**Be careful**: The generated description never contains readable password, but
for basic authentication, the password will just be base64 encoded.
S3Storage
^^^^^^^^^
Updating to v2.0
XWikiStorage
^^^^^^^^^^^^
Updating to v2.0
Handlers
--------
IndexStorage
^^^^^^^^^^^^
This handler indexes documents metadata into a database (which is a simple
document) to increase the speed of allDocs requests. However, it is not able to
manage the ``include_docs`` option.
The sub storages have to manage ``query`` and ``include_docs`` options.
Here is the description:
.. code-block:: javascript
{
"type": "index",
"indices": [{
"id": "index_title_subject.json", // doc id where to store indices
"index": ["title", "subject"], // metadata to index
"attachment": "db.json", // default "body"
"metadata": { // additional metadata to add to database, default undefined
"type": "Dataset",
"format": "application/json",
"title": "My index database",
"creator": "Me"
},
"sub_storage": <sub storage where to store index>
// default equal to parent sub_storage field
}, {
"id": "index_year.json",
"index": "year"
...
}],
"sub_storage": <sub storage description>
}
GIDStorage
^^^^^^^^^^
:ref:`Full description here <gid-storage>`.
Updating to v2.0
SplitStorage
^^^^^^^^^^^^
Updating to v2.0
Replicate Storage
^^^^^^^^^^^^^^^^^
Comming soon
Revision Based Handlers
-----------------------
A revision based handler is a storage which is able to do some document
versioning using simple storages listed above.
On JIO command parameter, ``_id`` is still used to identify a document, but
another id ``_rev`` must be defined to use a specific revision of this document.
On command responses, you will find another field ``rev`` which will represent the
new revision produced by your action. All the document history is kept unless
you decide to delete older revisions.
Other fields ``conflicts``, ``revisions`` and ``revs_info`` can be returned if the
options **conflicts: true**, **revs: true** or **revs_info: true** are set.
Revision Storage
^^^^^^^^^^^^^^^^
Updating to v2.0
Replicate Revision Storage
^^^^^^^^^^^^^^^^^^^^^^^^^^
Updating to v2.0
This diff is collapsed.
For developers
==============
Quick start
-----------
To get started with jIO, clone one of the repositories linked in :ref:`Download & Fork <download-fork>`.
To build the library you have to:
* Install `NodeJS <http://nodejs.org/>`_ (including NPM)
* Install Grunt command line with npm.
``# npm -g install grunt-cli``
* Install dev dependencies.
``$ npm install``
* Compile JS/CC parser.
``$ make`` (until we find how to compile it with grunt)
* Run build.
``$ grunt``
The repository also includes the built ready-to-use files, so in case you do
not want to build jIO yourself, just use *jio.js* as well as *complex_queries.js*
plus the storages and dependencies you need and you will be good to go.
Naming Conventions
------------------
All the code follows these :ref:`JavaScript Naming Conventions <naming-conventions>`.
How to design your own jIO Storage Library
------------------------------------------
Create a constructor:
.. code-block:: javascript
function MyStorage(storage_description) {
this._value = storage_description.value;
if (typeof this._value !== 'string') {
throw new TypeError("'value' description property is not a string");
}
}
Create 10 methods: ``post``, ``put``, ``putAttachment``, ``get``, ``getAttachment``,
``remove``, ``removeAttachment``, ``allDocs``, ``check`` and ``repair``.
.. code-block:: javascript
MyStorage.prototype.post = function (command, metadata, option) {
var document_id = metadata._id;
// [...]
};
MyStorage.prototype.get = function (command, param, option) {
var document_id = param._id;
// [...]
};
MyStorage.prototype.putAttachment = function (command, param, option) {
var document_id = param._id;
var attachment_id = param._attachment;
var attachment_data = param._blob;
// [...]
};
// [...]
(To help you design your methods, some tools are provided by jIO.util.)
The first parameter command provides some methods to act on the JIO job:
* ``success``, to tell JIO that the job is successfully terminated
``command.success(status[Text], [{custom key to add to the response}]);``
* ``resolve``, is equal to success
* ``error``, to tell JIO that the job cannot be done
``command.error(status[Text], [reason], [message], [{custom key to add to the response}])``
* ``retry``, to tell JIO that the job cannot be done now, but can be retried later. (same API than error)
* ``reject``, to tell JIO that the job cannot be done, let JIO to decide whether to retry or not. (same API than error)
The second parameter ``metadata`` or ``param`` is the first parameter provided by the JIO user.
The third parameter ``option`` is the option parameter provided by the JIO user.
Methods should return the following objects:
* post --> success("created", {"id": new_generated_id})
* put, remove, putAttachment or removeAttachment --> success(204)
* get --> success("ok", {"data": document_metadata})
* getAttachment -->
success("ok", {"data": binary_string, "content_type": content_type})
// or
success("ok", {"data": new Blob([data], {"type": content_type})})
* allDocs --> success("ok", {"data": row_object})
* check -->
.. code-block:: javascript
// if metadata provides "_id" -> check document state
// if metadata doesn't promides "_id" -> check storage state
success("no_content")
// or
error("conflict", "corrupted", "incoherent document or storage")
* repair -->
.. code-block:: javascript
// if metadata provides "_id" -> repair document state
// if metadata doesn't promides "_id" -> repair storage state
success("no_content")
// or
error("conflict", "corrupted", "impossible to repair document or storage")
// DON'T DESIGN STORAGES IF THEIR IS NO WAY TO REPAIR INCOHERENT STATES
After creating all methods, your storage must be added to jIO. This is done
with the ``jIO.addStorage()`` method, which requires two parameters: the storage
type (string) and a constructor (function). It is called like this:
.. code-block:: javascript
// add custom storage to jIO
jIO.addStorage('mystoragetype', MyStorage);
Please refer to *localstorage.js* implementation for a good example on how to
setup a storage and what methods are required.
Also keep in mind that jIO is a job-based library: whenever you trigger a method,
a job is created, which will later return a response, after being processed.
Job rules
---------
The jIO job manager follows several rules set at the creation of a new jIO
instance. When you try to call a method, jIO will create a job and will make
sure the job is really necessary and will be executed. Thanks to these job
rules, jIO knows what to do with the new job before adding it to the queue. You
can also add your own rules, as we're going to see now.
These are the jIO **default rules**:
.. code-block:: javascript
var jio_instance = jIO.createJIO(storage_description, {
"job_rules": [{
"code_name": "readers update",
"conditions": [
"sameStorageDescription",
"areReaders",
"sameMethod",
"sameParameters",
"sameOptions"
],
"action": "update"
}, {
"code_name": "metadata writers update",
"conditions": [
"sameStorageDescription",
"areWriters",
"useMetadataOnly",
"sameMethod",
"haveDocumentIds",
"sameParameters"
],
"action": "update"
}, {
"code_name": "writers wait",
"conditions": [
"sameStorageDescription",
"areWriters",
"haveDocumentIds",
"sameDocumentId"
],
"action": "wait"
}]
});
The following actions can be used:
* ``ok`` - accept the job
* ``wait`` - wait until the end of the selected job
* ``update`` - bind the selected job to this one
* ``deny`` - reject the job
The following condition function can be used:
* ``sameStorageDescription`` - check if the storage descriptions are different.
* ``areWriters`` - check if the commands are ``post``, ``put``, ``putAttachment``, ``remove``, ``removeAttachment``, or ``repair``.
* ``areReaders`` - check if the commands are ``get``, ``getAttachment``, ``allDocs`` or ``check``.
* ``useMetadataOnly`` - check if the commands are ``post``, ``put``, ``get``, ``remove`` or ``allDocs``.
* ``sameMethod`` - check if the commands are equal.
* ``sameDocumentId`` - check if the document ids are equal.
* ``sameParameters`` - check if the metadata or param are equal (deep comparison).
* ``sameOptions`` - check if the command options are equal.
* ``haveDocumentIds`` - test if the two commands contain document ids.
Create Job Condition
--------------------
You can create two types of function: job condition, and job comparison.
.. code-block:: javascript
// Job Condition
// Check if the job is a get command
jIO.addJobRuleCondition("isGetMethod", function (job) {
return job.method === 'get';
});
// Job Comparison
// Check if the jobs have the same 'title' property only if they are strings
jIO.addJobRuleCondition("sameTitleIfString", function (job, selected_job) {
if (typeof job.kwargs.title === 'string' &&
typeof selected_job.kwargs.title === 'string') {
return job.kwargs.title === selected_job.kwargs.title;
}
return false;
});
Add job rules
-------------
You just have to define job rules in the jIO options:
.. code-block:: javascript
// Do not accept to post or put a document which title is equal to another
// already running post or put document title
var jio_instance = jIO.createJIO(storage_description, {
"job_rules": [{
"code_name": "avoid similar title",
"conditions": [
"sameStorageDescription",
"areWriters",
"sameTitleIfString"
],
"action": "deny",
"before": "writers update" // optional
// "after": also exists
}]
});
Clear/Replace default job rules
-------------------------------
If a job's ``code_name`` is equal to ``readers update``, then adding this rule will replace it:
.. code-block:: javascript
var jio_instance = jIO.createJIO(storage_description, {
"job_rules": [{
"code_name": "readers update",
"conditions": [
"sameStorageDescription",
"areReaders",
"sameMethod",
"haveDocumentIds"
"sameParameters"
// sameOptions is removed
],
"action": "update"
}]
});
Or you can just clear all rules before adding new ones:
.. code-block:: javascript
var jio_instance = jIO.createJIO(storage_description, {
"clear_job_rules": true,
"job_rules": [{
// ...
}]
});
.. _download-fork:
Downloads
=========
Core:
* `[sha256.amd.js] <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/sha256.amd.js>`_
* `[rsvp-custom.js] <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/lib/rsvp/rsvp-custom.js>`_, AMD only version [`rsvp-custom.amd.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/lib/rsvp/rsvp-custom.amd.js>`_]
* jIO, `[jio.js] <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/jio.js>`_
* complex_queries, `[complex_queries.js] <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/complex_queries.js>`_
Storage dependencies:
* `jQuery <http://jquery.com/>`_, `[jquery.js] <http://code.jquery.com/jquery.js>`_
* `sjcl <https://crypto.stanford.edu/sjcl/>`_, `[sjcl.zip] <https://crypto.stanford.edu/sjcl/sjcl.zip>`_
* `sha1 <http://pajhome.org.uk/crypt/md5/sha1.html>`_, `[sha1.js] <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/lib/jsSha1/sha1.js>`_, AMD compatible version [`sha1.amd.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/sha1.amd.js>`_]
* `sha2, sha256 <http://anmar.eu.org/projects/jssha2/>`_, `[jssha2.zip] <http://anmar.eu.org/projects/jssha2/files/jssha2-0.3.zip>`_, AMD compatible versions `[sha2.amd.js] <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/sha2.amd.js>`_ `[sha256.amd.js] <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/sha256.amd.js>`_
Storage connectors:
* `localstorage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/localstorage.js>`_
* `davstorage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/davstorage.js>`_
* `s3storage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/s3storage.js>`_ (depends on sha1, jQuery) (WIP)
* `xwikistorage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/xwikistorage.js>`_ (depends on jQuery) (WIP)
* `erp5storage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/erp5storage.js>`_ (depends on jQuery) (WIP)
* restsqlstorage.js (depends on jQuery) (WIP)
* mioga2storage.js (depends on jQuery) (WIP)
Storage handlers:
* `indexstorage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/indexstorage.js>`_ (WIP)
* `gidstorage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/gidstorage.js>`_ (WIP)
* `splitstorage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/splitstorage.js>`_ (WIP)
* replicatestorage.js (WIP)
Revision based storage handlers:
* `revisionstorage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/revisionstorage.js>`_ (depends on sha256) (WIP)
* `replicaterevisionstorage.js <http://git.erp5.org/gitweb/jio.git/blob_plain/refs/heads/master:/src/jio.storage/replicatestorage.js>`_ (WIP)
Minified version
----------------
.. XXX this sounds harsh. Can we provide it or at least be more explicit?
To get the minified version of the jIO library, you have to build it yourself. See documentation.
Fork
----
jIO source code
=============================================== ============================================= ========================================== =======================================
Clone (read only) Git Erp5 Gitorious Github
``git clone http://git.erp5.org/repos/jio.git`` `View <http://git.erp5.org/gitweb/jio.git>`_ `View <https://gitorious.org/nexedi/jio>`_ `View <https://github.com/nexedi/jio>`_
=============================================== ============================================= ========================================== =======================================
.. _gid-storage:
JIO GIDStorage
==============
A storage to enable interoperability between all kind of storages.
A global ID (GID) is a document id which represents a unique document. This ID
will be used to find this unique document on all kind of backends.
This storage uses sub storage allDocs and complex queries to find unique documents, and converts their ids to gids.
Where it can be used
--------------------
When you want to duplicate / synchronize / split / edit data in different kind of storages (ERP5 + XWiki + Dav + ...).
Storage Description
-------------------
* ``type`` - ``"gid"``
* ``sub_storage`` - the sub storage description.
* ``constraints`` - the constraints to use to generate a gid by defining metadata types for some kind of document.
Example:
.. code-block:: javascript
{
"type": "gid",
"sub_storage": {<storage description>},
"constraints": {
"default": { // constraints for all kind of documents
// "document metadata": "type of metadata"
"type": "list"
"title": "string"
},
"Text": { // document of type 'Text' additional constraints
"language": "string"
}
}
}
This description tells the *GIDStorage* to use 2 metadata (``type``, ``title``) to define a
document as unique in the default case. If the document is of type ``Text``, then
the handler will use 3 metadata (``type``, ``title``, ``language``).
If these constraints are not respected, then the storage returns an error telling us to
review the document metadata. Here are samples of document respecting the above
constraints:
.. code-block:: javascript
{
"type": "Text",
"title": "Hello World!",
"language": "en"
}
{
"type": ["Text", "Web Page"],
"title": "My Web Page Title",
"language": "en-US",
"format": "text/html"
}
{
"type": "Image",
"title": "My Image Title"
}
Available metadata types are:
* ``"json"`` - The json value of the metadata.
* ``"string"`` - The value as string if it is not a list.
* ``"list"`` - The value as list.
* ``"date"`` - The value if it can be converted to a date (as string).
* ``"DCMIType"`` - A value matching one of the DCMIType Vocabulary (as string).
* ``"contentType"`` - A value which is a content type (as string).
* ``["DCMIType", "list"]`` - The value which contains a DCMIType (as list).
* ``[...]`` - make your own combination.
Document Requirements
---------------------
A metadata value must be a string. This string can be placed in an object which
key is 'content'. The object can contains custom keys with string values. A
metadata can contain several values. Example:
.. code-block:: javascript
{
"key": "value",
// or
"key": ["value1", "value2"],
// or
"key": {"attribute name": "attribute value", "content": "value"},
// or
"key": [
{"scheme": "DCTERMS.URI", "content": "http://foo.com/bar"},
"value2",
"value3",
...
],
...
}
Metadata which name begin with an underscore can contain anything.
.. code-block:: javascript
{
"_key": {"whatever": ["blue", []], "a": null}
}
Storage Requirements
--------------------
* This storage is not compatible with *RevisionStorage* and *ReplicateRevisionStorage*.
* Sub storage have to support complex queries options and ``include_docs`` option.
Dependencies
------------
No dependency.
Suggested storage tree
----------------------
Replication Between Storage::
Replicate Storage
+-- GID Storage
| `-- Local Storage
+-- GID Storage
| `-- Remote Storage 1
`-- GID Storage
`-- Remote Storage 2
**CAUTION: All gid storage must have the same description!**
Offline Application Usage::
Replicate Storage
+-- Index Storage with DB in Local Storage
| `-- GID Storage
| `-- ERP5 Storage
`-- GID Storage
`-- Local Storage
**CAUTION: All gid storage must have the same description!**
.. JIO documentation master file, created by
sphinx-quickstart on Fri Nov 15 11:55:08 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to JIO's documentation!
===============================
Contents:
.. toctree::
:maxdepth: 2
introduction
download
manage_documents
revision_storages
available_storages
gid_storage
complex_queries
metadata
developers
naming_conventions
authors
license
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. role:: js(code)
:language: javascript
Introduction
============
What is jIO?
------------
JIO is a JavaScript library that allows to manage JSON documents on local or
remote storages in asynchronous fashion. jIO is an abstracted API mapped after
CouchDB, that offers connectors to multiple storages, special handlers to
enhance functionality (replication, revisions, indexing) and a query module to
retrieve documents and specific information across storage trees.
How does it work?
-----------------
.. XXX three parts?
JIO is separated into three parts - jIO core and storage library(ies). The core
is using storage libraries (connectors) to interact with the associated remote
storage servers. Some queries can be used on top of the jIO allDocs method to
query documents based on defined criteria.
JIO uses a job management system, so every method called adds a job into a
queue. The queue is copied in the browser's local storage (by default), so it
can be restored in case of a browser crash. Jobs are being invoked
asynchronously with ongoing jobs not being able to re-trigger to prevent
conflicts.
Getting started
---------------
This walkthrough is designed to get you started using a basic jIO instance.
#. Download jIO core, the storages you want to use as well as the
complex-queries scripts as well as the dependencies required for the storages
you intend to use. :ref:`[Download & Fork] <download-fork>`
#. Add the scripts to your HTML page in the following order:
.. code-block:: html
<!-- jio core + dependency -->
<script src="sha256.amd.js"></script>
<script src="rsvp-custom.js"></script>
<script src="jio.js"></script>
<!-- storages + dependencies -->
<script src="complex_queries.js"></script>
<script src="localstorage.js"></script>
<script src="davstorage.js"></script>
<script ...>
With require js, the main.js will be like this:
.. code-block:: javascript
:linenos:
require.config({
"paths": {
// jio core + dependency
// the AMD compatible version of sha256.js -> see Download and Fork
"sha256": "sha256.amd",
"rsvp": "rsvp-custom",
"jio": "jio",
// storages + dependencies
"complex_queries": "complex_queries",
"localstorage": "localstorage",
"davstorage": "davstorage"
}
});
#. jIO connects to a number of storages and allows to add handlers (or
functions) to specifc storages.
You can use both handlers and available storages to build a storage
tree across which all documents will be maintained and managed by jIO.
See :ref:`List of Available Storages <list-of-available-storages>`.
.. code-block:: javascript
// create your jio instance
var my_jio = jIO.createJIO(storage_description);
.. XXX 6 methods or 10?
#. The jIO API provides six main methods to manage documents across the storage(s) specified in your jIO storage tree.
================== ===================================================== ========================================
Method Sample Call Description
================== ===================================================== ========================================
`post` :js:`my_jio.post(document, [options]);` Creates a new document
`put` :js:`my_jio.put(document, [options]);` Creates/Updates a document
`putAttachment` :js:`my_jio.putAttachement(attachment, [options]);` Updates/Adds an attachment to a document
`get` :js:`my_jio.get(document, [options]);` Reads a document
`getAttachment` :js:`my_jio.getAttachment(attachment, [options]);` Reads a document attachment
`remove` :js:`my_jio.remove(document, [options]);` Deletes a document and its attachments
`removeAttachment` :js:`my_jio.removeAttachment(attachment, [options]);` Deletes a document attachment
`allDocs` :js:`my_jio.allDocs([options]);` Retrieves a list of existing documents
`check` :js:`my_jio.check(document, [options]);` Check the document state
`repair` :js:`my_jio.repair(document, [options]);` Repair the document
================== ===================================================== ========================================
Copyright and license
=====================
jIO is an open-source library and is licensed under the LGPL license. More
information on LGPL can be found `here <http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License>`_
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Revision Storages: Conflicts and Resolution
===========================================
Why Conflicts can Occur
-----------------------
Using jIO you can store documents in multiple storage locations. With
increasing number of users working on a document and some storages not being
available or responding too slow, conflicts are more likely to occur. JIO
defines a conflict as multiple versions of a document existing in a storage
tree and a user trying to save on a version that does not match the latest
version of the document.
To keep track of document versions a revision storage must be used. When doing
so, jIO creates a document tree file for every document. This file contains all
existing versions and their status and is modified whenever a version is
added/updated/removed or when storages are being synchronized.
How to solve conflicts
----------------------
Using the document tree, jIO tries to make every version of a document
available on every storage. When multiple versions of a document exist, jIO
will select the **latest**, **left-most** version on the document tree, along with the
conflicting versions (when option **conflicts: true** is set in order for
developers to setup a routine to solve conflicts.
Technically a conflict is solved by deleting alternative versions of a document
("cutting leaves off from the document tree"). When a user decides to keep a
version of a document and manually deletes all conflicting versions, the
storage tree is updated accordingly and the document is available in a single
version on all storages.
Simple Conflict Example
-----------------------
You are keeping a namecard file on your PC updating from your smartphone. Your
smartphone ran out of battery and is offline when you update your namecard on
your PC with your new email adress. Someone else change this email from your PC
and once your smartphone is recharged, you go back online and the previous
update is executed.
#. Setting up the storage tree
.. code-block:: javascript
var jio_instance = jIO.newJio({
// replicate revision storage
"type":"replicaterevision",
"storagelist":[{
"type": "revision",
"sub_storage": {
"type": "dav",
...
}
}, {
"type": "revision",
"sub_storage": {
"type": "local",
...
}
}]
});
#. Create your namecard on your smartphone
.. code-block:: javascript
jio_instance.post({
"_id": "myNameCard",
"email": "me@web.com"
}).then(function (response) {
// response.id -> "myNameCard"
// response.rev -> "1-5782E71F1E4BF698FA3793D9D5A96393"
});
This will create the document on your webDav and local storage
#. Someone else updates your shared namecard on Webdav
.. code-block:: javascript
jio_instance.put({
"email": "my_new_me@web.com",
"_id": "myNameCard"
"_rev": "1-5782E71F1E4BF698FA3793D9D5A96393"
}).then(function (response) {
// response.id -> "myNameCard"
// response.rev -> "2-068E73F5B44FEC987B51354DFC772891"
});
Your smartphone is offline, so you will now have one version (1-578...) on
your smartphone and another version on webDav (2-068...) on your PC.
#. You modify your namecard while being offline
.. code-block:: javascript
jio_instance.get({"_id": "myNameCard"}).then(function (response) {
// response.id -> "myNameCard"
// response.rev -> "1-5782E71F1E4BF698FA3793D9D5A96393"
// response.data.email -> "me@web.com"
return jio_instance.put({
"_id": "myNameCard",
"email": "me_again@web.com"
});
}).then(function (response) {
// response.id -> "myNameCard"
// response.rev -> "2-3753476B70A49EA4D8C9039E7B04254C"
});
#. Later, your smartphone is online and you retrieve your namecard.
.. code-block:: javascript
jio_instance.get({"_id": "myNameCard"}).then(function (response) {
// response.id -> "myNameCard"
// response.rev -> "2-3753476B70A49EA4D8C9039E7B04254C"
// response.data.email -> "me_again@web.com"
});
When multiple versions of a document are available, jIO returns the latest,
left-most version on the document tree (2-375... and labels all other
versions as conflicting 2-068...).
#. Retrieve conflicts by setting option
.. code-block:: javascript
jio_instance.get({"_id": "myNameCard"}, {
"conflicts": true
}).then(function (response) {
// response.id -> "myNameCard"
// response.rev -> "2-3753476B70A49EA4D8C9039E7B04254C",
// response.conflicts -> ["2-068E73F5B44FEC987B51354DFC772891"]
});
The conflicting version (*2-068E...*) is displayed, because **{conflicts: true}** was
specified in the GET call. Deleting either version will solve the conflict.
#. Delete conflicting version
.. code-block:: javascript
jio_instance.remove({
"_id": "myNameCard",
"_rev": "2-068E73F5B44FEC987B51354DFC772891"
}).then(function (response) {
// response.id -> "myNameCard"
// response.rev -> "3-28910A4937537B5168E772896B70EC98"
});
When deleting the conflicting version of your namecard, jIO removes this
version from all storages and sets the document tree leaf of this version to
deleted. All storages now contain just a single version of your namecard
(2-3753...). Note that, on the document tree, removing a revison will
create a new revision with status set to *deleted*.
/*
* basic.css
* ~~~~~~~~~
*
* Sphinx stylesheet -- basic theme.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar #searchbox input[type="text"] {
width: 170px;
}
div.sphinxsidebar #searchbox input[type="submit"] {
width: 30px;
}
img {
border: 0;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li div.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable {
width: 100%;
}
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable dl, table.indextable dd {
margin-top: 0;
margin-bottom: 0;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
div.modindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
div.genindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
/* -- general body styles --------------------------------------------------- */
a.headerlink {
visibility: hidden;
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink {
visibility: visible;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
.field-list ul {
padding-left: 1em;
}
.first {
margin-top: 0 !important;
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
img.align-left, .figure.align-left, object.align-left {
clear: left;
float: left;
margin-right: 1em;
}
img.align-right, .figure.align-right, object.align-right {
clear: right;
float: right;
margin-left: 1em;
}
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px 7px 0 7px;
background-color: #ffe;
width: 40%;
float: right;
}
p.sidebar-title {
font-weight: bold;
}
/* -- topics ---------------------------------------------------------------- */
div.topic {
border: 1px solid #ccc;
padding: 7px 7px 0 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
div.admonition dl {
margin-bottom: 0;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
border: 0;
border-collapse: collapse;
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 5px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.field-list td, table.field-list th {
border: 0 !important;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
th {
text-align: left;
padding-right: 5px;
}
table.citation {
border-left: solid 1px gray;
margin-left: 1px;
}
table.citation td {
border-bottom: none;
}
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
list-style: decimal;
}
ol.loweralpha {
list-style: lower-alpha;
}
ol.upperalpha {
list-style: upper-alpha;
}
ol.lowerroman {
list-style: lower-roman;
}
ol.upperroman {
list-style: upper-roman;
}
dl {
margin-bottom: 15px;
}
dd p {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dt:target, .highlighted {
background-color: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.refcount {
color: #060;
}
.optional {
font-size: 1.3em;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #ffa;
}
.line-block {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}
.line-block .line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 1.5em;
}
.guilabel, .menuselection {
font-family: sans-serif;
}
.accelerator {
text-decoration: underline;
}
.classifier {
font-style: oblique;
}
abbr, acronym {
border-bottom: dotted 1px;
cursor: help;
}
/* -- code displays --------------------------------------------------------- */
pre {
overflow: auto;
overflow-y: hidden; /* fixes display issues on Chrome browsers */
}
td.linenos pre {
padding: 5px 0px;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
tt.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
tt.descclassname {
background-color: transparent;
}
tt.xref, a tt {
background-color: transparent;
font-weight: bold;
}
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
background-color: transparent;
}
.viewcode-link {
float: right;
}
.viewcode-back {
float: right;
font-family: sans-serif;
}
div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.body div.math p {
text-align: center;
}
span.eqno {
float: right;
}
/* -- printout stylesheet --------------------------------------------------- */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0 !important;
width: 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
#top-link {
display: none;
}
}
\ No newline at end of file
/*
* default.css_t
* ~~~~~~~~~~~~~
*
* Sphinx stylesheet -- default theme.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: sans-serif;
font-size: 100%;
background-color: #11303d;
color: #000;
margin: 0;
padding: 0;
}
div.document {
background-color: #1c4e63;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
div.body {
background-color: #ffffff;
color: #000000;
padding: 0 20px 30px 20px;
}
div.footer {
color: #ffffff;
width: 100%;
padding: 9px 0 9px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #ffffff;
text-decoration: underline;
}
div.related {
background-color: #133f52;
line-height: 30px;
color: #ffffff;
}
div.related a {
color: #ffffff;
}
div.sphinxsidebar {
}
div.sphinxsidebar h3 {
font-family: 'Trebuchet MS', sans-serif;
color: #ffffff;
font-size: 1.4em;
font-weight: normal;
margin: 0;
padding: 0;
}
div.sphinxsidebar h3 a {
color: #ffffff;
}
div.sphinxsidebar h4 {
font-family: 'Trebuchet MS', sans-serif;
color: #ffffff;
font-size: 1.3em;
font-weight: normal;
margin: 5px 0 0 0;
padding: 0;
}
div.sphinxsidebar p {
color: #ffffff;
}
div.sphinxsidebar p.topless {
margin: 5px 10px 10px 10px;
}
div.sphinxsidebar ul {
margin: 10px;
padding: 0;
color: #ffffff;
}
div.sphinxsidebar a {
color: #98dbcc;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
/* -- hyperlink styles ------------------------------------------------------ */
a {
color: #355f7c;
text-decoration: none;
}
a:visited {
color: #355f7c;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* -- body styles ----------------------------------------------------------- */
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: 'Trebuchet MS', sans-serif;
background-color: #f2f2f2;
font-weight: normal;
color: #20435c;
border-bottom: 1px solid #ccc;
margin: 20px -20px 10px -20px;
padding: 3px 0 3px 10px;
}
div.body h1 { margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 160%; }
div.body h3 { font-size: 140%; }
div.body h4 { font-size: 120%; }
div.body h5 { font-size: 110%; }
div.body h6 { font-size: 100%; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
text-align: justify;
line-height: 130%;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.admonition p {
margin-bottom: 5px;
}
div.admonition pre {
margin-bottom: 5px;
}
div.admonition ul, div.admonition ol {
margin-bottom: 5px;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 5px;
background-color: #eeffcc;
color: #333333;
line-height: 120%;
border: 1px solid #ac9;
border-left: none;
border-right: none;
}
tt {
background-color: #ecf0f3;
padding: 0 1px 0 1px;
font-size: 0.95em;
}
th {
background-color: #ede;
}
.warning tt {
background: #efc2c2;
}
.note tt {
background: #d6d6d6;
}
.viewcode-back {
font-family: sans-serif;
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
\ No newline at end of file
/*
* doctools.js
* ~~~~~~~~~~~
*
* Sphinx JavaScript utilities for all documentation.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/**
* select a different prefix for underscore
*/
$u = _.noConflict();
/**
* make the code below compatible with browsers without
* an installed firebug like debugger
if (!window.console || !console.firebug) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
"profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {};
}
*/
/**
* small helper function to urldecode strings
*/
jQuery.urldecode = function(x) {
return decodeURIComponent(x).replace(/\+/g, ' ');
}
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s == 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* small function to check if an array contains
* a given item.
*/
jQuery.contains = function(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == item)
return true;
}
return false;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node) {
if (node.nodeType == 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
var span = document.createElement("span");
span.className = className;
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this);
});
}
}
return this.each(function() {
highlight(this);
});
};
/**
* Small JavaScript module for the documentation.
*/
var Documentation = {
init : function() {
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initIndexTable();
},
/**
* i18n support
*/
TRANSLATIONS : {},
PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
LOCALE : 'unknown',
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext : function(string) {
var translated = Documentation.TRANSLATIONS[string];
if (typeof translated == 'undefined')
return string;
return (typeof translated == 'string') ? translated : translated[0];
},
ngettext : function(singular, plural, n) {
var translated = Documentation.TRANSLATIONS[singular];
if (typeof translated == 'undefined')
return (n == 1) ? singular : plural;
return translated[Documentation.PLURALEXPR(n)];
},
addTranslations : function(catalog) {
for (var key in catalog.messages)
this.TRANSLATIONS[key] = catalog.messages[key];
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
this.LOCALE = catalog.locale;
},
/**
* add context elements like header anchor links
*/
addContextElements : function() {
$('div[id] > :header:first').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this headline')).
appendTo(this);
});
$('dt[id]').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this definition')).
appendTo(this);
});
},
/**
* workaround a firefox stupidity
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlighted');
});
}, 10);
$('<p class="highlight-link"><a href="javascript:Documentation.' +
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
.appendTo($('#searchbox'));
}
},
/**
* init the domain index toggle buttons
*/
initIndexTable : function() {
var togglers = $('img.toggler').click(function() {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
$('tr.cg-' + idnum).toggle();
if (src.substr(-9) == 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
}).css('display', '');
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
togglers.click();
}
},
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('#searchbox .highlight-link').fadeOut(300);
$('span.highlighted').removeClass('highlighted');
},
/**
* make the url absolute
*/
makeURL : function(relativeURL) {
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
},
/**
* get the current relative url
*/
getCurrentURL : function() {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this == '..')
parts.pop();
});
var url = parts.join('/');
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
}
};
// quick alias for translations
_ = Documentation.gettext;
$(document).ready(function() {
Documentation.init();
});
This diff is collapsed.
/*
* nature.css_t
* ~~~~~~~~~~~~
*
* Sphinx stylesheet -- nature theme.
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: Arial, sans-serif;
font-size: 100%;
background-color: #111;
color: #555;
margin: 0;
padding: 0;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
hr {
border: 1px solid #B1B4B6;
}
div.document {
background-color: #eee;
}
div.body {
background-color: #ffffff;
color: #3E4349;
padding: 0 30px 30px 30px;
font-size: 0.9em;
}
div.footer {
color: #555;
width: 100%;
padding: 13px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #444;
text-decoration: underline;
}
div.related {
background-color: #6BA81E;
line-height: 32px;
color: #fff;
text-shadow: 0px 1px 0 #444;
font-size: 0.9em;
}
div.related a {
color: #E2F3CC;
}
div.sphinxsidebar {
font-size: 0.75em;
line-height: 1.5em;
}
div.sphinxsidebarwrapper{
padding: 20px 0;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
font-family: Arial, sans-serif;
color: #222;
font-size: 1.2em;
font-weight: normal;
margin: 0;
padding: 5px 10px;
background-color: #ddd;
text-shadow: 1px 1px 0 white
}
div.sphinxsidebar h4{
font-size: 1.1em;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p {
color: #888;
padding: 5px 20px;
}
div.sphinxsidebar p.topless {
}
div.sphinxsidebar ul {
margin: 10px 20px;
padding: 0;
color: #000;
}
div.sphinxsidebar a {
color: #444;
}
div.sphinxsidebar input {
border: 1px solid #ccc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar input[type=text]{
margin-left: 20px;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #005B81;
text-decoration: none;
}
a:hover {
color: #E32E00;
text-decoration: underline;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: Arial, sans-serif;
background-color: #BED4EB;
font-weight: normal;
color: #212224;
margin: 30px 0px 10px 0px;
padding: 5px 0 5px 10px;
text-shadow: 0px 1px 0 white
}
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
line-height: 1.5em;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.highlight{
background-color: white;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 10px;
background-color: White;
color: #222;
line-height: 1.2em;
border: 1px solid #C6C9CB;
font-size: 1.1em;
margin: 1.5em 0 1.5em 0;
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
-moz-box-shadow: 1px 1px 1px #d8d8d8;
}
tt {
background-color: #ecf0f3;
color: #222;
/* padding: 1px 2px; */
font-size: 1.1em;
font-family: monospace;
}
.viewcode-back {
font-family: Arial, sans-serif;
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
\ No newline at end of file
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f0f3f3; }
.highlight .c { color: #0099FF; font-style: italic } /* Comment */
.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */
.highlight .k { color: #006699; font-weight: bold } /* Keyword */
.highlight .o { color: #555555 } /* Operator */
.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #009999 } /* Comment.Preproc */
.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */
.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */
.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
.highlight .go { color: #AAAAAA } /* Generic.Output */
.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #99CC66 } /* Generic.Traceback */
.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #006699 } /* Keyword.Pseudo */
.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #FF6600 } /* Literal.Number */
.highlight .s { color: #CC3300 } /* Literal.String */
.highlight .na { color: #330099 } /* Name.Attribute */
.highlight .nb { color: #336666 } /* Name.Builtin */
.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */
.highlight .no { color: #336600 } /* Name.Constant */
.highlight .nd { color: #9999FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #CC00FF } /* Name.Function */
.highlight .nl { color: #9999FF } /* Name.Label */
.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #003333 } /* Name.Variable */
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #FF6600 } /* Literal.Number.Float */
.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */
.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */
.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */
.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */
.highlight .sc { color: #CC3300 } /* Literal.String.Char */
.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #CC3300 } /* Literal.String.Double */
.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */
.highlight .si { color: #AA0000 } /* Literal.String.Interpol */
.highlight .sx { color: #CC3300 } /* Literal.String.Other */
.highlight .sr { color: #33AAAA } /* Literal.String.Regex */
.highlight .s1 { color: #CC3300 } /* Literal.String.Single */
.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */
.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #003333 } /* Name.Variable.Class */
.highlight .vg { color: #003333 } /* Name.Variable.Global */
.highlight .vi { color: #003333 } /* Name.Variable.Instance */
.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
// Underscore.js 0.5.5
// (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the terms of the MIT license.
// Portions of Underscore are inspired by or borrowed from Prototype.js,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore/
(function(){var j=this,n=j._,i=function(a){this._wrapped=a},m=typeof StopIteration!=="undefined"?StopIteration:"__break__",b=j._=function(a){return new i(a)};if(typeof exports!=="undefined")exports._=b;var k=Array.prototype.slice,o=Array.prototype.unshift,p=Object.prototype.toString,q=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;b.VERSION="0.5.5";b.each=function(a,c,d){try{if(a.forEach)a.forEach(c,d);else if(b.isArray(a)||b.isArguments(a))for(var e=0,f=a.length;e<f;e++)c.call(d,
a[e],e,a);else{var g=b.keys(a);f=g.length;for(e=0;e<f;e++)c.call(d,a[g[e]],g[e],a)}}catch(h){if(h!=m)throw h;}return a};b.map=function(a,c,d){if(a&&b.isFunction(a.map))return a.map(c,d);var e=[];b.each(a,function(f,g,h){e.push(c.call(d,f,g,h))});return e};b.reduce=function(a,c,d,e){if(a&&b.isFunction(a.reduce))return a.reduce(b.bind(d,e),c);b.each(a,function(f,g,h){c=d.call(e,c,f,g,h)});return c};b.reduceRight=function(a,c,d,e){if(a&&b.isFunction(a.reduceRight))return a.reduceRight(b.bind(d,e),c);
var f=b.clone(b.toArray(a)).reverse();b.each(f,function(g,h){c=d.call(e,c,g,h,a)});return c};b.detect=function(a,c,d){var e;b.each(a,function(f,g,h){if(c.call(d,f,g,h)){e=f;b.breakLoop()}});return e};b.select=function(a,c,d){if(a&&b.isFunction(a.filter))return a.filter(c,d);var e=[];b.each(a,function(f,g,h){c.call(d,f,g,h)&&e.push(f)});return e};b.reject=function(a,c,d){var e=[];b.each(a,function(f,g,h){!c.call(d,f,g,h)&&e.push(f)});return e};b.all=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.every))return a.every(c,
d);var e=true;b.each(a,function(f,g,h){(e=e&&c.call(d,f,g,h))||b.breakLoop()});return e};b.any=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.some))return a.some(c,d);var e=false;b.each(a,function(f,g,h){if(e=c.call(d,f,g,h))b.breakLoop()});return e};b.include=function(a,c){if(b.isArray(a))return b.indexOf(a,c)!=-1;var d=false;b.each(a,function(e){if(d=e===c)b.breakLoop()});return d};b.invoke=function(a,c){var d=b.rest(arguments,2);return b.map(a,function(e){return(c?e[c]:e).apply(e,d)})};b.pluck=
function(a,c){return b.map(a,function(d){return d[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);var e={computed:-Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g>=e.computed&&(e={value:f,computed:g})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g<e.computed&&(e={value:f,computed:g})});return e.value};b.sortBy=function(a,c,d){return b.pluck(b.map(a,
function(e,f,g){return{value:e,criteria:c.call(d,e,f,g)}}).sort(function(e,f){e=e.criteria;f=f.criteria;return e<f?-1:e>f?1:0}),"value")};b.sortedIndex=function(a,c,d){d=d||b.identity;for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?(e=g+1):(f=g)}return e};b.toArray=function(a){if(!a)return[];if(a.toArray)return a.toArray();if(b.isArray(a))return a;if(b.isArguments(a))return k.call(a);return b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=function(a,c,d){return c&&!d?k.call(a,
0,c):a[0]};b.rest=function(a,c,d){return k.call(a,b.isUndefined(c)||d?1:c)};b.last=function(a){return a[a.length-1]};b.compact=function(a){return b.select(a,function(c){return!!c})};b.flatten=function(a){return b.reduce(a,[],function(c,d){if(b.isArray(d))return c.concat(b.flatten(d));c.push(d);return c})};b.without=function(a){var c=b.rest(arguments);return b.select(a,function(d){return!b.include(c,d)})};b.uniq=function(a,c){return b.reduce(a,[],function(d,e,f){if(0==f||(c===true?b.last(d)!=e:!b.include(d,
e)))d.push(e);return d})};b.intersect=function(a){var c=b.rest(arguments);return b.select(b.uniq(a),function(d){return b.all(c,function(e){return b.indexOf(e,d)>=0})})};b.zip=function(){for(var a=b.toArray(arguments),c=b.max(b.pluck(a,"length")),d=new Array(c),e=0;e<c;e++)d[e]=b.pluck(a,String(e));return d};b.indexOf=function(a,c){if(a.indexOf)return a.indexOf(c);for(var d=0,e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,c){if(a.lastIndexOf)return a.lastIndexOf(c);for(var d=
a.length;d--;)if(a[d]===c)return d;return-1};b.range=function(a,c,d){var e=b.toArray(arguments),f=e.length<=1;a=f?0:e[0];c=f?e[0]:e[1];d=e[2]||1;e=Math.ceil((c-a)/d);if(e<=0)return[];e=new Array(e);f=a;for(var g=0;1;f+=d){if((d>0?f-c:c-f)>=0)return e;e[g++]=f}};b.bind=function(a,c){var d=b.rest(arguments,2);return function(){return a.apply(c||j,d.concat(b.toArray(arguments)))}};b.bindAll=function(a){var c=b.rest(arguments);if(c.length==0)c=b.functions(a);b.each(c,function(d){a[d]=b.bind(a[d],a)});
return a};b.delay=function(a,c){var d=b.rest(arguments,2);return setTimeout(function(){return a.apply(a,d)},c)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(b.rest(arguments)))};b.wrap=function(a,c){return function(){var d=[a].concat(b.toArray(arguments));return c.apply(c,d)}};b.compose=function(){var a=b.toArray(arguments);return function(){for(var c=b.toArray(arguments),d=a.length-1;d>=0;d--)c=[a[d].apply(this,c)];return c[0]}};b.keys=function(a){if(b.isArray(a))return b.range(0,a.length);
var c=[];for(var d in a)q.call(a,d)&&c.push(d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=function(a){return b.select(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a,c){for(var d in c)a[d]=c[d];return a};b.clone=function(a){if(b.isArray(a))return a.slice(0);return b.extend({},a)};b.tap=function(a,c){c(a);return a};b.isEqual=function(a,c){if(a===c)return true;var d=typeof a;if(d!=typeof c)return false;if(a==c)return true;if(!a&&c||a&&!c)return false;
if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return true;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return false;if(a.length&&a.length!==c.length)return false;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return false;for(var f in a)if(!b.isEqual(a[f],c[f]))return false;return true};b.isEmpty=function(a){return b.keys(a).length==
0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=function(a){return!!(a&&a.concat&&a.unshift)};b.isArguments=function(a){return a&&b.isNumber(a.length)&&!b.isArray(a)&&!r.call(a,"length")};b.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return p.call(a)==="[object Number]"};b.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};b.isRegExp=function(a){return!!(a&&
a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};b.isNaN=function(a){return b.isNumber(a)&&isNaN(a)};b.isNull=function(a){return a===null};b.isUndefined=function(a){return typeof a=="undefined"};b.noConflict=function(){j._=n;return this};b.identity=function(a){return a};b.breakLoop=function(){throw m;};var s=0;b.uniqueId=function(a){var c=s++;return a?a+c:c};b.template=function(a,c){a=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+a.replace(/[\r\t\n]/g,
" ").replace(/'(?=[^%]*%>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<%=(.+?)%>/g,"',$1,'").split("<%").join("');").split("%>").join("p.push('")+"');}return p.join('');");return c?a(c):a};b.forEach=b.each;b.foldl=b.inject=b.reduce;b.foldr=b.reduceRight;b.filter=b.select;b.every=b.all;b.some=b.any;b.head=b.first;b.tail=b.rest;b.methods=b.functions;var l=function(a,c){return c?b(a).chain():a};b.each(b.functions(b),function(a){var c=b[a];i.prototype[a]=function(){var d=b.toArray(arguments);
o.call(d,this._wrapped);return l(c.apply(b,d),this._chain)}});b.each(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){c.apply(this._wrapped,arguments);return l(this._wrapped,this._chain)}});b.each(["concat","join","slice"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){return l(c.apply(this._wrapped,arguments),this._chain)}});i.prototype.chain=function(){this._chain=true;return this};i.prototype.value=function(){return this._wrapped}})();
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Index &mdash; JIO 2.0.0 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '2.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="JIO 2.0.0 documentation" href="index.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="#" title="General Index"
accesskey="I">index</a></li>
<li><a href="index.html">JIO 2.0.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<h1 id="index">Index</h1>
<div class="genindex-jumpbox">
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="index.html">
<img class="logo" src="_static/jio.png" alt="Logo"/>
</a></p>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="#" title="General Index"
>index</a></li>
<li><a href="index.html">JIO 2.0.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2013, Nexedi.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment