Commit d5fb474f authored by Marco Mariani's avatar Marco Mariani

docs: small style/content fixes

parent 7ac5b5a8
......@@ -5,6 +5,12 @@
margin-bottom: 0.4em;
}
pre {
padding-left: 15px;
padding-righ: 15px;
}
a.button {
-moz-border-radius:6px;
......
<h4><a href="./getting_started.html#download-fork" style="color:#008800">Downloads</a></h4>
<h4><a href="./getting_started.html">Getting Started</a></h4>
......@@ -55,7 +55,8 @@ NB: digest **is not implemented yet**.
.. code-block:: javascript
dav_storage.createDescription(url, auth_type, [realm], [username], [password]);
dav_storage.createDescription(url, auth_type,
[realm], [username], [password]);
All parameters are strings.
......@@ -103,17 +104,20 @@ Here is the description:
{
"type": "index",
"indices": [{
"id": "index_title_subject.json", // doc id where to store indices
"index": ["title", "subject"], // metadata to index
// doc id where to store indices
"id": "index_title_subject.json",
// metadata to index
"index": ["title", "subject"],
"attachment": "db.json", // default "body"
"metadata": { // additional metadata to add to database, default undefined
// additional metadata to add to database, default undefined
"metadata": {
"type": "Dataset",
"format": "application/json",
"title": "My index database",
"creator": "Me"
},
// default equal to parent sub_storage field
"sub_storage": <sub storage where to store index>
// default equal to parent sub_storage field
}, {
"id": "index_year.json",
"index": "year"
......
......@@ -6,7 +6,7 @@ What are Complex Queries?
In jIO, a complex query can ask a storage server to select, filter, sort, or
limit a document list before sending it back. If the server is not able to do
so, the complex query tool can act on the retreived list by itself. Only the
so, the complex query tool can do the filtering by itself on the client. Only the
``allDocs()`` method can use complex queries.
A query can either be a string (using a specific language useful for writing
......@@ -25,16 +25,15 @@ Complex queries can be used like database queries, for tasks such as:
For some storages (like localStorage), complex queries can be a powerful tool
to query accessible documents. When querying documents on a distant storage,
some server-side logic should be run to avoid having to request large amount of
documents to run a query on the client. If distant storages are static, an
alternative would be to use an indexStorage with appropriate indices as complex
queries will always try to run the query on the index before querying documents
itself.
some server-side logic should be run to avoid returning too many documents
to the client. If distant storages are static, an alternative would be to use
an indexStorage with appropriate indices as complex queries will always try
to run the query on the index before querying documents itself.
How to use Complex Queries with jIO?
------------------------------------
Complex queries can be triggered by including the option named query in the ``allDocs()`` method call.
Complex queries can be triggered by including the option named **query** in the ``allDocs()`` method call.
Example:
......@@ -64,7 +63,10 @@ Example:
options = {
query: '(creator:"% Doe") AND (format:"pdf")',
limit: [0, 100],
sort_on: [['last_modified', 'descending'], ['creation_date', 'descending']],
sort_on: [
['last_modified', 'descending'],
['creation_date', 'descending']
],
select_list: ['title'],
wildcard_character: '%'
};
......@@ -86,15 +88,20 @@ for how to use these methods, in and outside jIO. The module provides:
{
parseStringToObject: [Function: parseStringToObject],
stringEscapeRegexpCharacters: [Function: stringEscapeRegexpCharacters],
stringEscapeRegexpCharacters:
[Function: stringEscapeRegexpCharacters],
select: [Function: select],
sortOn: [Function: sortOn],
limit: [Function: limit],
convertStringToRegExp: [Function: convertStringToRegExp],
QueryFactory: { [Function: QueryFactory] create: [Function] },
Query: [Function: Query],
SimpleQuery: { [Function: SimpleQuery] super_: [Function: Query] },
ComplexQuery: { [Function: ComplexQuery] super_: [Function: Query] }
SimpleQuery: {
[Function: SimpleQuery] super_: [Function: Query]
},
ComplexQuery: {
[Function: ComplexQuery] super_: [Function: Query]
}
}
(Reference API coming soon.)
......@@ -113,7 +120,8 @@ Basic example:
var query = 'title: "Document number 1"';
// running the query
var result = complex_queries.QueryFactory.create(query).exec(object_list);
var result = complex_queries.QueryFactory.
create(query).exec(object_list);
// console.log(result);
// [ { "title": "Document number 1", "creator": "John Doe"} ]
......@@ -132,8 +140,12 @@ Other example:
}
);
// this case is equal to:
var result = complex_queries.QueryFactory.create(query).exec(object_list);
complex_queries.sortOn([['title', 'ascending'], ['year', 'descending']], result);
var result = complex_queries.QueryFactory.
create(query).exec(object_list);
complex_queries.sortOn([
['title', 'ascending'],
['year', 'descending']
], result);
complex_queries.limit([20, 20], result);
complex_queries.select(['title', 'year'], result);
......@@ -179,7 +191,8 @@ Example, convert Query object into a human readable string:
.. code-block:: javascript
var query = complex_queries.QueryFactory.create('year: < 2000 OR title: "*a"'),
var query = complex_queries.QueryFactory.
create('year: < 2000 OR title: "*a"'),
option = {
"wildcard_character": "*",
"limit": [0, 10]
......@@ -196,19 +209,24 @@ Example, convert Query object into a human readable string:
query.onParseStart = function (object, option) {
object.start = "The wildcard character is '" +
(option.wildcard_character || "%") +
"' and we need only the " + option.limit[1] + " elements from the numero " +
"' and we need only the " +
option.limit[1] +
" elements from the number " +
option.limit[0] + ". ";
};
query.onParseSimpleQuery = function (object, option) {
object.parsed = object.parsed.key + " " + human_read[object.parsed.operator] +
object.parsed = object.parsed.key +
" " + human_read[object.parsed.operator] +
object.parsed.value;
};
query.onParseComplexQuery = function (object, option) {
object.parsed = "I want all document where " +
object.parsed.query_list.join(" " + object.parsed.operator.toLowerCase() +
" ") + ". ";
object.parsed.query_list.join(" " +
object.parsed.operator.toLowerCase() +
" ") +
". ";
};
query.onParseEnd = function (object, option) {
......@@ -216,8 +234,9 @@ Example, convert Query object into a human readable string:
};
console.log(query.parse(option));
// logged: "The wildcard character is '*' and we need only the 10 elements
// from the numero 0. I want all document where year is lower than 2000 or title
// logged: "The wildcard character is '*' and we need
// only the 10 elements from the number 0. I want all
// document where year is lower than 2000 or title
// matches *a. Thank you!"
......@@ -237,7 +256,7 @@ Below you can find schemas for constructing queries.
"type": "string",
"format": "complex",
"default": "complex",
"description": "The type is used to recognize the query type."
"description": "Type is used to recognize the query type"
},
"operator": {
"type": "string",
......@@ -252,7 +271,9 @@ Below you can find schemas for constructing queries.
},
"required": true,
"default": [],
"description": "query_list is a list of queries which can be in serialized format of in object format."
"description": "query_list is a list of queries which " +
"can be in serialized format " +
"or in object format."
}
}
}
......@@ -269,7 +290,7 @@ Below you can find schemas for constructing queries.
"type": "string",
"format": "simple",
"default": "simple",
"description": "The type is used to recognize the query type."
"description": "Type is used to recognize the query type."
},
"operator": {
"type": "string",
......
......@@ -19,7 +19,7 @@ To build the library you have to:
* Compile JS/CC parser.
``$ make`` (until we find how to compile it with grunt)
``$ make`` (until we find out how to compile it with grunt)
* Run build.
......@@ -44,7 +44,8 @@ Create a constructor:
function MyStorage(storage_description) {
this._value = storage_description.value;
if (typeof this._value !== 'string') {
throw new TypeError("'value' description property is not a string");
throw new TypeError("'value' description property " +
"is not a string");
}
}
......@@ -53,17 +54,17 @@ Create 10 methods: ``post``, ``put``, ``putAttachment``, ``get``, ``getAttachmen
.. code-block:: javascript
MyStorage.prototype.post = function (command, metadata, option) {
MyStorage.prototype.post = function(command, metadata, option) {
var document_id = metadata._id;
// [...]
};
MyStorage.prototype.get = function (command, param, option) {
MyStorage.prototype.get = function(command, param, option) {
var document_id = param._id;
// [...]
};
MyStorage.prototype.putAttachment = function (command, param, option) {
MyStorage.prototype.putAttachment = function(command, param, option) {
var document_id = param._id;
var attachment_id = param._attachment;
var attachment_data = param._blob;
......@@ -99,21 +100,21 @@ 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})
* **post()** --> ``success("created", {"id": new_generated_id})``
* put, remove, putAttachment or removeAttachment --> success(204)
* **put()**, ``remove``, ``putAttachment`` or ``removeAttachment`` --> ``success(204)``
* get --> success("ok", {"data": document_metadata})
* **get()** --> ``success("ok", {"data": document_metadata})``
* getAttachment -->
* **getAttachment()** -->
success("ok", {"data": binary_string, "content_type": content_type})
``success("ok", {"data": binary_string, "content_type": content_type})``
// or
success("ok", {"data": new Blob([data], {"type": content_type})})
``success("ok", {"data": new Blob([data], {"type": content_type})})``
* allDocs --> success("ok", {"data": row_object})
* **allDocs()** --> ``success("ok", {"data": row_object})``
* check -->
* **check()** -->
.. code-block:: javascript
......@@ -123,7 +124,7 @@ Methods should return the following objects:
// or
error("conflict", "corrupted", "incoherent document or storage")
* repair -->
* **repair()** -->
.. code-block:: javascript
......@@ -131,8 +132,10 @@ Methods should return the following objects:
// 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
error("conflict", "corrupted",
"impossible to repair document or storage")
// DON'T DESIGN STORAGES IF THERE 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
......@@ -205,7 +208,7 @@ The following actions can be used:
* ``update`` - bind the selected job to this one
* ``deny`` - reject the job
The following condition function can be used:
The following condition functions can be used:
* ``sameStorageDescription`` - check if the storage descriptions are different.
* ``areWriters`` - check if the commands are ``post``, ``put``, ``putAttachment``, ``remove``, ``removeAttachment``, or ``repair``.
......@@ -226,19 +229,24 @@ You can create two types of function: job condition, and job comparison.
// 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;
});
// 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
......@@ -248,8 +256,9 @@ 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
// 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",
......
......@@ -5,17 +5,14 @@
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 and the dependencies required for the storages
you intend to use. :ref:`[Download & Fork] <download-fork>`
#. :ref:`Download <download-fork>` the core jIO, the storages you need and the
dependencies required for them.
#. Add the scripts to your HTML page in the following order:
.. code-block:: html
<!-- jio core + dependency -->
<!-- jio core + dependencies -->
<script src="sha256.amd.js"></script>
<script src="rsvp-custom.js"></script>
<script src="jio.js"></script>
......@@ -63,20 +60,30 @@ This walkthrough is designed to get you started using a basic jIO instance.
#. The jIO API provides ten main methods to manage documents across the storage(s) specified in your jIO storage tree.
====================== ===================================================== ========================================
Method Example 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
====================== ===================================================== ========================================
====================== ========================================================
Method Example
====================== ========================================================
``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's 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
====================== ========================================================
......
......@@ -98,7 +98,10 @@ metadata object can contain several values. Example:
// or
"key": ["value1", "value2"],
// or
"key": {"attribute name": "attribute value", "content": "value"},
"key": {
"attribute name": "attribute value",
"content": "value"
},
// or
"key": [
{"scheme": "DCTERMS.URI", "content": "http://foo.com/bar"},
......
......@@ -2,8 +2,7 @@ How to manage documents?
========================
jIO is mapped after the CouchDB APIs and extends them to provide unified, scalable
and high performance access via JavaScript to a wide variety of different
storage backends.
and high performance access via JavaScript to a wide variety of storage backends.
If you are not familiar with `Apache CouchDB <http://couchdb.apache.org/>`_:
it is a scalable, fault-tolerant, and schema-free document-oriented database.
......@@ -17,11 +16,11 @@ What is a document?
-------------------
A document is an association of metadata and attachment(s). The metadata is the
set of properties of the document and the attachments are the binaries of the content
of the document.
set of properties of the document and the attachments are binary (or text) objects
that represent the content of the document.
In jIO, metadata is just a dictionary with keys and values (JSON object), and
attachments are just simple strings.
In jIO, the metadata is a dictionary with keys and values (a JSON object), and
attachments are simple strings.
.. code-block:: javascript
......@@ -58,7 +57,7 @@ Basic Methods
-------------
Below you can see examples of the main jIO methods. All examples are using
revisions (as in revision storage or replicate revision storage), so you can
revisions (as in revision storage or replicated revision storage), so you can
see how method calls should be made with either of these storages.
.. code-block:: javascript
......@@ -79,8 +78,10 @@ see how method calls should be made with either of these storages.
});
// add an attachment to a document
jio_instance.putAttachment({"_id": "my_document", "_attachment": "its_attachment",
"_data": "abc", "_mimetype": "text/plain"}).
jio_instance.putAttachment({"_id": "my_document",
"_attachment": "its_attachment",
"_data": "abc",
"_mimetype": "text/plain"}).
then(function (response) {
// console.log(response);
});
......@@ -92,7 +93,8 @@ see how method calls should be made with either of these storages.
});
// read an attachment
jio_instance.getAttachment({"_id": "my_document", "_attachment": "its_attachment"}).
jio_instance.getAttachment({"_id": "my_document",
"_attachment": "its_attachment"}).
then(function (response) {
// console.log(response);
});
......@@ -104,7 +106,8 @@ see how method calls should be made with either of these storages.
});
// delete an attachment
jio_instance.removeAttachment({"_id": "my_document", "_attachment": "its_attachment"}).
jio_instance.removeAttachment({"_id": "my_document",
"_attachment": "its_attachment"}).
then(function (response) {
// console.log(response);
});
......@@ -137,8 +140,10 @@ To retrieve jIO responses, you have to provide callbacks like this:
.. code-block:: javascript
jio_instance.post(metadata, [options]).
then([responseCallback], [errorCallback], [progressionCallback]);
jio_instance.post(metadata, [options]).
then([responseCallback],
[errorCallback],
[progressionCallback]);
* On command success, ``responseCallback`` will be called with the jIO response as first parameter.
......@@ -253,10 +258,10 @@ In case of error, the ``errorCallback`` first parameter will look like:
Example: How to store a video on localStorage
---------------------------------------------
How to store a video on localStorage
------------------------------------
The following shows how to create a new jIO in localStorage and then post a document with two attachments.
The following example shows how to create a new jIO in localStorage and then post a document with two attachments.
.. code-block:: javascript
......
......@@ -60,37 +60,53 @@ List of metadata to use
Identification
^^^^^^^^^^^^^^
* **_id**, a specific jIO metadata which helps the storage to find a document
* **_id**
A specific jIO metadata which helps the storage to find a document
(can be a real path name, a dc:identifier, a uuid, ...). **String Only**
* **identifer**, :js:`{"identifier": "http://domain/jio_home_page"}, {"identifier": "urn:ISBN:978-1-2345-6789-X"},
{"identifier": [{"scheme": "DCTERMS.URI", "content": "http://domain/jio_home_page"}]}`
* **identifer**
| :js:`{"identifier": "http://domain/jio_home_page"}`
| :js:`{"identifier": "urn:ISBN:978-1-2345-6789-X"}`
| :js:`{"identifier": [{"scheme": "DCTERMS.URI", "content": "http://domain/jio_home_page"}]}`
an unambiguous reference to the resource within a given context. Recommended
best practice is to identify the resource by means of a string or number
An unambiguous reference to the resource within a given context. Recommended
best practice is to identify the resource with a string or number
conforming to a formal identification system. Examples of formal identification
systems include the Uniform Resource Identifier (URI) (including the Uniform
Resource Locator (URL), the Digital Object Identifier (DOI) and the
International Standard Book Number (ISBN).
systems include the `Uniform Resource Identifier <http://en.wikipedia.org/wiki/URI>`_ (URI)
(including the `Uniform Resource Locator <http://en.wikipedia.org/wiki/URL>`_ (URL),
the `Digital Object Identifier <http://en.wikipedia.org/wiki/Digital_object_identifier>`_ (DOI)
and the `International Standard Book Number <http://en.wikipedia.org/wiki/Isbn>`_ (ISBN).
* **format**, :js:`{"format": ["text/html", "52 kB"]}, {"format": ["image/jpeg", "100 x 100 pixels", "13.2 KiB"]}`
* **format**
| :js:`{"format": ["text/html", "52 kB"]}`
| :js:`{"format": ["image/jpeg", "100 x 100 pixels", "13.2 KiB"]}`
the physical or digital manifestation of the resource. Typically, Format may
The physical or digital manifestation of the resource. Typically, Format may
include the media-type or dimensions of the resource. Examples of dimensions
include size and duration. Format may be used to determine the software,
hardware or other equipment needed to display or operate the resource.
* **date**, :js:`{"date": "2011-12-13T14:15:16Z"}, {"date": {"scheme": "DCTERMS.W3CDTF", "content": "2011-12-13"}}`
* **date**
| :js:`{"date": "2011-12-13T14:15:16Z"}`
| :js:`{"date": {"scheme": "DCTERMS.W3CDTF", "content": "2011-12-13"}}`
a date associated with an event in the life cycle of the resource. Typically,
A date associated with an event in the life cycle of the resource. Typically,
Date will be associated with the creation or availability of the resource.
Recommended best practice for encoding the date value is defined in a profile
of ISO 8601 `Date and Time Formats, W3C Note <http://www.w3.org/TR/NOTE-datetime>`_
and follows the YYYY-MM-DD format.
* **type**, :js:`{"type": "Text"}, {"type": "Image"}, {"type": "Dataset"}`
* **type**
| :js:`{"type": "Text"}`
| :js:`{"type": "Image"}`
| :js:`{"type": "Dataset"}`
the nature or genre of the content of the resource. Type includes terms describing
The nature or genre of the content of the resource. Type includes terms describing
general categories, functions, genres, or aggregation levels for content.
Recommended best practice is to select a value from a controlled vocabulary.
**The type is not a MIME Type!**
......@@ -99,28 +115,38 @@ Identification
Intellectual property
^^^^^^^^^^^^^^^^^^^^^
* **creator**, :js:`{"creator": "Tristan Cavelier"}, {"creator": ["Tristan Cavelier", "Sven Franck"]}`
* **creator**
| :js:`{"creator": "Tristan Cavelier"}`
| :js:`{"creator": ["Tristan Cavelier", "Sven Franck"]}`
an entity primarily responsible for creating the content of the resource.
An entity primarily responsible for creating the content of the resource.
Examples of a Creator include a person, an organization, or a service.
Typically the name of the Creator should be used to indicate the entity.
* **publisher**, :js:`{"publisher": "Nexedi"}`
* **publisher**
| :js:`{"publisher": "Nexedi"}`
the entity responsible for making the resource available. Examples of a
The entity responsible for making the resource available. Examples of a
Publisher include a person, an organization, or a service. Typically, the name
of a Publisher should be used to indicate the entity.
* **contributor**, :js:`{"contributor": ["Full Name", "Full Name", ...]}`
* **contributor**
| :js:`{"contributor": ["Full Name", "Full Name", ...]}`
an entity responsible for making contributions to the content of the
An entity responsible for making contributions to the content of the
resource. Examples of a Contributor include a person, an organization or a
service. Typically, the name of a Contributor should be used to indicate the
entity.
* **rights**, :js:`{"rights": "Access limited to members"}, {"rights": "https://www.j-io.org/documentation/jio-documentation/#copyright-and-license"}`
* **rights**
| :js:`{"rights": "Access limited to members"}`
| :js:`{"rights": "https://www.j-io.org/documentation/jio-documentation/#copyright-and-license"}`
information about rights held in and over the resource. Typically a Rights
Information about rights held in and over the resource. Typically a Rights
element will contain a rights management statement for the resource, or
reference a service providing such information. Rights information often
encompasses Intellectual Property Rights (IPR), Copyright, and various Property
......@@ -131,48 +157,64 @@ Intellectual property
Content
^^^^^^^
* **title**, :js:`{"title": "jIO Home Page"}`
* **title**
| :js:`{"title": "jIO Home Page"}`
the name given to the resource. Typically, a Title will be a name by which the resource is formally known.
The name given to the resource. Typically, a Title will be a name by which the resource is formally known.
* **subject**, :js:`{"subject": "jIO"}, {"subject": ["jIO", "basics"]}`
* **subject**
| :js:`{"subject": "jIO"}`
| :js:`{"subject": ["jIO", "basics"]}`
the topic of the content of the resource. Typically, a Subject will be
The topic of the content of the resource. Typically, a Subject will be
expressed as keywords or key phrases or classification codes that describe the
topic of the resource. Recommended best practice is to select a value from a
controlled vocabulary or formal classification scheme.
* **description**, :js:`{"description": "Simple guide to show the basics of jIO"}, {"description": {"lang": "fr", "content": "Ma description"}}`
* **description**
| :js:`{"description": "Simple guide to show the basics of jIO"}`
| :js:`{"description": {"lang": "fr", "content": "Ma description"}}`
an account of the content of the resource. Description may include but is not
An account of the content of the resource. Description may include but is not
limited to: an abstract, table of contents, reference to a graphical
representation of content or a free-text account of the content.
* **language**, :js:`{"language": "en"}`
* **language**
| :js:`{"language": "en"}`
the language of the intellectual content of the resource. Recommended best
The language of the intellectual content of the resource. Recommended best
practice for the values of the Language element is defined by `RFC 3066 <http://www.ietf.org/rfc/rfc3066.txt>`_
which, in conjunction with `ISO 639 <http://www.oasis-open.org/cover/iso639a.html>`_, defines two- and
three-letter primary language tags with optional subtags. Examples include "en"
or "eng" for English, "akk" for Akkadian, and "en-GB" for English used in the
United Kingdom.
* **source**, :js:`{"source": ["Image taken from a drawing by Mr. Artist", "<phone number>"]}`,
* **source**
| :js:`{"source": ["Image taken from a drawing by Mr. Artist", "<phone number>"]}`
a Reference to a resource from which the present resource is derived. The
A Reference to a resource from which the present resource is derived. The
present resource may be derived from the Source resource in whole or part.
Recommended best practice is to reference the resource by means of a string or
number conforming to a formal identification system.
* **relation**, :js:`{"relation": "Resilience project"}`
* **relation**
| :js:`{"relation": "Resilience project"}`
a reference to a related resource. Recommended best practice is to reference
A reference to a related resource. Recommended best practice is to reference
the resource by means of a string or number conforming to a formal
identification system.
* **coverage**, :js:`{"coverage": "France"}`
* **coverage**
| :js:`{"coverage": "France"}`
the extent or scope of the content of the resource. Coverage will typically
The extent or scope of the content of the resource. Coverage will typically
include spatial location (a place name or geographic co-ordinates), temporal
period (a period label, date, or date range) or jurisdiction (such as a named
administrative entity). Recommended best practice is to select a value from a
......@@ -181,19 +223,24 @@ Content
places or time periods should be used in preference to numeric identifiers such
as sets of co-ordinates or date ranges.
* **category**, :js:`{"category": ["parent/26323", "resilience/javascript", "javascript/library/io"]}`
* **category**
| :js:`{"category": ["parent/26323", "resilience/javascript", "javascript/library/io"]}`
the category the resource is associated with. The categories may look like
The category the resource is associated with. The categories may look like
navigational facets, they correspond to the properties of the resource which
can be generated with metadata or some other information (see `faceted search <https://en.wikipedia.org/wiki/Faceted_search>`_).
* **product**, :js:`{"product": "..."}`
* **product**
| :js:`{"product": "..."}`
for e-commerce use.
For e-commerce use.
* **custom**, :js:`{custom1: value1, custom2: value2, ...}`
* **custom**
| :js:`{custom1: value1, custom2: value2, ...}`
.. XXX short description here
Examples
......@@ -205,17 +252,17 @@ Posting a webpage for jIO
.. code-block:: javascript
jio.put({
"_id" : "...",
"identifier" : "http://domain/jio_home_page",
"format" : ["text/html", "52 kB"],
"date" : new Date(),
"type" : "Text",
"creator" : ["Nexedi", "Tristan Cavelier", "Sven Franck"],
"title" : "jIO Home Page",
"subject" : ["jIO", "basics"],
"description" : "Simple guide to show the basics of jIO",
"category" : ["resilience/jio", "webpage"],
"language" : "en"
"_id" : "...",
"identifier" : "http://domain/jio_home_page",
"format" : ["text/html", "52 kB"],
"date" : new Date(),
"type" : "Text",
"creator" : ["Nexedi", "Tristan Cavelier", "Sven Franck"],
"title" : "jIO Home Page",
"subject" : ["jIO", "basics"],
"description": "Simple guide to show the basics of jIO",
"category" : ["resilience/jio", "webpage"],
"language" : "en"
}, callbacks); // send content as attachment
......@@ -226,20 +273,24 @@ Posting jIO library
.. code-block:: javascript
jio.put({
"_id" : "...",
"identifier" : "jio.js",
"date" : "2013-02-15",
"format" : "application/javascript",
"type" : "Software",
"creator" : ["Tristan Cavelier", "Sven Franck"],
"publisher" : "Nexedi",
"rights" :
"https://www.j-io.org/documentation/jio-documentation/#copyright-and-license",
"title" : "Javascript Input/Output",
"subject" : "jIO",
"category" : ["resilience/javascript", "javascript/library/io"]
"description" : "jIO is a client-side JavaScript library to manage " +
"documents across multiple storages."
"_id" : "...",
"identifier" : "jio.js",
"date" : "2013-02-15",
"format" : "application/javascript",
"type" : "Software",
"creator" : ["Tristan Cavelier", "Sven Franck"],
"publisher" : "Nexedi",
"rights" :
"https://www.j-io.org/documentation/" +
"jio-documentation/#copyright-and-license",
"title" : "Javascript Input/Output",
"subject" : "jIO",
"category" : [
"resilience/javascript",
"javascript/library/io"
]
"description": "jIO is a client-side JavaScript library to " +
"manage documents across multiple storages."
}, callbacks); // send content as attachment
......@@ -249,18 +300,23 @@ Posting a webpage for interoperability levels
.. code-block:: javascript
jio.put({
"_id" : "...",
"identifier" : "http://dublincore.org/documents/interoperability-levels/",
"date" : "2009-05-01",
"format" : "text/html",
"type" : "Text",
"creator" : ["Mikael Nilsson", "Thomas Baker", "Pete Johnston"],
"publisher" : "Dublin Core Metadata Initiative",
"title" : "Interoperability Levels for Dublin Core Metadata",
"description" : "This document discusses the design choices involved " +
"in designing applications for different types of " +
"interoperability. [...]",
"language" : "en"
"_id" : "...",
"identifier" : "http://dublincore.org/documents/" +
"interoperability-levels/",
"date" : "2009-05-01",
"format" : "text/html",
"type" : "Text",
"creator" : [
"Mikael Nilsson",
"Thomas Baker",
"Pete Johnston"
],
"publisher" : "Dublin Core Metadata Initiative",
"title" : "Interoperability Levels for Dublin Core Metadata",
"description": "This document discusses the design choices " +
"involved in designing applications for " +
"different types of interoperability. [...]",
"language" : "en"
}, callbacks); // send content as attachment
......@@ -270,16 +326,17 @@ Posting an image
.. code-block:: javascript
jio.put({
"_id" : "...",
"identifier" : "new_york_city_at_night",
"format" : ["image/jpeg", "7.2 MB", "8192 x 4096 pixels"],
"date" : "1999",
"type" : "Image",
"creator" : "Mr. Someone",
"title" : "New York City at Night",
"subject" : ["New York"],
"description" : "A photo of New York City taken just after midnight",
"coverage" : ["New York", "1996-1997"]
"_id" : "...",
"identifier" : "new_york_city_at_night",
"format" : ["image/jpeg", "7.2 MB", "8192 x 4096 pixels"],
"date" : "1999",
"type" : "Image",
"creator" : "Mr. Someone",
"title" : "New York City at Night",
"subject" : ["New York"],
"description": "A photo of New York City " +
"taken just after midnight",
"coverage" : ["New York", "1996-1997"]
}, callbacks); // send content as attachment
......@@ -290,15 +347,24 @@ Posting a book
.. code-block:: javascript
jio.put({
"_id" : "...",
"identifier" : {"scheme": "DCTERMS.URI", "content": "urn:ISBN:0385424728"},
"format" : "application/pdf",
"date" : {"scheme": "DCTERMS.W3CDTF", "content": getW3CDate()}, // see tools below
"creator" : "Original Author(s)",
"publisher" : "Me",
"title" : {"lang": "en", "content": "..."},
"description" : {"lang": "en", "Summary: ..."},
"language" : {"scheme": "DCTERMS.RFC4646", "content": "en-GB"}
"_id" : "...",
"identifier" : {
"scheme": "DCTERMS.URI",
"content": "urn:ISBN:0385424728"
},
"format" : "application/pdf",
"date" : {
"scheme": "DCTERMS.W3CDTF",
"content": getW3CDate()
}, // see tools below
"creator" : "Original Author(s)",
"publisher" : "Me",
"title" : {"lang": "en", "content": "..."},
"description": {"lang": "en", "Summary: ..."},
"language" : {
"scheme": "DCTERMS.RFC4646",
"content": "en-GB"
}
}, callbakcs); // send content as attachment
......@@ -308,14 +374,14 @@ Posting a video
.. code-block:: javascript
jio.put({
"_id" : "...",
"identifier" : "my_video",
"format" : ["video/ogg", "130 MB", "1080p", "20 seconds"],
"date" : getW3CDate(), // see tools below
"type" : "Video",
"creator" : "Me",
"title" : "My life",
"description" : "A video about my life"
"_id" : "...",
"identifier" : "my_video",
"format" : ["video/ogg", "130 MB", "1080p", "20 seconds"],
"date" : getW3CDate(), // see tools below
"type" : "Video",
"creator" : "Me",
"title" : "My life",
"description": "A video about my life"
}, callbacks); // send content as attachment
......@@ -326,20 +392,20 @@ Posting a job announcement
.. code-block:: javascript
jio.post({
"format" : "text/html",
"date" : "2013-02-14T14:44Z",
"type" : "Text",
"creator" : "James Douglas",
"publisher" : "Morgan Healey Ltd",
"title" : "E-Commerce Product Manager",
"subject" : "Job Announcement",
"description" : "...",
"language" : "en-GB",
"source" : "James@morganhealey.com",
"relation" : ["Totaljobs"],
"coverage" : "London, South East",
"job_type" : "Permanent",
"salary" : "£45,000 per annum"
"format" : "text/html",
"date" : "2013-02-14T14:44Z",
"type" : "Text",
"creator" : "James Douglas",
"publisher" : "Morgan Healey Ltd",
"title" : "E-Commerce Product Manager",
"subject" : "Job Announcement",
"description": "...",
"language" : "en-GB",
"source" : "James@morganhealey.com",
"relation" : ["Totaljobs"],
"coverage" : "London, South East",
"job_type" : "Permanent",
"salary" : "£45,000 per annum"
}, callbacks); // send content as attachment
// result: http://www.totaljobs.com/JobSeeking/E-Commerce-Product-Manager_job55787655
......@@ -362,7 +428,10 @@ With complex query:
.. code-block:: javascript
jio.allDocs({"query": "subject: \"jIO\" AND category: \"resilience\""}, callbacks);
jio.allDocs({
"query": 'subject: "jIO" AND category: "resilience"'
},
callbacks);
......
......@@ -44,12 +44,12 @@ Bad Example
}
Use JSLint
^^^^^^^^^^
Using JSLint
^^^^^^^^^^^^
`JSLint <http://www.jslint.com/>`_ is a quality tool that inspects code and warns
about potential problems. It is available online and can also be integrated
into several development environments, so errors will be highlighted when
into several development environments, so errors can be highlighted when
writing code.
Before validating your code in JSLint, you should use a code
......@@ -59,9 +59,14 @@ are a number of beautifiers available online. The following ones seem to work be
* `JSbeautifier.org <http://jsbeautifier.org/>`_
* `JS-Beautify <http://alexis.m2osw.com/js-beautify/>`_
In this project, JavaScript sources have to begin with the header: :js:`/*jslint indent: 2,
maxlen: 80, nomen: true */`, which means it uses two spaces indentation, 80
maximum characters per line and the use of '_' as first character in a variable name is allowed.
In this project, JavaScript sources have to begin with the header:
.. code-block:: javascript
/*jslint indent: 2, maxlen: 80, nomen: true */
which means it uses two spaces indentation, 80
maximum characters per line and allows variable names starting with '_'.
Other JSLint options can be added in sub functions if necessary.
Some allowed options are:
......@@ -77,7 +82,7 @@ Some allowed options are:
Coding Conventions
------------------
Coding conventions include generic patterns that ensure that written code follows certain formatting conventions.
Coding conventions include generic patterns that ensure the written code follows certain formatting conventions.
Uses two-space indentation
......@@ -502,8 +507,8 @@ Additional Readings
Resources, additional reading materials and links:
* `JavaScript Patterns <http://shop.oreilly.com/product/9780596806767.do>`_, main ressource used.
* `JSLint <http://www.jslint.com/>`_, code quality.
* `JavaScript Patterns <http://shop.oreilly.com/product/9780596806767.do>`_, main resource used.
* `JSLint <http://www.jslint.com/>`_, code quality tool.
* `YUIDoc <http://yuilibrary.com/projects/yuidoc>`_, generate documentation from code.
......@@ -5,7 +5,7 @@ Revision Storages: Conflicts and Resolution
Why Conflicts can Occur
-----------------------
Using jIO you can store documents in multiple storage locations. With
Using jIO you can store documents in multiple locations. With an
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
......@@ -26,7 +26,7 @@ will select the **latest**, **left-most** version on the document tree, along wi
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
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
......@@ -35,13 +35,15 @@ version on all storages.
Simple Conflict Example
-----------------------
.. TODO this is a little confusing
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 changes this email from your PC
and once your smartphone is recharged, you go back online and the previous
update is executed.
#. Set up the storage tree
#. Set up the storage tree:
.. code-block:: javascript
......@@ -64,7 +66,7 @@ update is executed.
});
#. Create the namecard on your smartphone
#. Create the namecard on your smartphone:
.. code-block:: javascript
......@@ -76,9 +78,9 @@ update is executed.
// response.rev -> "1-5782E71F1E4BF698FA3793D9D5A96393"
});
This will create the document on your webDav and local storage
This will create the document on your WebDAV and local storage
#. Someone else updates your shared namecard on Webdav
#. Someone else updates your shared namecard on WebDAV:
.. code-block:: javascript
......@@ -92,9 +94,9 @@ update is executed.
});
Your smartphone is offline, so now you will have one version (1-578...) on
your smartphone and another version on webDav (2-068...) on your PC.
your smartphone and another version on WebDAV (2-068...) on your PC.
#. You modify the namecard while being offline
#. You modify the namecard while being offline:
.. code-block:: javascript
......@@ -114,7 +116,7 @@ update is executed.
});
#. Later, your smartphone is online and you retrieve the other version of the namecard.
#. Later, your smartphone is online and you retrieve the other version of the namecard:
.. code-block:: javascript
......@@ -128,7 +130,7 @@ update is executed.
left-most version on the document tree (2-375... and labels all other
versions as conflicting 2-068...).
#. Retrieve conflicts by setting option
#. Retrieve conflicts by setting option:
.. code-block:: javascript
......@@ -143,7 +145,7 @@ update is executed.
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
#. Delete conflicting version:
.. code-block:: javascript
......
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