client/js/view-model.js
changeset 20 bd58970ffd16
parent 5 67085e6281e5
equal deleted inserted replaced
19:d49b927bfe62 20:bd58970ffd16
       
     1 /* Defines the View Model */
       
     2 
       
     3 Rkns.ViewModel = {}
       
     4 
       
     5 /* Project Class */
       
     6 
       
     7 Rkns.ViewModel.Project = function() {
       
     8     this.users = new Rkns.ViewModel.List();
       
     9     this.nodes = new Rkns.ViewModel.List();
       
    10     this.edges = new Rkns.ViewModel.List();
       
    11 }
       
    12 
       
    13 Rkns.ViewModel.Project.prototype.addNode = function(_props, _render_save) {
       
    14     var _node = new Rkns.ViewModel.Node(this, _props);
       
    15     this.nodes.push(_node);
       
    16     if (typeof _render_save !== "undefined" && (_render_save&Rkns._RENDER)) {
       
    17         var _controller = this.renderer.addController("Node", _node);
       
    18         _controller.redraw();
       
    19     }
       
    20     if (typeof _render_save !== "undefined" && (_render_save&Rkns._SAVE)) {
       
    21         this.remotemodel.addNode(_node);
       
    22     }
       
    23     return _node;
       
    24 }
       
    25 
       
    26 Rkns.ViewModel.Project.prototype.addEdge = function(_props, _render_save) {
       
    27     var _edge = new Rkns.ViewModel.Edge(this, _props);
       
    28     this.edges.push(_edge);
       
    29     if (typeof _render_save !== "undefined" && (_render_save&Rkns._RENDER)) {
       
    30         var _controller = this.renderer.addController("Edge", _edge);
       
    31         _controller.redraw();
       
    32     }
       
    33     if (typeof _render_save !== "undefined" && (_render_save&Rkns._SAVE)) {
       
    34         this.remotemodel.addEdge(_edge);
       
    35     }
       
    36     return _edge;
       
    37 }
       
    38 
       
    39 Rkns.ViewModel.Project.prototype.addUser = function(_props, _render_save) {
       
    40     var _user = new Rkns.ViewModel.User(this, _props);
       
    41     this.users.push(_user);
       
    42     if (typeof _render_save !== "undefined" && (_render_save&Rkns._SAVE)) {
       
    43         this.remotemodel.addUser(_user);
       
    44     }
       
    45     return _user;
       
    46 }
       
    47 
       
    48 
       
    49 Rkns.ViewModel.Project.prototype.updateNode = function(_element, _props, _render_save) {
       
    50     this.updateElement("Node", _element, _props, _render_save)
       
    51 }
       
    52 
       
    53 Rkns.ViewModel.Project.prototype.updateEdge = function(_element, _props, _render_save) {
       
    54     this.updateElement("Edge", _element, _props, _render_save)
       
    55 }
       
    56 
       
    57 Rkns.ViewModel.Project.prototype.updateElement = function(_type, _element, _props, _render_save) {
       
    58     Rkns._(_props).each(function(_v, _k) {
       
    59         _element[_k] = _v;
       
    60     });
       
    61     if (typeof _render_save !== "undefined" && (_render_save&Rkns._RENDER)) {
       
    62         if (typeof _element.__controller !== "undefined") {
       
    63             _element.__controller.redraw();
       
    64         } else {
       
    65             this._renderer.redraw();
       
    66         }
       
    67     }
       
    68     if (typeof _render_save !== "undefined" && (_render_save&Rkns._SAVE)) {
       
    69         this.remotemodel[ "update" + _type ](_element);
       
    70     }
       
    71 }
       
    72 
       
    73 Rkns.ViewModel.Project.prototype.removeNode = function(_node, _render_save) {
       
    74     this.nodes.removeId(_node.id);
       
    75     if (typeof _node.__controller !== "undefined") {
       
    76         this.renderer.removeController(_node.__controller);
       
    77     }
       
    78     var _this = this;
       
    79     this.edges = this.edges.filter(function(_edge) {
       
    80         var _keep = _edge.from !== _node && _edge.to !== _node;
       
    81         if (!_keep && typeof _edge.__controller !== "undefined") {
       
    82             _this.renderer.removeController(_edge.__controller);
       
    83         }
       
    84         return _keep;
       
    85     });
       
    86     if (typeof _render_save !== "undefined" && (_render_save&Rkns._RENDER)) {
       
    87         this.renderer.redraw();
       
    88     }
       
    89     if (typeof _render_save !== "undefined" && (_render_save&Rkns._SAVE)) {
       
    90         this.remotemodel.removeNode(_node.id);
       
    91     }
       
    92     return _node;
       
    93 }
       
    94 
       
    95 Rkns.ViewModel.Project.prototype.removeEdge = function(_edge, _render_save) {
       
    96     this.edges.removeId(_edge.id);
       
    97     if (typeof _edge.__controller !== "undefined") {
       
    98         this.renderer.removeController(_edge.__controller);
       
    99     }
       
   100     if (typeof _render_save !== "undefined" && (_render_save&Rkns._RENDER)) {
       
   101         this.renderer.redraw();
       
   102     }
       
   103     if (typeof _render_save !== "undefined" && (_render_save&Rkns._SAVE)) {
       
   104         this.remotemodel.removeEdge(_edge.id);
       
   105     }
       
   106     return _edge;
       
   107 }
       
   108 
       
   109 /* Base Element */
       
   110 
       
   111 Rkns.ViewModel._BaseElement = function(_project, _props) {
       
   112     if (typeof _props !== "undefined") {
       
   113         this._project = _project;
       
   114         this.id = _props.id || Rkns.Utils.getUID(this.type);
       
   115         this.title = _props.title || "(untitled " + this.type + ")";
       
   116         this.description = _props.description || "";
       
   117         this.uri = _props.uri || "";
       
   118     }
       
   119 }
       
   120 
       
   121 Rkns.ViewModel._BaseElement.prototype.addReference = function(_propName, _list, _id, _default) {
       
   122     var _element = _list.getElement(_id);
       
   123     if (typeof _element === "undefined" && typeof _default !== "undefined") {
       
   124         this[ _propName ] = _default;
       
   125         this[ _propName + "_id" ] = _default.id;
       
   126     } else {
       
   127         this[ _propName + "_id" ] = _id;
       
   128         this[ _propName ] = _element;
       
   129     }
       
   130 }
       
   131 
       
   132 Rkns.ViewModel._BaseElement.prototype.updateGraphics = function() {
       
   133     this._project.renderer.redraw();
       
   134 }
       
   135 
       
   136 Rkns.ViewModel._BaseElement.prototype.updateData = function() {
       
   137     this._project.remotemodel.save(this);
       
   138 }
       
   139 
       
   140 /* Element Class Generator */
       
   141 
       
   142 Rkns.ViewModel._elementClass = function(_type) {
       
   143     return Rkns.Utils.inherit(Rkns.ViewModel._BaseElement, function() {
       
   144         this.type = _type;
       
   145     });
       
   146 }
       
   147 
       
   148 /* User Model */
       
   149 
       
   150 Rkns.ViewModel.User = Rkns.ViewModel._elementClass("user");
       
   151 
       
   152 Rkns.ViewModel.User.prototype._init = function(_project, _props) {
       
   153     this.color = _props.color || "#666666";
       
   154 }
       
   155 
       
   156 /* Node Model */
       
   157 
       
   158 Rkns.ViewModel.Node = Rkns.ViewModel._elementClass("node");
       
   159 
       
   160 Rkns.ViewModel.Node.prototype._init = function(_project, _props) {
       
   161     this.addReference("created_by", this._project.users, _props.created_by, _project.current_user);
       
   162     this.position = _props.position;
       
   163     this.description = _props.description || "";
       
   164 }
       
   165 
       
   166 Rkns.ViewModel.Node.prototype.setPosition = function(_x, _y) {
       
   167     if (typeof _x === "object") {
       
   168         if (typeof _x.x !== "undefined" && typeof _x.y !== "undefined") {
       
   169             this.position.x = _x.x;
       
   170             this.position.y = _x.y;
       
   171         } else {
       
   172             if (typeof _x.length !== "undefined") {
       
   173                 this.position.x = _x[0];
       
   174                 this.position.y = _x[1];
       
   175             }
       
   176         }
       
   177     } else {
       
   178         if (typeof _y !== "undefined") {
       
   179             this.position.x = +_x;
       
   180             this.position.y = +_y;
       
   181         }
       
   182     }
       
   183 }
       
   184 
       
   185 /* Edge Model */
       
   186 
       
   187 Rkns.ViewModel.Edge = Rkns.ViewModel._elementClass("edge");
       
   188 
       
   189 Rkns.ViewModel.Edge.prototype._init = function(_project, _props) {
       
   190     this.addReference("created_by", this._project.users, _props.created_by, _project.current_user);
       
   191     this.addReference("from", this._project.nodes, _props.from);
       
   192     this.addReference("to", this._project.nodes, _props.to);
       
   193 }
       
   194 
       
   195 /* List Helper Functions -- See Metadataplayer */
       
   196 
       
   197 Rkns.ViewModel.List = function() {
       
   198     Array.call(this);
       
   199     this.idIndex = [];
       
   200 }
       
   201 
       
   202 Rkns.ViewModel.List.prototype = new Array();
       
   203 
       
   204 Rkns.ViewModel.List.prototype.hasId = function(_id) {
       
   205     return Rkns._(this.idIndex).include(_id);
       
   206 }
       
   207 
       
   208 Rkns.ViewModel.List.prototype.getIds = function(_id) {
       
   209     return this.idIndex;
       
   210 }
       
   211 
       
   212 /* On recent browsers, forEach and map are defined and do what we want.
       
   213  * Otherwise, we'll use the Underscore.js functions
       
   214  */
       
   215 if (typeof Array.prototype.forEach === "undefined") {
       
   216     Rkns.ViewModel.List.prototype.forEach = function(_callback) {
       
   217         var _this = this;
       
   218         Rkns._(this).forEach(function(_value, _key) {
       
   219             _callback(_value, _key, _this);
       
   220         });
       
   221     }
       
   222 }
       
   223 
       
   224 if (typeof Array.prototype.map === "undefined") {
       
   225     Rkns.ViewModel.List.prototype.map = function(_callback) {
       
   226         var _this = this;
       
   227         return Rkns._(this).map(function(_value, _key) {
       
   228             return _callback(_value, _key, _this);
       
   229         });
       
   230     }
       
   231 }
       
   232 
       
   233 /* We override Array's filter function because it doesn't return an Rkns.ViewModel.List
       
   234  */
       
   235 Rkns.ViewModel.List.prototype.filter = function(_callback) {
       
   236     var _this = this,
       
   237         _res = new Rkns.ViewModel.List();
       
   238     _res.addElements(Rkns._(this).filter(function(_value, _key) {
       
   239         return _callback(_value, _key, _this);
       
   240     }));
       
   241     return _res;
       
   242 }
       
   243 
       
   244 Rkns.ViewModel.List.prototype.slice = function(_start, _end) {
       
   245     var _res = new Rkns.ViewModel.List();
       
   246     _res.addElements(Array.prototype.slice.call(this, _start, _end));
       
   247     return _res;
       
   248 }
       
   249 
       
   250 Rkns.ViewModel.List.prototype.splice = function(_start, _end) {
       
   251     var _res = new Rkns.ViewModel.List();
       
   252     _res.addElements(Array.prototype.splice.call(this, _start, _end));
       
   253     this.idIndex.splice(_start, _end);
       
   254     return _res;
       
   255 }
       
   256 
       
   257 /* Array has a sort function, but it's not as interesting as Underscore.js's sortBy
       
   258  * and won't return a new Rkns.ViewModel.List
       
   259  */
       
   260 Rkns.ViewModel.List.prototype.sortBy = function(_callback) {
       
   261     var _this = this,
       
   262         _res = new Rkns.ViewModel.List();
       
   263     _res.addElements(Rkns._(this).sortBy(function(_value, _key) {
       
   264         return _callback(_value, _key, _this);
       
   265     }));
       
   266     return _res;
       
   267 }
       
   268 
       
   269 Rkns.ViewModel.List.prototype.push = function(_el) {
       
   270     if (typeof _el === "undefined" || typeof _el.id === "undefined") {
       
   271         return;
       
   272     }
       
   273     var _index = (Rkns._(this.idIndex).indexOf(_el.id));
       
   274     if (_index === -1) {
       
   275         this.idIndex.push(_el.id);
       
   276         Array.prototype.push.call(this, _el);
       
   277     } else {
       
   278         this[_index] = _el;
       
   279     }
       
   280 }
       
   281 
       
   282 Rkns.ViewModel.List.prototype.addElements = function(_array) {
       
   283     var _this = this;
       
   284     Rkns._(_array).forEach(function(_el) {
       
   285         _this.push(_el);
       
   286     });
       
   287 }
       
   288 
       
   289 Rkns.ViewModel.List.prototype.removeId = function(_id) {
       
   290     var _index = (Rkns._(this.idIndex).indexOf(_id));
       
   291     if (_index !== -1) {
       
   292         this.splice(_index,1);
       
   293     }
       
   294 }
       
   295 
       
   296 Rkns.ViewModel.List.prototype.removeIds = function(_list) {
       
   297     var _this = this;
       
   298     Rkns._(_list).forEach(function(_id) {
       
   299         _this.removeId(_id);
       
   300     });
       
   301 }
       
   302 
       
   303 Rkns.ViewModel.List.prototype.getElement = function(_id) {
       
   304     var _index = Rkns._(this.idIndex).indexOf(_id);
       
   305     if (_index === -1) {
       
   306         return undefined;
       
   307     } else {
       
   308         return this[_index];
       
   309     }
       
   310 }