PageRenderTime 116ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/public/javascripts/todos.js

https://bitbucket.org/jenkinsj/tabkiller
JavaScript | 323 lines | 201 code | 57 blank | 65 comment | 12 complexity | dedc1381b67dc97af2125c3d5df4001b MD5 | raw file
  1. var holder = window//document.getElementById('holder');
  2. holder.ondragover = function () { this.className = 'hover'; return false; };
  3. holder.ondragend = function () { this.className = ''; return false; };
  4. holder.ondrop = function (e) { e.preventDefault(); return false; };
  5. $(function ($, _, Backbone) {
  6. "use strict";
  7. var Post, Block, PostList, BlockList, Posts, Blocks, PostView, BlockView, AppView, App;
  8. // Post Model
  9. // ----------
  10. // Our basic **post** model has `title`, `order`, and `done` attributes.
  11. Post = Backbone.Model.extend({
  12. // MongoDB uses _id as default primary key
  13. idAttribute: "_id",
  14. // Default attributes for the todo item.
  15. defaults: function () {
  16. return {
  17. title: ""
  18. , block: null
  19. , done: false
  20. , url : ""
  21. , createdAt:new Date()
  22. , favicon: ""
  23. };
  24. },
  25. // Ensure that each todo created has `title`.
  26. initialize: function () {
  27. if (!this.get("title")) {
  28. this.set({"title": this.defaults.title});
  29. }
  30. },
  31. // timeago:function(){
  32. // },
  33. // Remove this Todo and delete its view.
  34. clear: function () {
  35. this.destroy();
  36. }
  37. });
  38. Block = Backbone.Model.extend({
  39. idAttribute: "_id",
  40. sync: function () { return false; }
  41. })
  42. // Todo Collection
  43. // ---------------
  44. PostList = Backbone.Collection.extend({
  45. // Reference to this collection's model.
  46. model: Post,
  47. // Note that url may also be defined as a function.
  48. url: function () {
  49. return "/bookmark"+ ((this.id) ? '/' + this.id : '')+ ((block) ? '?block=' + block : '');
  50. // + ((this.id) ? '/' + this.id : '');
  51. },
  52. });
  53. // Create our global collection of **Todos**.
  54. Posts = new PostList();
  55. // Reference to this collection's model.
  56. BlockList = Backbone.Collection.extend({
  57. // Reference to this collection's model.
  58. model: Block,
  59. // Note that url may also be defined as a function.
  60. // url: function () {
  61. // return "/bookmark" + ((this.id) ? '/' + this.id : '');
  62. // },
  63. });
  64. // Create our global collection of **Todos**.
  65. Blocks = new BlockList();
  66. // Todo Item View
  67. // --------------
  68. BlockView = Backbone.View.extend({
  69. tagName: "li",
  70. template: _.template($('#block-template').html()),
  71. events: {
  72. "click .block-link" : "bucketSelect",
  73. },
  74. render: function () {
  75. this.$el.html(this.template( this.model.toJSON() ));
  76. return this;
  77. },
  78. bucketSelect:function(){
  79. $("#new-post-block").val(this.model.get("id"))
  80. $(".selected-bucket").removeClass("selected-bucket")
  81. this.$el.addClass("selected-bucket");
  82. }
  83. });
  84. // The DOM element for a todo item...
  85. PostView = Backbone.View.extend({
  86. //... is a list tag.
  87. tagName: "li",
  88. // Cache the template function for a single item.
  89. template: _.template($('#item-template').html()),
  90. // The DOM events specific to an item.
  91. events: {
  92. "click .toggle" : "toggleDone",
  93. "click .edit" : "edit",
  94. "click a.destroy" : "clear",
  95. "click .submit-update" : "update",
  96. "click .menu" : "menu"
  97. },
  98. menu:function(e){
  99. var that=this;
  100. that.flag=false;
  101. this.dropdown.css({"display":"inline-block", "position":"absolute","left":$(event.target).position().left, "top":$(event.target).position().top+$(event.target).height()})
  102. $(window).bind("click", function(){
  103. if (that.flag==false) { that.flag=true; return false }
  104. that.dropdown.css({"display":"none"})
  105. $(this).unbind("click");
  106. })
  107. },
  108. // The TodoView listens for changes to its model, re-rendering. Since there's
  109. // a one-to-one correspondence between a **Todo** and a **TodoView** in this
  110. // app, we set a direct reference on the model for convenience.
  111. initialize: function () {
  112. this.model.bind('change', this.render, this);
  113. this.model.bind('destroy', this.remove, this);
  114. },
  115. // Re-render the titles of the todo item.
  116. render: function () {
  117. var JSON=this.model.toJSON()
  118. JSON.timeAgo=$.timeago(this.model.get("createdAt"))
  119. this.$el.html(this.template(JSON));
  120. this.input = this.$('.edit');
  121. this.bodyEdit = this.$(".title-edit")
  122. this.titleEdit = this.$(".body-edit")
  123. this.dropdown=this.$(".dropdown")
  124. this.menu=this.$(".menu")
  125. //this.controlBox.dropdown('method', );
  126. return this;
  127. },
  128. // Toggle the `"done"` state of the model.
  129. toggleDone: function () {
  130. this.model.toggle();
  131. },
  132. // If you hit `enter`, we're through editing the item.
  133. update: function (e) {
  134. var valuebody = this.bodyEdit.val().trim(),
  135. valuetitle = this.titleEdit.val().trim();
  136. if(valuetitle || valuebody) {
  137. this.model.save({title: valuetitle, body:valuebody});
  138. }
  139. this.$el.removeClass('editing');
  140. // if (e.keyCode === 13) {
  141. // this.close();
  142. // }
  143. },
  144. // Remove the item, destroy the model.
  145. clear: function () {
  146. this.model.clear();
  147. },
  148. edit:function () {
  149. this.$el.addClass("editing")
  150. this.titleEdit.val(this.model.get("title"));
  151. this.bodyEdit.val(this.model.get("body"))
  152. },
  153. });
  154. // The Application
  155. // ---------------
  156. // Our overall **AppView** is the top-level piece of UI.
  157. AppView = Backbone.View.extend({
  158. // Instead of generating a new element, bind to the existing skeleton of
  159. // the App already present in the HTML.
  160. el: $("#app"),
  161. username:username,
  162. // Our template for the line of statistics at the bottom of the app.
  163. // Delegated events for creating new items, and clearing completed ones.
  164. events: {
  165. "keypress #new-post-title": "createOnEnter",
  166. // "click #clear-completed": "clearCompleted",
  167. //"click #toggle-all": "toggleAllComplete"
  168. "click .submit" : "create"
  169. },
  170. // At initialization we bind to the relevant events on the `Todos`
  171. // collection, when items are added or changed. Kick things off by
  172. // loading any preexisting todos.
  173. initialize: function () {
  174. this.inputTitle = this.$("#new-post-title");
  175. this.inputBody = this.$("#new-post-body");
  176. this.inputUrl = this.$("#new-post-url");
  177. this.inputBlock = this.$("#new-post-block");
  178. // Blocks.bind('add', this.addBlock, this);
  179. Posts.bind('add', this.addOne, this);
  180. Posts.bind('reset', this.addAll, this);
  181. Posts.bind('all', this.render, this);
  182. //this.footer = this.$('footer');
  183. this.main = $('#main');
  184. $(window).on("drop")
  185. $("#new-bucket-link").bind("click",function(){
  186. $("#new-post-block").val("")
  187. $(".selected-bucket").removeClass("selected-bucket")
  188. $("#new-bucket").addClass("selected-bucket")
  189. })
  190. Posts.fetch();
  191. },
  192. // Re-rendering the App just means refreshing the statistics -- the rest
  193. // of the app doesn't change.
  194. render: function () {
  195. if (Posts.length) {
  196. this.main.show();
  197. //this.footer.show();
  198. } else {
  199. this.main.hide();
  200. }
  201. },
  202. // Add a single post item to the list by creating a view for it, and
  203. // appending its element to the `<ul>`.
  204. addOne: function (post) {
  205. var view, block;
  206. view = new PostView({model: post});
  207. block=App.findBlock(post.get("block"))
  208. $("ul.block-view",block).prepend(view.render().el);
  209. $("#list").prepend(block) //view.render().el);//.
  210. $(".block-link", block).click();//click the new bucket to focus it.
  211. },
  212. findBlock: function(blockId){
  213. var view,el, id;
  214. id=Blocks.where({id:blockId})
  215. if (id.length)
  216. el=id[0].get("el");
  217. else
  218. el=this.addBlock(blockId);
  219. return el
  220. },
  221. addBlock: function(blockId){
  222. var block = new Block({id:blockId});
  223. var blockview= new BlockView({model:block});
  224. var render=blockview.render().el;
  225. block.set({el:render});
  226. block.save();
  227. Blocks.add(block);
  228. return render
  229. },
  230. // Add all items in the **Todos** collection at once.
  231. addAll: function () {
  232. Posts.each(this.addOne);
  233. },
  234. // If you hit return in the main input field, create new **Todo** model
  235. createOnEnter: function (e) {
  236. if (e.keyCode !== 13) { return; }
  237. if (!this.inputTitle.val()) { return; }
  238. create();
  239. },
  240. create:function(){
  241. var blockVal;
  242. if (this.inputBlock.val()) blockVal=this.inputBlock.val(); else blockVal=null;
  243. Posts.create({
  244. title: this.inputUrl.val()
  245. , body: this.inputBody.val()
  246. , myPost: true
  247. , url: this.inputUrl.val()
  248. , user: {username:this.username}
  249. , block : blockVal
  250. });
  251. this.inputUrl.val("")
  252. }
  253. // toggleAllComplete: function () {
  254. // var done = this.allCheckbox.checked;
  255. // Posts.each(function (post) { post.save({'done': done}); });
  256. // }
  257. });
  258. // Finally, we kick things off by creating the **App**.
  259. App = new AppView();
  260. $(window).on("drop", function(e){
  261. var text=e.originalEvent.dataTransfer.getData('Text');
  262. if (text)
  263. $("#new-post-url").val(text),
  264. App.create();
  265. });
  266. }(jQuery, _, Backbone));