src/js/model.js
branchnew-model
changeset 868 a525cc2214e7
parent 866 3bf7aa8216e5
child 870 2c025db10a10
equal deleted inserted replaced
866:3bf7aa8216e5 868:a525cc2214e7
     1 /* model.js is where data is stored in a standard form, whatever the serializer */
     1 /* model.js is where data is stored in a standard form, whatever the serializer */
     2 
     2 
     3 IriSP.Model = {
     3 IriSP.Model = {
     4     SOURCE_STATUS_EMPTY : 0,
     4     _SOURCE_STATUS_EMPTY : 0,
     5     SOURCE_STATUS_WAITING : 1,
     5     _SOURCE_STATUS_WAITING : 1,
     6     SOURCE_STATUS_READY : 2,
     6     _SOURCE_STATUS_READY : 2,
     7     ID_AUTO_INCREMENT : 0,
     7     _ID_AUTO_INCREMENT : 0,
     8     getAI : function() {
     8     getAI : function() {
     9         return "autoid-" + (++this.ID_AUTO_INCREMENT);
     9         return "autoid-" + (++this._ID_AUTO_INCREMENT);
    10     },
    10     },
    11     isoToDate : function(_str) {
    11     isoToDate : function(_str) {
    12         // http://delete.me.uk/2005/03/iso8601.html
    12         // http://delete.me.uk/2005/03/iso8601.html
    13         var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
    13         var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
    14         var d = _str.match(new RegExp(regexp));
    14         var d = _str.match(new RegExp(regexp));
    42             + pad(d.getUTCMinutes())+':'  
    42             + pad(d.getUTCMinutes())+':'  
    43             + pad(d.getUTCSeconds())+'Z'  
    43             + pad(d.getUTCSeconds())+'Z'  
    44     }
    44     }
    45 }
    45 }
    46 
    46 
    47 /* */
    47 /*
    48 
    48  * IriSP.Model.List is a class for a list of elements (e.g. annotations, medias, etc. that each have a distinct ID)
       
    49  */
    49 IriSP.Model.List = function(_directory) {
    50 IriSP.Model.List = function(_directory) {
    50     Array.call(this);
    51     Array.call(this);
    51     this.directory = _directory;
    52     this.directory = _directory;
    52     this.idIndex = [];
    53     this.idIndex = [];
    53     if (typeof _directory == "undefined") {
    54     if (typeof _directory == "undefined") {
    65 
    66 
    66 IriSP.Model.List.prototype.hasId = function(_id) {
    67 IriSP.Model.List.prototype.hasId = function(_id) {
    67     return (IriSP._(this.idIndex).indexOf(_id) !== -1);
    68     return (IriSP._(this.idIndex).indexOf(_id) !== -1);
    68 }
    69 }
    69 
    70 
       
    71 /* On recent browsers, forEach and map are defined and do what we want.
       
    72  * Otherwise, we'll use the Underscore.js functions
       
    73  */
    70 if (typeof Array.prototype.forEach === "undefined") {
    74 if (typeof Array.prototype.forEach === "undefined") {
    71     IriSP.Model.List.prototype.forEach = function(_callback) {
    75     IriSP.Model.List.prototype.forEach = function(_callback) {
    72         var _this = this;
    76         var _this = this;
    73         IriSP._(this).forEach(function(_value, _key) {
    77         IriSP._(this).forEach(function(_value, _key) {
    74             _callback(_value, _key, _this);
    78             _callback(_value, _key, _this);
    83             return _callback(_value, _key, _this);
    87             return _callback(_value, _key, _this);
    84         });
    88         });
    85     }
    89     }
    86 }
    90 }
    87 
    91 
    88 /* We override Array's filter function because it doesn't return an IriSP.Model.List */
    92 /* We override Array's filter function because it doesn't return an IriSP.Model.List
       
    93  */
    89 IriSP.Model.List.prototype.filter = function(_callback) {
    94 IriSP.Model.List.prototype.filter = function(_callback) {
    90     var _this = this,
    95     var _this = this,
    91         _res = new IriSP.Model.List(this.directory);
    96         _res = new IriSP.Model.List(this.directory);
    92     _res.addElements(IriSP._(this).filter(function(_value, _key) {
    97     _res.addElements(IriSP._(this).filter(function(_value, _key) {
    93         return _callback(_value, _key, _this);
    98         return _callback(_value, _key, _this);
    94     }));
    99     }));
    95     return _res;
   100     return _res;
    96 }
   101 }
    97 
   102 
       
   103 /* Array has a sort function, but it's not as interesting as Underscore.js's sortBy
       
   104  * and won't return a new IriSP.Model.List
       
   105  */
    98 IriSP.Model.List.prototype.sortBy = function(_callback) {
   106 IriSP.Model.List.prototype.sortBy = function(_callback) {
    99     var _this = this,
   107     var _this = this,
   100         _res = new IriSP.Model.List(this.directory);
   108         _res = new IriSP.Model.List(this.directory);
   101     _res.contents = IriSP._(this).sortBy(function(_value, _key) {
   109     _res.contents = IriSP._(this).sortBy(function(_value, _key) {
   102         return _callback(_value, _key, _this);
   110         return _callback(_value, _key, _this);
   103     });
   111     });
   104     return _res;
   112     return _res;
   105 }
   113 }
   106 
   114 
       
   115 /* Title and Description are basic information for (almost) all element types,
       
   116  * here we can search by these criteria
       
   117  */
   107 IriSP.Model.List.prototype.searchByTitle = function(_text) {
   118 IriSP.Model.List.prototype.searchByTitle = function(_text) {
   108     var _rgxp = new RegExp('(' + _text.replace(/(\W)/gm,'\\$1') + ')','gim');
   119     var _rgxp = new RegExp('(' + _text.replace(/(\W)/gm,'\\$1') + ')','gim');
   109     return this.filter(function(_element) {
   120     return this.filter(function(_element) {
   110         return _rgxp.test(_element.title);
   121         return _rgxp.test(_element.title);
   111     });
   122     });
   135 
   146 
   136 IriSP.Model.List.prototype.push = function(_el) {
   147 IriSP.Model.List.prototype.push = function(_el) {
   137     if (typeof this.directory.getElement(_el.id) === "undefined") {
   148     if (typeof this.directory.getElement(_el.id) === "undefined") {
   138         this.directory.addElement(_el);
   149         this.directory.addElement(_el);
   139     }
   150     }
   140     this.idIndex.push(_el.id);
   151     var _index = (IriSP._(this.idIndex).indexOf(_el.id));
   141     Array.prototype.push.call(this, _el);
   152     if (_index === -1) {
       
   153         this.idIndex.push(_el.id);
       
   154         Array.prototype.push.call(this, _el);
       
   155     } else {
       
   156         this[_index] = _el;
       
   157     }
   142 }
   158 }
   143 
   159 
   144 IriSP.Model.List.prototype.addIds = function(_array) {
   160 IriSP.Model.List.prototype.addIds = function(_array) {
   145     var _l = _array.length,
   161     var _l = _array.length,
   146         _this = this;
   162         _this = this;
   155     IriSP._(_array).forEach(function(_el) {
   171     IriSP._(_array).forEach(function(_el) {
   156         _this.push(_el);
   172         _this.push(_el);
   157     });
   173     });
   158 }
   174 }
   159 
   175 
   160 /* */
   176 /* A simple time management object, that helps converting millisecs to seconds and strings,
       
   177  * without the clumsiness of the original Date object.
       
   178  */
   161 
   179 
   162 IriSP.Model.Time = function(_milliseconds) {
   180 IriSP.Model.Time = function(_milliseconds) {
   163     this.milliseconds = parseInt(typeof _milliseconds !== "undefined" ? _milliseconds : 0);
   181     this.milliseconds = parseInt(typeof _milliseconds !== "undefined" ? _milliseconds : 0);
   164 }
   182 }
   165 
   183 
   195     }
   213     }
   196     _res += pad(_hms.minutes) + ':' + pad(_hms.seconds);
   214     _res += pad(_hms.minutes) + ':' + pad(_hms.seconds);
   197     return _res;
   215     return _res;
   198 }
   216 }
   199 
   217 
   200 /* */
   218 /* IriSP.Model.Reference handles references between elements
       
   219  */
   201 
   220 
   202 IriSP.Model.Reference = function(_source, _idRef) {
   221 IriSP.Model.Reference = function(_source, _idRef) {
   203     this.source = _source;
   222     this.source = _source;
   204     if (typeof _idRef === "object") {
   223     if (typeof _idRef === "object") {
   205         this.isList = true;
   224         this.isList = true;
   207         this.contents.addIds(IriSP._(_idRef).map(function(_id) {
   226         this.contents.addIds(IriSP._(_idRef).map(function(_id) {
   208             return _source.getNamespaced(_id).fullname;
   227             return _source.getNamespaced(_id).fullname;
   209         }));
   228         }));
   210     } else {
   229     } else {
   211         this.isList = false;
   230         this.isList = false;
   212         this.contents = _source.getNamespaced(_idRef).fullname;
   231         this.contents = this.source.directory.getElement(_source.getNamespaced(_idRef).fullname);
   213     }
   232     }
   214 }
       
   215 
       
   216 IriSP.Model.Reference.prototype.getContents = function() {
       
   217     return (this.isList ? this.contents : this.source.directory.getElement(this.contents));
       
   218 }
   233 }
   219 
   234 
   220 /* */
   235 /* */
   221 
   236 
   222 IriSP.Model.Element = function(_id, _source) {
   237 IriSP.Model.Element = function(_id, _source) {
   241     this[_elementType] = new IriSP.Model.Reference(this.source, _idRef);
   256     this[_elementType] = new IriSP.Model.Reference(this.source, _idRef);
   242 }
   257 }
   243 
   258 
   244 IriSP.Model.Element.prototype.getReference = function(_elementType) {
   259 IriSP.Model.Element.prototype.getReference = function(_elementType) {
   245     if (typeof this[_elementType] !== "undefined") {
   260     if (typeof this[_elementType] !== "undefined") {
   246         return this[_elementType].getContents();
   261         return this[_elementType].contents;
   247     }
   262     }
   248 }
   263 }
   249 
   264 
   250 IriSP.Model.Element.prototype.getRelated = function(_elementType) {
   265 IriSP.Model.Element.prototype.getRelated = function(_elementType) {
   251     var _this = this;
   266     var _this = this;
   253         var _ref = _el[_this.elementType];
   268         var _ref = _el[_this.elementType];
   254         if (_ref.isList) {
   269         if (_ref.isList) {
   255             return _ref.contents.hasId(_this.id);
   270             return _ref.contents.hasId(_this.id);
   256         }
   271         }
   257         else {
   272         else {
   258             return _ref.contents === _this.id;
   273             return _ref.contents.id === _this.id;
   259         }
   274         }
   260     });
   275     });
   261 }
   276 }
   262 
   277 
   263 /* */
   278 /* */
   350 }
   365 }
   351 
   366 
   352 /* */
   367 /* */
   353 
   368 
   354 IriSP.Model.Source = function(_config) {
   369 IriSP.Model.Source = function(_config) {
   355     this.status = IriSP.Model.SOURCE_STATUS_EMPTY;
   370     this.status = IriSP.Model._SOURCE_STATUS_EMPTY;
   356     if (typeof _config !== "undefined") {
   371     if (typeof _config !== "undefined") {
   357         var _this = this;
   372         var _this = this;
   358         IriSP._(_config).forEach(function(_v, _k) {
   373         IriSP._(_config).forEach(function(_v, _k) {
   359             _this[_k] = _v;
   374             _this[_k] = _v;
   360         })
   375         })
   446     });
   461     });
   447     return _nsls;
   462     return _nsls;
   448 }
   463 }
   449 
   464 
   450 IriSP.Model.Source.prototype.get = function() {
   465 IriSP.Model.Source.prototype.get = function() {
   451     this.status = IriSP.Model.SOURCE_STATUS_READY;
   466     this.status = IriSP.Model._SOURCE_STATUS_READY;
   452     var _this = this;
   467     var _this = this;
   453     if (_this.callbackQueue.length) {
   468     if (_this.callbackQueue.length) {
   454         IriSP._(_this.callbackQueue).forEach(function(_callback) {
   469         IriSP._(_this.callbackQueue).forEach(function(_callback) {
   455             _callback.call(_this);
   470             _callback.call(_this);
   456         });
   471         });
   461 IriSP.Model.Source.prototype.serialize = function() {
   476 IriSP.Model.Source.prototype.serialize = function() {
   462     return this.serializer.serialize(this);
   477     return this.serializer.serialize(this);
   463 }
   478 }
   464 
   479 
   465 IriSP.Model.Source.prototype.onLoad = function(_callback) {
   480 IriSP.Model.Source.prototype.onLoad = function(_callback) {
   466     if (this.status === IriSP.Model.SOURCE_STATUS_READY) {
   481     if (this.status === IriSP.Model._SOURCE_STATUS_READY) {
   467         callback.call(this);
   482         console.log("Called on load, Ready");
       
   483         var _this = this;
       
   484         IriSP._.defer(function() {
       
   485             _callback.call(_this);
       
   486         });        
   468     } else {
   487     } else {
       
   488         console.log("Called on load, not ready");
   469         this.callbackQueue.push(_callback);
   489         this.callbackQueue.push(_callback);
   470     }
   490     }
   471 }
   491 }
   472 
   492 
   473 IriSP.Model.Source.prototype.getAnnotations = function() {
   493 IriSP.Model.Source.prototype.getAnnotations = function() {
   503 }
   523 }
   504 
   524 
   505 IriSP.Model.RemoteSource.prototype = new IriSP.Model.Source();
   525 IriSP.Model.RemoteSource.prototype = new IriSP.Model.Source();
   506 
   526 
   507 IriSP.Model.RemoteSource.prototype.get = function() {
   527 IriSP.Model.RemoteSource.prototype.get = function() {
   508     this.status = IriSP.Model.SOURCE_STATUS_WAITING;
   528     this.status = IriSP.Model._SOURCE_STATUS_WAITING;
   509     var _this = this;
   529     var _this = this;
   510     IriSP.jQuery.getJSON(this.url, function(_result) {
   530     IriSP.jQuery.getJSON(this.url, function(_result) {
   511         _this.serializer.deSerialize(_result, _this);
   531         _this.serializer.deSerialize(_result, _this);
       
   532         console.log('Received data, we have '+_this.callbackQueue.length+' callbacks waiting');
   512         if (_this.callbackQueue.length) {
   533         if (_this.callbackQueue.length) {
   513             IriSP._(_this.callbackQueue).forEach(function(_callback) {
   534             IriSP._(_this.callbackQueue).forEach(function(_callback) {
   514                 _callback.call(_this);
   535                 _callback.call(_this);
   515             });
   536             });
   516         }
   537         }
   517         _this.callbackQueue = [];
   538         _this.callbackQueue = [];
   518         _this.status = IriSP.Model.SOURCE_STATUS_READY;
   539         _this.status = IriSP.Model._SOURCE_STATUS_READY;
   519     });
   540     });
   520 }
   541 }
   521 
   542 
   522 /* */
   543 /* */
   523 
   544