Commit a1f3c2e9 authored by Tristan Cavelier's avatar Tristan Cavelier Committed by Sebastien Robin

Update jio.js and jio.storage.js

LocalStorage and DAVStorage seam to be functionnal.
ReplicateStorage is still missing.
parent 802a22f7
...@@ -6,20 +6,16 @@ ...@@ -6,20 +6,16 @@
<script type="text/javascript" src="js/jquery/jquery.js"></script> <script type="text/javascript" src="js/jquery/jquery.js"></script>
<script type="text/javascript" src="unhosted/jio.js"></script> <script type="text/javascript" src="unhosted/jio.js"></script>
<script type="text/javascript" src="unhosted/base64.js"></script> <script type="text/javascript" src="unhosted/base64.js"></script>
<script type="text/javascript" src="unhosted/sjcl.js"></script>
<script type="text/javascript" src="unhosted/jio.storage.js"></script> <script type="text/javascript" src="unhosted/jio.storage.js"></script>
<!-- <script type="text/javascript" src="unhosted/sjcl.js"></script> -->
</head> </head>
<body> <body>
<!-- <div id="test" class="test">&lt;div1&gt;</div>
<div id="test" class="test">&lt;div2&gt;</div> -->
<div id="divbody"> <div id="divbody">
<div id="divmessage"> <div id="divmessage"></div>
<div id="divdebug" style="color: grey"></div>
</div> <div id="diverror" style="color: red"></div>
<div id="divdebug" style="color: grey">
</div>
<div id="diverror" style="color: red">
</div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
...@@ -28,26 +24,117 @@ ...@@ -28,26 +24,117 @@
var objectDump = function (o) { var objectDump = function (o) {
console.log (JSON.stringify(o)); console.log (JSON.stringify(o));
}; };
var toString = function (o) {
return JSON.stringify(o);
};
var is_array = function (v) { var is_array = function (v) {
return Object.prototype.toString.apply(v) === '[object Array]'; return Object.prototype.toString.apply(v) === '[object Array]';
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Preparing jio
$.jio('subscribe',{'event':'job_done','func': function ( o ) {
$('#divdebug').html($('#divdebug').html() + '<br />' +
toString(o));
}});
$.jio('subscribe',{'event':'job_fail','func': function ( o ) {
$('#diverror').html($('#diverror').html() + '<br />' +
toString(o));
}});
$.jio('subscribe',{'event':'start_saving','func': function ( o ) {
$('#divmessage').html($('#divmessage').html() + '<br />' +
'Saving ...');
}});
$.jio('subscribe',{'event':'stop_saving','func': function ( o ) {
$('#divmessage').html($('#divmessage').html() + '<br />' +
'Saving ended.');
}});
$.jio('subscribe',{'event':'start_loading','func': function ( o ) {
$('#divmessage').html($('#divmessage').html() + '<br />' +
'Loading ...');
}});
$.jio('subscribe',{'event':'stop_loading','func': function ( o ) {
$('#divmessage').html($('#divmessage').html() + '<br />' +
'Loading ended.');
}});
$.jio('subscribe',{'event':'start_checkingNameAvailability', 'func': function ( o ) {
$('#divmessage').html($('#divmessage').html() + '<br />' +
'Checking name ' + o.job.userName + ' ...');
}});
$.jio('subscribe',{'event':'stop_checkingNameAvailability', 'func': function ( o ) {
$('#divmessage').html($('#divmessage').html() + '<br />' +
'Checking name ended: ' + o.job.message);
}});
$.jio('subscribe',{'event':'start_gettingList', 'func': function ( o ) {
$('#divmessage').html($('#divmessage').html() + '<br />' +
'Getting list ...');
}});
$.jio('subscribe',{'event':'stop_gettingList', 'func': function ( o ) {
$('#divmessage').html($('#divmessage').html() + '<br />' +
'Getting list ended: ' + toString(o.job.list) );
}});
// $.jio({'storage':{'type':'local','userName':'tristan'},
// 'applicant':{'ID':'www.ungproject.org'}});
$.jio({'storage':{'type':'dav','userName':'tristan','password':'test',
'location':'https://ca-davstorage:8080','provider':'Unknown'},
'applicant':{'ID':'www.ungproject.org'}});
// $.jio('isAvailable',{'userName':'toto'});
// $.jio('isAvailable',{'userName':'tristan'});
// $.jio('save',{'fileName':'SonNom','fileContent':'SonContenu'});
// $.jio({'fileName':'SonNom','fileContent':'SonContenu','method':'save'});
// $.jio({'fileName':'SonNom2','fileContent':'SonContenu2','method':'save'});
// $.jio('load',{'fileName':'SonNom'});
$.jio('getList');
////////////////////////////////////////////////////////////////////////////////
/*
// Preparing JIO // Preparing JIO
//// Setting events reactions //// Setting events reactions
JIO.subscribe('job_done', function (job) { JIO.subscribe('job_done', function (job) {
$('#divdebug').html($('#divdebug').html() + '<br/>' +
job.method + ': "' + job.fileName + '" OK!');
switch(job.method) { switch(job.method) {
case 'load': case 'load':
objectDump(job); objectDump(job);
$('#divdebug').html($('#divdebug').html() + $('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.fileName + '" OK!' +
' Content : "' + job.file.content + '"'); ' Content : "' + job.file.content + '"');
break; break;
case 'userNameAvailable':
objectDump(job);
$('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.userName + '" OK!' +
' isAvailable ? "' + job.userIsAvailable + '"' +
' message : ' + job.message);
break;
default:
objectDump(job);
$('#divdebug').html($('#divdebug').html() + '<br />' +
job.method + ': "' + job.fileName + '" OK!');
break;
} }
}); });
JIO.subscribe('job_fail', function (job) { JIO.subscribe('job_fail', function (job) {
$('#diverror').html($('#diverror').html() + '<br/>' + $('#diverror').html($('#diverror').html() + '<br/>' +
job.method + ': "' + job.fileName + '" FAILED! ' + job.message); job.method + ': "' + job.fileName + '" FAILED! ' +
job.message);
}); });
JIO.subscribe('start_saving', function () { JIO.subscribe('start_saving', function () {
console.log ('start_saving received'); console.log ('start_saving received');
...@@ -103,21 +190,26 @@ JIO.subscribe('stop_loading', function () { ...@@ -103,21 +190,26 @@ JIO.subscribe('stop_loading', function () {
//// init JIO //// init JIO
JIO.initialize({"type":"local","userName":"tristan"},"www.ungproject.com"); JIO.initialize({"type":"local","userName":"tristan"},"www.ungproject.com");
if ( !JIO.isReady() ) alert('Not ready');
//// end init //// end init
//// Let's test! //// Let's test!
JIO.loadDocument("SonNom"); if ( !JIO.isReady() ) alert('Not ready');
// JIO.saveDocument("Inside the document.","SonNom"); else {
// JIO.saveDocument("Inside the document.","SonNom");
// JIO.saveDocument("Inside the document.","SonNom2"); // JIO.userNameAvailable("tristan");
// JIO.getDocumentList(); // JIO.userNameAvailable("json");
// JIO.loadDocument("SonNom"); // JIO.loadDocument("SonNom");
// JIO.deleteDocument("SonNom"); // JIO.saveDocument("Inside the document.","SonNom");
// JIO.deleteDocument("SonNom"); // JIO.saveDocument("Inside the document.","SonNom");
// JIO.deleteDocument("SonNom3"); // JIO.saveDocument("Inside the document.","SonNom2");
// JIO.getDocumentList(); // JIO.getDocumentList();
// JIO.loadDocument("SonNom");
// JIO.deleteDocument("SonNom");
// JIO.deleteDocument("SonNom");
// JIO.deleteDocument("SonNom3");
// JIO.getDocumentList();
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/* */
//--> //-->
</script> </script>
</body> </body>
......
/*
JIO: Javascript I/O. A library to load, edit, save documents to
multiple storage backends using a common interface
*/
(function() {
////////////////////////////////////////////////////////////////////////////
// Define constants
var C = {
'STATUS_INITIAL': 'initial',
'STATUS_DONE': 'done',
'STATUS_ONGOING': 'ongoing',
'STATUS_FAIL': 'fail',
'METHOD_AVAILABLE': 'userNameAvailable',
'METHOD_SAVE': 'save',
'METHOD_LOAD': 'load',
'METHOD_GETLIST': 'getList',
'METHOD_DELETE': 'delete',
'EVENT_PREFIX': 'jio:',
'EVENT_JOB_DONE': 'job_done',
'EVENT_JOB_FAIL': 'job_fail',
'EVENT_START_AVAILABLE': 'start_usernameavailable',
'EVENT_STOP_AVAILABLE': 'stop_usernameavailable',
'EVENT_START_SAVING': 'start_saving',
'EVENT_STOP_SAVING': 'stop_saving',
'EVENT_START_LOADING': 'start_loading',
'EVENT_STOP_LOADING': 'stop_loading',
'EVENT_START_GETTINGLIST': 'start_gettinglist',
'EVENT_STOP_GETTINGLIST': 'stop_gettinglist',
'EVENT_START_DELETING': 'start_deleting',
'EVENT_STOP_DELETING': 'stop_deleting',
'FUNC_AVAILABLE':'userNameAvailableFromJob',
'FUNC_SAVE':'saveDocumentFromJob',
'FUNC_LOAD':'loadDocumentFromJob',
'FUNC_GETLIST':'getListFromJob',
'FUNC_DELETE':'deleteDocumentFromJob',
'DEFAULT_INTERVAL_DELAY': 100
};
C['DEFAULT_CONST_OBJECT'] = {};
C['DEFAULT_CONST_OBJECT'][C.METHOD_AVAILABLE] = {
'STARTEVENT':C.EVENT_START_AVAILABLE,
'STOPEVENT':C.EVENT_STOP_AVAILABLE,
'FUNC':C.FUNC_AVAILABLE};
C['DEFAULT_CONST_OBJECT'][C.METHOD_SAVE] = {
'STARTEVENT':C.EVENT_START_SAVING,
'STOPEVENT':C.EVENT_STOP_SAVING,
'FUNC':C.FUNC_SAVE};
C['DEFAULT_CONST_OBJECT'][C.METHOD_LOAD] = {
'STARTEVENT':C.EVENT_START_LOADING,
'STOPEVENT':C.EVENT_STOP_LOADING,
'FUNC':C.FUNC_LOAD};
C['DEFAULT_CONST_OBJECT'][C.METHOD_GETLIST] = {
'STARTEVENT':C.EVENT_START_GETTINGLIST,
'STOPEVENT':C.EVENT_STOP_GETTINGLIST,
'FUNC':C.FUNC_GETLIST};
C['DEFAULT_CONST_OBJECT'][C.METHOD_DELETE] = {
'STARTEVENT':C.EVENT_START_DELETING,
'STOPEVENT':C.EVENT_STOP_DELETING,
'FUNC':C.FUNC_DELETE};
var storageTypeObject = {};
var queue = null; // the jobs manager
var jioStorage = null;
var jioApplicant = null;
// TODO stock statusobject for this tab ? faster ? better ?
////////////////////////////////////////////////////////////////////////////
// JIO main object. Contains all IO methods
var JIO = {
listener: null,
/**
* prepare and return the jio object
* @param jioData : text or json content of jio.json or method to get it
* @param applicant : (optional) information about the person/application needing this JIO object (used to limit access)
* @return JIO object
*/
initialize: function(jioData, applicant) {
// JIO initialize
// jioData: object containing storage informations
// {type:,userName:,etc}
// applicant: a string of the applicant name
jioApplicant = {"ID":applicant};
if (!applicant) return false; // TODO to know: return false or alert user ?
if (!dependenceLoaded()) {
setTimeout(function() {JIO.initialize(jioData, jioApplicant);},50);
} else {
switch(typeof jioData) {
case "string" :
jioStorage = JSON.parse(jioData);
break;
case "object" :
jioStorage = jioData;
break;
case "function" :
jioStorage = jioData();
break;
default:
alert("Error while getting jio.json content");
break;
}
this.addStorageType('local',function (stor,app) {
return new JIO.LocalStorage(stor,app);
});
queue = new JIO.JobQueue();
this.listener = new JIO.JobListener(C.DEFAULT_INTERVAL_DELAY);
this.listener.start();
}
},
/**
* return the state of JIO object
* @return true if ready, false otherwise
*/
isReady: function() {if(queue && jioStorage) return true; return false;},
//IO functions
getLocation: function() {return this.location},
userNameAvailable: function(name) {
return queue.addJob (jioStorage,
new JIO.JobUser(C.METHOD_AVAILABLE,name));
},
loadDocument: function(fileName) {
return queue.addJob (jioStorage,
new JIO.Job(C.METHOD_LOAD,fileName));
},
saveDocument: function(fileContent, fileName) {
return queue.addJob (jioStorage,
new JIO.Job(C.METHOD_SAVE,fileName,fileContent));
},
deleteDocument: function(fileName) {
return queue.addJob (jioStorage,
new JIO.Job(C.METHOD_DELETE,fileName));
},
getDocumentList: function() {
return queue.addJob (jioStorage,
new JIO.Job(C.METHOD_GETLIST));
},
publish: function(event,obj) {
pubSub.publish(event,obj);
},
subscribe: function(event,func) {
pubSub.subscribe(event,func);
},
unsubscribe: function(event) {
pubSub.unsubscribe(event);
},
getApplicant: function() {
return jioApplicant;
},
getConstantObject: function() {
// return a copy of the constants
return JSON.parse(JSON.stringify(C));
},
addStorageType: function(newType,storageCreator) {
storageTypeObject[newType] = storageCreator;
}
}
// End JIO object
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// Publisher Subscriber
var pubSub = new function () {
var topics = {};
$.JIOPubSub = function (id) {
var callbacks;
var topic = id && topics[id];
if (!topic) {
callbacks = $.Callbacks();
topic = {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
if (id) {
topics[id] = topic;
}
}
return topic;
}
this.publish = function (eventname,obj) {
$.JIOPubSub(C.EVENT_PREFIX + eventname).publish(obj);
},
this.subscribe = function (eventname,func) {
$.JIOPubSub(C.EVENT_PREFIX + eventname).subscribe(func);
},
this.unsubscribe = function (eventname) {
$.JIOPubSub(C.EVENT_PREFIX + eventname).unsubscribe();
}
};
// End Publisher Subscriber
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// JIO Job Listener
JIO.JobListener = function (interval) {
// A little daemon which will start jobs from the joblist
this.interval = (interval ? interval : 200);
this.id = null;
};
JIO.JobListener.prototype = {
/**
* Set the time between two joblist check in millisec
*/
setIntervalDelay: function (interval) {
this.interval = interval;
},
/**
* Wait for jobs in the joblist inside the localStorage
*/
start: function () {this.id = setInterval (function(){
// if there are jobs
if (localStorage.joblist &&
localStorage.joblist !== '[]') {
queue.invokeAll();
}
},this.interval);},
/**
* Stop the listener
*/
stop: function () {
console.log ('stop listening');
clearInterval (this.id);
this.id = null;
}
};
// End Job Listener
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// Job & JobQueue
/**
* Function parameters
* Parameter storage: Constains {type:local/dav/...,userName:...,...}.
* Must be an 'object'.
* Parameter job: Contains {[id:..,]method:save/load/delete,
* fileName:name,fileContent:content[,status:"initial"]}.
* May be a 'string' or an 'object'
*/
JIO.Job = function (method,filename,filecontent) {
// Job Constructor & initializer
var tmp = {'id':0}
tmp['method'] = method;
tmp['fileName'] = filename;
tmp['fileContent'] = filecontent;
tmp['status'] = C.STATUS_INITIAL;
return tmp;
};
JIO.JobUser = function (method,username) {
// JobUser Constructor & initializer
var tmp = {'id':0}
tmp['method'] = method;
tmp['userName'] = username;
tmp['status'] = C.STATUS_INITIAL;
return tmp;
};
JIO.JobQueue = function () {
//// set first job ID
this.jobid = 1;
var localjoblist = getJobArrayFromLocalStorage();
if (localjoblist.length > 0) {
this.jobid = localjoblist[localjoblist.length - 1].id + 1;
};
localjoblist = null; // it is not necessary to fill memory with
// unused vars
// reset all jobs' status to initial
this.resetAll();
var returnedJobAnalyse = function (job) {
// analyse the [job]
//// analysing job method
if (!C.DEFAULT_CONST_OBJECT[job.method])
return false;
if (!ifRemainingJobs(job.method)) {
var statusobject = getStatusObjectFromLocalStorage();
statusobject[job.method] = C.STATUS_DONE;
setStatusObjectToLocalStorage(statusobject);
switch (job.method) {
case C.METHOD_GETLIST:
// TODO merge list if necessary (we can create
// this.getList, deleted after sending the event,
// filled with done event) -> merge here or show
// possible actions (manually, auto, ...)
JIO.publish (C.DEFAULT_CONST_OBJECT[job.method].STOPEVENT/*, merged list*/);
// deleting list
return;
default: // if it was not a specific method
JIO.publish (C.DEFAULT_CONST_OBJECT[job.method].STOPEVENT);
return;
}
}
//// end analyse
};
//// subscribe an event
var t = this;
JIO.subscribe (C.EVENT_JOB_DONE, function (job) {
console.log (C.EVENT_JOB_DONE+'_received');
t.done(job);
returnedJobAnalyse (job);
});
JIO.subscribe (C.EVENT_JOB_FAIL, function (job) {
console.log (C.EVENT_JOB_FAIL+'_received');
t.fail(job);
returnedJobAnalyse (job);
});
//// end subscribing
};
JIO.JobQueue.prototype = {
addJob: function (storage,job) {
// Add a job to the Job list
// storage : the storage object
// job : the job object (may be a 'string')
console.log ('addJob');
//// Adding job to the list in localStorage
// transforming job to an object
if ((typeof job) === 'string') job = JSON.parse(job);
// create joblist in local storage if unset
if (!localStorage.joblist) localStorage.joblist = "[]";
// set job id
job.id = this.jobid;
this.jobid ++;
// set job storage
job.storage = storage;
// save the new job
var localjoblist = getJobArrayFromLocalStorage();
localjoblist.push(job);
setJobArrayToLocalStorage (localjoblist);
//// job added
}, // end addJob
resetAll: function () {
// reset All job to 'initial'
console.log ('resetAll');
var jobarray = getJobArrayFromLocalStorage();
for (var i in jobarray) {
jobarray[i].status = C.STATUS_INITIAL;
}
setJobArrayToLocalStorage(jobarray);
},
invokeAll: function () {
// Do all jobs in the list
//// do All jobs
var jobarray = getJobArrayFromLocalStorage();
for (var i in jobarray) {
if (jobarray[i].status === C.STATUS_INITIAL) {
jobarray[i].status = C.STATUS_ONGOING;
this.invoke(jobarray[i]);
}
}
setJobArrayToLocalStorage(jobarray);
//// end, continue doing jobs asynchronously
},
invoke: function (job) {
// Do a job
console.log ('invoke');
//// analysing job method
// browsing methods
if (!C.DEFAULT_CONST_OBJECT[job.method])
// TODO do an appropriate error reaction ? unknown job method
return false;
var statusobject = getStatusObjectFromLocalStorage ();
objectDump(statusobject);
if (statusobject[job.method] === C.STATUS_DONE) {
statusobject[job.method] = C.STATUS_ONGOING;
setStatusObjectToLocalStorage(statusobject);
JIO.publish (C.DEFAULT_CONST_OBJECT[job.method].STARTEVENT);
}
// create an object and use it to save,load,...!
createStorageObject(job.storage,jioApplicant)[
C.DEFAULT_CONST_OBJECT[job.method].FUNC
](job,true); // overwrite
//// end method analyse
},
done: function (job) {
// This job is supposed done, we can remove it from localStorage.
console.log ('done');
var localjoblist = getJobArrayFromLocalStorage ();
// remove the job from the job list
localjoblist = arrayRemoveValues (localjoblist,function (o) {
return (o.id === job.id);
});
// save to local storage
setJobArrayToLocalStorage (localjoblist);
},
fail: function (job) {
// This job cannot be done, change its status into localStorage.
console.log ('fail');
var localjoblist = getJobArrayFromLocalStorage ();
//// find this unique job inside the list
for (var i in localjoblist) {
if (localjoblist[i].id === job.id) {
localjoblist[i] = job;
break;
}
}
// save to local storage
setJobArrayToLocalStorage (localjoblist);
},
clean: function () {
// Clean the job list, removing all jobs that have failed.
// It also change the localStorage Job list
setJobArrayToLocalStorage(
arrayRemoveValues(
getJobArrayFromLocalStorage(),
function(j){return (j.status === C.STATUS_FAIL);}
)
);
}
}; // end JIO.JobQueue
// End Job & JobQueue
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// LOCAL STORAGE
/**
* Class LocalStorage
* @class provides usual API to save/load/delete documents on the localStorage
* @param storagedata : object containing every element needed to build the storage
* @param applicant : object containing inforamtion about the person/application needing this JIO object
*/
JIO.LocalStorage = function(storagedata,applicant) {
this.applicant = applicant;
//// check user's localStorage part
this.userName = storagedata.userName;
if(!localStorage.getItem(this.userName)) {
localStorage[this.userName] = '{}'; // Create user
}
//// end check
}
JIO.LocalStorage.prototype = {
getDocumentsFromLocalStorage: function() {
return JSON.parse(localStorage[this.userName]);
},
writeToLocalStorage: function(documents) {
localStorage[this.userName] = JSON.stringify(documents);
}
}
/**
* check if an user already exist
* @param name : the name you want to check
* @return true if the name is free, false otherwise
*/
JIO.LocalStorage.prototype[C.FUNC_AVAILABLE] = function(job) {
setTimeout(function () {
if (localStorage[job.userName]) {
job.status = C.STATUS_DONE;
job.message = '' + job.userName + ' is not available.';
job.userIsAvailable = false;
JIO.publish (C.EVENT_JOB_DONE,job);
return false;
}
job.status = C.STATUS_DONE;
job.message = '' + job.userName + ' is available.';
job.userIsAvailable = true;
JIO.publish (C.EVENT_JOB_DONE,job);
return true;
}, C.DEFAULT_INTERVAL_DELAY);
};
/**
* save a document in the local storage from a job
* @param job : contains all the information to save the document
* @param overwrite : a boolean set to true if the document has to be overwritten
*/
JIO.LocalStorage.prototype[C.FUNC_SAVE] = function(job, overwrite) {
var t = this;
// wait a little in order to let some other instructions to continue
setTimeout(function () {
var documents = t.getDocumentsFromLocalStorage();
// TODO check modification date !!!
if(!documents[job.fileName]) { // create document
documents[job.fileName] = {
'fileName': job.fileName,
'content': job.fileContent,
'creationDate': Date.now(),
'lastModified': Date.now()
}
t.writeToLocalStorage();
job.status=C.STATUS_DONE;
job.message='success';
JIO.publish(C.EVENT_JOB_DONE,job);
return;
} else {
if(overwrite === true) { // overwrite
documents[job.fileName].lastModified = Date.now();
documents[job.fileName].content = job.fileContent;
t.writeToLocalStorage(documents);
job.status=C.STATUS_DONE;
job.message='success';
JIO.publish(C.EVENT_JOB_DONE,job);
return;
} else {
job.status=C.STATUS_FAIL;
job.message='Document already exists.';
job.errno=403;
JIO.publish(C.EVENT_JOB_FAIL,job);
return;
}
}
}, C.DEFAULT_INTERVAL_DELAY);
return;
} // end saveDocumentFromJob
/**
* load a document in the storage, copy the content into the job,
* then the function sends the job with an event.
* @param job : the job that contains all informations about
* loading operation.
*/
JIO.LocalStorage.prototype[C.FUNC_LOAD] = function(job) {
var t = this;
// wait a little in order to let some other instructions to continue
setTimeout(function () {
var documents = t.getDocumentsFromLocalStorage();
if(!documents[job.fileName]) {
job.status=C.STATUS_FAIL;
job.errno=404;
job.message='Document not found.';
JIO.publish (C.EVENT_JOB_FAIL,job);
} else {
job.status=C.STATUS_DONE;
job.file=documents[job.fileName];
job.message='success';
JIO.publish (C.EVENT_JOB_DONE,job);
}
}, C.DEFAULT_INTERVAL_DELAY)
}; // end loadDocumentFromJob
/**
* load the list of the documents in this storage
* @param job : the job that contains all informations about
* getting list operation.
*/
JIO.LocalStorage.prototype[C.FUNC_GETLIST] = function(job) {
// TODO update it
var t = this;
setTimeout(function () {
var documents = t.getDocumentsFromLocalStorage();
job.list = [];
for (var key in documents) {
job.list.push ({
'fileName':documents[key].fileName,
'creationDate':documents[key].creationDate,
'lastModified':documents[key].lastModified
});
}
JIO.publish (C.EVENT_JOB_DONE,job);
}, C.DEFAULT_INTERVAL_DELAY);
}; // end getListFromJob
/**
* Delete a document or a list of documents from the storage
* @param fileName : fileName to delete
* @param options : optional object containing
*/
JIO.LocalStorage.prototype[C.FUNC_DELETE] = function(job) {
// TODO update it
var t = this;
setTimeout (function () {
var documents = t.getDocumentsFromLocalStorage();
// TODO is it realy a problem if we try to delete a deleted file ?
if (!documents[job.fileName]) {
job.status = C.STATUS_FAIL;
job.errno = 404;
job.message = 'Document not found.';
JIO.publish (C.EVENT_JOB_FAIL,job);
return;
}
delete documents[job.fileName];
t.writeToLocalStorage(documents);
job.status = C.STATUS_DONE;
job.message = 'success';
JIO.publish (C.EVENT_JOB_DONE,job);
return;
}, C.DEFAULT_INTERVAL_DELAY);
}; // end deleteDocumentFromJob
// END LOCAL STORAGE
////////////////////////////////////////////////////////////////////////////
///////////
// Tools //
///////////
var dependenceLoaded = function () {
// tests if the dependencies are loaded
try {
// check jQuery
if ($)
return true;
else return false;
} catch (e) {
return false;
}
};
var ifRemainingJobs = function(method) {
// check if it remains [method] jobs (save,load,...)
// method : can me 'string' or 'undefined'
// undefined -> test if there is at least one job
// string -> test if there is at least one [method] job
if (!method) return (localStorage.joblist !== '[]');
joba = getJobArrayFromLocalStorage();
for (var k in joba) {
if (joba[k].method === method &&
joba[k].status !== C.STATUS_FAIL) return true;
}
return false;
};
/**
* Create a storage with [data] informations
* @param data : information found in jio.json and needed to create the storage
* @param applicant : information about the person/application needing this JIO object (allow limited access)
*/
function createStorageObject(data,applicant) {
if (!storageTypeObject[data.type])
return null; // error!
return storageTypeObject[data.type](data,applicant);
}
var checkOptionObject = function (current,defaultopts) {
if(!current) {
return defaultopts;
}
for (var k in defaultopts) {
if (current[k] === undefined)
current[k] = defaultopts[k];
}
return current;
};
var getJobArrayFromLocalStorage = function () {
var localjoblist = [];
if (localStorage.joblist)
localjoblist = JSON.parse(localStorage.joblist);
return localjoblist;
};
var setJobArrayToLocalStorage = function (jobarray) {
localStorage.joblist = JSON.stringify(jobarray);
};
var getStatusObjectFromLocalStorage = function () {
var tmp = {};
if (localStorage.status) {
tmp = JSON.parse (localStorage.status);
} else {
for (var Method in C.DEFAULT_CONST_OBJECT) {
tmp[Method] = C.STATUS_DONE;
}
}
return tmp;
};
var setStatusObjectToLocalStorage = function (statusobject) {
localStorage.status = JSON.stringify(statusobject);
};
var arrayRemoveValues = function (a,testfunc) {
// Removes the values from [a] where [testfunc(value)] returns true.
var isArray = function (a) {
return Object.prototype.toString.apply(a) === '[object Array]';
};
if (!isArray(a)) return a;
var na = [];
for (var k in a) {
if (!testfunc(a[k]))
na.push (a[k]);
}
return na;
};
// TODO DEBUG we can remove this function
var objectDump = function (o) {
console.log (JSON.stringify(o));
};
// the name to use for the framework. Ex : JIO.initialize(...), JIO.loadDocument...
window.JIO = JIO;
})();
/*
JIO: Javascript I/O. A library to load, edit, save documents to
multiple storage backends using a common interface
*/
(function() {
;(function ( $ ) {
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Define constants // private vars
var attr = {
var C = { 'jobMethodObject': {
'METHOD_SAVE': 'save', 'isAvailable': {
'METHOD_LOAD': 'load', 'start_event':'start_checkingNameAvailability',
'METHOD_GETLIST': 'getList', 'stop_event':'stop_checkingNameAvailability',
'METHOD_DELETE': 'delete', 'func':'checkNameAvailability',
'STATUS_INITIAL': 'initial', 'retvalue':'isAvailable' }, // returns 'boolean'
'STATUS_DONE': 'done', 'save': {
'STATUS_ONGOING': 'ongoing', 'start_event':'start_saving',
'STATUS_FAIL': 'fail', 'stop_event':'stop_saving',
'EVENT_PREFIX': 'jio:', 'func':'saveDocument',
'EVENT_JOB_DONE': 'job_done', 'retvalue':'isSaved' }, // returns 'boolean'
'EVENT_JOB_FAIL': 'job_fail', 'load': {
'EVENT_START_SAVING': 'start_saving', 'start_event':'start_loading',
'EVENT_STOP_SAVING': 'stop_saving', 'stop_event':'stop_loading',
'EVENT_START_LOADING': 'start_loading', 'func':'loadDocument',
'EVENT_STOP_LOADING': 'stop_loading', 'retvalue':'fileContent' }, // returns the file content 'string'
'EVENT_START_GETTINGLIST': 'start_gettinglist', 'getList': {
'EVENT_STOP_GETTINGLIST': 'stop_gettinglist', 'start_event':'start_gettingList',
'EVENT_START_DELETING': 'start_deleting', 'stop_event':'stop_gettingList',
'EVENT_STOP_DELETING': 'stop_deleting', 'func':'getDocumentList',
'FUNC_SAVE':'saveDocumentFromJob', 'retvalue':'list' }, // returns the document list 'array'
'FUNC_LOAD':'loadDocumentFromJob', 'remove': {
'FUNC_GETLIST':'getListFromJob', 'start_event':'start_removing',
'FUNC_DELETE':'deleteDocumentFromJob', 'stop_event':'stop_removing',
'DEFAULT_INTERVAL_DELAY': 100 'func':'removeDocument',
'retvalue':'isRemoved' } // returns 'boolean'
},
'queue': null, // the job manager
'storage': null, // the storage given at init
'applicant': null, // the applicant given at init
'listener': null, // the job listener
'pubsub': null, // publisher subscriber
'isReady': false, // check if jio is ready
'storageTypeObject': {}
}; };
C['DEFAULT_CONST_OBJECT'] = {};
C['DEFAULT_CONST_OBJECT'][C.METHOD_SAVE] = {
'STARTEVENT':C.EVENT_START_SAVING,
'STOPEVENT':C.EVENT_STOP_SAVING,
'FUNC':C.FUNC_SAVE};
C['DEFAULT_CONST_OBJECT'][C.METHOD_LOAD] = {
'STARTEVENT':C.EVENT_START_LOADING,
'STOPEVENT':C.EVENT_STOP_LOADING,
'FUNC':C.FUNC_LOAD};
C['DEFAULT_CONST_OBJECT'][C.METHOD_GETLIST] = {
'STARTEVENT':C.EVENT_START_GETTINGLIST,
'STOPEVENT':C.EVENT_STOP_GETTINGLIST,
'FUNC':C.FUNC_GETLIST};
C['DEFAULT_CONST_OBJECT'][C.METHOD_DELETE] = {
'STARTEVENT':C.EVENT_START_DELETING,
'STOPEVENT':C.EVENT_STOP_DELETING,
'FUNC':C.FUNC_DELETE};
var storageTypeObject = {};
var queue = null; // the jobs manager
var jioStorage = null;
var jioApplicant = null;
// TODO stock statusobject for this tab ? faster ? better ?
// end private vars
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// JIO main object. Contains all IO methods
var JIO = {
listener: null,
/**
* prepare and return the jio object
* @param jioData : text or json content of jio.json or method to get it
* @param applicant : (optional) information about the person/application needing this JIO object (used to limit access)
* @return JIO object
*/
initialize: function(jioData, applicant) {
// JIO initialize
// jioData: object containing storage informations
// {type:,userName:,etc}
// applicant: a string of the applicant name
jioApplicant = {"ID":applicant};
if (!applicant) return false; // TODO to know: return false or alert user ?
if (!dependenceLoaded()) {
setTimeout(function() {JIO.initialize(jioData, jioApplicant)},50);
} else {
switch(typeof jioData) {
case "string" :
jioStorage = JSON.parse(jioData);
break;
case "object" :
jioStorage = jioData;
break;
case "function" :
jioStorage = jioData();
break;
default:
alert("Error while getting jio.json content");
break;
}
this.addStorageType('local',function (stor,app) {
return new JIO.LocalStorage(stor,app);
});
queue = new JIO.JobQueue();
this.listener = new JIO.JobListener(C.DEFAULT_INTERVAL_DELAY);
this.listener.start();
}
},
/**
* return the state of JIO object
* @return true if ready, false otherwise
*/
isReady: function() {if(queue && jioStorage) return true; return false;},
//IO functions
getLocation: function() {return this.location},
userNameAvailable: function(name, options) {
// return this.storage.userNameAvailable(name, options !== undefined ? options : {});
},
loadDocument: function(fileName) {
return queue.addJob (jioStorage,
new JIO.Job(C.METHOD_LOAD,fileName));
},
saveDocument: function(fileContent, fileName) {
return queue.addJob (jioStorage,
new JIO.Job(C.METHOD_SAVE,fileName,fileContent));
},
deleteDocument: function(fileName, options) {
console.error ('niy');
// return this.jioMessage.postMessage (
// {"method":"delete","fileName":fileName,"status":"initial"},
// options);
},
getDocumentList: function(options) {
console.error ('niy');
// return this.jioMessage.postMessage (
// {"method":"getList","status":"initial"},
// options);
},
publish: function(event,obj) {
pubSub.publish(event,obj);
},
subscribe: function(event,func) {
pubSub.subscribe(event,func);
},
unsubscribe: function(event) {
pubSub.unsubscribe(event);
},
getApplicant: function() {
return jioApplicant;
},
getConstantObject: function() {
return C;
},
addStorageType: function(newType,storageCreator) {
storageTypeObject[newType] = storageCreator;
}
}
// End JIO object
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Tools
var objectDump = function (o) {
// TODO DEBUG we can remove this function
console.log (JSON.stringify(o));
};
var toString = function (o) {
// TODO DEBUG we can remove this function
return (JSON.stringify(o));
};
var supportLocalStorage = function () {
// Modernizr function
try { return !!localStorage.getItem; }
catch (e) { return false; }
};
var ifRemainingJobs = function(method) {
// check if it remains [method] jobs (save,load,...)
// method : can me 'string' or 'undefined'
// undefined -> test if there is at least one job
// string -> test if there is at least one [method] job
//////////////////////////////////////////////////////////////////////////// if (!method) return (localStorage.joblist !== '[]');
// Publisher Subscriber var joba = getJobArrayFromLocalStorage();
for (var k in joba) {
var pubSub = new function () { if (joba[k].method === method &&
var topics = {}; joba[k].status !== 'fail') return true;
$.JIOPubSub = function (id) {
var callbacks;
var topic = id && topics[id];
if (!topic) {
callbacks = $.Callbacks();
topic = {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
if (id) {
topics[id] = topic;
}
}
return topic;
} }
this.publish = function (eventname,obj) { return false;
$.JIOPubSub(C.EVENT_PREFIX + eventname).publish(obj); };
}, var getStatusObjectFromLocalStorage = function () {
this.subscribe = function (eventname,func) { var tmp = {};
$.JIOPubSub(C.EVENT_PREFIX + eventname).subscribe(func); if (localStorage.status) {
}, tmp = JSON.parse (localStorage.status);
this.unsubscribe = function (eventname) { } else { // if it does not exists, create it
$.JIOPubSub(C.EVENT_PREFIX + eventname).unsubscribe(); for (var method in attr.jobMethodObject) {
tmp[method] = 'done';
}
} }
return tmp;
}; };
var setStatusObjectToLocalStorage = function (statusobject) {
// End Publisher Subscriber localStorage.status = JSON.stringify(statusobject);
//////////////////////////////////////////////////////////////////////////// };
var getJobArrayFromLocalStorage = function () {
var localjoblist = [];
if (localStorage.joblist)
localjoblist = JSON.parse(localStorage.joblist);
return localjoblist;
};
var setJobArrayToLocalStorage = function (jobarray) {
localStorage.joblist = JSON.stringify(jobarray);
};
var createStorageObject = function ( options ) {
// create a storage thanks to attr.storageTypeObject
if (!attr.storageTypeObject[ options.storage.type])
return null; // error!
return attr.storageTypeObject[ options.storage.type ](options);
}
// end Tools
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// JIO Job Listener
JIO.JobListener = function (interval) { ////////////////////////////////////////////////////////////////////////////
// A little daemon which will start jobs from the joblist // Publisher Subcriber
var PubSub = function () {
this.interval = (interval ? interval : 200); if (!$.jiopubsub) {
this.id = null; var topics = {};
$.jiopubsub = function (id) {
var callbacks;
var topic = id && topics[id];
if (!topic) {
callbacks = $.Callbacks();
topic = {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
if (id) {
topics[id] = topic;
}
}
return topic;
};
}
}; };
PubSub.prototype = {
JIO.JobListener.prototype = { publish: function (eventname,obj) {
$.jiopubsub(eventname).publish(obj);
/**
* Set the time between two joblist check in millisec
*/
setIntervalDelay: function (interval) {
this.interval = interval;
}, },
subscribe: function (eventname,func) {
/** $.jiopubsub(eventname).subscribe(func);
* Wait for jobs in the joblist inside the localStorage },
*/ unsubscribe: function (eventname) {
start: function () {this.id = setInterval (function(){ $.jiopubsub(eventname).unsubscribe();
// if there are jobs
if (localStorage.joblist &&
localStorage.joblist !== '[]') {
queue.invokeAll();
}
},this.interval);},
/**
* Stop the listener
*/
stop: function () {
console.log ('stop listening');
clearInterval (this.id);
this.id = null;
} }
}; };
attr.pubsub = new PubSub();
// End Job Listener // end Publisher Subcriber
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Job & JobQueue // Job & JobQueue
var Job = function ( options ) {
/** // Job constructor
* Function parameters console.log ('Job');
* Parameter storage: Constains {type:local/dav/...,userName:...,...}. var job = $.extend({},options);
* Must be an 'object'. job['id']=0;
* Parameter job: Contains {[id:..,]method:save/load/delete, job['status']='initial';
* fileName:name,fileContent:content[,status:"initial"]}. return job;
* May be a 'string' or an 'object'
*/
JIO.Job = function (method,filename,filecontent) {
// Job Constructor & initializer
return {'id':0,'method':method,'fileName':filename,
'fileContent':filecontent,'status':C.STATUS_INITIAL};
}; };
JIO.JobQueue = function () { var JobQueue = function () {
//// set first job ID //// set first job ID
console.log ('Queue');
this.jobid = 1; this.jobid = 1;
var localjoblist = getJobArrayFromLocalStorage(); var localjoblist = getJobArrayFromLocalStorage();
if (localjoblist.length > 0) { if (localjoblist.length > 0) {
this.jobid = localjoblist[localjoblist.length - 1].id + 1; this.jobid = localjoblist[localjoblist.length - 1].id + 1;
}; };
localjoblist = null; // it is not necessary to fill memory with localjoblist = undefined; // it is not necessary to fill memory with
// unused vars
// reset all jobs' status to initial // reset all jobs' status to initial
this.resetAll(); this.resetAll();
var returnedJobAnalyse = function (job) { var returnedJobAnalyse = function ( job ) {
// analyse the [job] // analyse the [o.job]
//// analysing job method //// analysing job method
if (!C.DEFAULT_CONST_OBJECT[job.method]) if (!attr.jobMethodObject[job.method])
return false; return false;
if (!ifRemainingJobs(job.method)) { if (!ifRemainingJobs(job.method)) {
var statusobject = getStatusObjectFromLocalStorage(); var statusobject = getStatusObjectFromLocalStorage();
statusobject[job.method] = C.STATUS_DONE; statusobject[job.method] = 'done';
setStatusObjectToLocalStorage(statusobject); setStatusObjectToLocalStorage(statusobject);
switch (job.method) { switch (job.method) {
case C.METHOD_GETLIST: // TODO merging is done with jio? or by the user's scripts?
case 'isAvailable':
// TODO merge name availability between storages
// TODO send job ?
$.jio('publish',{'event': attr.jobMethodObject[
job.method].stop_event, 'job':job});
return;
case 'getList':
// TODO merge list if necessary (we can create // TODO merge list if necessary (we can create
// this.getList, deleted after sending the event, // this.getList, deleted after sending the event,
// filled with done event) -> merge here or show // filled with done event) -> merge here or show
// possible actions (manually, auto, ...) // possible actions (manually, auto, ...)
JIO.publish (C.DEFAULT_CONST_OBJECT[job.method].STOPEVENT/*, merged list*/); $.jio('publish',{'event': attr.jobMethodObject[
// deleting list job.method].stop_event , 'job':job});
///*, 'retvalue': merged list */});
// delete list
return; return;
default: // if it was not a specific method default:
JIO.publish (C.DEFAULT_CONST_OBJECT[job.method].STOPEVENT); $.jio('publish',{'event': attr.jobMethodObject[
job.method].stop_event});
return; return;
} }
} }
//// end analyse //// end analyse
}; };
//// subscribe an event
var t = this;
JIO.subscribe (C.EVENT_JOB_DONE, function (job) {
console.log (C.EVENT_JOB_DONE+'_received');
t.done(job);
returnedJobAnalyse (job);
});
JIO.subscribe (C.EVENT_JOB_FAIL, function (job) { //// sebscribe an event
var t = this;
console.log (C.EVENT_JOB_FAIL+'_received'); $.jio('subscribe',{'event':'job_done','func':function (o) {
t.fail(job); if (methods.isReady()) {
returnedJobAnalyse (job); t.done(o.job);
}); returnedJobAnalyse (o.job);
}
}});
$.jio('subscribe',{'event':'job_fail','func':function (o) {
if (methods.isReady()) {
t.fail(o.job);
returnedJobAnalyse (o.job);
}
}});
//// end subscribing //// end subscribing
}; };
JIO.JobQueue.prototype = { JobQueue.prototype = {
addJob: function ( o ) {
addJob: function (storage,job) {
// Add a job to the Job list // Add a job to the Job list
// storage : the storage object // o.storage : the storage object
// job : the job object (may be a 'string') // o.job : the job object (may be a 'string')
console.log ('addJob');
console.log ('addJob');
//// Adding job to the list in localStorage //// Adding job to the list in localStorage
// transforming job to an object // transforming job/storage to an object
if ((typeof job) === 'string') job = JSON.parse(job); try { o.job = JSON.parse(o.job); } catch (e) {};
try { o.storage = JSON.parse(o.storage); } catch (e) {};
// create joblist in local storage if unset // create joblist in local storage if unset
if (!localStorage.joblist) localStorage.joblist = "[]"; if (!localStorage.joblist) localStorage.joblist = "[]";
// set job id // set job id
job.id = this.jobid; o.job.id = this.jobid;
this.jobid ++; this.jobid ++;
// set job storage
job.storage = storage;
// save the new job // save the new job
var localjoblist = getJobArrayFromLocalStorage(); var localjoblist = getJobArrayFromLocalStorage();
localjoblist.push(job); localjoblist.push(o.job);
setJobArrayToLocalStorage (localjoblist); setJobArrayToLocalStorage (localjoblist);
//// job added //// job added
}, // end addJob }, // end addJob
removeJob: function ( options ) {
// remove a job from localStorage
// options.job : the job object containing at least {id:..}.
// options.where : remove values where options.where(a,b) === true
console.log ('removeJob');
//// set tests functions
var settings = $.extend ({'where':function (j) {return true;}},
options);
var andwhere ;
if (settings.job) {
andwhere = function (j) {return (j.id === settings.job.id);};
} else {
andwhere = function (j) {return true;};
}
//// end set tests functions
//// modify the job list
var jobarray = getJobArrayFromLocalStorage();
var newjobarray = [];
var found = false;
// fill now jobarray with the
for (var k in jobarray) {
if ( settings.where(jobarray[k]) && andwhere(jobarray[k]) ) {
found = true;
} else {
newjobarray.push ( jobarray[k] );
}
}
if (found) {
setJobArrayToLocalStorage (newjobarray);
} else {
$.error ('Job not found, when trying to remove one.');
}
//// end modifying
console.log ('end removeJob');
},
resetAll: function () { resetAll: function () {
// reset All job to 'initial' // reset All job to 'initial'
console.log ('resetAll');
console.log ('resetAll');
var jobarray = getJobArrayFromLocalStorage(); var jobarray = getJobArrayFromLocalStorage();
for (var i in jobarray) { for (var i in jobarray) {
jobarray[i].status = C.STATUS_INITIAL; jobarray[i].status = 'initial';
} }
setJobArrayToLocalStorage(jobarray); setJobArrayToLocalStorage(jobarray);
console.log ('end resetAll');
}, },
invokeAll: function () { invokeAll: function () {
// Do all jobs in the list // Do all jobs in the list
//// do All jobs //// do All jobs
var jobarray = getJobArrayFromLocalStorage(); var jobarray = getJobArrayFromLocalStorage();
for (var i in jobarray) { for (var i in jobarray) {
if (jobarray[i].status === C.STATUS_INITIAL) { if (jobarray[i].status === 'initial') {
jobarray[i].status = C.STATUS_ONGOING; jobarray[i].status = 'ongoing';
this.invoke(jobarray[i]); this.invoke(jobarray[i]);
} }
} }
...@@ -369,339 +311,482 @@ ...@@ -369,339 +311,482 @@
invoke: function (job) { invoke: function (job) {
// Do a job // Do a job
console.log ('invoke');
console.log ('invoke');
//// analysing job method //// analysing job method
// browsing methods // browsing methods
if (!C.DEFAULT_CONST_OBJECT[job.method]) if (!attr.jobMethodObject[job.method])
// TODO do an appropriate error reaction ? unknown job method // TODO do an appropriate error reaction ? unknown job method
return false; return false;
var statusobject = getStatusObjectFromLocalStorage (); var statusobject = getStatusObjectFromLocalStorage ();
objectDump(statusobject); if (statusobject[job.method] === 'done') {
if (statusobject[job.method] === C.STATUS_DONE) { statusobject[job.method] = 'ongoing';
statusobject[job.method] = C.STATUS_ONGOING;
setStatusObjectToLocalStorage(statusobject); setStatusObjectToLocalStorage(statusobject);
JIO.publish (C.DEFAULT_CONST_OBJECT[job.method].STARTEVENT); $.jio('publish',
{'event':attr.jobMethodObject[job.method].start_event,
'job':job});
} }
// create an object and use it to save,load,...! // create an object and use it to save,load,...!
createStorageObject(job.storage,jioApplicant)[ createStorageObject({'storage':job.storage,
C.DEFAULT_CONST_OBJECT[job.method].FUNC 'applicant':attr.applicant})[
](job,true); // overwrite attr.jobMethodObject[job.method].func
](job);
//// end method analyse //// end method analyse
console.log ('end invoke');
}, },
done: function (job) { done: function (job) {
// This job is supposed done, we can remove it from localStorage. // This job is supposed done, we can remove it from localStorage.
console.log ('done');
this.removeJob ({'job':job});
var localjoblist = getJobArrayFromLocalStorage ();
// remove the job from the job list
localjoblist = arrayRemoveValues (localjoblist,function (o) {
return (o.id === job.id);
});
// save to local storage
setJobArrayToLocalStorage (localjoblist);
}, },
fail: function (job) { fail: function (job) {
// This job cannot be done, change its status into localStorage. // This job cannot be done, change its status into localStorage.
console.log ('fail');
var localjoblist = getJobArrayFromLocalStorage (); var jobarray = getJobArrayFromLocalStorage ();
//// find this unique job inside the list //// find this unique job inside the list
for (var i in localjoblist) { for (var i in jobarray) {
if (localjoblist[i].id === job.id) { if (jobarray[i].id === job.id) {
localjoblist[i] = job; jobarray[i] = job;
break; break;
} }
} }
// save to local storage // save to local storage
setJobArrayToLocalStorage (localjoblist); setJobArrayToLocalStorage (jobarray);
}, },
clean: function () { clean: function () {
// Clean the job list, removing all jobs that have failed. // Clean the job list, removing all jobs that have failed.
// It also change the localStorage Job list // It also change the localStorage Job list
setJobArrayToLocalStorage(
arrayRemoveValues(
getJobArrayFromLocalStorage(),
function(j){return (j.status === C.STATUS_FAIL);}
)
);
}
}; // end JIO.JobQueue
// End Job & JobQueue this.removeJob (undefined,
{'where':
function (j) {
return (j.status === 'fail');
} });
}
};
// end Job & JobQueue
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// LOCAL STORAGE // jio job listener
var JobListener = function ( options ) {
/** // A little daemon which will start jobs from the joblist
* Class LocalStorage
* @class provides usual API to save/load/delete documents on the localStorage var settings = $.extend({'interval': 100},options);
* @param storagedata : object containing every element needed to build the storage this.interval = settings.interval;
* @param applicant : object containing inforamtion about the person/application needing this JIO object this.id = null;
*/ };
JIO.LocalStorage = function(storagedata,applicant) {
this.applicant = applicant;
//// check user's localStorage part
this.userName = storagedata.userName;
if(!localStorage.getItem(this.userName)) {
localStorage[this.userName] = '{}'; // Create user
}
//// end check
} JobListener.prototype = {
JIO.LocalStorage.prototype = { setIntervalDelay: function (interval) {
// Set the time between two joblist check in millisec
/** this.interval = interval;
* check if an user already exist
* @param name : the name you want to check
* @return true if the name is free, false otherwise
*/
userNameAvailable: function(name) {
if (localStorage[name]) return false;
return true;
}, },
start: function () {
getDocumentsFromLocalStorage: function() { if (!this.id) {
return JSON.parse(localStorage[this.userName]); this.id = setInterval (function () {
// if there are jobs
if (localStorage.joblist &&
localStorage.joblist !== '[]') {
attr.queue.invokeAll();
}
},this.interval);
console.log ('listener started');
return true;
} else {
return false;
}
}, },
stop: function () {
writeToLocalStorage: function(documents) { if (this.id) {
localStorage[this.userName] = JSON.stringify(documents); console.log ('listener stopped');
clearInterval (this.id);
this.id = null;
}
} }
} }
// end jio job listener
////////////////////////////////////////////////////////////////////////////
/** ////////////////////////////////////////////////////////////////////////////
* save a document in the local storage from a job // jio methods
* @param job : contains all the information to save the document var methods = {
* @param overwrite : a boolean set to true if the document has to be overwritten init: function ( options ) {
*/ var settings = $.extend({},options);
JIO.LocalStorage.prototype[C.FUNC_SAVE] = function(job, overwrite) { // if already initialized
var t = this; if (methods.isReady()) {
// wait a little in order to let some other instructions to continue methods.doMethod(settings);
setTimeout(function () { return false;
var documents = t.getDocumentsFromLocalStorage();
// TODO check modification date !!!
if(!documents[job.fileName]) { // create document
documents[job.fileName] = {
'fileName': job.fileName,
'content': job.fileContent,
'creationDate': Date.now(),
'lastModified': Date.now()
}
t.writeToLocalStorage();
job.status=C.STATUS_DONE;
job.message='success';
JIO.publish(C.EVENT_JOB_DONE,job);
return;
} else {
if(overwrite === true) { // overwrite
documents[job.fileName].lastModified = Date.now();
documents[job.fileName].content = job.fileContent;
t.writeToLocalStorage(documents);
job.status=C.STATUS_DONE;
job.message='success';
JIO.publish(C.EVENT_JOB_DONE,job);
return;
} else {
job.status=C.STATUS_FAIL;
job.message='Document already exists.';
job.errno=403;
JIO.publish(C.EVENT_JOB_FAIL,job);
return;
}
} }
}, C.DEFAULT_INTERVAL_DELAY); console.log ('initializing');
return; // check dependencies
} // end saveDocumentFromJob if (!supportLocalStorage()) {
alert ('Your browser does not support local storage. '+
/** '$.jio cannot be initialized.');
* load a document in the storage, copy the content into the job, $.error ('localStorage not supported');
* then the function sends the job with an event. return false;
* @param job : the job that contains all informations about
* loading operation.
*/
JIO.LocalStorage.prototype[C.FUNC_LOAD] = function(job) {
var t = this;
// wait a little in order to let some other instructions to continue
setTimeout(function () {
var documents = t.getDocumentsFromLocalStorage();
if(!documents[job.fileName]) {
job.status=C.STATUS_FAIL;
job.errno=404;
job.message='Document not found.';
JIO.publish (C.EVENT_JOB_FAIL,job);
} else {
job.status=C.STATUS_DONE;
job.file=documents[job.fileName];
job.message='success';
JIO.publish (C.EVENT_JOB_DONE,job);
} }
}, C.DEFAULT_INTERVAL_DELAY) // check settings
}; // end loadDocumentFromJob if (!settings.storage ||
!settings.applicant) {
/** $.error ('Storage or applicant are not correctly set.');
* load the list of the documents in this storage return false;
* @param job : the job that contains all informations about
* getting list operation.
*/
JIO.LocalStorage.prototype[C.FUNC_GETLIST] = function(job) {
// TODO update it
var t = this;
setTimeout(function () {
var documents = t.getDocumentsFromLocalStorage();
job.list = [];
for (var key in documents) {
job.list.push ({
'fileName':documents[key].fileName,
'creationDate':documents[key].creationDate,
'lastModified':documents[key].lastModified
});
} }
JIO.publish (C.EVENT_JOB_DONE,job); // objectify settings if there are strings
}, C.DEFAULT_INTERVAL_DELAY); try { attr.storage = JSON.parse(settings.storage); }
}; // end getListFromJob catch (e) { attr.storage = settings.storage; }
try { attr.applicant = JSON.parse(settings.applicant); }
/** catch (e) { attr.applicant = settings.applicant; }
* Delete a document or a list of documents from the storage
* @param fileName : fileName to delete // check if key exists in attr.storageTypeObject
* @param options : optional object containing if (!settings.storage.type) {
*/ $.error ('Storage incomplete.');
JIO.LocalStorage.prototype[C.FUNC_DELETE] = function(job) { return false;
// TODO update it }
var t = this; if (!attr.storageTypeObject[settings.storage.type]) {
setTimeout (function () { $.error ('Unknown storage type "' + settings.storage.type + '".');
var documents = t.getDocumentsFromLocalStorage(); return false;
// TODO is it realy a problem if we try to delete a deleted file ?
if (!documents[job.fileName]) {
job.status = C.STATUS_FAIL;
job.errno = 404;
job.message = 'Document not found.';
JIO.publish (C.EVENT_JOB_FAIL,job);
return;
} }
delete documents[job.fileName];
t.writeToLocalStorage(documents);
job.status = C.STATUS_DONE;
job.message = 'success';
JIO.publish (C.EVENT_JOB_DONE,job);
return;
}, C.DEFAULT_INTERVAL_DELAY);
}; // end deleteDocumentFromJob
// END LOCAL STORAGE
////////////////////////////////////////////////////////////////////////////
///////////
// Tools //
///////////
var dependenceLoaded = function () {
// tests if the dependencies are loaded
try { // TODO set a tab id for THIS jio ?
// check jQuery // set a tab id to every jobs ?
if ($) // see todo from methods.close
//attr.pubsub = new PubSub();
if (!attr.queue)
attr.queue = new JobQueue();
if (!attr.listener)
attr.listener = new JobListener();
attr.listener.start();
attr.isReady = true;
},
isReady: function () {
// check if jio is ready
return attr.isReady;
},
addStorageType: function ( options ) {
var settings = $.extend({},options);
// add LocalStorage to storage object
if (settings.type && settings.creator) {
attr.storageTypeObject [settings.type] = settings.creator;
return true; return true;
else return false; }
} catch (e) {
return false; return false;
},
getApplicant: function () {
// return applicant
return attr.applicant;
},
publish: function ( options ) {
if (!methods.isReady()) return null;
console.log ('publish ' + options.event);
var tmp = $.extend({},options);
tmp.event = undefined;
attr.pubsub.publish(options.event,tmp);
},
subscribe: function ( options ) {
console.log ('subscribe');
attr.pubsub.subscribe(options.event,options.func);
},
unsubscribe: function ( options ) {
console.log ('unsubscribe');
attr.pubsub.unsubscribe(options.event);
},
doMethod: function ( options ) {
// $.jio({'fileName':'a','fileContent':'b','method':'save'}
if (options.method) {
if (methods[options.method]) {
methods[options.method]( options );
} else {
$.error ('Method ' + options.method + ' not found.')
}
}
},
isAvailable: function ( options ) {
// $.jio('isAvailable',{'userName':'toto'});
console.log ('isAvailable');
if (!methods.isReady()) return null;
var settings = $.extend ({
'userName': attr.storage.userName,
'storage': attr.storage,
'applicant': attr.applicant,
'method': 'isAvailable'
},options);
// check dependencies
if (settings.userName) {
return attr.queue.addJob ( {'job':(new Job ( settings ))} ) ;
}
return null;
},
save: function ( options ) {
// $.jio('save',{'fileName':'a','fileContent':'b','options':{
// 'overwrite':false}}
console.log ('save');
if (!methods.isReady()) return null;
var settings = $.extend({
'storage': attr.storage,
'applicant': attr.applicant,
'lastModified': Date.now(),
'method':'save'
},options);
// check dependencies
if (settings.fileName && settings.fileContent) {
return attr.queue.addJob ( {'job':(new Job ( settings ))} ) ;
}
return null;
},
load: function ( options ) {
// $.jio('load',{'fileName':'a'});
console.log ('load');
if (!methods.isReady()) return null;
var settings = $.extend ({
'storage':attr.storage,
'applicant':attr.applicant,
'method':'load'
},options);
// check dependencies
if ( settings.fileName ) {
return attr.queue.addJob ( {'job':(new Job ( settings ))} ) ;
}
return null;
},
getList: function ( options ) {
// $.jio('getList');
console.log ('getList');
if (!methods.isReady()) return null;
var settings = $.extend ({
'storage': attr.storage,
'applicant': attr.applicant,
'method':'getList'
},options);
return attr.queue.addJob ( {'job':(new Job ( settings ))} );
},
remove: function ( options ) {
// $.jio('remove',{'fileName':'a'});
console.log ('remove');
if (!methods.isReady()) return null;
var settings = $.extend ({
'storage': attr.storage,
'applicant': attr.applicant,
'method':'remove'
},options);
if ( settings.fileName ) {
return attr.queue.addJob ( {'job':(new Job( settings ))} );
}
return null;
},
clean: function ( options ) {
// clean the job, removing all job that have failed.
attr.queue.clean();
},
close: function ( options ) {
// finish some job if possible and close jio.
// it can be re-init later.
// TODO if someone is managing the browser closure or go to previous
// page, $.jio('close') will close tab id (if any) to free its jobs,
// so that other tabs may do them.
attr.listener.stop();
attr.isReady = false;
} }
}; };
// end JIO methods
var ifRemainingJobs = function(method) { ////////////////////////////////////////////////////////////////////////////
// check if it remains [method] jobs (save,load,...) // JIO arguments manager
// method : can me 'string' or 'undefined' $.jio = function ( method ) {
// undefined -> test if there is at least one job if ( methods[method] ) {
// string -> test if there is at least one [method] job return methods[method].apply( this, Array.prototype.slice.call (
arguments, 1));
if (!method) return (localStorage.joblist !== '[]'); } else if ( typeof method === 'object' || ! method ) {
joba = getJobArrayFromLocalStorage(); return methods.init.apply( this, arguments );
for (var k in joba) { } else {
if (joba[k].method === method && $.error ('Method ' + method + ' does not exists on JQuery.jio' );
joba[k].status !== C.STATUS_FAIL) return true;
} }
return false;
}; };
// end JIO arguments manager
////////////////////////////////////////////////////////////////////////////
/** ////////////////////////////////////////////////////////////////////////////
* Create a storage with [data] informations // Local Storage
* @param data : information found in jio.json and needed to create the storage var LocalStorage = function ( options ) {
* @param applicant : information about the person/application needing this JIO object (allow limited access) this.userName = options.storage.userName;
*/ // check user's localStorage
function createStorageObject(data,applicant) { if(!localStorage[this.userName]) {
if (!storageTypeObject[data.type]) localStorage[this.userName] = '{}'; // create user
return null; // error!
return storageTypeObject[data.type](data,applicant);
}
var checkOptionObject = function (current,defaultopts) {
if(!current) {
return defaultopts;
}
for (var k in defaultopts) {
if (current[k] === undefined)
current[k] = defaultopts[k];
} }
return current;
};
var getJobArrayFromLocalStorage = function () {
var localjoblist = [];
if (localStorage.joblist)
localjoblist = JSON.parse(localStorage.joblist);
return localjoblist;
};
var setJobArrayToLocalStorage = function (jobarray) {
localStorage.joblist = JSON.stringify(jobarray);
}; };
LocalStorage.prototype = {
readDocumentsFromLocalStorage: function () {
return JSON.parse (localStorage[this.userName]);
},
writeDocumentsToLocalStorage: function (documents) {
localStorage[this.userName] = JSON.stringify(documents);
},
checkNameAvailability: function ( job ) {
// wait a little in order to simulate asynchronous operation
setTimeout(function () {
if (localStorage[job.userName]) {
job.status = 'done';
job.message = ''+ job.userName + ' is not available.';
job.isAvailable = false;
$.jio('publish',{'event': 'job_done',
'job': job});
} else {
job.status = 'done';
job.message = ''+ job.userName + ' is available.';
job.isAvailable = true;
$.jio('publish',{'event': 'job_done',
'job': job});
}
}, 100);
}, // end userNameAvailable
saveDocument: function ( job ) {
// Save a document in the local storage
// job : the job object
// job.options : the save options
// job.options.overwrite : true -> overwrite
// job.options.force : true -> save even if jobdate < existingdate
// or overwrite: false
var settings = $.extend({'overwrite':true,
'force':false},job.options);
var t = this;
// wait a little in order to simulate asynchronous saving
setTimeout (function () {
var documents = t.readDocumentsFromLocalStorage();
if (!documents[job.fileName]) { // create document
documents[job.fileName] = {
'fileName': job.fileName,
'fileContent': job.fileContent,
'creationDate': Date.now (),
'lastModified': Date.now ()
}
t.writeDocumentsToLocalStorage(documents);
job.status = 'done';
job.message = 'Document saved.';
job.isSaved = true;
$.jio('publish',{'event':'job_done',
'job':job});
return true;
}
if ( settings.overwrite || settings.force ) { // overwrite
if ( ! settings.force ) { // force write
// checking modification date
if ( ! documents[
job.fileName].lastModified < job.lastModified ) {
// date problem!
job.status = 'fail';
job.message = 'Modification date is earlier than ' +
'existing modification date.';
job.isSaved = false;
$.jio('publish',{'event':'job_done',
'job':job});
return false;
}
}
documents[job.fileName].lastModified = Date.now();
documents[job.fileName].fileContent = job.fileContent;
t.writeDocumentsToLocalStorage(documents);
job.status = 'done';
job.message = 'Document saved';
job.isSaved = true;
$.jio('publish',{'event':'job_done',
'job':job});
return true;
}
// already exists
job.status = 'fail';
job.message = 'Document already exists.';
job.errno = 403;
job.isSaved = false;
$.jio('publish',{'event':'job_fail',
'job': job});
return false;
}, 100);
}, // end saveDocument
var getStatusObjectFromLocalStorage = function () { loadDocument: function ( job ) {
var tmp = {}; // load a document in the storage, copy the content into the job
if (localStorage.status) { // job : the job
tmp = JSON.parse (localStorage.status);
} else { var t = this;
for (var Method in C.DEFAULT_CONST_OBJECT) { // wait a little in order to simulate asynchronous operation
tmp[Method] = C.STATUS_DONE; setTimeout(function () {
} var documents = t.readDocumentsFromLocalStorage();
if (!documents[job.fileName]) {
job.status = 'fail';
job.errno = 404;
job.message = 'Document not found.';
$.jio('publish',{'event':'job_fail',
'job':job});
} else {
job.status = 'done';
job.message = 'Document loaded.';
job.fileContent = documents[job.fileName].fileContent;
$.jio('publish',{'event':'job_done',
'job':job});
}
}, 100);
}, // end loadDocument
getDocumentList: function (job) {
var t = this;
setTimeout(function () {
var documents = t.readDocumentsFromLocalStorage();
job.list = [];
for (var k in documents) {
job.list.push ({
'fileName':documents[k].fileName,
'creationDate':documents[k].creationDate,
'lastModified':documents[k].lastModified});
}
job.status = 'done';
job.message = 'List received.';
$.jio('publish',{'event':'job_done',
'job':job});
}, 100);
}, // end getDocumentList
removeDocument: function () {
var t = this;
setTimeout (function () {
var documents = t.readDocumentsFromLocalStorage();
if (!documents[job.fileName]) {
// job.status = 'fail';
// job.errno = 404;
// job.message = 'Document not found.';
// job.isRemoved = false;
// $.jio('publish',{'event':'job_fail',
// 'job':job});
job.status = 'done';
job.message = 'Document already removed.';
job.isRemoved = true;
$.jio('publish',{'event':'job_done',
'job':job});
} else {
delete documents[job.fileName];
t.writeToLocalStorage(documents);
job.status = 'done';
job.message = 'Document removed.';
job.isRemoved = true;
$.jio('publish',{'event':'job_done',
'job':job});
}
}, 100);
} }
return tmp;
};
var setStatusObjectToLocalStorage = function (statusobject) {
localStorage.status = JSON.stringify(statusobject);
}; };
var arrayRemoveValues = function (a,testfunc) { // add key to storageObject
// Removes the values from [a] where [testfunc(value)] returns true. methods.addStorageType({'type':'local','creator':function (o) {
return new LocalStorage(o);
}});
var isArray = function (a) { // end Local Storage
return Object.prototype.toString.apply(a) === '[object Array]'; ////////////////////////////////////////////////////////////////////////////
};
if (!isArray(a)) return a;
var na = [];
for (var k in a) {
if (!testfunc(a[k]))
na.push (a[k]);
}
return na;
};
// TODO DEBUG we can remove this function
var objectDump = function (o) {
console.log (JSON.stringify(o));
};
// the name to use for the framework. Ex : JIO.initialize(...), JIO.loadDocument... })( jQuery );
window.JIO = JIO;
})();
// There's only one comment at the top (and the bottom) of this file!
;(function ( $ ) {
// test dependencies
try {
if (Base64) {}
else {return false;}
} catch (e) {
$.error('Base64 is required by jio.storage.js');
return false;
};
////////////////////////////////////////////////////////////////////////////
// private vars
var attr = {
'jobMethodObject': {
'available': {
'start_event':'start_testingNameAvailability',
'stop_event':'stop_testingNameAvailability',
'func':'checkNameAvailability',
'retvalue':'isAvailable' }, // returns 'boolean'
'save': {
'start_event':'start_saving',
'stop_event':'stop_saving',
'func':'saveDocument',
'retvalue':'isSaved' }, // returns 'boolean'
'load': {
'start_event':'start_loading',
'stop_event':'stop_loading',
'func':'loadDocument',
'retvalue':'fileContent' }, // returns the file content 'string'
'getList': {
'start_event':'start_gettingList',
'stop_event':'stop_gettingList',
'func':'getDocumentList',
'retvalue':'list' }, // returns the document list 'array'
'remove': {
'start_event':'start_removing',
'stop_event':'stop_removing',
'func':'removeDocument',
'retvalue':'isRemoved' } // returns 'boolean'
}
};
// end private vars
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// Tools
var objectDump = function (o) {
// TODO DEBUG we can remove this function
console.log (JSON.stringify(o));
};
var toString = function (o) {
// TODO DEBUG we can remove this function
return (JSON.stringify(o));
};
// end Tools
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// DAVStorage
var DAVStorage = function ( options ) {
};
DAVStorage.prototype = {
mkcol: function ( options ) {
// create folders in dav storage, synchronously
// options : contains mkcol list
// options.location : the davstorage locations
// options.path : if path=/foo/bar then creates location/dav/foo/bar
var settings = $.extend ({},options);
if (options.location && options.path) {
var ok = false;
$.ajax ( {
url: options.location + '/dav/' + options.path,
type: 'MKCOL',
async: false,
// xhrFields: {withCredentials: 'true'}, // cross domain
success: function () {
// done
console.log ('ok');
ok = true;
},
error: function (type) {
switch (type.status) {
case 405: // Method Not Allowed
ok = true; // already done
break;
}
console.log ('error?');
}
} );
return ok;
} else {
return false;
}
},
checkNameAvailability: function ( job ) {
$.ajax ( {
url: job.storage.location + '/dav/' + job.userName,
type: "HEAD",
async: true,
// xhrFields: {withCredentials: 'true'}, // cross domain
success: function () {
job.status = 'done';
job.message = job.userName + ' is not available.';
job.isAvailable = false;
$.jio('publish',{'event':'job_done',
'job':job});
},
error: function (type) {
switch (type.status) {
case 301: // Moved Permanantly
job.status = 'done';
job.message = job.userName + ' is not available.';
job.isAvailable = false;
$.jio('publish',{'event':'job_done',
'job':job});
break;
case 404: // Not Found
// TODO always returning 404 !! Why ??
console.warn ('always returning 404 ?');
job.status = 'done';
job.message = job.userName + ' is available.';
job.isAvailable = true;
$.jio('publish',{'event':'job_done',
'job':job});
break;
default:
job.status = 'fail';
job.message = 'Cannot check if ' + job.userName +
' is available.';
job.isAvailable = false;
job.errno = type.status;
// $.error ( type.status ': Fail while trying to check ' +
// job.userName );
$.jio('publish',{'event':'job_fail',
'job':job});
break;
}
}
});
},
saveDocument: function ( job ) {
var settings = $.extend ({'overwrite':true,
'force':false},job.options);
// TODO if path of ../dav/user/applic does not exists, it won't work !!
var saveOnDav = function () {
//// save on dav
$.ajax ( {
url: job.storage.location + '/dav/' +
job.storage.userName + '/' +
job.applicant.ID + '/' +
job.fileName,
type: 'PUT',
data: job.fileContent,
async: true,
dataType: 'text', // TODO is it necessary ?
headers: {'Authorization':'Basic '+Base64.encode(
job.storage.userName + ':' + job.storage.password )},
// xhrFields: {withCredentials: 'true'}, // cross domain
success: function () {
job.status = 'done';
job.message = 'Document saved.';
job.isSaved = true;
$.jio('publish',{'event':'job_done',
'job':job});
},
error: function (type) {
job.status = 'fail';
job.message = 'Cannot save document.';
job.errno = type.status;
job.isSaved = false;
$.jio('publish',{'event':'job_fail',
'job':job});
}
} );
//// end saving on dav
};
// if force, do not check anything, just save
if (settings.force) {
return saveOnDav();
}
//// start loading document
$.ajax ( {
url: job.storage.location + '/dav/' +
job.storage.userName + '/' +
job.applicant.ID + '/' +
job.fileName,
type: 'GET',
async: true,
headers: {'Authorization':'Basic '+Base64.encode(
job.storage.userName + ':' + job.storage.password )},
// xhrFields: {withCredentials: 'true'}, // cross domain
success: function (content) { // TODO content ?
// TODO merge files
// Document already exists
if (settings.overwrite) { // overwrite
// TODO check date !!!
return saveOnDav();
}
// do not overwrite
job.status = 'fail';
job.message = 'Document already exists.';
job.errno = 302;
job.isSaved = false;
$.jio('publish',{'event':'job_fail',
'job':job});
return false;
},
error: function (type) {
switch (type.status) {
case 404: // Document not found
// we can save on it
return saveOnDav();
default: // Unknown error
job.status = 'fail';
job.message = 'Unknown error.';
job.errno = type.status;
job.isSaved = false;
$.jio('publish',{'event':'job_fail',
'job':job});
return false;
}
}
} );
//// end loading document
},
loadDocument: function ( job ) {
// load the document into davstorage
// TODO check if job's features are good
$.ajax ( {
url: job.storage.location + '/dav/' +
job.storage.userName + '/' +
job.applicant.ID + '/' +
job.fileName,
type: "GET",
async: true,
dataType: 'text', // TODO is it necessary ?
headers: {'Authorization':'Basic '+Base64.encode(
job.storage.userName + ':' +
job.storage.password )},
// xhrFields: {withCredentials: 'true'}, // cross domain
success: function (content) {
job.status = 'done';
job.message = 'Document loaded.';
job.fileContent = content;
$.jio('publish',{'event':'job_done',
'job':job});
},
error: function (type) {
switch (type.status) {
case 404:
job.message = 'Document not found.'; break;
default:
job.message = 'Cannot load "' + job.fileName + '".'; break;
}
job.status = 'fail';
job.errno = type.status;
$.jio('publish',{'event':'job_fail',
'job':job});
}
} );
},
getDocumentList: function ( job ) {
$.ajax ( {
url: job.storage.location + '/dav/' +
job.storage.userName + '/' + job.applicant.ID + '/',
async: true,
type: 'PROPFIND',
dataType: 'xml',
headers: {'Authorization': 'Basic '+Base64.encode(
job.storage.userName + ':' +
job.storage.password ), Depth: '1'},
success: function (xmlData) {
var documentArrayList = [];
$("D\\:response",xmlData).each(function(i,data) {
if(i>0) { // exclude parent folder
var file = {};
var nt = ($($("D\\:href",
xmlData).get(i)).text()).split('/');
file.fileName = (nt[nt.length-1] ?
nt[nt.length-1] :
nt[nt.length-2]+'/');
if (file.fileName === '.htaccess' ||
file.fileName === '.htpasswd')
return;
file.lastModified = $($("lp1\\:getlastmodified",
xmlData).get(i)).text();
file.creationDate = $($("lp1\\:creationdate",
xmlData).get(i)).text();
documentArrayList.push (file);
}
});
job.status = 'done';
job.message = 'List received.';
job.list = documentArrayList;
$.jio('publish',{'event':'job_done',
'job':job});
},
error: function (type) {
job.status = 'fail';
job.message = 'Cannot get list.';
job.errno = type.status;
$.jio('publish',{'event':'job_fail',
'job':job});
}
} );
},
removeDocument: function ( job ) {
$.ajax ( {
url: job.storage.location + '/dav/' +
job.storage.userName + '/' +
job.applicant.ID + '/' +
job.fileName,
type: "DELETE",
async: true,
headers: {'Authorization':'Basic '+Base64.encode(
job.storage.userName + ':' +
job.storage.password )},
// xhrFields: {withCredentials: 'true'}, // cross domain
success: function () {
job.status = 'done';
job.message = 'Document removed.';
job.isRemoved = true;
$.jio('publish',{'event':'job_done',
'job':job});
},
error: function (type) {
switch (type.status) {
case 404:
job.status = 'done';
job.message = 'Document already removed.';
job.errno = type.status;
$.jio('publish',{'event':'job_done',
'job':job});
break;
default:
job.status = 'fail';
job.message = 'Cannot remove "' + job.fileName + '".';
job.errno = type.status;
$.jio('publish',{'event':'job_fail',
'job':job});
break;
}
}
} );
}
};
// add key to storageObject
$.jio('addStorageType',{'type':'dav','creator':function (o) {
return new DAVStorage(o);
}});
// end DAVStorage
////////////////////////////////////////////////////////////////////////////
})( jQuery );
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