integration/js/model.js
changeset 154 60ca7678f074
parent 144 57f1d252b8f9
equal deleted inserted replaced
153:0b710028f3d3 154:60ca7678f074
     1 /* TODO: Separate Project-specific data from Source */
     1 
     2 
     2 /* js is where data is stored in a standard form, whatever the serializer */
     3 /* model.js is where data is stored in a standard form, whatever the serializer */
     3 
       
     4 //TODO: Separate Project-specific data from Source
       
     5 
     4 IriSP.Model = (function (ns) {
     6 IriSP.Model = (function (ns) {
     5     
     7     
     6     function pad(n, x, b) {
     8     function pad(n, x, b) {
     7         b = b || 10;
     9         b = b || 10;
     8         var s = (x).toString(b);
    10         var s = (x).toString(b);
    29     
    31     
    30     var removeChars = [
    32     var removeChars = [
    31         String.fromCharCode(768), String.fromCharCode(769), String.fromCharCode(770), String.fromCharCode(771), String.fromCharCode(807),
    33         String.fromCharCode(768), String.fromCharCode(769), String.fromCharCode(770), String.fromCharCode(771), String.fromCharCode(807),
    32         "{", "}", "(", ")", "[", "]", "【", "】", "、", "・", "‥", "。", "「", "」", "『", "』", "〜", ":", "!", "?", " ",
    34         "{", "}", "(", ")", "[", "]", "【", "】", "、", "・", "‥", "。", "「", "」", "『", "』", "〜", ":", "!", "?", " ",
    33         ",", " ", ";", "(", ")", ".", "*", "+", "\\", "?", "|", "{", "}", "[", "]", "^", "#", "/"
    35         ",", " ", ";", "(", ")", ".", "*", "+", "\\", "?", "|", "{", "}", "[", "]", "^", "#", "/"
    34     ]
    36     ];
    35     
    37     
    36 var Model = {
    38 var Model = {},
    37     _SOURCE_STATUS_EMPTY : 0,
    39     _SOURCE_STATUS_EMPTY = Model._SOURCE_STATUS_EMPTY = 0,
    38     _SOURCE_STATUS_WAITING : 1,
    40     _SOURCE_STATUS_WAITING = Model._SOURCE_STATUS_WAITING = 1,
    39     _SOURCE_STATUS_READY : 2,
    41     _SOURCE_STATUS_READY = Model._SOURCE_STATUS_READY = 2,
    40     getUID : function() {
    42     extendPrototype = Model.extendPrototype = function(toClass, fromClass) {
       
    43         var fromP = fromClass.prototype,
       
    44             toP = toClass.prototype;
       
    45         for (var k in fromP) {
       
    46             if (fromP.hasOwnProperty(k)) {
       
    47                 toP[k] = fromP[k];
       
    48             }
       
    49         }
       
    50     },
       
    51     getUID = Model.getUID = function() {
    41         return uidbase + pad(4, (++uidincrement % 0x10000), 16) + "-" + rand16(4) + "-" + rand16(6) + rand16(6);
    52         return uidbase + pad(4, (++uidincrement % 0x10000), 16) + "-" + rand16(4) + "-" + rand16(6) + rand16(6);
    42     },
    53     },
    43     isLocalURL : function(url) {
    54     isLocalURL = Model.isLocalURL = function(url) {
    44         var matches = url.match(/^(\w+:)\/\/([^/]+)/);
    55         var matches = url.match(/^(\w+:)\/\/([^/]+)/);
    45         if (matches) {
    56         if (matches) {
    46             return(matches[1] === document.location.protocol && matches[2] === document.location.host)
    57             return(matches[1] === document.location.protocol && matches[2] === document.location.host);
    47         }
    58         }
    48         return true;
    59         return true;
    49     },
    60     },
    50     regexpFromTextOrArray : function(_textOrArray, _testOnly, _iexact) {
    61     regexpFromTextOrArray = Model.regexpFromTextOrArray = function(_textOrArray, _testOnly, _iexact) {
    51         var _testOnly = _testOnly || false,
    62         var _testOnly = _testOnly || false,
    52             _iexact = _iexact || false;
    63             _iexact = _iexact || false;
    53         function escapeText(_text) {
    64         function escapeText(_text) {
    54             return _text.replace(/([\\\*\+\?\|\{\[\}\]\(\)\^\$\.\#\/])/gm, '\\$1');
    65             return _text.replace(/([\\\*\+\?\|\{\[\}\]\(\)\^\$\.\#\/])/gm, '\\$1');
    55         }
    66         }
    65         if (_iexact) {
    76         if (_iexact) {
    66             _source = '^' + _source + '$';
    77             _source = '^' + _source + '$';
    67         }
    78         }
    68         return new RegExp( _source, _flags);
    79         return new RegExp( _source, _flags);
    69     },
    80     },
    70     fullTextRegexps: function(_text) {
    81     fullTextRegexps = Model.fullTextRegexps = function(_text) {
    71         var remsrc = "[\\" + removeChars.join("\\") + "]",
    82         var remsrc = "[\\" + removeChars.join("\\") + "]",
    72             remrx = new RegExp(remsrc,"gm"),
    83             remrx = new RegExp(remsrc,"gm"),
    73             txt = _text.toLowerCase().replace(remrx,"")
    84             txt = _text.toLowerCase().replace(remrx,""),
    74             res = [],
    85             res = [],
    75             charsrx = ns._(charsub).map(function(c) {
    86             charsrx = ns._(charsub).map(function(c) {
    76                 return new RegExp(c);
    87                 return new RegExp(c);
    77             }),
    88             }),
    78             src = "";
    89             src = "";
    86             });
    97             });
    87             src += l;
    98             src += l;
    88         }
    99         }
    89         return "(" + src + ")";
   100         return "(" + src + ")";
    90     },
   101     },
    91     isoToDate : function(_str) {
   102     isoToDate = Model.isoToDate = function(_str) {
    92         // http://delete.me.uk/2005/03/iso8601.html
   103         // http://delete.me.uk/2005/03/iso8601.html
    93         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})))?)?)?)?";
   104         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})))?)?)?)?";
    94         var d = _str.match(new RegExp(regexp));
   105         var d = _str.match(new RegExp(regexp));
    95     
   106     
    96         var offset = 0;
   107         var offset = 0;
   111         time = (Number(date) + (offset * 60 * 1000));
   122         time = (Number(date) + (offset * 60 * 1000));
   112         var _res = new Date();
   123         var _res = new Date();
   113         _res.setTime(Number(time));
   124         _res.setTime(Number(time));
   114         return _res;
   125         return _res;
   115     },
   126     },
   116     dateToIso : function(_d) {
   127     dateToIso = Model.dateToIso = function(_d) {
   117         var d = _d ? new Date(_d) : new Date();
   128         var d = _d ? new Date(_d) : new Date();
   118         return d.getUTCFullYear()+'-'  
   129         return d.getUTCFullYear()+'-'  
   119             + pad(2, d.getUTCMonth()+1)+'-'  
   130             + pad(2, d.getUTCMonth()+1)+'-'  
   120             + pad(2, d.getUTCDate())+'T'  
   131             + pad(2, d.getUTCDate())+'T'  
   121             + pad(2, d.getUTCHours())+':'  
   132             + pad(2, d.getUTCHours())+':'  
   122             + pad(2, d.getUTCMinutes())+':'  
   133             + pad(2, d.getUTCMinutes())+':'  
   123             + pad(2, d.getUTCSeconds())+'Z'  
   134             + pad(2, d.getUTCSeconds())+'Z'  ;
   124     }
   135     };
   125 }
       
   126 
   136 
   127 /*
   137 /*
   128  * Model.List is a class for a list of elements (e.g. annotations, medias, etc. that each have a distinct ID)
   138  * List is a class for a list of elements (e.g. annotations, medias, etc. that each have a distinct ID)
   129  */
   139  */
   130 Model.List = function(_directory) {
   140 var List = Model.List = function(_directory) {
   131     Array.call(this);
   141     Array.call(this);
   132     this.directory = _directory;
   142     this.directory = _directory;
   133     this.idIndex = [];
   143     this.idIndex = [];
   134     this.__events = {};
   144     this.__events = {};
   135     if (typeof _directory == "undefined") {
   145     if (typeof _directory == "undefined") {
   136         console.trace();
   146         console.trace();
   137         throw "Error : new Model.List(directory): directory is undefined";
   147         throw "Error : new List(directory): directory is undefined";
   138     }
   148     }
   139     var _this =  this;
   149     var _this =  this;
   140     this.on("clear-search", function() {
   150     this.on("clear-search", function() {
   141         _this.searching = false;
   151         _this.searching = false;
   142         _this.regexp = undefined;
   152         _this.regexp = undefined;
   143         _this.forEach(function(_element) {
   153         _this.forEach(function(_element) {
   144             _element.found = undefined;
   154             _element.found = undefined;
   145         });
   155         });
   146         _this.trigger("search-cleared");
   156         _this.trigger("search-cleared");
   147     })
   157     });
   148 }
   158 };
   149 
   159 
   150 Model.List.prototype = new Array();
   160 List.prototype = new Array();
   151 
   161 
   152 Model.List.prototype.hasId = function(_id) {
   162 List.prototype.hasId = function(_id) {
   153     return ns._(this.idIndex).include(_id);
   163     return ns._(this.idIndex).include(_id);
   154 }
   164 };
   155 
   165 
   156 /* On recent browsers, forEach and map are defined and do what we want.
   166 /* On recent browsers, forEach and map are defined and do what we want.
   157  * Otherwise, we'll use the Underscore.js functions
   167  * Otherwise, we'll use the Underscore.js functions
   158  */
   168  */
   159 if (typeof Array.prototype.forEach === "undefined") {
   169 if (typeof Array.prototype.forEach === "undefined") {
   160     Model.List.prototype.forEach = function(_callback) {
   170     List.prototype.forEach = function(_callback) {
   161         var _this = this;
   171         var _this = this;
   162         ns._(this).forEach(function(_value, _key) {
   172         ns._(this).forEach(function(_value, _key) {
   163             _callback(_value, _key, _this);
   173             _callback(_value, _key, _this);
   164         });
   174         });
   165     }
   175     };
   166 }
   176 };
   167 
   177 
   168 if (typeof Array.prototype.map === "undefined") {
   178 if (typeof Array.prototype.map === "undefined") {
   169     Model.List.prototype.map = function(_callback) {
   179     List.prototype.map = function(_callback) {
   170         var _this = this;
   180         var _this = this;
   171         return ns._(this).map(function(_value, _key) {
   181         return ns._(this).map(function(_value, _key) {
   172             return _callback(_value, _key, _this);
   182             return _callback(_value, _key, _this);
   173         });
   183         });
   174     }
   184     };
   175 }
   185 };
   176 
   186 
   177 Model.List.prototype.pluck = function(_key) {
   187 List.prototype.pluck = function(_key) {
   178     return this.map(function(_value) {
   188     return this.map(function(_value) {
   179         return _value[_key];
   189         return _value[_key];
   180     });
   190     });
   181 }
   191 };
   182 
   192 
   183 /* We override Array's filter function because it doesn't return an Model.List
   193 /* We override Array's filter function because it doesn't return an List
   184  */
   194  */
   185 Model.List.prototype.filter = function(_callback) {
   195 List.prototype.filter = function(_callback) {
   186     var _this = this,
   196     var _this = this,
   187         _res = new Model.List(this.directory);
   197         _res = new List(this.directory);
   188     _res.addElements(ns._(this).filter(function(_value, _key) {
   198     _res.addElements(ns._(this).filter(function(_value, _key) {
   189         return _callback(_value, _key, _this);
   199         return _callback(_value, _key, _this);
   190     }));
   200     }));
   191     return _res;
   201     return _res;
   192 }
   202 };
   193 
   203 
   194 Model.List.prototype.slice = function(_start, _end) {
   204 List.prototype.slice = function(_start, _end) {
   195     var _res = new Model.List(this.directory);
   205     var _res = new List(this.directory);
   196     _res.addElements(Array.prototype.slice.call(this, _start, _end));
   206     _res.addElements(Array.prototype.slice.call(this, _start, _end));
   197     return _res;
   207     return _res;
   198 }
   208 };
   199 
   209 
   200 Model.List.prototype.splice = function(_start, _end) {
   210 List.prototype.splice = function(_start, _end) {
   201     var _res = new Model.List(this.directory);
   211     var _res = new List(this.directory);
   202     _res.addElements(Array.prototype.splice.call(this, _start, _end));
   212     _res.addElements(Array.prototype.splice.call(this, _start, _end));
   203     this.idIndex.splice(_start, _end);
   213     this.idIndex.splice(_start, _end);
   204     return _res;
   214     return _res;
   205 }
   215 };
   206 
   216 
   207 /* Array has a sort function, but it's not as interesting as Underscore.js's sortBy
   217 /* Array has a sort function, but it's not as interesting as Underscore.js's sortBy
   208  * and won't return a new Model.List
   218  * and won't return a new List
   209  */
   219  */
   210 Model.List.prototype.sortBy = function(_callback) {
   220 List.prototype.sortBy = function(_callback) {
   211     var _this = this,
   221     var _this = this,
   212         _res = new Model.List(this.directory);
   222         _res = new List(this.directory);
   213     _res.addElements(ns._(this).sortBy(function(_value, _key) {
   223     _res.addElements(ns._(this).sortBy(function(_value, _key) {
   214         return _callback(_value, _key, _this);
   224         return _callback(_value, _key, _this);
   215     }));
   225     }));
   216     return _res;
   226     return _res;
   217 }
   227 };
   218 
   228 
   219 /* Title and Description are basic information for (almost) all element types,
   229 /* Title and Description are basic information for (almost) all element types,
   220  * here we can search by these criteria
   230  * here we can search by these criteria
   221  */
   231  */
   222 Model.List.prototype.searchByTitle = function(_text, _iexact) {
   232 List.prototype.searchByTitle = function(_text, _iexact) {
   223     var _iexact = _iexact || false,
   233     var _iexact = _iexact || false,
   224         _rgxp = Model.regexpFromTextOrArray(_text, true, _iexact);
   234         _rgxp = regexpFromTextOrArray(_text, true, _iexact);
   225     return this.filter(function(_element) {
   235     return this.filter(function(_element) {
   226         return _rgxp.test(_element.title);
   236         return _rgxp.test(_element.title);
   227     });
   237     });
   228 }
   238 };
   229 
   239 
   230 Model.List.prototype.searchByDescription = function(_text, _iexact) {
   240 List.prototype.searchByDescription = function(_text, _iexact) {
   231     var _iexact = _iexact || false,
   241     var _iexact = _iexact || false,
   232         _rgxp = Model.regexpFromTextOrArray(_text, true, _iexact);
   242         _rgxp = regexpFromTextOrArray(_text, true, _iexact);
   233     return this.filter(function(_element) {
   243     return this.filter(function(_element) {
   234         return _rgxp.test(_element.description);
   244         return _rgxp.test(_element.description);
   235     });
   245     });
   236 }
   246 };
   237 
   247 
   238 Model.List.prototype.searchByTextFields = function(_text, _iexact) {
   248 List.prototype.searchByTextFields = function(_text, _iexact) {
   239     var _iexact = _iexact || false,
   249     var _iexact = _iexact || false,
   240         _rgxp =  Model.regexpFromTextOrArray(_text, true, _iexact);
   250         _rgxp =  regexpFromTextOrArray(_text, true, _iexact);
   241     return this.filter(function(_element) {
   251     return this.filter(function(_element) {
   242         var keywords = (_element.keywords || _element.getTagTexts() || []).join(", ");
   252         var keywords = (_element.keywords || _element.getTagTexts() || []).join(", ");
   243         return _rgxp.test(_element.description) || _rgxp.test(_element.title) || _rgxp.test(keywords);
   253         return _rgxp.test(_element.description) || _rgxp.test(_element.title) || _rgxp.test(keywords);
   244     });
   254     });
   245 }
   255 };
   246 
   256 
   247 Model.List.prototype.search = function(_text) {
   257 List.prototype.search = function(_text) {
   248     if (!_text) {
   258     if (!_text) {
   249         this.trigger("clear-search");
   259         this.trigger("clear-search");
   250         return this;
   260         return this;
   251     }
   261     }
   252     this.searching = true;
   262     this.searching = true;
   253     this.trigger("search", _text);
   263     this.trigger("search", _text);
   254     var rxsource = Model.fullTextRegexps(_text)
   264     var rxsource = fullTextRegexps(_text),
   255         rgxp = new RegExp(rxsource,"im"),
   265         rgxp = new RegExp(rxsource,"im");
   256         this.regexp = new RegExp(rxsource,"gim");
   266     this.regexp = new RegExp(rxsource,"gim");
   257     var res = this.filter(function(_element, _k) {
   267     var res = this.filter(function(_element, _k) {
   258         var titlematch = rgxp.test(_element.title),
   268         var titlematch = rgxp.test(_element.title),
   259             descmatch = rgxp.test(_element.description),
   269             descmatch = rgxp.test(_element.description),
   260             _isfound = !!(titlematch || descmatch);
   270             _isfound = !!(titlematch || descmatch);
   261         _element.found = _isfound;
   271         _element.found = _isfound;
   262         _element.trigger(_isfound ? "found" : "not-found");
   272         _element.trigger(_isfound ? "found" : "not-found");
   263         return _isfound;
   273         return _isfound;
   264     });
   274     });
   265     this.trigger(res.length ? "found" : "not-found",res);
   275     this.trigger(res.length ? "found" : "not-found",res);
   266     return res;
   276     return res;
   267 }
   277 };
   268 
   278 
   269 Model.List.prototype.getTitles = function() {
   279 List.prototype.getTitles = function() {
   270     return this.map(function(_el) {
   280     return this.map(function(_el) {
   271         return _el.title;
   281         return _el.title;
   272     });
   282     });
   273 }
   283 };
   274 
   284 
   275 Model.List.prototype.addId = function(_id) {
   285 List.prototype.addId = function(_id) {
   276     var _el = this.directory.getElement(_id)
   286     var _el = this.directory.getElement(_id);
   277     if (!this.hasId(_id) && typeof _el !== "undefined") {
   287     if (!this.hasId(_id) && typeof _el !== "undefined") {
   278         this.idIndex.push(_id);
   288         this.idIndex.push(_id);
   279         Array.prototype.push.call(this, _el);
   289         Array.prototype.push.call(this, _el);
   280     }
   290     }
   281 }
   291 };
   282 
   292 
   283 Model.List.prototype.push = function(_el) {
   293 List.prototype.push = function(_el) {
   284     if (typeof _el === "undefined") {
   294     if (typeof _el === "undefined") {
   285         return;
   295         return;
   286     }
   296     }
   287     var _index = (ns._(this.idIndex).indexOf(_el.id));
   297     var _index = (ns._(this.idIndex).indexOf(_el.id));
   288     if (_index === -1) {
   298     if (_index === -1) {
   289         this.idIndex.push(_el.id);
   299         this.idIndex.push(_el.id);
   290         Array.prototype.push.call(this, _el);
   300         Array.prototype.push.call(this, _el);
   291     } else {
   301     } else {
   292         this[_index] = _el;
   302         this[_index] = _el;
   293     }
   303     }
   294 }
   304 };
   295 
   305 
   296 Model.List.prototype.addIds = function(_array) {
   306 List.prototype.addIds = function(_array) {
   297     var _l = _array.length,
   307     var _l = _array.length,
   298         _this = this;
   308         _this = this;
   299     ns._(_array).forEach(function(_id) {
   309     ns._(_array).forEach(function(_id) {
   300         _this.addId(_id);
   310         _this.addId(_id);
   301     });
   311     });
   302 }
   312 };
   303 
   313 
   304 Model.List.prototype.addElements = function(_array) {
   314 List.prototype.addElements = function(_array) {
   305     var _this = this;
   315     var _this = this;
   306     ns._(_array).forEach(function(_el) {
   316     ns._(_array).forEach(function(_el) {
   307         _this.push(_el);
   317         _this.push(_el);
   308     });
   318     });
   309 }
   319 };
   310 
   320 
   311 Model.List.prototype.removeId = function(_id, _deleteFromDirectory) {
   321 List.prototype.removeId = function(_id, _deleteFromDirectory) {
   312     var _deleteFromDirectory = _deleteFromDirectory || false,
   322     var _deleteFromDirectory = _deleteFromDirectory || false,
   313         _index = (ns._(this.idIndex).indexOf(_id));
   323         _index = (ns._(this.idIndex).indexOf(_id));
   314     if (_index !== -1) {
   324     if (_index !== -1) {
   315         this.splice(_index,1);
   325         this.splice(_index,1);
   316     }
   326     }
   317     if (_deleteFromDirectory) {
   327     if (_deleteFromDirectory) {
   318         delete this.directory.elements[_id];
   328         delete this.directory.elements[_id];
   319     }
   329     }
   320 }
   330 };
   321 
   331 
   322 Model.List.prototype.removeElement = function(_el, _deleteFromDirectory) {
   332 List.prototype.removeElement = function(_el, _deleteFromDirectory) {
   323     var _deleteFromDirectory = _deleteFromDirectory || false;
   333     var _deleteFromDirectory = _deleteFromDirectory || false;
   324     this.removeId(_el.id);
   334     this.removeId(_el.id);
   325 }
   335 };
   326 
   336 
   327 Model.List.prototype.removeIds = function(_list, _deleteFromDirectory) {
   337 List.prototype.removeIds = function(_list, _deleteFromDirectory) {
   328     var _deleteFromDirectory = _deleteFromDirectory || false,
   338     var _deleteFromDirectory = _deleteFromDirectory || false,
   329         _this = this;
   339         _this = this;
   330     ns._(_list).forEach(function(_id) {
   340     ns._(_list).forEach(function(_id) {
   331         _this.removeId(_id);
   341         _this.removeId(_id);
   332     });
   342     });
   333 }
   343 };
   334 
   344 
   335 Model.List.prototype.removeElements = function(_list, _deleteFromDirectory) {
   345 List.prototype.removeElements = function(_list, _deleteFromDirectory) {
   336     var _deleteFromDirectory = _deleteFromDirectory || false,
   346     var _deleteFromDirectory = _deleteFromDirectory || false,
   337         _this = this;
   347         _this = this;
   338     ns._(_list).forEach(function(_el) {
   348     ns._(_list).forEach(function(_el) {
   339         _this.removeElement(_el);
   349         _this.removeElement(_el);
   340     });
   350     });
   341 }
   351 };
   342 
   352 
   343 Model.List.prototype.on = function(_event, _callback) {
   353 List.prototype.on = function(_event, _callback) {
   344     if (typeof this.__events[_event] === "undefined") {
   354     if (typeof this.__events[_event] === "undefined") {
   345         this.__events[_event] = [];
   355         this.__events[_event] = [];
   346     }
   356     }
   347     this.__events[_event].push(_callback);
   357     this.__events[_event].push(_callback);
   348 }
   358 };
   349 
   359 
   350 Model.List.prototype.off = function(_event, _callback) {
   360 List.prototype.off = function(_event, _callback) {
   351     if (typeof this.__events[_event] !== "undefined") {
   361     if (typeof this.__events[_event] !== "undefined") {
   352         this.__events[_event] = ns._(this.__events[_event]).reject(function(_fn) {
   362         this.__events[_event] = ns._(this.__events[_event]).reject(function(_fn) {
   353             return _fn === _callback;
   363             return _fn === _callback;
   354         });
   364         });
   355     }
   365     }
   356 }
   366 };
   357 
   367 
   358 Model.List.prototype.trigger = function(_event, _data) {
   368 List.prototype.trigger = function(_event, _data) {
   359     var _list = this;
   369     var _list = this;
   360     ns._(this.__events[_event]).each(function(_callback) {
   370     ns._(this.__events[_event]).each(function(_callback) {
   361         _callback.call(_list, _data);
   371         _callback.call(_list, _data);
   362     });
   372     });
   363 }
   373 };
   364 
   374 
   365 /* A simple time management object, that helps converting millisecs to seconds and strings,
   375 /* A simple time management object, that helps converting millisecs to seconds and strings,
   366  * without the clumsiness of the original Date object.
   376  * without the clumsiness of the original Date object.
   367  */
   377  */
   368 
   378 
   369 Model.Time = function(_milliseconds) {
   379 var Time = Model.Time = function(_milliseconds) {
   370     this.milliseconds = 0;
   380     this.milliseconds = 0;
   371     this.setMilliseconds(_milliseconds);
   381     this.setMilliseconds(_milliseconds);
   372 }
   382 };
   373 
   383 
   374 Model.Time.prototype.setMilliseconds = function(_milliseconds) {
   384 Time.prototype.setMilliseconds = function(_milliseconds) {
   375     var _ante = this.milliseconds;
   385     var _ante = this.milliseconds;
   376     switch(typeof _milliseconds) {
   386     switch(typeof _milliseconds) {
   377         case "string":
   387         case "string":
   378             this.milliseconds = parseInt(_milliseconds);
   388             this.milliseconds = parseInt(_milliseconds);
   379             break;
   389             break;
   387             this.milliseconds = 0;
   397             this.milliseconds = 0;
   388     }
   398     }
   389     if (this.milliseconds === NaN) {
   399     if (this.milliseconds === NaN) {
   390         this.milliseconds = _ante;
   400         this.milliseconds = _ante;
   391     }
   401     }
   392 }
   402 };
   393 
   403 
   394 Model.Time.prototype.setSeconds = function(_seconds) {
   404 Time.prototype.setSeconds = function(_seconds) {
   395     this.milliseconds = 1000 * _seconds;
   405     this.milliseconds = 1000 * _seconds;
   396 }
   406 };
   397 
   407 
   398 Model.Time.prototype.getSeconds = function() {
   408 Time.prototype.getSeconds = function() {
   399     return this.milliseconds / 1000;
   409     return this.milliseconds / 1000;
   400 }
   410 };
   401 
   411 
   402 Model.Time.prototype.getHMS = function() {
   412 Time.prototype.getHMS = function() {
   403     var _totalSeconds = Math.abs(Math.floor(this.getSeconds()));
   413     var _totalSeconds = Math.abs(Math.floor(this.getSeconds()));
   404     return {
   414     return {
   405         hours : Math.floor(_totalSeconds / 3600),
   415         hours : Math.floor(_totalSeconds / 3600),
   406         minutes : (Math.floor(_totalSeconds / 60) % 60),
   416         minutes : (Math.floor(_totalSeconds / 60) % 60),
   407         seconds : _totalSeconds % 60,
   417         seconds : _totalSeconds % 60,
   408         milliseconds: this.milliseconds % 1000
   418         milliseconds: this.milliseconds % 1000
   409     } 
   419     };
   410 }
   420 };
   411 
   421 
   412 Model.Time.prototype.add = function(_milliseconds) {
   422 Time.prototype.add = function(_milliseconds) {
   413     this.milliseconds += new Model.Time(_milliseconds).milliseconds;
   423     this.milliseconds += new Time(_milliseconds).milliseconds;
   414 }
   424 };
   415 
   425 
   416 Model.Time.prototype.valueOf = function() {
   426 Time.prototype.valueOf = function() {
   417     return this.milliseconds;
   427     return this.milliseconds;
   418 }
   428 };
   419 
   429 
   420 Model.Time.prototype.toString = function(showCs) {
   430 Time.prototype.toString = function(showCs) {
   421     var _hms = this.getHMS(),
   431     var _hms = this.getHMS(),
   422         _res = '';
   432         _res = '';
   423     if (_hms.hours) {
   433     if (_hms.hours) {
   424         _res += _hms.hours + ':'
   434         _res += _hms.hours + ':';
   425     }
   435     }
   426     _res += pad(2, _hms.minutes) + ':' + pad(2, _hms.seconds);
   436     _res += pad(2, _hms.minutes) + ':' + pad(2, _hms.seconds);
   427     if (showCs) {
   437     if (showCs) {
   428         _res += "." + Math.floor(_hms.milliseconds / 100)
   438         _res += "." + Math.floor(_hms.milliseconds / 100);
   429     }
   439     }
   430     return _res;
   440     return _res;
   431 }
   441 };
   432 
   442 
   433 /* Model.Reference handles references between elements
   443 /* Reference handles references between elements
   434  */
   444  */
   435 
   445 
   436 Model.Reference = function(_source, _idRef) {
   446 var Reference = Model.Reference = function(_source, _idRef) {
   437     this.source = _source;
   447     this.source = _source;
   438     this.id = _idRef;
   448     this.id = _idRef;
   439     if (typeof _idRef === "object") {
   449     if (typeof _idRef === "object") {
   440         this.isList = true;
   450         this.isList = true;
   441     } else {
   451     } else {
   442         this.isList = false;
   452         this.isList = false;
   443     }
   453     }
   444     this.refresh();
   454     this.refresh();
   445 }
   455 };
   446 
   456 
   447 Model.Reference.prototype.refresh = function() {
   457 Reference.prototype.refresh = function() {
   448     if (this.isList) {
   458     if (this.isList) {
   449         this.contents = new Model.List(this.source.directory);
   459         this.contents = new List(this.source.directory);
   450         this.contents.addIds(this.id);
   460         this.contents.addIds(this.id);
   451     } else {
   461     } else {
   452         this.contents = this.source.getElement(this.id);
   462         this.contents = this.source.getElement(this.id);
   453     }
   463     }
   454     
   464     
   455 }
   465 };
   456 
   466 
   457 Model.Reference.prototype.getContents = function() {
   467 Reference.prototype.getContents = function() {
   458     if (typeof this.contents === "undefined" || (this.isList && this.contents.length != this.id.length)) {
   468     if (typeof this.contents === "undefined" || (this.isList && this.contents.length != this.id.length)) {
   459         this.refresh();
   469         this.refresh();
   460     }
   470     }
   461     return this.contents;
   471     return this.contents;
   462 }
   472 };
   463 
   473 
   464 Model.Reference.prototype.isOrHasId = function(_idRef) {
   474 Reference.prototype.isOrHasId = function(_idRef) {
   465     if (this.isList) {
   475     if (this.isList) {
   466         return (ns._(this.id).indexOf(_idRef) !== -1)
   476         return (ns._(this.id).indexOf(_idRef) !== -1);
   467     } else {
   477     } else {
   468         return (this.id == _idRef);
   478         return (this.id == _idRef);
   469     }
   479     }
   470 }
   480 };
   471 
   481 
   472 /* */
   482 /* */
   473 
   483 
   474 Model.Element = function(_id, _source) {
   484 var BaseElement = Model.Element = function(_id, _source) {
   475     this.elementType = 'element';
   485     this.elementType = 'element';
   476     this.title = "";
   486     this.title = "";
   477     this.description = "";
   487     this.description = "";
   478     this.__events = {}
   488     this.__events = {};
   479     if (typeof _source === "undefined") {
   489     if (typeof _source === "undefined") {
   480         return;
   490         return;
   481     }
   491     }
   482     if (typeof _id === "undefined" || !_id) {
   492     if (typeof _id === "undefined" || !_id) {
   483         _id = Model.getUID();
   493         _id = getUID();
   484     }
   494     }
   485     this.id = _id;
   495     this.id = _id;
   486     this.source = _source;
   496     this.source = _source;
   487     if (_source !== this) {
   497     if (_source !== this) {
   488         this.source.directory.addElement(this);
   498         this.source.directory.addElement(this);
   489     }
   499     }
   490 }
   500 };
   491 
   501 
   492 Model.Element.prototype.toString = function() {
   502 BaseElement.prototype.toString = function() {
   493     return this.elementType + (this.elementType !== 'element' ? ', id=' + this.id + ', title="' + this.title + '"' : '');
   503     return this.elementType + (this.elementType !== 'element' ? ', id=' + this.id + ', title="' + this.title + '"' : '');
   494 }
   504 };
   495 
   505 
   496 Model.Element.prototype.setReference = function(_elementType, _idRef) {
   506 BaseElement.prototype.setReference = function(_elementType, _idRef) {
   497     this[_elementType] = new Model.Reference(this.source, _idRef);
   507     this[_elementType] = new Reference(this.source, _idRef);
   498 }
   508 };
   499 
   509 
   500 Model.Element.prototype.getReference = function(_elementType) {
   510 BaseElement.prototype.getReference = function(_elementType) {
   501     if (typeof this[_elementType] !== "undefined") {
   511     if (typeof this[_elementType] !== "undefined") {
   502         return this[_elementType].getContents();
   512         return this[_elementType].getContents();
   503     }
   513     }
   504 }
   514 };
   505 
   515 
   506 Model.Element.prototype.getRelated = function(_elementType, _global) {
   516 BaseElement.prototype.getRelated = function(_elementType, _global) {
   507     _global = (typeof _global !== "undefined" && _global);
   517     _global = (typeof _global !== "undefined" && _global);
   508     var _this = this;
   518     var _this = this;
   509     return this.source.getList(_elementType, _global).filter(function(_el) {
   519     return this.source.getList(_elementType, _global).filter(function(_el) {
   510         var _ref = _el[_this.elementType];
   520         var _ref = _el[_this.elementType];
   511         return _ref && _ref.isOrHasId(_this.id);
   521         return _ref && _ref.isOrHasId(_this.id);
   512     });
   522     });
   513 }
   523 };
   514 
   524 
   515 Model.Element.prototype.on = function(_event, _callback) {
   525 BaseElement.prototype.on = function(_event, _callback) {
   516     if (typeof this.__events[_event] === "undefined") {
   526     if (typeof this.__events[_event] === "undefined") {
   517         this.__events[_event] = [];
   527         this.__events[_event] = [];
   518     }
   528     }
   519     this.__events[_event].push(_callback);
   529     this.__events[_event].push(_callback);
   520 }
   530 };
   521 
   531 
   522 Model.Element.prototype.off = function(_event, _callback) {
   532 BaseElement.prototype.off = function(_event, _callback) {
   523     if (typeof this.__events[_event] !== "undefined") {
   533     if (typeof this.__events[_event] !== "undefined") {
   524         this.__events[_event] = ns._(this.__events[_event]).reject(function(_fn) {
   534         this.__events[_event] = ns._(this.__events[_event]).reject(function(_fn) {
   525             return _fn === _callback;
   535             return _fn === _callback;
   526         });
   536         });
   527     }
   537     }
   528 }
   538 };
   529 
   539 
   530 Model.Element.prototype.trigger = function(_event, _data) {
   540 BaseElement.prototype.trigger = function(_event, _data) {
   531     var _element = this;
   541     var _element = this;
   532     ns._(this.__events[_event]).each(function(_callback) {
   542     ns._(this.__events[_event]).each(function(_callback) {
   533         _callback.call(_element, _data);
   543         _callback.call(_element, _data);
   534     });
   544     });
   535 }
   545 };
   536 
   546 
   537 /* */
   547 /* */
   538 
   548 
   539 Model.Playable = function(_id, _source) {
   549 var Playable = Model.Playable = function(_id, _source) {
   540     Model.Element.call(this, _id, _source);
   550     BaseElement.call(this, _id, _source);
   541     if (typeof _source === "undefined") {
   551     if (typeof _source === "undefined") {
   542         return;
   552         return;
   543     }
   553     }
   544     this.elementType = 'playable';
   554     this.elementType = 'playable';
   545     this.currentTime = new Model.Time();
   555     this.currentTime = new Time();
   546     this.volume = .5;
   556     this.volume = .5;
   547     this.paused = true;
   557     this.paused = true;
   548     this.muted = false;
   558     this.muted = false;
   549     this.loadedMetadata = false;
   559     this.loadedMetadata = false;
   550     var _this = this;
   560     var _this = this;
   555         _this.paused = true;
   565         _this.paused = true;
   556     });
   566     });
   557     this.on("timeupdate", function(_time) {
   567     this.on("timeupdate", function(_time) {
   558         _this.currentTime = _time;
   568         _this.currentTime = _time;
   559         _this.getAnnotations().filter(function(_a) {
   569         _this.getAnnotations().filter(function(_a) {
   560             return (_a.end <= _time || _a.begin > _time) && _a.playing
   570             return (_a.end <= _time || _a.begin > _time) && _a.playing;
   561         }).forEach(function(_a) {
   571         }).forEach(function(_a) {
   562             _a.playing = false;
   572             _a.playing = false;
   563             _a.trigger("leave");
   573             _a.trigger("leave");
   564             _this.trigger("leave-annotation",_a);
   574             _this.trigger("leave-annotation",_a);
   565         });
   575         });
   566         _this.getAnnotations().filter(function(_a) {
   576         _this.getAnnotations().filter(function(_a) {
   567             return _a.begin <= _time && _a.end > _time && !_a.playing
   577             return _a.begin <= _time && _a.end > _time && !_a.playing;
   568         }).forEach(function(_a) {
   578         }).forEach(function(_a) {
   569             _a.playing = true;
   579             _a.playing = true;
   570             _a.trigger("enter");
   580             _a.trigger("enter");
   571             _this.trigger("enter-annotation",_a);
   581             _this.trigger("enter-annotation",_a);
   572         });
   582         });
   573     });
   583     });
   574     this.on("loadedmetadata", function() {
   584     this.on("loadedmetadata", function() {
   575         _this.loadedMetadata = true;
   585         _this.loadedMetadata = true;
   576     })
   586     });
   577 }
   587 };
   578 
   588 
   579 Model.Playable.prototype = new Model.Element();
   589 extendPrototype(Playable, BaseElement);
   580 
   590 
   581 Model.Playable.prototype.getCurrentTime = function() { 
   591 Playable.prototype.getCurrentTime = function() { 
   582     return this.currentTime;
   592     return this.currentTime;
   583 }
   593 };
   584 
   594 
   585 Model.Playable.prototype.getVolume = function() {
   595 Playable.prototype.getVolume = function() {
   586     return this.volume;
   596     return this.volume;
   587 }
   597 };
   588 
   598 
   589 Model.Playable.prototype.getPaused = function() {
   599 Playable.prototype.getPaused = function() {
   590     return this.paused;
   600     return this.paused;
   591 }
   601 };
   592 
   602 
   593 Model.Playable.prototype.getMuted = function() {
   603 Playable.prototype.getMuted = function() {
   594     return this.muted;
   604     return this.muted;
   595 }
   605 };
   596 
   606 
   597 Model.Playable.prototype.setCurrentTime = function(_time) {
   607 Playable.prototype.setCurrentTime = function(_time) {
   598     this.trigger("setcurrenttime",_time);
   608     this.trigger("setcurrenttime",_time);
   599 }
   609 };
   600 
   610 
   601 Model.Playable.prototype.setVolume = function(_vol) {
   611 Playable.prototype.setVolume = function(_vol) {
   602     this.trigger("setvolume",_vol);
   612     this.trigger("setvolume",_vol);
   603 }
   613 };
   604 
   614 
   605 Model.Playable.prototype.setMuted = function(_muted) {
   615 Playable.prototype.setMuted = function(_muted) {
   606     this.trigger("setmuted",_muted);
   616     this.trigger("setmuted",_muted);
   607 }
   617 };
   608 
   618 
   609 Model.Playable.prototype.play = function() {
   619 Playable.prototype.play = function() {
   610     this.trigger("setplay");
   620     this.trigger("setplay");
   611 }
   621 };
   612 
   622 
   613 Model.Playable.prototype.pause = function() {
   623 Playable.prototype.pause = function() {
   614     this.trigger("setpause");
   624     this.trigger("setpause");
   615 }
   625 };
   616 
   626 
   617 Model.Playable.prototype.show = function() {}
   627 Playable.prototype.show = function() {};
   618 
   628 
   619 Model.Playable.prototype.hide = function() {}
   629 Playable.prototype.hide = function() {};
   620 
   630 
   621 /* */
   631 /* */
   622 
   632 
   623 Model.Media = function(_id, _source) {
   633 var Media = Model.Media = function(_id, _source) {
   624     Model.Playable.call(this, _id, _source);
   634     Playable.call(this, _id, _source);
   625     this.elementType = 'media';
   635     this.elementType = 'media';
   626     this.duration = new Model.Time();
   636     this.duration = new Time();
   627     this.video = '';
   637     this.video = '';
   628     var _this = this;
   638     var _this = this;
   629 }
   639 };
   630 
   640 
   631 Model.Media.prototype = new Model.Playable();
   641 extendPrototype(Media, Playable);
   632 
   642 
   633 /* Default functions to be overriden by players */
   643 /* Default functions to be overriden by players */
   634     
   644     
   635 Model.Media.prototype.setDuration = function(_durationMs) {
   645 Media.prototype.setDuration = function(_durationMs) {
   636     this.duration.setMilliseconds(_durationMs);
   646     this.duration.setMilliseconds(_durationMs);
   637 }
   647 };
   638 
   648 
   639 Model.Media.prototype.getAnnotations = function() {
   649 Media.prototype.getAnnotations = function() {
   640     return this.getRelated("annotation");
   650     return this.getRelated("annotation");
   641 }
   651 };
   642 
   652 
   643 Model.Media.prototype.getAnnotationsByTypeTitle = function(_title) {
   653 Media.prototype.getAnnotationsByTypeTitle = function(_title) {
   644     var _annTypes = this.source.getAnnotationTypes().searchByTitle(_title).pluck("id");
   654     var _annTypes = this.source.getAnnotationTypes().searchByTitle(_title).pluck("id");
   645     if (_annTypes.length) {
   655     if (_annTypes.length) {
   646         return this.getAnnotations().filter(function(_annotation) {
   656         return this.getAnnotations().filter(function(_annotation) {
   647             return ns._(_annTypes).indexOf(_annotation.getAnnotationType().id) !== -1;
   657             return ns._(_annTypes).indexOf(_annotation.getAnnotationType().id) !== -1;
   648         });
   658         });
   649     } else {
   659     } else {
   650         return new Model.List(this.source.directory)
   660         return new List(this.source.directory);
   651     }
   661     }
   652 }
   662 };
   653 
   663 
   654 /* */
   664 /* */
   655 
   665 
   656 Model.Tag = function(_id, _source) {
   666 var Tag = Model.Tag = function(_id, _source) {
   657     Model.Element.call(this, _id, _source);
   667     BaseElement.call(this, _id, _source);
   658     this.elementType = 'tag';
   668     this.elementType = 'tag';
   659 }
   669 };
   660 
   670 
   661 Model.Tag.prototype = new Model.Element();
   671 extendPrototype(Tag, BaseElement);
   662 
   672 
   663 Model.Tag.prototype.getAnnotations = function() {
   673 Tag.prototype.getAnnotations = function() {
   664     return this.getRelated("annotation");
   674     return this.getRelated("annotation");
   665 }
   675 };
   666 
   676 
   667 /* */
   677 /* */
   668 Model.AnnotationType = function(_id, _source) {
   678 var AnnotationType = Model.AnnotationType = function(_id, _source) {
   669     Model.Element.call(this, _id, _source);
   679     BaseElement.call(this, _id, _source);
   670     this.elementType = 'annotationType';
   680     this.elementType = 'annotationType';
   671 }
   681 };
   672 
   682 
   673 Model.AnnotationType.prototype = new Model.Element();
   683 extendPrototype(AnnotationType, BaseElement);
   674 
   684 
   675 Model.AnnotationType.prototype.getAnnotations = function() {
   685 AnnotationType.prototype.getAnnotations = function() {
   676     return this.getRelated("annotation");
   686     return this.getRelated("annotation");
   677 }
   687 };
   678 
   688 
   679 /* Annotation
   689 /* Annotation
   680  * */
   690  * */
   681 
   691 
   682 Model.Annotation = function(_id, _source) {
   692 var Annotation = Model.Annotation = function(_id, _source) {
   683     Model.Element.call(this, _id, _source);
   693     BaseElement.call(this, _id, _source);
   684     this.elementType = 'annotation';
   694     this.elementType = 'annotation';
   685     this.begin = new Model.Time();
   695     this.begin = new Time();
   686     this.end = new Model.Time();
   696     this.end = new Time();
   687     this.tag = new Model.Reference(_source, []);
   697     this.tag = new Reference(_source, []);
   688     this.playing = false;
   698     this.playing = false;
   689     var _this = this;
   699     var _this = this;
   690     this.on("click", function() {
   700     this.on("click", function() {
   691         _this.getMedia().setCurrentTime(_this.begin);
   701         _this.getMedia().setCurrentTime(_this.begin);
   692     });
   702     });
   693 }
   703 };
   694 
   704 
   695 Model.Annotation.prototype = new Model.Element();
   705 extendPrototype(Annotation, BaseElement);
   696 
   706 
   697 Model.Annotation.prototype.setBegin = function(_beginMs) {
   707 Annotation.prototype.setBegin = function(_beginMs) {
   698     this.begin.setMilliseconds(Math.max(0,_beginMs));
   708     this.begin.setMilliseconds(Math.max(0,_beginMs));
   699     this.trigger("change-begin");
   709     this.trigger("change-begin");
   700     if (this.end < this.begin) {
   710     if (this.end < this.begin) {
   701         this.setEnd(this.begin);
   711         this.setEnd(this.begin);
   702     }
   712     }
   703 }
   713 };
   704 
   714 
   705 Model.Annotation.prototype.setEnd = function(_endMs) {
   715 Annotation.prototype.setEnd = function(_endMs) {
   706     this.end.setMilliseconds(Math.min(_endMs, this.getMedia().duration.milliseconds));
   716     this.end.setMilliseconds(Math.min(_endMs, this.getMedia().duration.milliseconds));
   707     this.trigger("change-end");
   717     this.trigger("change-end");
   708     if (this.end < this.begin) {
   718     if (this.end < this.begin) {
   709         this.setBegin(this.end);
   719         this.setBegin(this.end);
   710     }
   720     }
   711 }
   721 };
   712 
   722 
   713 Model.Annotation.prototype.setDuration = function(_durMs) {
   723 Annotation.prototype.setDuration = function(_durMs) {
   714     this.setEnd(_durMs + this.begin.milliseconds);
   724     this.setEnd(_durMs + this.begin.milliseconds);
   715 }
   725 };
   716 
   726 
   717 Model.Annotation.prototype.setMedia = function(_idRef) {
   727 Annotation.prototype.setMedia = function(_idRef) {
   718     this.setReference("media", _idRef);
   728     this.setReference("media", _idRef);
   719 }
   729 };
   720 
   730 
   721 Model.Annotation.prototype.getMedia = function() {
   731 Annotation.prototype.getMedia = function() {
   722     return this.getReference("media");
   732     return this.getReference("media");
   723 }
   733 };
   724 
   734 
   725 Model.Annotation.prototype.setAnnotationType = function(_idRef) {
   735 Annotation.prototype.setAnnotationType = function(_idRef) {
   726     this.setReference("annotationType", _idRef);
   736     this.setReference("annotationType", _idRef);
   727 }
   737 };
   728 
   738 
   729 Model.Annotation.prototype.getAnnotationType = function() {
   739 Annotation.prototype.getAnnotationType = function() {
   730     return this.getReference("annotationType");
   740     return this.getReference("annotationType");
   731 }
   741 };
   732 
   742 
   733 Model.Annotation.prototype.setTags = function(_idRefs) {
   743 Annotation.prototype.setTags = function(_idRefs) {
   734     this.setReference("tag", _idRefs);
   744     this.setReference("tag", _idRefs);
   735 }
   745 };
   736 
   746 
   737 Model.Annotation.prototype.getTags = function() {
   747 Annotation.prototype.getTags = function() {
   738     return this.getReference("tag");
   748     return this.getReference("tag");
   739 }
   749 };
   740 
   750 
   741 Model.Annotation.prototype.getTagTexts = function() {
   751 Annotation.prototype.getTagTexts = function() {
   742     return this.getTags().getTitles();
   752     return this.getTags().getTitles();
   743 }
   753 };
   744 
   754 
   745 Model.Annotation.prototype.getDuration = function() {
   755 Annotation.prototype.getDuration = function() {
   746     return new Model.Time(this.end.milliseconds - this.begin.milliseconds)
   756     return new Time(this.end.milliseconds - this.begin.milliseconds);
   747 }
   757 };
   748 
   758 
   749 /* */
   759 /* */
   750 
   760 
   751 Model.MashedAnnotation = function(_mashup, _annotation) {
   761 var MashedAnnotation = Model.MashedAnnotation = function(_mashup, _annotation) {
   752     Model.Element.call(this, _mashup.id + "_" + _annotation.id, _annotation.source);
   762     BaseElement.call(this, _mashup.id + "_" + _annotation.id, _annotation.source);
   753     this.elementType = 'mashedAnnotation';
   763     this.elementType = 'mashedAnnotation';
   754     this.annotation = _annotation;
   764     this.annotation = _annotation;
   755     this.begin = new Model.Time();
   765     this.begin = new Time();
   756     this.end = new Model.Time();
   766     this.end = new Time();
   757     this.duration = new Model.Time();
   767     this.duration = new Time();
   758     this.title = this.annotation.title;
   768     this.title = this.annotation.title;
   759     this.description = this.annotation.description;
   769     this.description = this.annotation.description;
   760     this.color = this.annotation.color;
   770     this.color = this.annotation.color;
   761     var _this = this;
   771     var _this = this;
   762     this.on("click", function() {
   772     this.on("click", function() {
   766         _this.annotation.trigger("enter");
   776         _this.annotation.trigger("enter");
   767     });
   777     });
   768     this.on("leave", function() {
   778     this.on("leave", function() {
   769         _this.annotation.trigger("leave");
   779         _this.annotation.trigger("leave");
   770     });
   780     });
   771 }
   781 };
   772 
   782 
   773 Model.MashedAnnotation.prototype = new Model.Element(null);
   783 extendPrototype(MashedAnnotation, BaseElement);
   774 
   784 
   775 Model.MashedAnnotation.prototype.getMedia = function() {
   785 MashedAnnotation.prototype.getMedia = function() {
   776     return this.annotation.getReference("media");
   786     return this.annotation.getReference("media");
   777 }
   787 };
   778 
   788 
   779 Model.MashedAnnotation.prototype.getAnnotationType = function() {
   789 MashedAnnotation.prototype.getAnnotationType = function() {
   780     return this.annotation.getReference("annotationType");
   790     return this.annotation.getReference("annotationType");
   781 }
   791 };
   782 
   792 
   783 Model.MashedAnnotation.prototype.getTags = function() {
   793 MashedAnnotation.prototype.getTags = function() {
   784     return this.annotation.getReference("tag");
   794     return this.annotation.getReference("tag");
   785 }
   795 };
   786 
   796 
   787 Model.MashedAnnotation.prototype.getTagTexts = function() {
   797 MashedAnnotation.prototype.getTagTexts = function() {
   788     return this.annotation.getTags().getTitles();
   798     return this.annotation.getTags().getTitles();
   789 }
   799 };
   790 
   800 
   791 Model.MashedAnnotation.prototype.getDuration = function() {
   801 MashedAnnotation.prototype.getDuration = function() {
   792     return this.annotation.getDuration();
   802     return this.annotation.getDuration();
   793 }
   803 };
   794 
   804 
   795 Model.MashedAnnotation.prototype.setBegin = function(_begin) {
   805 MashedAnnotation.prototype.setBegin = function(_begin) {
   796     this.begin.setMilliseconds(_begin);
   806     this.begin.setMilliseconds(_begin);
   797     this.duration.setMilliseconds(this.annotation.getDuration());
   807     this.duration.setMilliseconds(this.annotation.getDuration());
   798     this.end.setMilliseconds(_begin + this.duration);
   808     this.end.setMilliseconds(_begin + this.duration);
   799 }
   809 };
   800 
   810 
   801 /* */
   811 /* */
   802 
   812 
   803 Model.Mashup = function(_id, _source) {
   813 var Mashup = Model.Mashup = function(_id, _source) {
   804     Model.Playable.call(this, _id, _source);
   814     Playable.call(this, _id, _source);
   805     this.elementType = 'mashup';
   815     this.elementType = 'mashup';
   806     this.duration = new Model.Time();
   816     this.duration = new Time();
   807     this.segments = new Model.List(_source.directory);
   817     this.segments = new List(_source.directory);
   808     this.loaded = false;
   818     this.loaded = false;
   809     var _this = this;
   819     var _this = this;
   810     this._updateTimes = function() {
   820     this._updateTimes = function() {
   811         _this.updateTimes();
   821         _this.updateTimes();
   812         _this.trigger("change");
   822         _this.trigger("change");
   813     }
   823     };
   814     this.on("add", this._updateTimes);
   824     this.on("add", this._updateTimes);
   815     this.on("remove", this._updateTimes);
   825     this.on("remove", this._updateTimes);
   816 }
   826 };
   817 
   827 
   818 Model.Mashup.prototype = new Model.Playable();
   828 extendPrototype(Mashup, Playable);
   819 
   829 
   820 Model.Mashup.prototype.updateTimes = function() {
   830 Mashup.prototype.updateTimes = function() {
   821     var _time = 0;
   831     var _time = 0;
   822     this.segments.forEach(function(_segment) {
   832     this.segments.forEach(function(_segment) {
   823         _segment.setBegin(_time);
   833         _segment.setBegin(_time);
   824         _time = _segment.end;
   834         _time = _segment.end;
   825     });
   835     });
   826     this.duration.setMilliseconds(_time);
   836     this.duration.setMilliseconds(_time);
   827 }
   837 };
   828 
   838 
   829 Model.Mashup.prototype.addAnnotation = function(_annotation, _defer) {
   839 Mashup.prototype.addAnnotation = function(_annotation, _defer) {
   830     var _mashedAnnotation = new Model.MashedAnnotation(this, _annotation),
   840     var _mashedAnnotation = new MashedAnnotation(this, _annotation),
   831         _defer = _defer || false;
   841         _defer = _defer || false;
   832     this.segments.push(_mashedAnnotation);
   842     this.segments.push(_mashedAnnotation);
   833     _annotation.on("change-begin", this._updateTimes);
   843     _annotation.on("change-begin", this._updateTimes);
   834     _annotation.on("change-end", this._updateTimes);
   844     _annotation.on("change-end", this._updateTimes);
   835     if (!_defer) {
   845     if (!_defer) {
   836         this.trigger("add");
   846         this.trigger("add");
   837     }
   847     }
   838 }
   848 };
   839 
   849 
   840 Model.Mashup.prototype.addAnnotationById = function(_elId, _defer) {
   850 Mashup.prototype.addAnnotationById = function(_elId, _defer) {
   841     var _annotation = this.source.getElement(_elId),
   851     var _annotation = this.source.getElement(_elId),
   842         _defer = _defer || false;
   852         _defer = _defer || false;
   843     if (typeof _annotation !== "undefined") {
   853     if (typeof _annotation !== "undefined") {
   844         this.addAnnotation(_annotation, _defer);
   854         this.addAnnotation(_annotation, _defer);
   845     }
   855     }
   846 }
   856 };
   847 
   857 
   848 Model.Mashup.prototype.addAnnotations = function(_segments) {
   858 Mashup.prototype.addAnnotations = function(_segments) {
   849     var _this = this;
   859     var _this = this;
   850     ns._(_segments).forEach(function(_segment) {
   860     ns._(_segments).forEach(function(_segment) {
   851         _this.addAnnotation(_segment, true);
   861         _this.addAnnotation(_segment, true);
   852     });
   862     });
   853     this.trigger("add");
   863     this.trigger("add");
   854 }
   864 };
   855 
   865 
   856 Model.Mashup.prototype.addAnnotationsById = function(_segments) {
   866 Mashup.prototype.addAnnotationsById = function(_segments) {
   857     var _this = this;
   867     var _this = this;
   858     ns._(_segments).forEach(function(_segment) {
   868     ns._(_segments).forEach(function(_segment) {
   859         _this.addAnnotationById(_segment, true);
   869         _this.addAnnotationById(_segment, true);
   860     });
   870     });
   861     this.trigger("add");
   871     this.trigger("add");
   862 }
   872 };
   863 
   873 
   864 Model.Mashup.prototype.removeAnnotation = function(_annotation, _defer) {
   874 Mashup.prototype.removeAnnotation = function(_annotation, _defer) {
   865     var _defer = _defer || false;
   875     var _defer = _defer || false;
   866     _annotation.off("change-begin", this._updateTimes);
   876     _annotation.off("change-begin", this._updateTimes);
   867     _annotation.off("change-end", this._updateTimes);
   877     _annotation.off("change-end", this._updateTimes);
   868     this.segments.removeId(this.id + "_" + _annotation.id);
   878     this.segments.removeId(this.id + "_" + _annotation.id);
   869     if (!_defer) {
   879     if (!_defer) {
   870         this.trigger("remove");
   880         this.trigger("remove");
   871     }
   881     }
   872 }
   882 };
   873 
   883 
   874 Model.Mashup.prototype.removeAnnotationById = function(_annId, _defer) {
   884 Mashup.prototype.removeAnnotationById = function(_annId, _defer) {
   875     var _defer = _defer || false;
   885     var _defer = _defer || false;
   876     var _annotation = this.source.getElement(_annId);
   886     var _annotation = this.source.getElement(_annId);
   877 
   887 
   878     if (_annotation) {
   888     if (_annotation) {
   879         this.removeAnnotation(_annotation, _defer);
   889         this.removeAnnotation(_annotation, _defer);
   880     }
   890     }
   881     if (!_defer) {
   891     if (!_defer) {
   882         this.trigger("remove");
   892         this.trigger("remove");
   883     }
   893     }
   884 }
   894 };
   885 
   895 
   886 Model.Mashup.prototype.setAnnotations = function(_segments) {
   896 Mashup.prototype.setAnnotations = function(_segments) {
   887     while (this.segments.length) {
   897     while (this.segments.length) {
   888         this.removeAnnotation(this.segments[0].annotation, true);
   898         this.removeAnnotation(this.segments[0].annotation, true);
   889     }
   899     }
   890     this.addAnnotations(_segments);
   900     this.addAnnotations(_segments);
   891 }
   901 };
   892 
   902 
   893 Model.Mashup.prototype.setAnnotationsById = function(_segments) {
   903 Mashup.prototype.setAnnotationsById = function(_segments) {
   894     while (this.segments.length) {
   904     while (this.segments.length) {
   895         this.removeAnnotation(this.segments[0].annotation, true);
   905         this.removeAnnotation(this.segments[0].annotation, true);
   896     }
   906     }
   897     this.addAnnotationsById(_segments);
   907     this.addAnnotationsById(_segments);
   898 }
   908 };
   899 
   909 
   900 Model.Mashup.prototype.hasAnnotation = function(_annotation) {
   910 Mashup.prototype.hasAnnotation = function(_annotation) {
   901     return !!ns._(this.segments).find(function(_s) {
   911     return !!ns._(this.segments).find(function(_s) {
   902         return _s.annotation === _annotation
   912         return _s.annotation === _annotation;
   903     });
   913     });
   904 }
   914 };
   905 
   915 
   906 Model.Mashup.prototype.getAnnotation = function(_annotation) {
   916 Mashup.prototype.getAnnotation = function(_annotation) {
   907     return ns._(this.segments).find(function(_s) {
   917     return ns._(this.segments).find(function(_s) {
   908         return _s.annotation === _annotation
   918         return _s.annotation === _annotation;
   909     });
   919     });
   910 }
   920 };
   911 
   921 
   912 Model.Mashup.prototype.getAnnotationById = function(_id) {
   922 Mashup.prototype.getAnnotationById = function(_id) {
   913     return ns._(this.segments).find(function(_s) {
   923     return ns._(this.segments).find(function(_s) {
   914         return _s.annotation.id === _id
   924         return _s.annotation.id === _id;
   915     });
   925     });
   916 }
   926 };
   917 
   927 
   918 Model.Mashup.prototype.getAnnotations = function() {
   928 Mashup.prototype.getAnnotations = function() {
   919     return this.segments;
   929     return this.segments;
   920 }
   930 };
   921 
   931 
   922 Model.Mashup.prototype.getOriginalAnnotations = function() {
   932 Mashup.prototype.getOriginalAnnotations = function() {
   923     var annotations = new Model.List(this.source.directory);
   933     var annotations = new List(this.source.directory);
   924     this.segments.forEach(function(_s) {
   934     this.segments.forEach(function(_s) {
   925         annotations.push(_s.annotation);
   935         annotations.push(_s.annotation);
   926     });
   936     });
   927     return annotations;
   937     return annotations;
   928 }
   938 };
   929 
   939 
   930 Model.Mashup.prototype.getMedias = function() {
   940 Mashup.prototype.getMedias = function() {
   931     var medias = new Model.List(this.source.directory);
   941     var medias = new List(this.source.directory);
   932     this.segments.forEach(function(_annotation) {
   942     this.segments.forEach(function(_annotation) {
   933         medias.push(_annotation.getMedia())
   943         medias.push(_annotation.getMedia());
   934     })
   944     });
   935     return medias;
   945     return medias;
   936 }
   946 };
   937 
   947 
   938 Model.Mashup.prototype.getAnnotationsByTypeTitle = function(_title) {
   948 Mashup.prototype.getAnnotationsByTypeTitle = function(_title) {
   939     var _annTypes = this.source.getAnnotationTypes().searchByTitle(_title).pluck("id");
   949     var _annTypes = this.source.getAnnotationTypes().searchByTitle(_title).pluck("id");
   940     if (_annTypes.length) {
   950     if (_annTypes.length) {
   941         return this.getAnnotations().filter(function(_annotation) {
   951         return this.getAnnotations().filter(function(_annotation) {
   942             return ns._(_annTypes).indexOf(_annotation.getAnnotationType().id) !== -1;
   952             return ns._(_annTypes).indexOf(_annotation.getAnnotationType().id) !== -1;
   943         });
   953         });
   944     } else {
   954     } else {
   945         return new Model.List(this.source.directory)
   955         return new List(this.source.directory);
   946     }
   956     }
   947 }
   957 };
   948 
   958 
   949 Model.Mashup.prototype.getAnnotationAtTime = function(_time) {
   959 Mashup.prototype.getAnnotationAtTime = function(_time) {
   950     var _list = this.segments.filter(function(_annotation) {
   960     var _list = this.segments.filter(function(_annotation) {
   951         return _annotation.begin <= _time && _annotation.end > _time;
   961         return _annotation.begin <= _time && _annotation.end > _time;
   952     });
   962     });
   953     if (_list.length) {
   963     if (_list.length) {
   954         return _list[0];
   964         return _list[0];
   955     } else {
   965     } else {
   956         return undefined;
   966         return undefined;
   957     }
   967     }
   958 }
   968 };
   959 
   969 
   960 Model.Mashup.prototype.getMediaAtTime = function(_time) {
   970 Mashup.prototype.getMediaAtTime = function(_time) {
   961     var _annotation = this.getAnnotationAtTime(_time);
   971     var _annotation = this.getAnnotationAtTime(_time);
   962     if (typeof _annotation !== "undefined") {
   972     if (typeof _annotation !== "undefined") {
   963         return _annotation.getMedia();
   973         return _annotation.getMedia();
   964     } else {
   974     } else {
   965         return undefined;
   975         return undefined;
   966     }
   976     }
   967 }
   977 };
   968 
   978 
   969 /* */
   979 /* */
   970 
   980 
   971 Model.Source = function(_config) {
   981 var Source = Model.Source = function(_config) {
   972     Model.Element.call(this, false, this);
   982     BaseElement.call(this, false, this);
   973     this.status = Model._SOURCE_STATUS_EMPTY;
   983     this.status = _SOURCE_STATUS_EMPTY;
   974     this.elementType = "source";
   984     this.elementType = "source";
   975     if (typeof _config !== "undefined") {
   985     if (typeof _config !== "undefined") {
   976         var _this = this;
   986         var _this = this;
   977         ns._(_config).forEach(function(_v, _k) {
   987         ns._(_config).forEach(function(_v, _k) {
   978             _this[_k] = _v;
   988             _this[_k] = _v;
   979         })
   989         });
   980         this.callbackQueue = [];
   990         this.callbackQueue = [];
   981         this.contents = {};
   991         this.contents = {};
   982         this.get();
   992         this.get();
   983     }
   993     }
   984 }
   994 };
   985 
   995 
   986 Model.Source.prototype = new Model.Element();
   996 extendPrototype(Source, BaseElement);
   987 
   997 
   988 Model.Source.prototype.addList = function(_listId, _contents) {
   998 Source.prototype.addList = function(_listId, _contents) {
   989     if (typeof this.contents[_listId] === "undefined") {
   999     if (typeof this.contents[_listId] === "undefined") {
   990         this.contents[_listId] = new Model.List(this.directory);
  1000         this.contents[_listId] = new List(this.directory);
   991     }
  1001     }
   992     this.contents[_listId].addElements(_contents);
  1002     this.contents[_listId].addElements(_contents);
   993 }
  1003 };
   994 
  1004 
   995 Model.Source.prototype.getList = function(_listId, _global) {
  1005 Source.prototype.getList = function(_listId, _global) {
   996     _global = (typeof _global !== "undefined" && _global);
  1006     _global = (typeof _global !== "undefined" && _global);
   997     if (_global) {
  1007     if (_global) {
   998         return this.directory.getGlobalList().filter(function(_e) {
  1008         return this.directory.getGlobalList().filter(function(_e) {
   999             return (_e.elementType === _listId);
  1009             return (_e.elementType === _listId);
  1000         });
  1010         });
  1001     } else {
  1011     } else {
  1002         return this.contents[_listId] || new IriSP.Model.List(this.directory);
  1012         if (typeof this.contents[_listId] === "undefined") {
  1003     }
  1013             this.contents[_listId] = new List(this.directory);
  1004 }
  1014         }
  1005 
  1015         return this.contents[_listId];
  1006 Model.Source.prototype.forEach = function(_callback) {
  1016     }
       
  1017 };
       
  1018 
       
  1019 Source.prototype.forEach = function(_callback) {
  1007     var _this = this;
  1020     var _this = this;
  1008     ns._(this.contents).forEach(function(_value, _key) {
  1021     ns._(this.contents).forEach(function(_value, _key) {
  1009         _callback.call(_this, _value, _key);
  1022         _callback.call(_this, _value, _key);
  1010     })
  1023     });
  1011 }
  1024 };
  1012 
  1025 
  1013 Model.Source.prototype.getElement = function(_elId) {
  1026 Source.prototype.getElement = function(_elId) {
  1014     return this.directory.getElement(_elId);
  1027     return this.directory.getElement(_elId);
  1015 }
  1028 };
  1016 
  1029 
  1017 Model.Source.prototype.get = function() {
  1030 Source.prototype.get = function() {
  1018     this.status = Model._SOURCE_STATUS_WAITING;
  1031     this.status = _SOURCE_STATUS_WAITING;
  1019     this.handleCallbacks();
  1032     this.handleCallbacks();
  1020 }
  1033 };
  1021 
  1034 
  1022 /* We defer the callbacks calls so they execute after the queue is cleared */
  1035 /* We defer the callbacks calls so they execute after the queue is cleared */
  1023 Model.Source.prototype.deferCallback = function(_callback) {
  1036 Source.prototype.deferCallback = function(_callback) {
  1024     var _this = this;
  1037     var _this = this;
  1025     ns._.defer(function() {
  1038     ns._.defer(function() {
  1026         _callback.call(_this);
  1039         _callback.call(_this);
  1027     });
  1040     });
  1028 }
  1041 };
  1029 
  1042 
  1030 Model.Source.prototype.handleCallbacks = function() {
  1043 Source.prototype.handleCallbacks = function() {
  1031     this.status = Model._SOURCE_STATUS_READY;
  1044     this.status = _SOURCE_STATUS_READY;
  1032     while (this.callbackQueue.length) {
  1045     while (this.callbackQueue.length) {
  1033         this.deferCallback(this.callbackQueue.splice(0,1)[0]);
  1046         this.deferCallback(this.callbackQueue.splice(0,1)[0]);
  1034     }
  1047     }
  1035 }
  1048 };
  1036 Model.Source.prototype.onLoad = function(_callback) {
  1049 Source.prototype.onLoad = function(_callback) {
  1037     if (this.status === Model._SOURCE_STATUS_READY) {
  1050     if (this.status === _SOURCE_STATUS_READY) {
  1038         this.deferCallback(_callback);
  1051         this.deferCallback(_callback);
  1039     } else {
  1052     } else {
  1040         this.callbackQueue.push(_callback);
  1053         this.callbackQueue.push(_callback);
  1041     }
  1054     }
  1042 }
  1055 };
  1043 
  1056 
  1044 Model.Source.prototype.serialize = function() {
  1057 Source.prototype.serialize = function() {
  1045     return this.serializer.serialize(this);
  1058     return this.serializer.serialize(this);
  1046 }
  1059 };
  1047 
  1060 
  1048 Model.Source.prototype.deSerialize = function(_data) {
  1061 Source.prototype.deSerialize = function(_data) {
  1049     this.serializer.deSerialize(_data, this);
  1062     this.serializer.deSerialize(_data, this);
  1050 }
  1063 };
  1051 
  1064 
  1052 Model.Source.prototype.getAnnotations = function(_global) {
  1065 Source.prototype.getAnnotations = function(_global) {
  1053     _global = (typeof _global !== "undefined" && _global);
  1066     _global = (typeof _global !== "undefined" && _global);
  1054     return this.getList("annotation", _global);
  1067     return this.getList("annotation", _global);
  1055 }
  1068 };
  1056 
  1069 
  1057 Model.Source.prototype.getMedias = function(_global) {
  1070 Source.prototype.getMedias = function(_global) {
  1058     _global = (typeof _global !== "undefined" && _global);
  1071     _global = (typeof _global !== "undefined" && _global);
  1059     return this.getList("media", _global);
  1072     return this.getList("media", _global);
  1060 }
  1073 };
  1061 
  1074 
  1062 Model.Source.prototype.getTags = function(_global) {
  1075 Source.prototype.getTags = function(_global) {
  1063     _global = (typeof _global !== "undefined" && _global);
  1076     _global = (typeof _global !== "undefined" && _global);
  1064     return this.getList("tag", _global);
  1077     return this.getList("tag", _global);
  1065 }
  1078 };
  1066 
  1079 
  1067 Model.Source.prototype.getMashups = function(_global) {
  1080 Source.prototype.getMashups = function(_global) {
  1068     _global = (typeof _global !== "undefined" && _global);
  1081     _global = (typeof _global !== "undefined" && _global);
  1069     return this.getList("mashup", _global);
  1082     return this.getList("mashup", _global);
  1070 }
  1083 };
  1071 
  1084 
  1072 Model.Source.prototype.getAnnotationTypes = function(_global) {
  1085 Source.prototype.getAnnotationTypes = function(_global) {
  1073     _global = (typeof _global !== "undefined" && _global);
  1086     _global = (typeof _global !== "undefined" && _global);
  1074     return this.getList("annotationType", _global);
  1087     return this.getList("annotationType", _global);
  1075 }
  1088 };
  1076 
  1089 
  1077 Model.Source.prototype.getAnnotationsByTypeTitle = function(_title, _global) {
  1090 Source.prototype.getAnnotationsByTypeTitle = function(_title, _global) {
  1078     _global = (typeof _global !== "undefined" && _global);
  1091     _global = (typeof _global !== "undefined" && _global);
  1079     var _res = new Model.List(this.directory),
  1092     var _res = new List(this.directory),
  1080         _annTypes = this.getAnnotationTypes(_global).searchByTitle(_title);
  1093         _annTypes = this.getAnnotationTypes(_global).searchByTitle(_title);
  1081     _annTypes.forEach(function(_annType) {
  1094     _annTypes.forEach(function(_annType) {
  1082         _res.addElements(_annType.getAnnotations(_global));
  1095         _res.addElements(_annType.getAnnotations(_global));
  1083     })
  1096     });
  1084     return _res;
  1097     return _res;
  1085 }
  1098 };
  1086 
  1099 
  1087 Model.Source.prototype.getDuration = function() {
  1100 Source.prototype.getDuration = function() {
  1088     var _m = this.currentMedia;
  1101     var _m = this.currentMedia;
  1089     if (typeof _m !== "undefined") {
  1102     if (typeof _m !== "undefined") {
  1090         return this.currentMedia.duration;
  1103         return this.currentMedia.duration;
  1091     }
  1104     }
  1092 }
  1105 };
  1093 
  1106 
  1094 Model.Source.prototype.getCurrentMedia = function(_opts) {
  1107 Source.prototype.getCurrentMedia = function(_opts) {
  1095     if (typeof this.currentMedia === "undefined") {
  1108     if (typeof this.currentMedia === "undefined") {
  1096         if (_opts.is_mashup) {
  1109         if (_opts.is_mashup) {
  1097             var _mashups = this.getMashups();
  1110             var _mashups = this.getMashups();
  1098             if (_mashups.length) {
  1111             if (_mashups.length) {
  1099                 this.currentMedia = _mashups[0];
  1112                 this.currentMedia = _mashups[0];
  1104                 this.currentMedia = _medias[0];
  1117                 this.currentMedia = _medias[0];
  1105             }
  1118             }
  1106         }
  1119         }
  1107     }
  1120     }
  1108     return this.currentMedia;
  1121     return this.currentMedia;
  1109 }
  1122 };
  1110 
  1123 
  1111 Model.Source.prototype.merge = function(_source) {
  1124 Source.prototype.merge = function(_source) {
  1112     var _this = this;
  1125     var _this = this;
  1113     _source.forEach(function(_value, _key) {
  1126     _source.forEach(function(_value, _key) {
  1114         _this.getList(_key).addElements(_value);
  1127         _this.getList(_key).addElements(_value);
  1115     });
  1128     });
  1116 }
  1129 };
  1117 
  1130 
  1118 /* */
  1131 /* */
  1119 
  1132 
  1120 Model.RemoteSource = function(_config) {
  1133 var RemoteSource = Model.RemoteSource = function(_config) {
  1121     Model.Source.call(this, _config);
  1134     Source.call(this, _config);
  1122 }
  1135 };
  1123 
  1136 
  1124 Model.RemoteSource.prototype = new Model.Source();
  1137 extendPrototype(RemoteSource, Source);
  1125 
  1138 
  1126 Model.RemoteSource.prototype.get = function() {
  1139 RemoteSource.prototype.get = function() {
  1127     this.status = Model._SOURCE_STATUS_WAITING;
  1140     this.status = _SOURCE_STATUS_WAITING;
  1128     var _this = this,
  1141     var _this = this,
  1129         urlparams = this.url_params || {},
  1142         urlparams = this.url_params || {},
  1130         dataType = (Model.isLocalURL(this.url) ? "json" : "jsonp");
  1143         dataType = (isLocalURL(this.url) ? "json" : "jsonp");
  1131     urlparams.format = dataType;
  1144     urlparams.format = dataType;
  1132     ns.jQuery.ajax({
  1145     ns.jQuery.ajax({
  1133         url: this.url,
  1146         url: this.url,
  1134         dataType: dataType,
  1147         dataType: dataType,
  1135         data: urlparams,
  1148         data: urlparams,
  1137         success: function(_result) {
  1150         success: function(_result) {
  1138             _this.deSerialize(_result);
  1151             _this.deSerialize(_result);
  1139             _this.handleCallbacks();
  1152             _this.handleCallbacks();
  1140         }
  1153         }
  1141     });
  1154     });
  1142 }
  1155 };
  1143 
  1156 
  1144 /* */
  1157 /* */
  1145 
  1158 
  1146 Model.Directory = function() {
  1159 var Directory = Model.Directory = function() {
  1147     this.remoteSources = {};
  1160     this.remoteSources = {};
  1148     this.elements = {};
  1161     this.elements = {};
  1149 }
  1162 };
  1150 
  1163 
  1151 Model.Directory.prototype.remoteSource = function(_properties) {
  1164 Directory.prototype.remoteSource = function(_properties) {
  1152     if (typeof _properties !== "object" || typeof _properties.url === "undefined") {
  1165     if (typeof _properties !== "object" || typeof _properties.url === "undefined") {
  1153         throw "Error : Model.Directory.remoteSource(configuration): configuration.url is undefined";
  1166         throw "Error : Directory.remoteSource(configuration): configuration.url is undefined";
  1154     }
  1167     }
  1155     var _config = ns._({ directory: this }).extend(_properties);
  1168     var _config = ns._({ directory: this }).extend(_properties);
  1156     _config.url_params = _config.url_params || {};
  1169     _config.url_params = _config.url_params || {};
  1157     var _hash = _config.url + "?" + ns.jQuery.param(_config.url_params);
  1170     var _hash = _config.url + "?" + ns.jQuery.param(_config.url_params);
  1158     if (typeof this.remoteSources[_hash] === "undefined") {
  1171     if (typeof this.remoteSources[_hash] === "undefined") {
  1159         this.remoteSources[_hash] = new Model.RemoteSource(_config);
  1172         this.remoteSources[_hash] = new RemoteSource(_config);
  1160     }
  1173     }
  1161     return this.remoteSources[_hash];
  1174     return this.remoteSources[_hash];
  1162 }
  1175 };
  1163 
  1176 
  1164 Model.Directory.prototype.newLocalSource = function(_properties) {
  1177 Directory.prototype.newLocalSource = function(_properties) {
  1165     var _config = ns._({ directory: this }).extend(_properties),
  1178     var _config = ns._({ directory: this }).extend(_properties),
  1166         _res = new Model.Source(_config);
  1179         _res = new Source(_config);
  1167     return _res;
  1180     return _res;
  1168 }
  1181 };
  1169 
  1182 
  1170 Model.Directory.prototype.getElement = function(_id) {
  1183 Directory.prototype.getElement = function(_id) {
  1171     return this.elements[_id];
  1184     return this.elements[_id];
  1172 }
  1185 };
  1173 
  1186 
  1174 Model.Directory.prototype.addElement = function(_element) {
  1187 Directory.prototype.addElement = function(_element) {
  1175     this.elements[_element.id] = _element;
  1188     this.elements[_element.id] = _element;
  1176 }
  1189 };
  1177 
  1190 
  1178 Model.Directory.prototype.getGlobalList = function() {
  1191 Directory.prototype.getGlobalList = function() {
  1179     var _res = new Model.List(this);
  1192     var _res = new List(this);
  1180     _res.addIds(ns._(this.elements).keys());
  1193     _res.addIds(ns._(this.elements).keys());
  1181     return _res;
  1194     return _res;
  1182 }
  1195 };
  1183 
       
  1184 return Model;
  1196 return Model;
  1185 
  1197 
  1186 })(IriSP);
  1198 })(IriSP);
  1187 
  1199 
  1188 /* END model.js */
  1200 /* END js */
  1189 
  1201