diff --git a/models/Node.js b/models/Node.js index ef0d19f..c87ad04 100644 --- a/models/Node.js +++ b/models/Node.js @@ -63,7 +63,7 @@ function setUpDB(){ MySnap.remove({}, function(err) { console.log('collection removed') }); var curtisId = "53e4079cd7dbc73d16c87c53"; - addNode("0root", [], ["123456"], curtisId , "a42a" , function(err, rootNode){ + addNode("0root", [], [], curtisId , "a42a" , function(err, rootNode){ console.log("rootNode", rootNode); addNode("Welcolme!", [], [rootNode._id], curtisId , "b42b", function(err, firstBullet){ rootNode.children = [firstBullet._id] diff --git a/public/js/app.js b/public/js/app.js index 7cfa7a0..b837793 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -10,11 +10,21 @@ $(function(){ setTimeout(function(){ $(".toggleSidebar").click(); }, 2); - - + vo = {}; }); +(function($) { + + $.fn.isFirstViz = function(){ + return $(this).is($(this).parent().children(":visible:first")); + } + $.fn.isLastViz = function(){ + return $(this).is($(this).parent().children(":visible:last")); + } +}(jQuery)); + + @@ -69,67 +79,7 @@ Array.prototype.removeOne = function(parId){ this.remove(parIndex); } -voInitializer = function(that, event){ - //var that = this; - vo = {}; - vo.hitEnter = (event.which == 13); - vo.hitTab = (event.which ==9); - vo.atEnd = ( $(that).getSelection().end == $(that).val().length); - vo.atBeg = ( $(that).getSelection().start == 0); - - //cursor = $(this).getSelection().start; - vo.hitBack = (event.which ==8); - vo.empty = ($(that).val().length ==0); - vo.highLighted = !vo.empty && ( $(that).getSelection().end != $(that).getSelection().start ) - - vo.rootLevel = $(that).closest("ul").is(".root") - vo.lastBullet = ( $(that).closest("li").is(":first-child") && vo.rootLevel); - vo.thisLI = $(event.target).closest("li"); - vo.thisId = vo.thisLI.attr("data-id"); //data-id. - vo.thisIndex = vo.thisLI.index(); //returns -1 if there's no match. - vo.thisModel = nodesCollection.findWhere({_id: vo.thisId}); - vo.thisView = vo.thisModel.get("views").slice(-1)[0]; //we're assuming a tree. - //(also, I'm not garbage collecting extra views when you zoom in/out, so we have to grab last element). - - //alert(thisIndex) - //thisModel = nodesCollection.get(thisId); - vo.siblingLI = vo.thisLI.prev(); - vo.siblingIndex = vo.siblingLI.index(); - vo.siblingId = vo.siblingLI.attr("data-id"); - vo.siblingModel = nodesCollection.findWhere({_id: vo.siblingId}); - - // console.log(nodesCollection); - // console.log(vo.thisModel); - - // if(!editing){ - // // alert("editing!"); - // socket.emit("editing", [vo.thisId, CurrentUser.google.name]); - // editing=true; - // } - - if(vo.rootLevel){ - vo.parentLI = undefined; - vo.parentId = (vo.thisLI.closest("ul").attr("data-id")) - vo.grandParentId = undefined; // won't matter since outTab prevents it. //unless programattic. - } - else{ //not root level. - //debugger; - vo.parentLI = vo.thisLI.parent().closest("li"); - vo.parentId = (vo.parentLI.attr("data-id")); - if(vo.parentLI.attr("data-depth") == 0){ //could test this another way. - vo.grandParentId = vo.parentLI.closest("ul").attr("data-id"); - //console.log("grandParentId" + grandParentId) - } - else{ - vo.grandParentId = (vo.parentLI.parent().closest("li").attr('data-id')); - //console.log("grandParentId" + grandParentId) - } - } - vo.grandParentModel = nodesCollection.findWhere({_id: vo.grandParentId}); - vo.parentModel = nodesCollection.findWhere({_id: vo.parentId}); - - vo.cursorHack = false; -} //(vo-initializer) + diff --git a/public/js/backbone/models/node.js b/public/js/backbone/models/node.js index acdd6a1..497d037 100644 --- a/public/js/backbone/models/node.js +++ b/public/js/backbone/models/node.js @@ -1,3 +1,17 @@ var NodeModel = Backbone.Model.extend({ + getAncestry: function(){ + var that = this; + + var ancestry = []; + var parents = that.get("parents"); + while(parents.length != 0){ + ancestry.push(parents); + parents = nodesCollection.findWhere({_id: parents[0]}).get("parents"); + // parents = that.findModel(parents[0]).get("parents"); + //making the assumption/simplification that it's a tree. Not a graph. + } + return ancestry; + } + }); \ No newline at end of file diff --git a/public/js/backbone/router.js b/public/js/backbone/router.js index 62af0f8..9d04da1 100644 --- a/public/js/backbone/router.js +++ b/public/js/backbone/router.js @@ -38,32 +38,21 @@ var AppRouter = Backbone.Router.extend({ data.google.id = null; data.google.token = null; data.google.email = null; - CurrentUser = data; - - // console.log("CURRENT USER"); - // console.log(CurrentUser); + CurrentUser = data; } }, - - error: function(data){ console.log("ERROR- AjaxLoginDATA"); } });//ajax }, - // index: function(otherID){ - // var that = this; - - // otherID = otherID || - - // }, - viewRoot: function(id, snapCollection){ var rootModel; var metaCollection; - var snapView = 0; + var snapView = 0; + if(snapCollection){ rootModel = snapCollection.findWhere({cur_id: id}); metaCollection = snapCollection @@ -73,27 +62,62 @@ var AppRouter = Backbone.Router.extend({ rootModel = nodesCollection.findWhere({_id: id}); metaCollection = nodesCollection; } - var rootView = new listView({ - viewWindow: ".main1", + depth: -1, model: rootModel, metaCollection: metaCollection, snapView: snapView }) + $(".main1").html(rootView.render().$el); this.changeView(rootView); }, changeView: function(view) { - if ( null != this.currentView ) { + if ( this.currentView != null ) { this.currentView.undelegateEvents(); } this.currentView = view; $("textarea").textareaAutoExpand(); - - }, + viewSearchSubset: function(matchedNodes){ + console.log("matchedNodes", matchedNodes); + var SUBSET = matchedNodes + + augmentedSet = [] + _.each(SUBSET, function(matchedNode){ + augmentedSet.push([matchedNode.get("_id")]); + augmentedSet.push(matchedNode.getAncestry()); + }); + var finalSet = _.union(_.flatten(augmentedSet)); + var rootView = new listView({ + depth: -1, + model: nodesCollection.findWhere({_id: $('.root').attr('data-id')}), + metaCollection: nodesCollection, + snapView: 0 , + searchSet: finalSet + }) + $(".main1").html(rootView.render().$el); + this.changeView(rootView); + }, + + + + + + + + + + + + + + + + + setUpSocket: function(){ var that = this; diff --git a/public/js/backbone/views/listView.js b/public/js/backbone/views/listView.js index d5ef037..6636a2e 100644 --- a/public/js/backbone/views/listView.js +++ b/public/js/backbone/views/listView.js @@ -1,18 +1,8 @@ var listView = Backbone.View.extend({ - initialize: function(options){ - var that = this; - that.metaCollection = options["metaCollection"]; - that.snapView = options["snapView"]; - - this.viewWindow = $(options["viewWindow"]); - that.model = options["model"]; - (that.model.attributes["views"] = this.model.attributes["views"] || []).push(that); - that.$el.attr("data-id", that.model.get("_id")); - this.childViews = []; - - this.render(); - }, + this.UL = this.$el; + assignProperties(this, options); + }, tagName: 'ul', className: 'root subList dd-list', @@ -26,27 +16,11 @@ var listView = Backbone.View.extend({ return that; }, - findModel: function(id){ - if(this.snapView){ - return this.metaCollection.findWhere({cur_id: id}); - } - else{ - return this.metaCollection.findWhere({_id: id}); - } - }, - - renderPath: function(){ var that = this; var pathDiv = ""; - var ancestry = []; - var parents = that.model.get("parents"); - while(parents.length != 0){ - ancestry.push(parents); - parents = that.findModel(parents[0]).get("parents"); - //making the assumption/simplification that it's a tree. Not a graph. - } + var ancestry = that.model.getAncestry(); _.each(ancestry.reverse(), function(parent){ var parentModel = that.findModel(parent[0]); @@ -59,59 +33,6 @@ var listView = Backbone.View.extend({ $("#pathDiv").html(pathDiv); }, - //identical except for the .$el part at the end. - renderChildren: function(){ - var that = this; - - var childrenIds = that.model.get("children"); - _.each(childrenIds, function(childId, index){ - var childModel = that.findModel(childId); - - var tempView = new showView({ - depth: 0, - model: childModel, - metaCollection: that.metaCollection, - snapView: that.snapView - }); - - var tempLI = tempView.render().$el; - tempLI.children("textarea").textareaAutoExpand(); - that.$el.append(tempLI); - that.childViews.push(tempView); - }); - that.viewWindow.html(that.$el); - }, - - //adds a CHILD node. - addNode: function(newNode, index, cur){ - var that = this; - var newView = new showView({ - model: newNode, - depth: 0, - metaCollection: that.metaCollection, - snapView: that.snapView - }); - var newLI = newView.render().$el; - - if(index == 0){ //just handles edge case where you're using this for indent - that.$el.prepend(newLI); - }else{ - that.$el.children(":nth-child(" + (index) + ")").after(newLI); - } - //that.$el.children(":nth-child(" + (index) + ")").after(newLI); - - that.childViews.insert(index , newView); - cur = true; - if(cur){ - if(vo.cursorHack){ return newView; } - newLI.children().children("textarea").focus(); - } - else{ - newView.lock(); - } - return newView; - }, - updateId: function(newId){ that.$el.attr("data-id", newId); @@ -128,16 +49,4 @@ var listView = Backbone.View.extend({ unlock: function(){ console.log("ROOT UNLOCKED"); }, - - removeNode: function(index){ - var that = this; - - console.log(that.childViews); - that.childViews[index].remove(); - that.childViews.remove(index); - }, - pushView: function(view){ - this.childViews.push(view); - this.$el.children().last().after(view.$el); - } }); \ No newline at end of file diff --git a/public/js/backbone/views/metaView.js b/public/js/backbone/views/metaView.js new file mode 100644 index 0000000..44f2c48 --- /dev/null +++ b/public/js/backbone/views/metaView.js @@ -0,0 +1,89 @@ +function assignProperties(object, options){ //object is a showView or listView + var that = object; + that.metaCollection = options["metaCollection"]; + that.snapView = options["snapView"]; + + that.model = options["model"]; + that.depth = options["depth"]; + (that.model.attributes["views"] = that.model.attributes["views"] || []).push(that); + that.$el.attr("data-id", that.model.get("_id")); //booya! + that.childViews = []; + + that.searchSet = options["searchSet"]; + + object.renderChildren = function(){ + var that = object; + + var childrenIds = that.model.get("children"); + _.each(childrenIds, function(childId, index){ + var childModel = that.findModel(childId); + var tempView = new showView({ + depth: that.depth + 1, + model: childModel, + metaCollection: that.metaCollection, + snapView: that.snapView, + searchSet: that.searchSet + }); + that.pushView(tempView, childId); + }); + } + + object.pushView = function(tempView, childId){ + debugger; + var searchSet= object.searchSet; + that.childViews.push(tempView); + var tempLI = tempView.render().$el + that.UL.append(tempLI); + if(searchSet && !_.contains(searchSet, childId)){ + $(tempLI).hide(); + } + } + + object.findModel = function(id){ + if(object.snapView){ + return object.metaCollection.findWhere({cur_id: id}); + } + else{ + return object.metaCollection.findWhere({_id: id}); + } + } + + object.removeNode = function(index){ + var that = this; + that.childViews[index].remove(); + that.childViews.remove(index); + } + + object.addNode = function(newNode, index, cur){ + var that = this; + var newView = new showView({ + model: newNode, + depth: that.depth +1, + metaCollection: that.metaCollection, + snapView: that.snapView + + }); + + var newLI = newView.render().$el; + + + //var empty = (that.$el.children("ul").children().length == 0); + if(index == 0){ //just handles edge case where you're using this for indent + that.UL.prepend(newLI); + }else{ + that.UL.children(":nth-child(" + (index) + ")").after(newLI); + } + + that.childViews.insert(index , newView); + if(cur){ + newLI.children().children("textarea").focus().textareaAutoExpand(); + } + else{ + newView.lock(); + } + return newView; + } + + + +} \ No newline at end of file diff --git a/public/js/backbone/views/showView.js b/public/js/backbone/views/showView.js index 0f85f25..0370a83 100644 --- a/public/js/backbone/views/showView.js +++ b/public/js/backbone/views/showView.js @@ -1,31 +1,12 @@ var showView = Backbone.View.extend({ initialize: function(options){ - var that = this; - that.metaCollection = options["metaCollection"]; - that.snapView = options["snapView"]; - - this.model = options["model"]; - this.depth = options["depth"]; - (that.model.attributes["views"] = this.model.attributes["views"] || []).push(that); - that.$el.attr("data-id", that.model.get("_id")); //booya! - this.childViews = []; - + //that.UL; + assignProperties(this, options); }, tagName: 'li', className: "herez node", - events: {"click .markdown" : "showMarkDownEditor"}, - - - findModel: function(id){ - if(this.snapView){ - return this.metaCollection.findWhere({cur_id: id}); - } - else{ - return this.metaCollection.findWhere({_id: id}); - } - }, - + events: {"click .markdown" : "showMarkDownEditor"}, //todo = refactor this function. render: function(){ @@ -41,6 +22,7 @@ var showView = Backbone.View.extend({ that.$el.attr("data-id", id); that.$el.html(html); + that.UL = that.$el.children("ul"); if(that.snapView){ that.$el.children().children("textarea").prop("disabled", true); that.$el.addClass("snapLI"); @@ -51,27 +33,6 @@ var showView = Backbone.View.extend({ return that; }, - renderChildren: function(){ - var that = this; - var childrenIds = that.model.get("children"); - - _.each(childrenIds, function(childId, index){ - var childModel = that.findModel(childId); - var tempView = new showView({ - depth: that.depth + 1, - model: childModel, - metaCollection: that.metaCollection, - snapView: that.snapView - }); - that.childViews.push(tempView) - that.$el.children("ul").append(tempView.render().$el); - }); - - }, - - unhide: function(){ - alert("bleh"); - }, // Moved to app.js to handle bubbling issues. collapse: function(){ @@ -128,37 +89,6 @@ var showView = Backbone.View.extend({ // setTimeout(function(){ MathJax.Callback(["CreatePreview",Preview]); }, 300); }, - addNode: function(newNode, index, cur){ - var that = this; - console.log("addNodeText" + newNode.get("text")) - var newView = new showView({ - model: newNode, - depth: that.depth +1, - metaCollection: that.metaCollection, - snapView: that.snapView - - }); - - var newLI = newView.render().$el; - - - //var empty = (that.$el.children("ul").children().length == 0); - if(index == 0){ //just handles edge case where you're using this for indent - that.$el.children("ul").prepend(newLI); - }else{ - that.$el.children("ul").children(":nth-child(" + (index) + ")").after(newLI); - } - - that.childViews.insert(index , newView); - if(cur){ - newLI.children().children("textarea").focus().textareaAutoExpand(); - } - else{ - newView.lock(); - } - return newView; - }, - updateId: function(newId){ this.$el.attr("data-id", newId); this.$el.children("ul").attr("data-id", newId); @@ -176,15 +106,6 @@ var showView = Backbone.View.extend({ this.$el.children().children("textarea").removeAttr("readonly"); this.$el.children().children("textarea").val(this.model.get("text")); this.$el.removeClass("editing"); - }, - removeNode: function(index){ - var that = this; - that.childViews[index].remove(); - that.childViews.remove(index); - }, - pushView: function(view){ - this.childViews.push(view); - this.$el.children("ul").children().last().after(view.$el); } diff --git a/public/js/libs/externalLibs/jqueryTextComplete.js b/public/js/libs/externalLibs/jqueryTextComplete.js new file mode 100644 index 0000000..3a3fbd4 --- /dev/null +++ b/public/js/libs/externalLibs/jqueryTextComplete.js @@ -0,0 +1,4 @@ +/*! jquery-textcomplete - v0.3.3 - 2014-09-25 */if("undefined"==typeof jQuery)throw new Error("jQuery.textcomplete requires jQuery");+function(a){"use strict";var b=function(a){console.warn&&console.warn(a)};a.fn.textcomplete=function(c,d){var e=Array.prototype.slice.call(arguments);return this.each(function(){var f=a(this),g=f.data("textComplete");if(g||(g=new a.fn.textcomplete.Completer(this,d||{}),f.data("textComplete",g)),"string"==typeof c){if(!g)return;e.shift(),g[c].apply(g,e)}else a.each(c,function(c){a.each(["header","footer","placement","maxCount"],function(a){c[a]&&(g.option[a]=c[a],b(a+"as a strategy param is deplicated. Use option."),delete c[a])})}),g.register(a.fn.textcomplete.Strategy.parse(c))})}}(jQuery),+function(a){"use strict";function b(c,d){if(this.$el=a(c),this.id="textcomplete"+e++,this.strategies=[],this.views=[],this.option=a.extend({},b.DEFAULTS,d),!this.$el.is("textarea")&&!c.isContentEditable)throw new Error("textcomplete must be called to a Textarea or a ContentEditable.");if(c===document.activeElement)this.initialize();else{var f=this;this.$el.one("focus."+this.id,function(){f.initialize()})}}var c=function(a){var b,c;return function(){var d=Array.prototype.slice.call(arguments);if(b)return c=d,void 0;b=!0;var e=this;d.unshift(function f(){if(c){var d=c;c=void 0,d.unshift(f),a.apply(e,d)}else b=!1}),a.apply(this,d)}},d=function(a){return"[object String]"===Object.prototype.toString.call(a)},e=0;b.DEFAULTS={appendTo:a("body"),zIndex:"100"},a.extend(b.prototype,{id:null,option:null,strategies:null,adapter:null,dropdown:null,$el:null,initialize:function(){var b=this.$el.get(0);this.dropdown=new a.fn.textcomplete.Dropdown(b,this,this.option);var c,d;this.option.adapter?c=this.option.adapter:(d=this.$el.is("textarea")?"number"==typeof b.selectionEnd?"Textarea":"IETextarea":"ContentEditable",c=a.fn.textcomplete[d]),this.adapter=new c(b,this,this.option)},destroy:function(){this.$el.off("."+this.id),this.adapter.destroy(),this.dropdown.destroy(),this.$el=this.adapter=this.dropdown=null},trigger:function(a,b){this.dropdown||this.initialize(),null!=a||(a=this.adapter.getTextFromHeadToCaret());var c=this._extractSearchQuery(a);if(c.length){var d=c[1];if(b&&this._term===d)return;this._term=d,this._search.apply(this,c)}else this._term=null,this.dropdown.deactivate()},fire:function(a){return this.$el.trigger(a),this},register:function(a){Array.prototype.push.apply(this.strategies,a)},select:function(a,b){this.adapter.select(a,b),this.fire("change").fire("textComplete:select",a,b),this.adapter.focus()},_clearAtNext:!0,_term:null,_extractSearchQuery:function(a){for(var b=0;b').css({display:"none",left:0,position:"absolute",zIndex:b.zIndex}).appendTo(c)),d}}),a.extend(b.prototype,{$el:null,$inputEl:null,completer:null,footer:null,header:null,id:null,maxCount:10,placement:"",shown:!1,data:[],className:"",destroy:function(){this.deactivate(),this.$el.off("."+this.id),this.$inputEl.off("."+this.id),this.clear(),this.$el=this.$inputEl=this.completer=null,delete d[this.id]},render:function(b){var c=this._buildContents(b),d=a.map(this.data,function(a){return a.value});this.data.length?(this._renderHeader(d),this._renderFooter(d),c&&(this._renderContents(c),this._activateIndexedItem()),this._setScroll()):this.shown&&this.deactivate()},setPosition:function(a){return this.$el.css(this._applyPlacement(a)),this},clear:function(){this.$el.html(""),this.data=[],this._index=0,this._$header=this._$footer=null},activate:function(){return this.shown||(this.clear(),this.$el.show(),this.className&&this.$el.addClass(this.className),this.completer.fire("textComplete:show"),this.shown=!0),this},deactivate:function(){return this.shown&&(this.$el.hide(),this.className&&this.$el.removeClass(this.className),this.completer.fire("textComplete:hide"),this.shown=!1),this},isUp:function(a){return 38===a.keyCode||a.ctrlKey&&80===a.keyCode},isDown:function(a){return 40===a.keyCode||a.ctrlKey&&78===a.keyCode},isEnter:function(a){var b=a.ctrlKey||a.altKey||a.metaKey||a.shiftKey;return!b&&(13===a.keyCode||9===a.keyCode)},isPageup:function(a){return 33===a.keyCode},isPagedown:function(a){return 34===a.keyCode},_data:null,_index:null,_$header:null,_$footer:null,_bindEvents:function(){this.$el.on("mousedown."+this.id,".textcomplete-item",a.proxy(this._onClick,this)),this.$el.on("mouseover."+this.id,".textcomplete-item",a.proxy(this._onMouseover,this)),this.$inputEl.on("keydown."+this.id,a.proxy(this._onKeydown,this))},_onClick:function(b){var c=a(b.target);b.preventDefault(),b.originalEvent.keepTextCompleteDropdown=this.id,c.hasClass("textcomplete-item")||(c=c.closest(".textcomplete-item"));var d=this.data[parseInt(c.data("index"),10)];this.completer.select(d.value,d.strategy);var e=this;setTimeout(function(){e.deactivate()},0)},_onMouseover:function(b){var c=a(b.target);b.preventDefault(),c.hasClass("textcomplete-item")||(c=c.closest(".textcomplete-item")),this._index=parseInt(c.data("index"),10),this._activateIndexedItem()},_onKeydown:function(a){this.shown&&(this.isUp(a)?(a.preventDefault(),this._up()):this.isDown(a)?(a.preventDefault(),this._down()):this.isEnter(a)?(a.preventDefault(),this._enter()):this.isPageup(a)?(a.preventDefault(),this._pageup()):this.isPagedown(a)&&(a.preventDefault(),this._pagedown()))},_up:function(){0===this._index?this._index=this.data.length-1:this._index-=1,this._activateIndexedItem(),this._setScroll()},_down:function(){this._index===this.data.length-1?this._index=0:this._index+=1,this._activateIndexedItem(),this._setScroll()},_enter:function(){var a=this.data[parseInt(this._getActiveElement().data("index"),10)];this.completer.select(a.value,a.strategy),this._setScroll()},_pageup:function(){var b=0,c=this._getActiveElement().position().top-this.$el.innerHeight();this.$el.children().each(function(d){return a(this).position().top+a(this).outerHeight()>c?(b=d,!1):void 0}),this._index=b,this._activateIndexedItem(),this._setScroll()},_pagedown:function(){var b=this.data.length-1,c=this._getActiveElement().position().top+this.$el.innerHeight();this.$el.children().each(function(d){return a(this).position().top>c?(b=d,!1):void 0}),this._index=b,this._activateIndexedItem(),this._setScroll()},_activateIndexedItem:function(){this.$el.find(".textcomplete-item.active").removeClass("active"),this._getActiveElement().addClass("active")},_getActiveElement:function(){return this.$el.children(".textcomplete-item:nth("+this._index+")")},_setScroll:function(){var a=this._getActiveElement(),b=a.position().top,c=a.outerHeight(),d=this.$el.innerHeight(),e=this.$el.scrollTop();0===this._index||this._index==this.data.length-1||0>b?this.$el.scrollTop(b+e):b+c>d&&this.$el.scrollTop(b+c+e-d)},_buildContents:function(a){var b,d,e,f="";for(d=0;d',f+=b.strategy.template(b.value),f+="");return f},_renderHeader:function(b){if(this.header){this._$header||(this._$header=a('
  • ').prependTo(this.$el));var c=a.isFunction(this.header)?this.header(b):this.header;this._$header.html(c)}},_renderFooter:function(b){if(this.footer){this._$footer||(this._$footer=a('').appendTo(this.$el));var c=a.isFunction(this.footer)?this.footer(b):this.footer;this._$footer.html(c)}},_renderContents:function(a){this._$footer?this._$footer.before(a):this.$el.append(a)},_applyPlacement:function(a){return-1!==this.placement.indexOf("top")?a={top:"auto",bottom:this.$el.parent().height()-a.top+a.lineHeight,left:a.left}:(a.bottom="auto",delete a.lineHeight),-1!==this.placement.indexOf("absleft")?a.left=0:-1!==this.placement.indexOf("absright")&&(a.right=0,a.left="auto"),a}}),a.fn.textcomplete.Dropdown=b}(jQuery),+function(a){"use strict";function b(b){a.extend(this,b),this.cache&&(this.search=c(this.search))}var c=function(a){var b={};return function(c,d){b[c]?d(b[c]):a.call(this,c,function(a){b[c]=(b[c]||[]).concat(a),d.apply(null,arguments)})}};b.parse=function(c){return a.map(c,function(a){return new b(a)})},a.extend(b.prototype,{match:null,replace:null,search:null,cache:!1,context:function(){return!0},index:2,template:function(a){return a},idProperty:null}),a.fn.textcomplete.Strategy=b}(jQuery),+function(a){"use strict";function b(){}var c=Date.now||function(){return(new Date).getTime()},d=function(a,b){var d,e,f,g,h,i=function(){var j=c()-g;b>j?d=setTimeout(i,b-j):(d=null,h=a.apply(f,e),f=e=null)};return function(){return f=this,e=arguments,g=c(),d||(d=setTimeout(i,b)),h}};a.extend(b.prototype,{id:null,completer:null,el:null,$el:null,option:null,initialize:function(b,c,e){this.el=b,this.$el=a(b),this.id=c.id+this.constructor.name,this.completer=c,this.option=e,this.option.debounce&&(this._onKeyup=d(this._onKeyup,this.option.debounce)),this._bindEvents()},destroy:function(){this.$el.off("."+this.id),this.$el=this.el=this.completer=null},select:function(){throw new Error("Not implemented")},getCaretPosition:function(){var a=this._getCaretRelativePosition(),b=this.$el.offset();return a.top+=b.top,a.left+=b.left,a},focus:function(){this.$el.focus()},_bindEvents:function(){this.$el.on("keyup."+this.id,a.proxy(this._onKeyup,this))},_onKeyup:function(a){this._skipSearch(a)||this.completer.trigger(this.getTextFromHeadToCaret(),!0)},_skipSearch:function(a){switch(a.keyCode){case 40:case 38:return!0}if(a.ctrlKey)switch(a.keyCode){case 78:case 80:return!0}}}),a.fn.textcomplete.Adapter=b}(jQuery),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}b.DIV_PROPERTIES={left:-9999,position:"absolute",top:0,whiteSpace:"pre-wrap"},b.COPY_PROPERTIES=["border-width","font-family","font-size","font-style","font-variant","font-weight","height","letter-spacing","word-spacing","line-height","text-decoration","text-align","width","padding-top","padding-right","padding-bottom","padding-left","margin-top","margin-right","margin-bottom","margin-left","border-style","box-sizing","tab-size"],a.extend(b.prototype,a.fn.textcomplete.Adapter.prototype,{select:function(b,c){var d=this.getTextFromHeadToCaret(),e=this.el.value.substring(this.el.selectionEnd),f=c.replace(b);a.isArray(f)&&(e=f[1]+e,f=f[0]),d=d.replace(c.match,f),this.$el.val(d+e),this.el.selectionStart=this.el.selectionEnd=d.length},_getCaretRelativePosition:function(){var b=a("
    ").css(this._copyCss()).text(this.getTextFromHeadToCaret()),c=a("").text(".").appendTo(b);this.$el.before(b);var d=c.position();return d.top+=c.height()-this.$el.scrollTop(),d.lineHeight=c.height(),b.remove(),d},_copyCss:function(){return a.extend({overflow:this.el.scrollHeight>this.el.offsetHeight?"scroll":"auto"},b.DIV_PROPERTIES,this._getStyles())},_getStyles:function(a){var c=a("
    ").css(["color"]).color;return"undefined"!=typeof c?function(){return this.$el.css(b.COPY_PROPERTIES)}:function(){var c=this.$el,d={};return a.each(b.COPY_PROPERTIES,function(a,b){d[b]=c.css(b)}),d}}(a),getTextFromHeadToCaret:function(){return this.el.value.substring(0,this.el.selectionEnd)}}),a.fn.textcomplete.Textarea=b}(jQuery),+function(a){"use strict";function b(b,d,e){this.initialize(b,d,e),a(""+c+"").css({position:"absolute",top:-9999,left:-9999}).insertBefore(b)}var c="吶";a.extend(b.prototype,a.fn.textcomplete.Textarea.prototype,{select:function(b,c){var d=this._getTextFromHeadToCaret(),e=this.el.value.substring(d.length),f=c.replace(b);a.isArray(f)&&(e=f[1]+e,f=f[0]),d=d.replace(c.match,f),this.$el.val(d+e),this.el.focus();var g=this.el.createTextRange();g.collapse(!0),g.moveEnd("character",d.length),g.moveStart("character",d.length),g.select()},_getTextFromHeadToCaret:function(){this.el.focus();var a=document.selection.createRange();a.moveStart("character",-this.el.value.length);var b=a.text.split(c);return 1===b.length?b[0]:b[1]}}),a.fn.textcomplete.IETextarea=b}(jQuery),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}a.extend(b.prototype,a.fn.textcomplete.Adapter.prototype,{select:function(b,c){var d=this.getTextFromHeadToCaret(),e=window.getSelection(),f=e.getRangeAt(0),g=f.cloneRange();g.selectNodeContents(f.startContainer);var h=g.toString(),i=h.substring(f.startOffset),j=c.replace(b);a.isArray(j)&&(i=j[1]+i,j=j[0]),d=d.replace(c.match,j),f.selectNodeContents(f.startContainer),f.deleteContents();var k=document.createTextNode(d+i);f.insertNode(k),f.setStart(k,d.length),f.collapse(!0),e.removeAllRanges(),e.addRange(f)},_getCaretRelativePosition:function(){var b=window.getSelection().getRangeAt(0).cloneRange(),c=document.createElement("span");b.insertNode(c),b.selectNodeContents(c),b.deleteContents();var d=a(c),e=d.offset();e.left-=this.$el.offset().left,e.top+=d.height()-this.$el.offset().top,e.lineHeight=d.height();var f=this.$el.attr("dir")||this.$el.css("direction");return"rtl"===f&&(e.left-=this.listView.$el.width()),e},getTextFromHeadToCaret:function(){var a=window.getSelection().getRangeAt(0),b=a.cloneRange();return b.selectNodeContents(a.startContainer),b.toString().substring(0,a.startOffset)}}),a.fn.textcomplete.ContentEditable=b}(jQuery); +/* +//@ sourceMappingURL=dist/jquery.textcomplete.min.map +*/ \ No newline at end of file diff --git a/public/js/libs/myLogic/addNode.js b/public/js/libs/myLogic/addNode.js index 4f589a3..1d8bc3a 100644 --- a/public/js/libs/myLogic/addNode.js +++ b/public/js/libs/myLogic/addNode.js @@ -1,11 +1,50 @@ -var guidGenerator = function() { - var S4 = function() { - return (((1+Math.random())*0x10000)|0).toString(16).substring(1); - }; - return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); +addNode = function(botStr, topStr){ + var modelJSON = generateJSON(botStr); + var newNode = new NodeModel(modelJSON); + nodesCollection.add(newNode); + + if(topStr || topStr==""){ + vo.thisModel.set("text", topStr); + _.each(vo.thisModel.get("views"), function(view){ view.updateText(topStr); }); + socket.emitWrapper("edit", [vo.thisId, topStr]); + } + + var data = [ [vo.parentId, vo.thisIndex+1] , modelJSON ]; + socket.emitWrapper("newNode", data); + + + + vo.parentModel.get("children").insert(vo.thisIndex + 1, modelJSON._id); + + + var parentViews = vo.parentModel.get("views"); + var tempIndex = vo.thisIndex+1; //adding nodes alters the index. + _.each(parentViews, function(parentView){ + parentView.addNode(newNode, tempIndex, true); + }); + + INPUT_PROCESSED=true; + } -addNode = function(botStr, topStr){ + + + + + + + + + + + + + + + + + +generateJSON = function(botStr){ var randomId = guidGenerator(); var modelJSON = { _id: randomId @@ -14,39 +53,19 @@ addNode = function(botStr, topStr){ , children: [] , author: CurrentUser }; - - - if(topStr || topStr==""){ - console.log("TOPSTR IS"); - console.log(topStr); - vo.thisModel.set("text", topStr); - _.each(vo.thisModel.get("views"), function(view){ - view.updateText(topStr); - }); - socket.emitWrapper("edit", [vo.thisId, topStr]); - } - - - var newNode = new NodeModel(modelJSON); - nodesCollection.add(newNode); - - vo.parentModel.get("children").insert(vo.thisIndex + 1, randomId); - - var data = [ [vo.parentId, vo.thisIndex+1] , modelJSON ]; - console.log("AddNode DATA"); console.log(data); - socket.emitWrapper("newNode", data); - - var parentViews = vo.parentModel.get("views"); - - var tempIndex = vo.thisIndex+1; //adding nodes alters the index. - _.each(parentViews, function(parentView){ - parentView.addNode(newNode, tempIndex, true); - }); - // vo.thisLI.next().children().children("textarea").focus(); - INPUT_PROCESSED=true; - console.log("FINISHED- ADD NODE") - + return modelJSON; } + + + +guidGenerator = function() { + var S4 = function() { + return (((1+Math.random())*0x10000)|0).toString(16).substring(1); + }; + return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); +} + + /* topStr is to the left. (also, the bottom part will be to the right. ) before: Textarea= topStr + botStr @@ -76,6 +95,9 @@ splitText = function(that, callback){ callback(botStr, topStr); //addNode(botStr, topStr); } + + + transclude = function(){ vo.parentModel.get("children").insert(vo.thisIndex+1, vo.thisId); var modelJSON = { diff --git a/public/js/libs/myLogic/keydownHandler.js b/public/js/libs/myLogic/keydownHandler.js index 88dd49f..3603e86 100644 --- a/public/js/libs/myLogic/keydownHandler.js +++ b/public/js/libs/myLogic/keydownHandler.js @@ -1,8 +1,24 @@ + + +searchHandler = function(event){ + console.log("searchHandler"); + if(event.which != 13){return;} + event.preventDefault(); + var search = event.target.value; + + var SUBSET = nodesCollection.filter(function(model){ + return model.get('text').indexOf(search) != -1; + }); + myRouter.viewSearchSubset(SUBSET); + +} + keydownHandler = function(event){ //the entire body is wrapped in this. var that = this; // console.log("keyDownHandler"); - INPUT_PROCESSED=true; + INPUT_PROCESSED=true; + if(event.target.id == 'searchBar'){searchHandler(event); return;} if(event.which == undefined){ console.log("ABORTED- event.which==undefined"); return; } if(!CurrentUser){ alert("only logged in users can edit"); return;}//prevent non-logged in users from editing. @@ -60,17 +76,13 @@ keydownHandler = function(event){ //the entire body is wrapped in this. return; }// if(!vo.atEnd && !vo.atBeg){ //split bullet(Works correctly) - // var topStr = ''; - // var botStr = ''; - splitText(that, /*botStr, topStr,*/ addNode); + splitText(that, addNode); return; - //addNode(botStr, topStr); } if(!vo.atEnd && vo.atBeg){//addNode (before). (equivalent to splitting bullet) vo.thisIndex--; //a hack that works. //var myLI = vo.thisLI; // setTimeout(function(){myLI.children().children("textarea").focus()}, 3); - vo.cursorHack=true; addNode(""); return; @@ -155,26 +167,26 @@ if((vo.hitTab && event.shiftKey) || (event.keyCode == 37 && event.shiftKey)){// } } - if(event.keyCode == 38 && event.shiftKey) { - if(vo.thisLI.is(":first-child")){return;}//don't factor this out into the above if-statement + if(event.keyCode == 38 && event.shiftKey) { //move up + if(vo.thisLI.isFirstViz()){return;}//don't factor this out into the above if-statement moveNode(vo.thisModel, vo.thisIndex, vo.parentModel, vo.parentModel, vo.thisIndex-1, true); return; } - if(event.keyCode == 40 && event.shiftKey) { - if(vo.thisLI.is(":last-child")){return;} + if(event.keyCode == 40 && event.shiftKey) { //move down + if( vo.thisLI.isLastViz() ){return;} moveNode(vo.thisModel, vo.thisIndex, vo.parentModel, vo.parentModel, vo.thisIndex+1, true); return; } if(event.keyCode == 38){//up - if(vo.thisLI.is(":first-child")){ + if( vo.thisLI.isLastViz() ){ vo.thisLI.parent().parent().children().children("textarea").focus(); } else{ vo.thisLI.prev().children().children("textarea").focus(); } } - if(event.keyCode == 40){ + if(event.keyCode == 40){ //down vo.thisLI.next().children().children("textarea").focus(); } diff --git a/public/js/libs/myLogic/moveNode.js b/public/js/libs/myLogic/moveNode.js index 286642e..c247e4c 100644 --- a/public/js/libs/myLogic/moveNode.js +++ b/public/js/libs/myLogic/moveNode.js @@ -1,13 +1,9 @@ //Handles indenting,outdenting,moving up/down, and drag-n-drop. var moveNode = function(thisModel, dragIndex, oldParModel, newParModel, dropIndex, chr){ + //removeNode from OldParent part 1 = #models - console.log("\n\n"); - console.log(dragIndex); - console.log(oldParModel.get("children")); oldParModel.get("children").remove(dragIndex); thisModel.get("parents").removeOne(oldParModel.get("_id")); - console.log(oldParModel.get("children")); - console.log("\n\n"); //removeNode from OldParent part 2 = #views _.each(oldParModel.get("views"), function(oldParView){ @@ -23,6 +19,10 @@ var moveNode = function(thisModel, dragIndex, oldParModel, newParModel, dropInde newParView.addNode(thisModel, dropIndex, chr); }); + + + + var ids = [thisModel.get("_id"), oldParModel.get("_id"), newParModel.get("_id")]; var arrays = [thisModel.get("parents"), oldParModel.get("children"), newParModel.get("children")]; var indices = [dragIndex, dropIndex]; diff --git a/public/js/libs/myLogic/removeNode.js b/public/js/libs/myLogic/removeNode.js index 042b7ad..e3f7732 100644 --- a/public/js/libs/myLogic/removeNode.js +++ b/public/js/libs/myLogic/removeNode.js @@ -27,7 +27,7 @@ var upDateParentModelViews = function(vo, broadcast){ if(!broadcast){ //broadCast=true means we received this update from somebody else. //UI STUFF // console.log("what"); - if( vo.thisLI.is(":first-child") ){ + if( vo.thisLI.isFirstViz() ){ if(vo.thisLI.attr('data-depth')!=0){ var len = vo.thisLI.parent().parent().children().children("textarea").val().length; vo.thisLI.parent().parent().children().children("textarea").focus(); diff --git a/public/js/libs/myLogic/voInitializer.js b/public/js/libs/myLogic/voInitializer.js new file mode 100644 index 0000000..392181a --- /dev/null +++ b/public/js/libs/myLogic/voInitializer.js @@ -0,0 +1,58 @@ +/* +I realize that a lot of this logic depends on the UI. +This is an unfortunate consequence of the fact that when I was originally +doing this, I wasn't using back-bone, and wasn't using models. +*/ +voInitializer = function(that, event){ + //var that = this; + vo = {}; + vo.hitEnter = (event.which == 13); + vo.hitTab = (event.which ==9); + vo.atEnd = ( $(that).getSelection().end == $(that).val().length); + vo.atBeg = ( $(that).getSelection().start == 0); + + //cursor = $(this).getSelection().start; + vo.hitBack = (event.which ==8); + vo.empty = ($(that).val().length ==0); + vo.highLighted = !vo.empty && ( $(that).getSelection().end != $(that).getSelection().start ) + + vo.rootLevel = $(that).closest("ul").is(".root") + vo.lastBullet = ( $(that).closest("li").isFirstViz() && vo.rootLevel); //(not useful) + vo.thisLI = $(event.target).closest("li"); + vo.thisId = vo.thisLI.attr("data-id"); //data-id. + vo.thisIndex = vo.thisLI.index(); //returns -1 if there's no match. + vo.thisModel = nodesCollection.findWhere({_id: vo.thisId}); + vo.thisView = vo.thisModel.get("views").slice(-1)[0]; //we're assuming a tree. + //(also, I'm not garbage collecting extra views when you zoom in/out, so we have to grab last element). + + vo.siblingLI = vo.thisLI.prevAll(":visible:first"); + vo.siblingIndex = vo.siblingLI.index(); + vo.siblingId = vo.siblingLI.attr("data-id"); + vo.siblingModel = nodesCollection.findWhere({_id: vo.siblingId}); + + + + + if(vo.rootLevel){ + vo.parentLI = undefined; + vo.parentId = (vo.thisLI.closest("ul").attr("data-id")) + vo.grandParentId = undefined; // won't matter since outTab prevents it. //unless programattic. + } + else{ //not root level. + //debugger; + vo.parentLI = vo.thisLI.parent().closest("li"); + vo.parentId = (vo.parentLI.attr("data-id")); + if(vo.parentLI.attr("data-depth") == 0){ //could test this another way. + vo.grandParentId = vo.parentLI.closest("ul").attr("data-id"); + //console.log("grandParentId" + grandParentId) + } + else{ + vo.grandParentId = (vo.parentLI.parent().closest("li").attr('data-id')); + //console.log("grandParentId" + grandParentId) + } + } + vo.grandParentModel = nodesCollection.findWhere({_id: vo.grandParentId}); + vo.parentModel = nodesCollection.findWhere({_id: vo.parentId}); + + vo.cursorHack = false; +} //(vo-initializer) \ No newline at end of file diff --git a/public/js/listeners/dragDropListeners.js b/public/js/listeners/dragDropListeners.js index 9933f90..3b867c8 100644 --- a/public/js/listeners/dragDropListeners.js +++ b/public/js/listeners/dragDropListeners.js @@ -38,7 +38,7 @@ $('body').on("mousedown", ".handle", function(e){ dragState.oldParModel = nodesCollection.findWhere({_id: dragState.thisLI.parent().attr("data-id") }); - var firstLI = $(".root").children(":first-child"); + var firstLI = $(".root").children(":visible:first"); var firstEntry = [0, firstLI, "above"]; containerArray.push(firstEntry); @@ -59,7 +59,7 @@ $('body').on("mousedown", ".handle", function(e){ li = $(li); var collapsed = (li.children(".zoomButton").hasClass("collapsed") || li.children("ul").children().length == 0); var opened = !collapsed; - var last = li.is(":last-child"); + var last = li.isLastViz(); if( !(opened || last) ){ var entry = [ thisTop , li , "below" ]; @@ -68,7 +68,7 @@ $('body').on("mousedown", ".handle", function(e){ else{ if(opened){ console.log("opened"); - var firstChild = li.children("ul").children(":first-child") + var firstChild = li.children("ul").children(":visible:first") var firstEntry = [ thisTop , firstChild, "above"]; containerArray.push(firstEntry); diff --git a/views/index.ejs b/views/index.ejs index 7140cdf..0e72d36 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -24,6 +24,7 @@ + @@ -38,10 +39,9 @@ - - + + @@ -69,7 +70,7 @@
    CoNote - +