/public/javascripts/board.js

https://github.com/versionone/boardello · JavaScript · 332 lines · 265 code · 54 blank · 13 comment · 24 complexity · bf3dccd961939e14a988d0d432242c8c MD5 · raw file

  1. var Board = Backbone.Model.extend({
  2. defaults: {
  3. top: 0,
  4. left: 0,
  5. title: 'New Board',
  6. grabbed: false
  7. },
  8. initialize: function(){
  9. var model = this;
  10. _.bindAll(this, 'addCard', 'clear', 'addUser', 'remoteInitialize', 'grab', 'move', 'letGo');
  11. if (!model.id) model.set({id: 1 + Math.random() * 100000000000000000})
  12. model.set({ cards: new Cards(), users: new Users(), boards: new Boards() });
  13. Networking
  14. .bind('remote:initial-state', model.remoteInitialize)
  15. .bind('remote:new-user', model.addUser)
  16. .bind('remote:clear-board', function() { model.clear(true); })
  17. .bind('remote:card-created', function(card){ model.addCard(card, true) })
  18. .bind('remote:card-converted', function(message){
  19. model.convertCardToBoard(message.convertId, message.moveId, message.board)
  20. })
  21. .bind('remote:board-moving', function(data) {
  22. if (data.id == model.id) {
  23. model.move(data.left, data.top, true)
  24. }
  25. })
  26. .bind('remote:board-grabbed', function(data) {
  27. if (data.id == model.id) {
  28. model.grab(true);
  29. }
  30. })
  31. .bind('remote:board-letgo', function(data) {
  32. if (data.id == model.id) {
  33. model.letGo(true);
  34. }
  35. })
  36. .bind('remote:card-transfered', function(data){
  37. model.get('cards').get(data.cardId).delete(true);
  38. model.get('boards').get(data.boardId).addCard(data.card, true);
  39. });
  40. model.get('cards')
  41. .bind('reset', function(collection, options){
  42. if (!options.remote)
  43. Networking.trigger('clear-board', model.toJSON());
  44. })
  45. .bind('add', function(card, collection, options){
  46. if (!options.remote)
  47. Networking.trigger('card-created', card.toJSON());
  48. })
  49. .bind('convertToBoard', function(card, collection, options) {
  50. var message = { convertId: card.id, moveId: options.cardId };
  51. message.board = model.convertCardToBoard(message.convertId, message.moveId).toJSON();
  52. Networking.trigger('card-converted', message);
  53. });
  54. model.get('boards')
  55. .bind('card-transfered', function(board, collection, options) {
  56. //TODO move to a model method....
  57. var cards = model.get('cards')
  58. , transfer = cards.get(options.cardId)
  59. var transfered = new Card({
  60. left: transfer.get('left'),
  61. top: transfer.get('top'),
  62. title: transfer.get('title')
  63. });
  64. board.addCard(transfered, true);
  65. transfer.delete(true);
  66. var message = { boardId: board.id, cardId: transfer.id, card: transfered.toJSON() };
  67. Networking.trigger('card-transfered', message);
  68. })
  69. .bind('board-transfered', function(board, collection, options) {
  70. // var boards = model.get('boards')
  71. // , transfer = boards.get(options.boardId)
  72. // var transfered = new Board({
  73. // left: transfer.get('left'),
  74. // top: transfer.get('top'),
  75. // title: transfer.get('title')
  76. // });
  77. // board.get('boards').add(transfered);
  78. // transfer.delete();
  79. })
  80. model
  81. .bind('change:left', function(_board, value, options) {
  82. if (!options.remote)
  83. Networking.trigger('board-moving', model.toJSON());
  84. })
  85. .bind('change:top', function(_board, value, options) {
  86. if (!options.remote)
  87. Networking.trigger('board-moving', model.toJSON());
  88. })
  89. .bind('change:grabbed', function(_board, value, options) {
  90. if (!options.remote) {
  91. var eventName = model.get('grabbed') ? 'board-grabbed' : 'board-letgo';
  92. Networking.trigger(eventName, model.toJSON());
  93. }
  94. });
  95. },
  96. remoteInitialize: function(state) {
  97. var model = this;
  98. _.each(state.cards, function(card) {
  99. model.addCard(card, true);
  100. });
  101. _.each(state.users, function(user) {
  102. model.addUser(user, true);
  103. });
  104. _.each(state.boards, function(board) {
  105. model.addBoard(board, true);
  106. });
  107. },
  108. addCard: function(card, remote){
  109. this.get('cards').add(card, { remote: remote })
  110. return card;
  111. },
  112. clear: function(remote) {
  113. this.get('cards').reset([], { remote: remote })
  114. },
  115. addUser: function(user, remote){
  116. var users = this.get('users');
  117. users.add(user, { remote: remote });
  118. return user;
  119. },
  120. convertCardToBoard: function(convertId, moveId, board) {
  121. var model = this
  122. , cards = model.get('cards')
  123. , convert = cards.get(convertId)
  124. , move = cards.get(moveId);
  125. //convert to board
  126. var boardId = board ? board.id : null;
  127. var converted = new Board({
  128. id: boardId,
  129. left: convert.get('left'),
  130. top: convert.get('top'),
  131. title: convert.get('title')
  132. });
  133. model.addBoard(converted, true);
  134. convert.delete(true);
  135. //move dragged card to board
  136. var moved = new Card({
  137. left: move.get('left'),
  138. top: move.get('top'),
  139. title: move.get('title')
  140. });
  141. converted.addCard(moved, true);
  142. move.delete(true);
  143. return converted;
  144. },
  145. addBoard: function(board, remote) {
  146. var model = this
  147. , boards = model.get('boards');
  148. boards.add(board, { remote: remote });
  149. return board;
  150. },
  151. grab: function(remote) {
  152. var grabbed = this.get('grabbed');
  153. if (!grabbed) this.set({grabbed: true}, { remote: remote });
  154. return !grabbed;
  155. },
  156. move: function(left, top, remote){
  157. this.set({left: left, top: top}, { remote: remote });
  158. if (remote) this.set({ remoteMoving: true });
  159. },
  160. letGo: function(remote) {
  161. this.set({grabbed: false}, { remote : remote });
  162. },
  163. transferCard: function(cardId) {
  164. this.trigger('card-transfered', this, this.collection, { cardId: cardId });
  165. },
  166. transferBoard: function(boardId) {
  167. this.trigger('board-transfered', this, this.collection, { boardId: boardId });
  168. }
  169. });
  170. var Boards = Backbone.Collection.extend({
  171. model: Board
  172. });
  173. var BoardView = Backbone.View.extend({
  174. tagName: 'div',
  175. className: 'board',
  176. events: {
  177. 'dblclick': 'addCard',
  178. 'click .clear': 'clear'
  179. },
  180. initialize: function(){
  181. _.bindAll(this, 'render', 'addCard', 'cardAdded', 'userAdded', 'clear', 'boardAdded', 'isNested')
  182. var view = this
  183. , model = view.model
  184. , cards = model.get('cards')
  185. , users = model.get('users')
  186. , boards = model.get('boards');
  187. model
  188. .bind('change:top', view.render)
  189. .bind('change:left', view.render);
  190. cards
  191. .bind('add', view.cardAdded)
  192. .bind('reset', view.render);
  193. users.bind('add', view.userAdded)
  194. boards.bind('add', view.boardAdded)
  195. },
  196. render: function(){
  197. //wtf is this doing here??
  198. _.each(this.model.get('users').models, this.userAdded);
  199. var $el = $(this.el)
  200. , model = this.model
  201. , view = this;
  202. if (view.isNested()) {
  203. $el
  204. .html('<div class="title">'+model.get('title')+'</title>')
  205. .data('id', model.id)
  206. .css({
  207. left: model.get('left'),
  208. top: model.get('top')
  209. })
  210. .draggable({
  211. start: function(){
  212. return model.grab();
  213. },
  214. drag: function(event, ui){
  215. model.move(ui.position.left, ui.position.top);
  216. },
  217. stop: function() {
  218. model.letGo();
  219. },
  220. grid: [10,10]
  221. })
  222. .droppable({
  223. drop: function(event, ui){
  224. var $dropped = ui.draggable
  225. , itemId = $dropped.data().id;
  226. if ($dropped.is('.card')) model.transferCard(itemId);
  227. if ($dropped.is('.board')) model.transferBoard(itemId);
  228. }
  229. });
  230. }
  231. return this
  232. },
  233. addCard: function(e){
  234. if (this.isNested()) {
  235. $(this.el).effect('puff', { percent: 500 }, 500)
  236. e.stopPropagation()
  237. return
  238. }
  239. var card = new Card();
  240. var left = this.findNearestGridCoordinate(e.clientX, 10);
  241. var top = this.findNearestGridCoordinate(e.clientY, 10);
  242. card.set({title: 'newcard', left: left, top: top});
  243. this.model.addCard(card);
  244. },
  245. cardAdded: function(card){
  246. if (this.isNested()) {
  247. return;
  248. }
  249. var cardView = new CardView({ model: card });
  250. $(this.el).append(cardView.el)
  251. cardView.render();
  252. },
  253. userAdded: function(user){
  254. if (this.isNested()) return;
  255. var userView = new UserView({ model: user });
  256. $(this.el).append(userView.el);
  257. userView.render();
  258. },
  259. clear: function(){
  260. if (confirm('are you sure?')) {
  261. this.model.clear();
  262. }
  263. },
  264. boardAdded: function(board) {
  265. if (this.isNested()) return;
  266. var boardView = new BoardView({ model: board });
  267. $(this.el).append(boardView.el)
  268. boardView.render();
  269. },
  270. findNearestGridCoordinate: function(position, gridSize) {
  271. if (position % gridSize === 0) return position;
  272. if (position % gridSize < gridSize / 2) return position - (position % gridSize);
  273. return position + (gridSize - position % gridSize);
  274. },
  275. isNested: function(){
  276. return !!this.model.collection;
  277. }
  278. });