/public/js/commonplace.js

https://github.com/fredoliveira/commonplace-nodebb · JavaScript · 187 lines · 140 code · 34 blank · 13 comment · 15 complexity · 718a30c47aa9d4f8f78f8376fdbcc271 MD5 · raw file

  1. function urlify(text) {
  2. var urlRegex = /(https?:\/\/[^\s]+)/g;
  3. return text.replace(urlRegex, function(url) {
  4. return '<a href="' + url + '">' + url + '</a>';
  5. })
  6. }
  7. function parsetext(text) {
  8. /* convert urls */
  9. text = urlify(text);
  10. /* and breaks into br */
  11. return text.replace(/\n/g, "<br />");
  12. }
  13. $(document).ready(function() {
  14. window.Fragment = Backbone.Model.extend({
  15. //idAttribute: "_id"
  16. });
  17. window.FragmentList = Backbone.Collection.extend({
  18. model: Fragment,
  19. url: 'fragments'
  20. });
  21. /*
  22. Generic FragmentView
  23. ====================
  24. Should be passed a template parameter to know what to render. Example:
  25. new FragmentView({model: fragment, template: "#fragment-sidebar"});
  26. */
  27. window.FragmentView = Backbone.View.extend({
  28. className: 'fragment',
  29. events: {
  30. "click .handle": "showTools",
  31. "click .edit": "edit",
  32. "click .delete": "clear",
  33. "dlbclick div.content": "edit",
  34. "keypress textarea.edit-fragment": "closeOnEnter"
  35. },
  36. initialize: function(options) {
  37. _.bindAll(this, 'render', 'remove');
  38. this.template = _.template($(options['template']).html());
  39. this.model.bind('change', this.render);
  40. this.model.bind('destroy', this.remove);
  41. },
  42. render: function() {
  43. $(this.el).html(this.template(this.model.toJSON()));
  44. this.setContent();
  45. this.$('abbr').timeago();
  46. return this;
  47. },
  48. setContent: function() {
  49. var content = this.model.get('content');
  50. this.$('.content').html(converter.makeHtml(content));
  51. this.input = this.$('.edit-fragment');
  52. this.input.bind('blur', _.bind(this.closeAndSave, this));
  53. this.input.val(content);
  54. },
  55. edit: function() {
  56. $(this.el).addClass("editing");
  57. this.input.focus();
  58. },
  59. closeAndSave: function() {
  60. // TODO: wondering if this should save, or just close.
  61. this.model.save({content: this.input.val()});
  62. $(this.el).removeClass("editing");
  63. },
  64. closeOnEnter: function(e) {
  65. if (e.keyCode == 13 && e.shiftKey) {
  66. if(this.input.val() != '') {
  67. this.model.save({content: this.input.val()});
  68. $(this.el).removeClass("editing");
  69. }
  70. } else {
  71. return;
  72. }
  73. },
  74. showTools: function() {
  75. this.$('.tools').toggle();
  76. },
  77. clear: function() {
  78. this.model.destroy();
  79. }
  80. });
  81. window.Timeline = Backbone.View.extend({
  82. el: $('#timeline'),
  83. initialize: function() {
  84. Fragments.bind('add', this.addOne, this);
  85. Fragments.bind('reset', this.addAll, this);
  86. Fragments.bind('all', this.render, this);
  87. },
  88. render: function() {
  89. return this;
  90. },
  91. addOne: function(fragment) {
  92. if (fragment.get('type') == 2) {
  93. var view = new FragmentView({model: fragment, template: "#fragment-image"});
  94. } else {
  95. var view = new FragmentView({model: fragment, template: "#fragment"});
  96. }
  97. // FIXME, should use this.el
  98. $('#timeline').prepend(view.render().el);
  99. },
  100. addAll: function() {
  101. Fragments.each(this.addOne)
  102. }
  103. });
  104. window.FragmentForm = Backbone.View.extend({
  105. el: $('#new'),
  106. events: {
  107. "click .text": "showText",
  108. "click .image": "showImage",
  109. "keypress #new-fragment": "createOnEnter"
  110. },
  111. initialize: function() {
  112. _.bindAll(this, 'render');
  113. this.input = this.$('#new-fragment');
  114. },
  115. render: function() {
  116. return this;
  117. },
  118. createOnEnter: function(e) {
  119. if (e.keyCode == 13 && e.shiftKey) {
  120. if(this.input.val() != '') {
  121. Fragments.create(this.newAttributes());
  122. this.input.val('');
  123. }
  124. } else {
  125. return;
  126. }
  127. },
  128. newAttributes: function() {
  129. return {
  130. content: this.input.val()
  131. };
  132. },
  133. showText: function() {
  134. this.$('#new-image').hide();
  135. this.$('#new-fragment').show();
  136. this.$('.text').addClass('current');
  137. this.$('.text').removeClass('current');
  138. },
  139. showImage: function() {
  140. this.$('#new-fragment').hide();
  141. this.$('#new-image').show();
  142. this.$('.image').removeClass('current');
  143. }
  144. });
  145. /* grab our fragments from the server */
  146. window.Fragments = new FragmentList;
  147. /* init our views */
  148. window.timeline = new Timeline;
  149. window.fragmentForm = new FragmentForm;
  150. Fragments.fetch();
  151. window.converter = new Showdown.converter();
  152. $('textarea#new-fragment').autoResize({extraSpace : 60});
  153. });