diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 2b12a39e..00000000 --- a/Gemfile.lock +++ /dev/null @@ -1,145 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - actionmailer (3.2.11) - actionpack (= 3.2.11) - mail (~> 2.4.4) - actionpack (3.2.11) - activemodel (= 3.2.11) - activesupport (= 3.2.11) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.4) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.2.1) - activemodel (3.2.11) - activesupport (= 3.2.11) - builder (~> 3.0.0) - activerecord (3.2.11) - activemodel (= 3.2.11) - activesupport (= 3.2.11) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activeresource (3.2.11) - activemodel (= 3.2.11) - activesupport (= 3.2.11) - activesupport (3.2.11) - i18n (~> 0.6) - multi_json (~> 1.0) - arel (3.0.2) - authlogic (3.1.0) - activerecord (>= 3.0.7) - activerecord (>= 3.0.7) - best_in_place (2.0.2) - jquery-rails - rails (~> 3.1) - builder (3.0.4) - cancan (1.6.7) - coffee-rails (3.2.2) - coffee-script (>= 2.2.0) - railties (~> 3.2.0) - coffee-script (2.2.0) - coffee-script-source - execjs - coffee-script-source (1.3.3) - erubis (2.7.0) - execjs (1.4.0) - multi_json (~> 1.0) - formtastic (2.0.2) - rails (~> 3.0) - formula (0.3.3) - rails (> 3.0.0) - hike (1.2.1) - i18n (0.6.1) - jbuilder (0.8.2) - activesupport (>= 3.0.0) - journey (1.0.4) - jquery-rails (2.1.2) - railties (>= 3.1.0, < 5.0) - thor (~> 0.14) - json (1.7.6) - libv8 (3.11.8.13) - mail (2.4.4) - i18n (>= 0.4.0) - mime-types (~> 1.16) - treetop (~> 1.4.8) - mime-types (1.19) - multi_json (1.5.0) - pg (0.12.2) - pg (0.12.2-x86-mingw32) - polyglot (0.3.3) - rack (1.4.3) - rack-cache (1.2) - rack (>= 0.4) - rack-ssl (1.3.2) - rack - rack-test (0.6.2) - rack (>= 1.0) - rails (3.2.11) - actionmailer (= 3.2.11) - actionpack (= 3.2.11) - activerecord (= 3.2.11) - activeresource (= 3.2.11) - activesupport (= 3.2.11) - bundler (~> 1.0) - railties (= 3.2.11) - rails3-jquery-autocomplete (1.0.10) - rails (~> 3.0) - railties (3.2.11) - actionpack (= 3.2.11) - activesupport (= 3.2.11) - rack-ssl (~> 1.3.2) - rake (>= 0.8.7) - rdoc (~> 3.4) - thor (>= 0.14.6, < 2.0) - rake (10.0.3) - rb-readline (0.4.2) - rdoc (3.12) - json (~> 1.4) - ref (1.0.2) - sass (3.2.7) - sass-rails (3.2.3) - railties (~> 3.2.0.beta) - sass (>= 3.1.10) - tilt (~> 1.3) - sprockets (2.2.2) - hike (~> 1.2) - multi_json (~> 1.0) - rack (~> 1.0) - tilt (~> 1.1, != 1.3.0) - therubyracer (0.11.4) - libv8 (~> 3.11.8.12) - ref - thor (0.16.0) - tilt (1.3.3) - treetop (1.4.12) - polyglot - polyglot (>= 0.3.1) - tzinfo (0.3.35) - uglifier (1.3.0) - execjs (>= 0.3.0) - multi_json (~> 1.0, >= 1.0.2) - -PLATFORMS - ruby - x86-mingw32 - -DEPENDENCIES - authlogic - best_in_place - cancan - coffee-rails (~> 3.2.1) - formtastic - formula - jbuilder - jquery-rails (= 2.1.2) - json - pg - rails (= 3.2.11) - rails3-jquery-autocomplete - rb-readline - sass-rails (= 3.2.3) - therubyracer - uglifier (>= 1.0.3) diff --git a/Gemfile~ b/Gemfile~ new file mode 100644 index 00000000..1f7c3bd8 --- /dev/null +++ b/Gemfile~ @@ -0,0 +1,46 @@ +source 'https://rubygems.org' + +gem 'rails', '3.2.11' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' + +gem 'pg' +gem 'authlogic' +gem 'cancan' +gem 'formula' +gem 'formtastic' +gem 'json' +gem 'rails3-jquery-autocomplete' +gem 'best_in_place' +#gem 'therubyracer' #optional +#gem 'rb-readline' + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', '~> 3.2.3' + gem 'coffee-rails', '~> 3.2.1' + + # See https://github.com/sstephenson/execjs#readme for more supported runtimes + # gem 'therubyracer' + + gem 'uglifier', '>= 1.0.3' +end + +gem 'jquery-rails', '2.1.2' + +# To use ActiveModel has_secure_password +# gem 'bcrypt-ruby', '~> 3.0.0' + +# To use Jbuilder templates for JSON + gem 'jbuilder' + +# Use unicorn as the web server +# gem 'unicorn' + +# Deploy with Capistrano +# gem 'capistrano' + +# To use debugger +# gem 'ruby-debug19', :require => 'ruby-debug' diff --git a/app/assets/javascripts/Jit/find.js b/app/assets/javascripts/Jit/find.js index 476fa1c9..f9381bfc 100644 --- a/app/assets/javascripts/Jit/find.js +++ b/app/assets/javascripts/Jit/find.js @@ -85,7 +85,7 @@ var findMappers = ['name', 'topic (by name)', 'map (by name)', 'synapse (by topi function hideAll(duration) { if (duration == null) duration = 500; Mconsole.graph.eachNode( function (n) { - if (!(n.getData('inCommons') || n.getData('onCanvas'))) { + if (!(n.getData('greenCircle') || n.getData('whiteCircle'))) { n.setData('alpha', 0.4, 'end'); n.eachAdjacency(function(adj) { adj.setData('alpha', 0.4, 'end'); @@ -120,26 +120,26 @@ function onCanvasSearch(searchQuery, mapID, mapperID) { nodeName = n.name.toLowerCase(); if (name != null) { if (nodeName.indexOf(searchQuery) !== -1 && searchQuery != "") { - n.setData('onCanvas', true); + n.setData('whiteCircle', true); } else { - n.setData('onCanvas', false); + n.setData('whiteCircle', false); } } else if (mapID != null) { if (n.getData('inmaps').indexOf(parseInt(mapID)) !== -1) { - n.setData('onCanvas', true); + n.setData('whiteCircle', true); } else { - n.setData('onCanvas', false); + n.setData('whiteCircle', false); } } else if (mapperID != null) { if (n.getData('userid').toString() == mapperID) { - n.setData('onCanvas', true); + n.setData('whiteCircle', true); } else { - n.setData('onCanvas', false); + n.setData('whiteCircle', false); } } Mconsole.plot(); @@ -149,7 +149,9 @@ function onCanvasSearch(searchQuery, mapID, mapperID) { function clearCanvas() { Mconsole.graph.eachNode(function(n) { Mconsole.graph.removeNode(n.id); - Mconsole.labels.disposeLabel(n.id); + //TODO shouldn't we use disposeLabel? Yes, but it breaks things so it's + //hide for now + Mconsole.labels.hideLabel(n.id); }); Mconsole.plot(); } @@ -164,8 +166,7 @@ function clearCanvasExceptRoot() { ids.forEach(function(id, index) { if (id != root.id) { Mconsole.graph.removeNode(id); - //don't use disposeLabel or they'll never come back! - //maybe there's a better way that recreates the labels later?? + //TODO is hideLabel correct? Maybe it is... Mconsole.labels.hideLabel(id); $('#topic_' + id + '_label').hide(); } @@ -175,9 +176,11 @@ function clearCanvasExceptRoot() { function clearFoundData() { Mconsole.graph.eachNode( function(n) { - if (n.getData('inCommons') === true) { + if (n.getData('greenCircle') === true) { Mconsole.graph.removeNode(n.id); - Mconsole.labels.disposeLabel(n.id); + //TODO is hideLabel correct? Maybe it is... + Mconsole.labels.hideLabel(n.id); + $('#topic_' + n.id + '_label').hide(); } }); Mconsole.plot(); diff --git a/app/assets/javascripts/Jit/graphsettings-event-handlers.js b/app/assets/javascripts/Jit/graphsettings-event-handlers.js index 72e1fc8a..f18d6085 100644 --- a/app/assets/javascripts/Jit/graphsettings-event-handlers.js +++ b/app/assets/javascripts/Jit/graphsettings-event-handlers.js @@ -33,12 +33,13 @@ function nodeDoubleClickHandler(node, e) { return; } - if (node.getData('inCommons') == false) { + //greenCircle being true denotes it's actually "in the commons" still + if (node.getData('greenCircle') == false) { return; } //this line adds it to the console if you close seek - node.setData('inCommons', false); + node.setData('greenCircle', false); //this is just aesthetic deselectNode(node); @@ -60,6 +61,9 @@ function nodeDoubleClickHandler(node, e) { }//doubleClickNodeHandler +/* + * Returns a boolean saying if the node was double clicked in our understanding of the word + */ function nodeWasDoubleClicked() { //grab the timestamp of the click var storedTime = MetamapsModel.lastNodeClick; @@ -73,24 +77,6 @@ function nodeWasDoubleClicked() { } }//nodeWasDoubleClicked; -function selectNode(node) { - node.selected = true; - node.setData('dim', 30, 'current'); - node.setData('onCanvas',true); - node.eachAdjacency(function (adj) { - selectEdge(adj); - }); -} - -function deselectNode(node) { - delete node.selected; - node.setData('onCanvas', false); - node.eachAdjacency(function(adj) { - deselectEdge(adj); - }); - node.setData('dim', 25, 'current'); -} - function selectNodeOnClickHandler(node, e) { if (Mconsole.busy) return; @@ -150,17 +136,65 @@ function canvasDoubleClickHandler(canvasLoc,e) { } }//canvasDoubleClickHandler +function handleSelectionBeforeDragging(node, e) { + // four cases: + // 1 nothing is selected, so pretend you aren't selecting + // 2 others are selected only and shift, so additionally select this one + // 3 others are selected only, no shift: drag only this one + // 4 this node and others were selected, so drag them (just return false) + //return value: deselect node again after? + if (MetamapsModel.selectedNodes.length == 0) { + selectNode(node); + return 'deselect'; + } + if (MetamapsModel.selectedNodes.indexOf(node) == -1) { + if (e.shiftKey) { + selectNode(node); + return 'nothing'; + } else { + return 'only-drag-this-one'; + } + } + return 'nothing'; //case 4? +} + function onDragMoveTopicHandler(node, eventInfo, e) { if (node && !node.nodeFrom) { $('#new_synapse').fadeOut('fast'); $('#new_topic').fadeOut('fast'); var pos = eventInfo.getPos(); - // if it's a left click, move the node - if (e.button == 0 && !e.altKey && (e.buttons == 0 || e.buttons == 1 || e.buttons == undefined)) { + // if it's a left click, or a touch, move the node + if ( e.touches || (e.button == 0 && !e.altKey && (e.buttons == 0 || e.buttons == 1 || e.buttons == undefined))) { + //if the node dragged isn't already selected, select it + var whatToDo = handleSelectionBeforeDragging(node, e); + if (whatToDo == 'only-drag-this-one') { + node.pos.setc(pos.x, pos.y); + node.setData('xloc', pos.x); + node.setData('yloc', pos.y); + } else { + var len = MetamapsModel.selectedNodes.length; + + //first define offset for each node + var xOffset = new Array(); + var yOffset = new Array(); + for (var i = 0; i < len; i += 1) { + n = MetamapsModel.selectedNodes[i]; + xOffset[i] = n.getData('xloc') - node.getData('xloc'); + yOffset[i] = n.getData('yloc') - node.getData('yloc'); + }//for + + for (var i = 0; i < len; i += 1) { + n = MetamapsModel.selectedNodes[i]; + n.pos.setc(pos.x + xOffset[i], pos.y + yOffset[i]); + n.setData('xloc', pos.x + xOffset[i]); + n.setData('yloc', pos.y + yOffset[i]); + }//for + }//if + + if (whatToDo == 'deselect') { + deselectNode(node); + } dragged = node.id; - node.pos.setc(pos.x, pos.y); - node.data.$xloc = pos.x; - node.data.$yloc = pos.y; Mconsole.plot(); } // if it's a right click or holding down alt, start synapse creation ->third option is for firefox @@ -204,3 +238,63 @@ function onDragMoveTopicHandler(node, eventInfo, e) { } } } + +var lastDist = 0; + +function getDistance(p1, p2) { + return Math.sqrt(Math.pow((p2.x - p1.x), 2) + Math.pow((p2.y - p1.y), 2)); +} + +function touchPanZoomHandler(eventInfo, e) { + if (e.touches.length == 1) { + var thispos = touchPos, + currentPos = eventInfo.getPos(), + canvas = Mconsole.canvas, + ox = canvas.translateOffsetX, + oy = canvas.translateOffsetY, + sx = canvas.scaleOffsetX, + sy = canvas.scaleOffsetY; + currentPos.x *= sx; + currentPos.y *= sy; + currentPos.x += ox; + currentPos.y += oy; + //var x = currentPos.x - thispos.x, + // y = currentPos.y - thispos.y; + var x = currentPos.x - thispos.x, + y = currentPos.y - thispos.y; + touchPos = currentPos; + Mconsole.canvas.translate(x * 1/sx, y * 1/sy); + } + else if (e.touches.length == 2) { + var touch1 = e.touches[0]; + var touch2 = e.touches[1]; + + var dist = getDistance({ + x: touch1.clientX, + y: touch1.clientY + }, { + x: touch2.clientX, + y: touch2.clientY + }); + + if(!lastDist) { + lastDist = dist; + } + + var scale = dist / lastDist; + + console.log(scale); + + if (8 >= Mconsole.canvas.scaleOffsetX*scale && Mconsole.canvas.scaleOffsetX*scale >= 1) { + Mconsole.canvas.scale(scale, scale); + } + if (Mconsole.canvas.scaleOffsetX < 0.5) { + Mconsole.canvas.viz.labels.hideLabels(true); + } + else if (Mconsole.canvas.scaleOffsetX > 0.5) { + Mconsole.canvas.viz.labels.hideLabels(false); + } + lastDist = dist; + } + +} diff --git a/app/assets/javascripts/Jit/graphsettings-model.js b/app/assets/javascripts/Jit/graphsettings-model.js index 61ba0981..dbfecf4f 100644 --- a/app/assets/javascripts/Jit/graphsettings-model.js +++ b/app/assets/javascripts/Jit/graphsettings-model.js @@ -9,11 +9,13 @@ var MetamapsModel = new Object(); MetamapsModel.embed = false; -//array of all selected edges +//array of all selected edges, same for nodes MetamapsModel.selectedEdges = new Array(); +MetamapsModel.selectedNodes = new Array(); //is any showcard open right now? which one? MetamapsModel.showcardInUse = null; +MetamapsModel.widthOfLabel = null; //is the mouse hovering over an edge? which one? MetamapsModel.edgeHoveringOver = false; diff --git a/app/assets/javascripts/Jit/graphsettings.js b/app/assets/javascripts/Jit/graphsettings.js index 4d8eef7c..b9002d79 100644 --- a/app/assets/javascripts/Jit/graphsettings.js +++ b/app/assets/javascripts/Jit/graphsettings.js @@ -58,7 +58,7 @@ function graphSettings(type, embed) { }, //Update node positions when dragged onDragMove: function (node, eventInfo, e) { - onDragMoveTopicHandler(node, eventInfo, e); + onDragMoveTopicHandler(node, eventInfo, e); }, onDragEnd: function(node, eventInfo, e) { onDragEndTopicHandler(node, eventInfo, e, false); @@ -67,16 +67,45 @@ function graphSettings(type, embed) { onDragCancelHandler(node, eventInfo, e, false); }, //Implement the same handler for touchscreens + onTouchStart: function (node, eventInfo, e) { + //$jit.util.event.stop(e); //stop default touchmove event + //Mconsole.events.onMouseDown(e, null, eventInfo); + Mconsole.events.touched = true; + touchPos = eventInfo.getPos(); + var canvas = Mconsole.canvas, + ox = canvas.translateOffsetX; + oy = canvas.translateOffsetY, + sx = canvas.scaleOffsetX, + sy = canvas.scaleOffsetY; + touchPos.x *= sx; + touchPos.y *= sy; + touchPos.x += ox; + touchPos.y += oy; + + touchDragNode = node; + }, + //Implement the same handler for touchscreens onTouchMove: function (node, eventInfo, e) { - $jit.util.event.stop(e); //stop default touchmove event - this.onDragMove(node, eventInfo, e); + if (touchDragNode) onDragMoveTopicHandler(touchDragNode, eventInfo, e); + else { + touchPanZoomHandler(eventInfo, e); + Mconsole.labels.hideLabel(Mconsole.graph.getNode(MetamapsModel.showcardInUse)); + } + }, + //Implement the same handler for touchscreens + onTouchEnd: function (node, eventInfo, e) { + + }, + //Implement the same handler for touchscreens + onTouchCancel: function (node, eventInfo, e) { + }, //Add also a click handler to nodes onClick: function (node, eventInfo, e) { if (e.target.id != "infovis-canvas") return false; //topic and synapse editing cards - hideCards(); + if (!Mconsole.events.moved) hideCards(); //clicking on a node, or clicking on blank part of canvas? if (node.nodeFrom) { @@ -84,6 +113,8 @@ function graphSettings(type, embed) { } else if (node && !node.nodeFrom) { selectNodeOnClickHandler(node, e); } else { + //topic and synapse editing cards + if (!Mconsole.events.moved) hideCards(); canvasDoubleClickHandler(eventInfo.getPos(), e); }//if } @@ -235,12 +266,12 @@ var nodeSettings = { var pos = node.pos.getc(true), dim = node.getData('dim'), cat = node.getData('metacode'), - inCommons = node.getData('inCommons'), - onCanvas = node.getData('onCanvas'), + greenCircle = node.getData('greenCircle'), + whiteCircle = node.getData('whiteCircle'), ctx = canvas.getCtx(); // if the topic is from the Commons draw a green circle around it - if (inCommons) { + if (greenCircle) { ctx.beginPath(); ctx.arc(pos.x, pos.y, dim+3, 0, 2 * Math.PI, false); ctx.strokeStyle = '#67be5f'; // green @@ -248,7 +279,7 @@ var nodeSettings = { ctx.stroke(); } // if the topic is on the Canvas draw a white circle around it - if (onCanvas) { + if (whiteCircle) { ctx.beginPath(); ctx.arc(pos.x, pos.y, dim+3, 0, 2 * Math.PI, false); if (! MetamapsModel.embed) ctx.strokeStyle = 'white'; @@ -480,6 +511,7 @@ function onDragEndTopicHandler(node, eventInfo, e, allowRealtime) { tempNode2 = null; tempInit = false; } else if (dragged != 0 && goRealtime) { + //TODO: dragged is invalid if multiple nodes were dragged saveLayout(dragged); } }//onDragEndTopicHandler @@ -499,18 +531,28 @@ function onDragCancelHandler(node, eventInfo, e, centred) { } function onPlaceLabelHandler(domElement, node) { - var style = domElement.style; - var left = parseInt(style.left); - var top = parseInt(style.top); - var w = domElement.offsetWidth; - style.left = (left - w / 2 + 107) + 'px'; - style.top = (top-165) + 'px'; - style.display = ''; - var label = document.getElementById('topic_' + node.id + '_label'); - $(label).show(); - w = label.offsetWidth; - style = label.style; - style.left = (-(w / 2 + 106)) + 'px'; + var style = domElement.style; + var left = parseInt(style.left); + var top = parseInt(style.top); + var w = $('#topic_' + node.id + '_label').width(); + style.left = (left - w / 2) + 'px'; + style.top = (top+20) + 'px'; + style.display = ''; + + // now position the showcard + if (MetamapsModel.showcardInUse != null) { + top = $('#' + MetamapsModel.showcardInUse).css('top'); + left = parseInt($('#' + MetamapsModel.showcardInUse).css('left')); + if (0 != $('#topic_' + MetamapsModel.showcardInUse + '_label').width()) { + MetamapsModel.widthOfLabel = $('#topic_' + MetamapsModel.showcardInUse + '_label').width(); + } + w = MetamapsModel.widthOfLabel/2; + left = (left + w) + 'px'; + $('#showcard').css('top', top); + $('#showcard').css('left', left); + + Mconsole.labels.hideLabel(Mconsole.graph.getNode(MetamapsModel.showcardInUse)); + } } // thanks to http://stackoverflow.com/questions/4338963/ diff --git a/app/assets/javascripts/Jit/jit2.0.0.js b/app/assets/javascripts/Jit/jit2.0.0.js index 7e15717b..0a5fdc9e 100644 --- a/app/assets/javascripts/Jit/jit2.0.0.js +++ b/app/assets/javascripts/Jit/jit2.0.0.js @@ -2591,6 +2591,7 @@ Extras.Classes.Navigation = new Class({ $.event.stop($.event.get(e, win)); var val = this.config.zooming / 1000, ans = 1 + scroll * val; + // START METAMAPS CODE if (ans > 1) { if (5 >= this.canvas.scaleOffsetX) { this.canvas.scale(ans, ans); @@ -2607,6 +2608,8 @@ Extras.Classes.Navigation = new Class({ else if (this.canvas.scaleOffsetX > 0.5) { this.canvas.viz.labels.hideLabels(false); } + // END METAMAPS CODE + // ORIGINAL CODE this.canvas.scale(ans, ans); }, onMouseDown: function(e, win, eventInfo) { diff --git a/app/assets/javascripts/Jit/loadgraphs.js b/app/assets/javascripts/Jit/loadgraphs.js index 2335a4ba..8a1c585b 100644 --- a/app/assets/javascripts/Jit/loadgraphs.js +++ b/app/assets/javascripts/Jit/loadgraphs.js @@ -118,6 +118,25 @@ function initialize(type, loadLater, embed){ else if ( type == "arranged" || type == "chaotic") { Mconsole.animate(chooseAnimate); } + + // prevent touch events on the canvas from default behaviour + $("#infovis-canvas").bind('touchstart', function(event) { + event.preventDefault(); + Mconsole.events.touched = true; + }); + + // prevent touch events on the canvas from default behaviour + $("#infovis-canvas").bind('touchmove', function(event) { + //touchPanZoomHandler(event); + }); + + // prevent touch events on the canvas from default behaviour + $("#infovis-canvas").bind('touchend touchcancel', function(event) { + lastDist = 0; + if (!Mconsole.events.touchMoved && !touchDragNode) hideCurrentCard(); + Mconsole.events.touched = Mconsole.events.touchMoved = false; + touchDragNode = false; + }); }); // end }// if not loadLater diff --git a/app/assets/javascripts/Jit/onCreateLabelHandler.js b/app/assets/javascripts/Jit/onCreateLabelHandler.js index 71f0d0de..e960bc7a 100644 --- a/app/assets/javascripts/Jit/onCreateLabelHandler.js +++ b/app/assets/javascripts/Jit/onCreateLabelHandler.js @@ -15,22 +15,6 @@ */ function onCreateLabelHandler(domElement, node) { - var html = generateShowcardHTML(); - html = replaceVariables(html, node); - - var showCard = document.createElement('div'); - showCard.className = 'showcard topic_' + node.id; - if (authorizeToEdit(node)) { - var perm = document.createElement('div'); - perm.className = 'permission canEdit'; - perm.innerHTML = html; - showCard.appendChild(perm); - } else { - showCard.innerHTML = html; - } - showCard.style.display = "none"; - domElement.appendChild(showCard); - // Create a 'name' button and add it to the main node label var nameContainer = document.createElement('span'), style = nameContainer.style; @@ -42,7 +26,7 @@ function onCreateLabelHandler(domElement, node) { style.fontSize = "0.9em"; style.color = "#222222"; - bindCallbacks(showCard, nameContainer, node); + bindNameContainerCallbacks(nameContainer, node); } function generateShowcardHTML() { @@ -273,41 +257,41 @@ function hideCard(node) { $(card).fadeOut('fast', function(){ node.setData('dim', 25, 'current'); - $('.name.topic_' + node.id).show(); + Mconsole.labels.hideLabel(Mconsole.graph.getNode(node.id), true) Mconsole.plot(); }); MetamapsModel.showcardInUse = null; } -function bindCallbacks(showCard, nameContainer, node) { - // add some events to the label - $(showCard).find('img.icon').click(function(){ - hideCard(node); - }); - - $(showCard).find('.scroll').mCustomScrollbar(); +function bindNameContainerCallbacks(nameContainer, node) { + nameContainer.onmouseover = function(){ + $('.name.topic_' + node.id + ' .nodeOptions').css('display','block'); + } + + nameContainer.onmouseout = function(){ + $('.name.topic_' + node.id + ' .nodeOptions').css('display','none'); + } + + var showCard = document.getElementById('showcard'); // add some events to the label $(nameContainer).find('.label').click(function(e){ - $('.name').css('display','block'); - $('.name.topic_' + node.id).css('display','none'); - $('.showcard.topic_' + node.id).fadeIn('fast'); - $('.showcard.topic_' + node.id).find('.scroll').mCustomScrollbar("update"); - node.setData('dim', 1, 'current'); - hideCurrentCard(); - MetamapsModel.showcardInUse = node.id; - Mconsole.plot(); - }); - - nameContainer.onmouseover = function(){ - $('.name.topic_' + node.id + ' .nodeOptions').css('display','block'); - } - - nameContainer.onmouseout = function(){ - $('.name.topic_' + node.id + ' .nodeOptions').css('display','none'); - } + showCard.innerHTML = ''; + + var html = generateShowcardHTML(); + html = replaceVariables(html, node); + + showCard.className = 'showcard topic_' + node.id; + if (authorizeToEdit(node)) { + var perm = document.createElement('div'); + perm.className = 'permission canEdit'; + perm.innerHTML = html; + showCard.appendChild(perm); + } else { + showCard.innerHTML = html; + } //bind best_in_place ajax callbacks $(showCard).find('.best_in_place_metacode').bind("ajax:success", function() { @@ -323,6 +307,7 @@ function bindCallbacks(showCard, nameContainer, node) { $(showCard).find('.best_in_place_name').bind("ajax:success", function() { var name = $(this).html(); $(nameContainer).find('.label').html(name); + node.name = name; }); $(showCard).find('.best_in_place_desc').bind("ajax:success", function() { @@ -378,4 +363,24 @@ function bindCallbacks(showCard, nameContainer, node) { else if (permission == "public") el.html("pu"); else if (permission == "private") el.html("pr"); }); + + var top = $('#' + node.id).css('top'); + var left = parseInt($('#' + node.id).css('left')); + var w = $('#topic_' + node.id + '_label').width(); + w = w/2; + left = (left + w) + 'px'; + $('#showcard').css('top', top); + $('#showcard').css('left', left); + + $('.showcard.topic_' + node.id).fadeIn('fast'); + $('.showcard.topic_' + node.id).find('.scroll').mCustomScrollbar(); + node.setData('dim', 1, 'current'); + MetamapsModel.showcardInUse = node.id; + Mconsole.plot(); + Mconsole.labels.hideLabel(Mconsole.graph.getNode(node.id)) + // add some events to the label + $(showCard).find('img.icon').click(function(){ + hideCard(node); + }); + }); } diff --git a/app/assets/javascripts/Jit/select-edit-delete-nodes-and-edges.js b/app/assets/javascripts/Jit/select-edit-delete-nodes-and-edges.js index 47a845c8..fa5ee66c 100644 --- a/app/assets/javascripts/Jit/select-edit-delete-nodes-and-edges.js +++ b/app/assets/javascripts/Jit/select-edit-delete-nodes-and-edges.js @@ -287,7 +287,32 @@ function deleteSelectedEdges() { MetamapsModel.selectedEdges = new Array(); } +function selectNode(node) { + if (MetamapsModel.selectedNodes.indexOf(node) != -1) return; + node.selected = true; + node.setData('dim', 30, 'current'); + node.setData('whiteCircle',true); + node.eachAdjacency(function (adj) { + selectEdge(adj); + }); + MetamapsModel.selectedNodes.push(node); +} + +function deselectNode(node) { + delete node.selected; + node.setData('whiteCircle', false); + node.eachAdjacency(function(adj) { + deselectEdge(adj); + }); + node.setData('dim', 25, 'current'); + + //remove the node + MetamapsModel.selectedNodes.splice( + MetamapsModel.selectedNodes.indexOf(node), 1); +} + function selectEdge(edge) { + if (MetamapsModel.selectedEdges.indexOf(edge) != -1) return; var showDesc = edge.getData("showDesc"); if (! showDesc) { edge.setData('showDesc', true, 'current'); @@ -348,6 +373,8 @@ function hideNode(nodeid) { alert("You can't hide this topic, it is the root of your graph."); return; } + + deselectNode(node); node.setData('alpha', 0, 'end'); node.eachAdjacency(function(adj) { @@ -361,15 +388,18 @@ function hideNode(nodeid) { Mconsole.graph.removeNode(nodeid); Mconsole.labels.disposeLabel(nodeid); } + function hideSelectedNodes() { Mconsole.graph.eachNode( function (n) { - if (n.data.$onCanvas == true) { + if (n.getData('whiteCircle') == true) { hideNode(n.id); } }); } function removeNode(nodeid) { + var node = Mconsole.graph.getNode(nodeid); + deselectNode(node); if (mapperm) { $.ajax({ type: "POST", @@ -380,7 +410,7 @@ function removeNode(nodeid) { function removeSelectedNodes() { if (mapperm) { Mconsole.graph.eachNode( function (n) { - if (n.data.$onCanvas == true) { + if (n.getData('whiteCircle') == true) { removeNode(n.id); } }); @@ -399,7 +429,7 @@ function deleteNode(nodeid) { } function deleteSelectedNodes() { Mconsole.graph.eachNode( function (n) { - if (n.data.$onCanvas == true) { + if (n.getData('whiteCircle') == true) { deleteNode(n.id); } }); diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 012cbcc2..86984539 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -21,7 +21,7 @@ // other options are 'graph' var viewMode = "list"; -var labelType, useGradients, nativeTextSupport, animate, json, Mconsole = null, gType, tempNode = null, tempInit = false, tempNode2 = null, metacodeIMGinit = false, findOpen = false, analyzeOpen = false, organizeOpen = false, goRealtime = false, mapid = null, mapperm = false; +var labelType, useGradients, nativeTextSupport, animate, json, Mconsole = null, gType, tempNode = null, tempInit = false, tempNode2 = null, metacodeIMGinit = false, findOpen = false, analyzeOpen = false, organizeOpen = false, goRealtime = false, mapid = null, mapperm = false, touchPos, touchDragNode; $(document).ready(function() { @@ -69,11 +69,25 @@ var labelType, useGradients, nativeTextSupport, animate, json, Mconsole = null, height: '0px' }, 300, function() { sliding1 = false; + menuIsOpen = false; }); } },800); } ); + + var menuIsOpen = false; + $("#mainTitle a").bind('touchend', function(evt) { + if (!menuIsOpen) { + menuIsOpen = true; + var listLength = $('.logo .menu li').length * 28; + $('.footer .menu').animate({ + height: listLength + 'px' + }, 300); + evt.preventDefault(); + evt.stopPropogation(); + } + }); addHoverForSettings(); @@ -99,7 +113,7 @@ var labelType, useGradients, nativeTextSupport, animate, json, Mconsole = null, saveLayoutAll(); }); -}); +}); // end document.ready function addHoverForSettings() { // controls the sliding hover of the settings for cards diff --git a/app/assets/stylesheets/ForceDirected.css b/app/assets/stylesheets/ForceDirected.css index 9c4662df..0e70f5da 100644 --- a/app/assets/stylesheets/ForceDirected.css +++ b/app/assets/stylesheets/ForceDirected.css @@ -4,6 +4,7 @@ .label { display:block; + white-space: nowrap; padding: 2px 4px; background:#ddd; opacity:0.8; @@ -13,5 +14,4 @@ span.name { cursor: pointer; position: absolute; - top: 185px; } diff --git a/app/assets/stylesheets/base.css b/app/assets/stylesheets/base.css index c9b3122d..a9bd8a59 100644 --- a/app/assets/stylesheets/base.css +++ b/app/assets/stylesheets/base.css @@ -7,6 +7,9 @@ } .showcard, #showcard { + position:absolute; + display:none; + margin-top: -181px; width:216px; height:320px; color:#FFF; diff --git a/app/controllers/synapses_controller.rb b/app/controllers/synapses_controller.rb index 4a4910ab..e1fe3f90 100644 --- a/app/controllers/synapses_controller.rb +++ b/app/controllers/synapses_controller.rb @@ -5,7 +5,17 @@ class SynapsesController < ApplicationController respond_to :html, :js, :json - autocomplete :synapse, :desc, :full => true + def autocomplete_synapse_desc + term = params[:term] + if term && !term.empty? + items = Synapse.select('DISTINCT "desc"'). + where('LOWER("desc") like ?', term.downcase + '%'). + limit(10).order('"desc"') + else + items = {} + end + render :json => json_for_autocomplete(items, :desc) + end # GET synapses # or GET users/:user_id/synapses diff --git a/app/views/main/console.html.erb b/app/views/main/console.html.erb index b992b2fd..93abd496 100644 --- a/app/views/main/console.html.erb +++ b/app/views/main/console.html.erb @@ -23,6 +23,7 @@
+
<% if authenticated? %> diff --git a/app/views/main/search.js.erb b/app/views/main/search.js.erb index 9cc2e6dd..2be2dcc4 100644 --- a/app/views/main/search.js.erb +++ b/app/views/main/search.js.erb @@ -19,8 +19,8 @@ var even = true; var temp = Mconsole.graph.getNode('<%= topic.id %>'); temp.setData('dim', 1, 'start'); temp.setData('dim', 25, 'end'); - temp.setData('inCommons',true); - temp.setData('onCanvas',false); + temp.setData('greenCircle',true); + temp.setData('whiteCircle',false); temp.setPos(new $jit.Complex(myX, myY), 'current'); temp.setPos(new $jit.Complex(myX, myY), 'start'); temp.setPos(new $jit.Complex(myX, myY), 'end'); @@ -28,17 +28,16 @@ var even = true; Mconsole.labels.plotLabel(Mconsole.canvas, temp, Mconsole.config); myX += 100; even = !even; - } - else { + } else { var temp = Mconsole.graph.getNode('<%= topic.id %>'); - if (temp == null || temp.getData('inCommons')) { + if (temp == undefined) { var newnode = <%= topic.self_as_json.html_safe %>; Mconsole.graph.addNode(newnode); var temp = Mconsole.graph.getNode('<%= topic.id %>'); temp.setData('dim', 1, 'start'); temp.setData('dim', 25, 'end'); - temp.setData('inCommons',true); - temp.setData('onCanvas',false); + temp.setData('greenCircle',true); + temp.setData('whiteCircle',false); if (myX > (w-100)) { myX = -w + 400; myY += 200; @@ -85,7 +84,7 @@ var even = true; username: '<%= synapse.user.name %>', permission: '<%= synapse.permission %>' }); - temp.data.$direction = d; + temp.setData('direction', d); Mconsole.fx.plotLine(temp, Mconsole.canvas); } <% end %> diff --git a/app/views/maps/show.html.erb b/app/views/maps/show.html.erb index e199d5eb..662664ec 100644 --- a/app/views/maps/show.html.erb +++ b/app/views/maps/show.html.erb @@ -42,6 +42,7 @@
+
diff --git a/app/views/topics/create.js.erb b/app/views/topics/create.js.erb index a69c0a3c..18cb397d 100644 --- a/app/views/topics/create.js.erb +++ b/app/views/topics/create.js.erb @@ -25,8 +25,8 @@ if (!$.isEmptyObject(Mconsole.graph.nodes)) { var temp = Mconsole.graph.getNode('<%= @topic.id %>'); temp.setData('dim', 1, 'start'); temp.setData('dim', 40, 'end'); - temp.setData('onCanvas', false); - temp.setData('inCommons', false); + temp.setData('whiteCircle', false); + temp.setData('greenCircle', false); if (gType == "centered") { var tempPos = new $jit.Complex(x, y); @@ -72,7 +72,7 @@ if (!$.isEmptyObject(Mconsole.graph.nodes)) { modes: ['node-property:dim'], duration: 500, onComplete: function() { - selectNodeOnClickHandler(temp); + selectNode(temp); } }); @@ -84,8 +84,8 @@ if (!$.isEmptyObject(Mconsole.graph.nodes)) { var temp = Mconsole.graph.getNode('<%= @topic.id %>'); temp.setData('dim', 1, 'start'); temp.setData('dim', 25, 'end'); - temp.setData('onCanvas', false); - temp.setData('inCommons', false); + temp.setData('whiteCircle', false); + temp.setData('greenCircle', false); if (gType == "arranged" || gType == "chaotic") { <% if not @mapping.nil? %> temp.setData('mappingid', <%= @mapping.id %>); @@ -101,7 +101,7 @@ if (!$.isEmptyObject(Mconsole.graph.nodes)) { modes: ['node-property:dim'], duration: 500, onComplete: function() { - selectNodeOnClickHandler(temp); + selectNode(temp); } }); } diff --git a/app/views/topics/show.html.erb b/app/views/topics/show.html.erb index c48bcc46..552e2819 100644 --- a/app/views/topics/show.html.erb +++ b/app/views/topics/show.html.erb @@ -30,6 +30,7 @@
+