(function(root) {
'use strict';
var Backbone = root.Backbone;
var Models = root.Rkns.Models = {};
Models.getUID = function(obj) {
var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
.replace(/[xy]/g,
function(c) {
var r = Math.random() * 16 | 0, v = c === 'x' ? r
: (r & 0x3 | 0x8);
return v.toString(16);
});
if (typeof obj !== 'undefined') {
return obj.type + '-' + guid;
}
else {
return guid;
}
};
var RenkanModel = Backbone.RelationalModel.extend({
idAttribute : '_id',
constructor : function(options) {
if (typeof options !== 'undefined') {
options._id = options._id || options.id || Models.getUID(this);
options.title = options.title || '';
options.description = options.description || '';
options.uri = options.uri || '';
if (typeof this.prepare === 'function') {
options = this.prepare(options);
}
}
Backbone.RelationalModel.prototype.constructor.call(this, options);
},
validate : function() {
if (!this.type) {
return 'object has no type';
}
},
addReference : function(_options, _propName, _list, _id, _default) {
var _element = _list.get(_id);
if (typeof _element === 'undefined' &&
typeof _default !== 'undefined') {
_options[_propName] = _default;
}
else {
_options[_propName] = _element;
}
}
});
// USER
var User = Models.User = RenkanModel.extend({
type : 'user',
prepare : function(options) {
options.color = options.color || '#666666';
return options;
},
toJSON : function() {
return {
_id : this.get('_id'),
title : this.get('title'),
uri : this.get('uri'),
description : this.get('description'),
color : this.get('color')
};
}
});
// NODE
var Node = Models.Node = RenkanModel.extend({
type : 'node',
relations : [ {
type : Backbone.HasOne,
key : 'created_by',
relatedModel : User
} ],
prepare : function(options) {
var project = options.project;
this.addReference(options, 'created_by', project.get('users'),
options.created_by, project.current_user);
options.description = options.description || '';
return options;
},
toJSON : function() {
return {
_id : this.get('_id'),
title : this.get('title'),
uri : this.get('uri'),
description : this.get('description'),
position : this.get('position'),
image : this.get('image'),
style : this.get('style'),
created_by : this.get('created_by') ? this.get('created_by')
.get('_id') : null,
size : this.get('size'),
clip_path : this.get('clip_path'),
shape : this.get('shape'),
type : this.get('type')
};
}
});
// EDGE
var Edge = Models.Edge = RenkanModel.extend({
type : 'edge',
relations : [ {
type : Backbone.HasOne,
key : 'created_by',
relatedModel : User
}, {
type : Backbone.HasOne,
key : 'from',
relatedModel : Node
}, {
type : Backbone.HasOne,
key : 'to',
relatedModel : Node
} ],
prepare : function(options) {
var project = options.project;
this.addReference(options, 'created_by', project.get('users'),
options.created_by, project.current_user);
this.addReference(options, 'from', project.get('nodes'),
options.from);
this.addReference(options, 'to', project.get('nodes'), options.to);
return options;
},
toJSON : function() {
return {
_id : this.get('_id'),
title : this.get('title'),
uri : this.get('uri'),
description : this.get('description'),
from : this.get('from') ? this.get('from').get('_id') : null,
to : this.get('to') ? this.get('to').get('_id') : null,
style : this.get('style'),
created_by : this.get('created_by') ? this.get('created_by')
.get('_id') : null
};
}
});
// View
var View = Models.View = RenkanModel.extend({
type : 'view',
relations : [ {
type : Backbone.HasOne,
key : 'created_by',
relatedModel : User
} ],
prepare : function(options) {
var project = options.project;
this.addReference(options, 'created_by', project.get('users'),
options.created_by, project.current_user);
options.description = options.description || '';
if (typeof options.offset !== 'undefined') {
var offset = {};
if (Array.isArray(options.offset)) {
offset.x = options.offset[0];
offset.y = options.offset.length > 1 ? options.offset[1]
: options.offset[0];
}
else if (options.offset.x != null) {
offset.x = options.offset.x;
offset.y = options.offset.y;
}
options.offset = offset;
}
return options;
},
toJSON : function() {
return {
_id : this.get('_id'),
zoom_level : this.get('zoom_level'),
offset : this.get('offset'),
title : this.get('title'),
description : this.get('description'),
created_by : this.get('created_by') ? this.get('created_by')
.get('_id') : null,
hidden_nodes: this.get('hidden_nodes')
// Don't need project id
};
}
});
// PROJECT
var Project = Models.Project = RenkanModel.extend({
schema_version : '2',
type : 'project',
blacklist : [ 'saveStatus', 'loadingStatus'],
relations : [ {
type : Backbone.HasMany,
key : 'users',
relatedModel : User,
reverseRelation : {
key : 'project',
includeInJSON : '_id'
}
}, {
type : Backbone.HasMany,
key : 'nodes',
relatedModel : Node,
reverseRelation : {
key : 'project',
includeInJSON : '_id'
}
}, {
type : Backbone.HasMany,
key : 'edges',
relatedModel : Edge,
reverseRelation : {
key : 'project',
includeInJSON : '_id'
}
}, {
type : Backbone.HasMany,
key : 'views',
relatedModel : View,
reverseRelation : {
key : 'project',
includeInJSON : '_id'
}
} ],
addUser : function(_props, _options) {
_props.project = this;
var _user = User.findOrCreate(_props);
this.get('users').push(_user, _options);
return _user;
},
addNode : function(_props, _options) {
_props.project = this;
var _node = Node.findOrCreate(_props);
this.get('nodes').push(_node, _options);
return _node;
},
addEdge : function(_props, _options) {
_props.project = this;
var _edge = Edge.findOrCreate(_props);
this.get('edges').push(_edge, _options);
return _edge;
},
addView : function(_props, _options) {
_props.project = this;
// TODO: check if need to replace with create only
var _view = View.findOrCreate(_props);
// TODO: Should we remember only one view?
this.get('views').push(_view, _options);
return _view;
},
removeNode : function(_model) {
this.get('nodes').remove(_model);
},
removeEdge : function(_model) {
this.get('edges').remove(_model);
},
validate : function(options) {
var _project = this;
_.each(
[].concat(options.users, options.nodes, options.edges,options.views),
function(_item) {
if (_item) {
_item.project = _project;
}
}
);
},
getSchemaVersion : function(data) {
var t = data;
if(typeof(t) === 'undefined') {
t = this;
}
var version = t.schema_version;
if(!version) {
return 1;
}
else {
return version;
}
},
// Add event handler to remove edges when a node is removed
initialize : function() {
var _this = this;
this.on('remove:nodes', function(_node) {
_this.get('edges').remove(
_this.get('edges').filter(
function(_edge) {
return _edge.get('from') === _node ||
_edge.get('to') === _node;
}));
});
},
toJSON : function() {
var json = _.clone(this.attributes);
for ( var attr in json) {
if ((json[attr] instanceof Backbone.Model) ||
(json[attr] instanceof Backbone.Collection) ||
(json[attr] instanceof RenkanModel)) {
json[attr] = json[attr].toJSON();
}
}
return _.omit(json, this.blacklist);
}
});
var RosterUser = Models.RosterUser = Backbone.Model
.extend({
type : 'roster_user',
idAttribute : '_id',
constructor : function(options) {
if (typeof options !== 'undefined') {
options._id = options._id ||
options.id ||
Models.getUID(this);
options.title = options.title || '(untitled ' + this.type + ')';
options.description = options.description || '';
options.uri = options.uri || '';
options.project = options.project || null;
options.site_id = options.site_id || 0;
if (typeof this.prepare === 'function') {
options = this.prepare(options);
}
}
Backbone.Model.prototype.constructor.call(this, options);
},
validate : function() {
if (!this.type) {
return 'object has no type';
}
},
prepare : function(options) {
options.color = options.color || '#666666';
return options;
},
toJSON : function() {
return {
_id : this.get('_id'),
title : this.get('title'),
uri : this.get('uri'),
description : this.get('description'),
color : this.get('color'),
project : (this.get('project') != null) ? this.get(
'project').get('id') : null,
site_id : this.get('site_id')
};
}
});
var UsersList = Models.UsersList = Backbone.Collection.extend({
model : RosterUser
});
})(window);