PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/public/js/main.js

https://bitbucket.org/KarlisLukstins/sticky-fork
JavaScript | 328 lines | 278 code | 35 blank | 15 comment | 23 complexity | 276b8cf782faefb252762cf0e612370a MD5 | raw file
  1. 'use strict';
  2. var socket = require('socket.io-client')();
  3. require('jquery-ui');
  4. var $ = require('jquery');
  5. var Backbone = require('backbone');
  6. Backbone.$ = $;
  7. $(function(){
  8. var noteModel = Backbone.Model.extend({
  9. defaults: { id:null, content: null, x: null, y: null },
  10. isImage: function(){ return !!this.get('image'); }
  11. });
  12. var noteView = Backbone.View.extend({
  13. events:{
  14. 'dblclick': 'makeEditable',
  15. 'blur span': 'blur'
  16. },
  17. initialize: function(){
  18. // console.log('view:noteView', 'initialize');
  19. },
  20. render: function() {
  21. // console.log('view:noteView', 'render');
  22. var noteClass, noteContent;
  23. if( this.model.isImage() ){
  24. noteClass = 'noteImg';
  25. noteContent = 'image url here';
  26. } else {
  27. noteClass = 'noteTxt';
  28. noteContent = 'enter your text';
  29. }
  30. var $note = $(this.el);
  31. $note.css('position', 'absolute');
  32. $note.addClass('note');
  33. $note.addClass(noteClass);
  34. var content = this.model.get('content') || noteContent;
  35. if( this.model.isImage() && this.checkImageUrlContent( content ) ){
  36. $note.css('background-image', 'url(' + content + ')').addClass('done');
  37. } else {
  38. $note.html('<span>' + content + '</span>');
  39. }
  40. // console.log( this.model.cid, this.cid);
  41. // $note.attr( 'data-view', this );
  42. $note.data('view', this);
  43. $('#notes').append( this.el );
  44. this.bindView();
  45. this.updateView();
  46. return this;
  47. },
  48. updateView: function(){
  49. // console.log('view:noteView', 'updateView');
  50. var $note = $(this.el);
  51. $note.css({
  52. left: this.model.get('x'),
  53. top: this.model.get('y')
  54. });
  55. },
  56. bindView: function(){
  57. var _this = this;
  58. // bind dragging
  59. $( this.el ).draggable({
  60. stack: ".ui-draggable",
  61. cursor: "crosshair",
  62. stop: function( event, ui ){
  63. _this.move(ui);
  64. }
  65. });
  66. },
  67. blur: function(){
  68. console.log('view:noteView', 'blur');
  69. var $el = $('span', this.el);
  70. var text = $el.text();
  71. this.update( text );
  72. // check for URL content , only for image type
  73. if( ! this.model.isImage() ){
  74. return;
  75. }
  76. if( this.checkImageUrlContent(text) ){
  77. $( this.el ).css('background-image', 'url(' + text + ')').addClass('done');
  78. $el.text('');
  79. } else {
  80. console.info('note image, bad url');
  81. }
  82. },
  83. checkImageUrlContent: function( text ){
  84. var regexUrl = new RegExp(/[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi);
  85. return text.match(regexUrl);
  86. },
  87. makeEditable: function(){
  88. console.log('view:noteView', 'makeEditable');
  89. var $el = $('span', this.el);
  90. var txt = $el.text();
  91. if( txt == 'image url here' || txt == 'enter your text' ){
  92. $el.text('');
  93. }
  94. $el.attr('contentEditable', true).focus();
  95. },
  96. move: function( ui ){
  97. console.log('view:noteView', 'move', ui);
  98. var data = {
  99. id: this.id,
  100. x: ui.position.left,
  101. y: ui.position.top
  102. };
  103. socket.emit('move', data);
  104. },
  105. update: function( content ){
  106. console.log('view:noteView', 'update', this.id, content);
  107. var data = {
  108. id: this.id,
  109. content: content
  110. };
  111. socket.emit('update', data);
  112. },
  113. delete: function(){
  114. console.log('view:noteView', 'delete', this);
  115. var data = {
  116. id: this.id
  117. };
  118. socket.emit('delete', data);
  119. this.el.remove();
  120. this.model.collection.remove( this.model );
  121. return false;
  122. }
  123. });
  124. var notesCollection = Backbone.Collection.extend({ model: noteModel });
  125. var notes = new notesCollection();
  126. var notesView = Backbone.View.extend({
  127. views: {},
  128. initialize: function(){
  129. this.collection.bind('add', function(model) {
  130. // console.log( 'model add', model );
  131. this.views[ model.cid ] = new noteView({ model: model, id: model.id, cid: model.cid }).render();
  132. }, this);
  133. }
  134. });
  135. var notesView = new notesView({ collection: notes });
  136. var desktopModel = Backbone.Model.extend({ defaults:{ id: null, name: null, selected: null } });
  137. var desktopsCollection = Backbone.Collection.extend({ model: desktopModel });
  138. var desktops = new desktopsCollection();
  139. var DesktopView = Backbone.View.extend({
  140. events: {
  141. 'click': 'onDesktop'
  142. },
  143. onDesktop: function( e ){
  144. console.log( this.model );
  145. console.log('DesktopView:onDesktop', this.model.id );
  146. // reset active desktops
  147. this.model.collection.each(function( desktop ){
  148. desktop.set('selected', false)
  149. });
  150. this.model.set('selected', true);
  151. socket.emit('loadNotes', { id: this.model.id });
  152. this.updateView();
  153. },
  154. render: function(){
  155. this.$el.html('<a><span></span>'+ this.model.get('name') +'</a>' ) ;
  156. $('#desktopSelector').append( this.$el );
  157. this.updateView();
  158. },
  159. updateView: function(){
  160. // console.log('updateView:onDesktop', this );
  161. if( this.model.get('selected') ) {
  162. $('#desktopSelector a').removeClass('active');
  163. var $desktop = $('a', this.$el);
  164. $desktop.addClass('active');
  165. }
  166. }
  167. });
  168. var DesktopsView = Backbone.View.extend({
  169. el: 'body',
  170. events: {
  171. 'click #addDesktop': 'addDesktop',
  172. 'click #noteTxt': 'addNoteTxt',
  173. 'click #noteImg': 'addNoteImg'
  174. },
  175. addDesktop: function(){
  176. console.info('click', 'addDesktop');
  177. socket.emit('desktopAdd', true);
  178. },
  179. addNoteTxt: function(){
  180. console.info('click', 'note txt');
  181. this.addNote('txt');
  182. },
  183. addNoteImg: function(){
  184. console.info('click', 'note img');
  185. this.addNote('img');
  186. },
  187. addNote: function( type ){
  188. console.log('DesktopsView:addNote (type)', type);
  189. var _desktopId = null;
  190. // look for selected
  191. this.collection.each(function( desktop ){
  192. console.log( 'selected', desktop.get('selected') );
  193. if( desktop.get('selected') ){
  194. _desktopId = desktop.id;
  195. return false;
  196. }
  197. });
  198. if( !_desktopId ){
  199. console.log( 'no active desktop ');
  200. _desktopId = this.setActiveDesktop();
  201. if( !_desktopId ){
  202. return;
  203. }
  204. }
  205. console.log('_desktopId', _desktopId );
  206. var data = {
  207. id: _desktopId
  208. };
  209. if( type == 'img' ){
  210. data.image = true;
  211. }
  212. socket.emit('create', data);
  213. },
  214. render: function(){
  215. $('#desktopSelector').empty();
  216. this.setActiveDesktop();
  217. this.collection.each(function( desktop ){
  218. var desktopView = new DesktopView({ model: desktop });
  219. desktopView.render();
  220. });
  221. },
  222. setActiveDesktop: function(){
  223. // set first active desktop
  224. if( this.collection.length ) {
  225. var _select = this.collection.first();
  226. _select.set('selected', true);
  227. return _select.id;
  228. }
  229. },
  230. loadNotes: function() {
  231. if( ! this.collection.length ){
  232. console.log( 'no desktops' );
  233. return;
  234. }
  235. var _desktop = this.collection.first();
  236. socket.emit('loadNotes', { id: _desktop.id });
  237. }
  238. });
  239. var desktopsView = new DesktopsView({ collection: desktops });
  240. /* onload request data */
  241. socket.emit('loadDesktops', true);
  242. socket.on('loadDesktops', function( res ){
  243. console.log('io:loadDesktops', res);
  244. for( var i = 0, l = res.length; i < l ; i++){
  245. var _data = {
  246. id: res[i]._id,
  247. name: res[i].name
  248. };
  249. desktops.add( _data );
  250. }
  251. desktopsView.render();
  252. desktopsView.loadNotes();
  253. });
  254. /* bind elements */
  255. $("#bin").droppable({
  256. accept: ".note",
  257. activeClass: "active",
  258. hoverClass: "hover",
  259. tolerance: "pointer",
  260. drop: function( event, ui ){
  261. console.log( 'droppable view', $(ui.draggable).data('view') );
  262. $( ui.draggable ).data('view').delete();
  263. }
  264. });
  265. socket.on('loadNotes', function( res ){
  266. // clean
  267. notes.reset();
  268. $('#notes').empty();
  269. console.log('io:loadNotes', res );
  270. for( var i = 0, l = res.length; i < l ; i++){
  271. var _data = res[i].data;
  272. _data.id = res[i]._id;
  273. notes.add( _data );
  274. }
  275. });
  276. socket.on('noteCreate', function( data ){
  277. console.log('io:noteCreate', data );
  278. data.data.id = data._id;
  279. notes.add( data.data );
  280. });
  281. socket.on('desktopCreate', function( data ){
  282. console.log('io:desktopCreate', data );
  283. data.id = data._id;
  284. desktops.add( data );
  285. desktopsView.render();
  286. });
  287. socket.on('deleted', function( data ){
  288. console.info('io:deleted (only info notice)', data );
  289. });
  290. socket.on('moved', function( data ){
  291. console.info('io:moved (only info notice)', data );
  292. });
  293. });