diff --git a/app/assets/javascripts/src/Metamaps.JIT.js b/app/assets/javascripts/src/Metamaps.JIT.js index 038f1a67..88436a80 100644 --- a/app/assets/javascripts/src/Metamaps.JIT.js +++ b/app/assets/javascripts/src/Metamaps.JIT.js @@ -37,8 +37,9 @@ Metamaps.JIT = { /** * convert our topic JSON into something JIT can use */ - prepareVizData: function () { - var self = Metamaps.JIT; + convertModelsToJIT: function(topics, synapses) { + var jitReady = []; + var synapsesToRemove = []; var topic; var mapping; @@ -48,18 +49,14 @@ Metamaps.JIT = { var edge; var edges = []; - // reset/empty vizData - self.vizData = []; - Metamaps.Visualize.loadLater = false; - - Metamaps.Topics.each(function (t) { + topics.each(function (t) { node = t.createNode(); nodes[node.id] = node; }); - Metamaps.Synapses.each(function (s) { + synapses.each(function (s) { edge = s.createEdge(); - if(Metamaps.Topics.get(s.get('node1_id')) === undefined || Metamaps.Topics.get(s.get('node2_id')) === undefined) { + if (topics.get(s.get('node1_id')) === undefined || topics.get(s.get('node2_id')) === undefined) { // this means it's an invalid synapse synapsesToRemove.push(s); } @@ -89,17 +86,31 @@ Metamaps.JIT = { } }); + _.each(nodes, function (node) { + jitReady.push(node); + }); + + return [jitReady, synapsesToRemove]; + }, + prepareVizData: function () { + var self = Metamaps.JIT; + var mapping; + + // reset/empty vizData + self.vizData = []; + Metamaps.Visualize.loadLater = false; + + var results = self.convertModelsToJIT(Metamaps.Topics, Metamaps.Synapses); + + self.vizData = results[0]; + // clean up the synapses array in case of any faulty data - _.each(synapsesToRemove, function (synapse) { + _.each(results[1], function (synapse) { mapping = synapse.getMapping(); Metamaps.Synapses.remove(synapse); Metamaps.Mappings.remove(mapping); }); - _.each(nodes, function (node) { - self.vizData.push(node); - }); - if (self.vizData.length == 0) { Metamaps.Visualize.loadLater = true; } @@ -1319,7 +1330,9 @@ Metamaps.JIT = { if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '
  • Delete
  • '; - if (Metamaps.Active.Topic) menustring += '
  • Center this topic
  • '; + if (Metamaps.Active.Topic) { + menustring += '
  • Center this topic
  • '; + } menustring += '
  • Open in new tab
  • '; if (Metamaps.Active.Mapper) { var options = ''; rightclickmenu.innerHTML = menustring; @@ -1426,7 +1448,70 @@ Metamaps.JIT = { Metamaps.Control.updateSelectedMetacodes($(this).attr('data-id')); }); - }, //selectNodeOnRightClickHandler + + // fetch relatives + var fetched = false; + $('.rc-siblings').hover(function () { + if (!fetched) { + Metamaps.JIT.populateRightClickSiblings(node); + fetched = true; + } + }); + $('.rc-siblings .fetchAll').click(function () { + $('.rightclickmenu').remove(); + // data-id is a metacode id + Metamaps.Topic.fetchRelatives(node); + }); + }, //selectNodeOnRightClickHandler, + populateRightClickSiblings: function(node) { + var self = Metamaps.JIT; + + // depending on how many topics are selected, do different things + /*if (Metamaps.Selected.Nodes.length > 1) { + // we don't bother filling the submenu with + // specific numbers, because there are too many topics + // selected to find those numbers + $('#loadingSiblings').remove(); + return; + }*/ + + var topic = node.getData('topic'); + + // add a loading icon for now + var loader = new CanvasLoader('loadingSiblings'); + loader.setColor('#4FC059'); // default is '#000000' + loader.setDiameter(15); // default is 40 + loader.setDensity(41); // default is 40 + loader.setRange(0.9); // default is 1.3 + loader.show(); // Hidden by default + + var topics = Metamaps.Topics.map(function(t){ return t.id }); + var topics_string = topics.join(); + + var successCallback = function(data) { + $('#loadingSiblings').remove(); + + for (var key in data) { + var string = Metamaps.Metacodes.get(key).get('name') + ' (' + data[key] + ')'; + $('#fetchSiblingList').append('
  • ' + string + '
  • '); + } + + $('.rc-siblings .getSiblings').click(function () { + $('.rightclickmenu').remove(); + // data-id is a metacode id + Metamaps.Topic.fetchRelatives(node, $(this).attr('data-id')); + }); + }; + + $.ajax({ + type: "Get", + url: "/topics/" + topic.id + "/relative_numbers.json?network=" + topics_string, + success: successCallback, + error: function () { + + } + }); + }, selectEdgeOnClickHandler: function (adj, e) { if (Metamaps.Visualize.mGraph.busy) return; diff --git a/app/assets/javascripts/src/Metamaps.js b/app/assets/javascripts/src/Metamaps.js index ff2203c4..5b2109bc 100644 --- a/app/assets/javascripts/src/Metamaps.js +++ b/app/assets/javascripts/src/Metamaps.js @@ -219,7 +219,6 @@ Metamaps.Backbone.init = function () { var mapping; var node = this.get('node'); node.setData('topic', this); - node.id = this.isNew() ? this.cid : this.id; if (Metamaps.Active.Map) { mapping = this.getMapping(); @@ -1508,6 +1507,8 @@ Metamaps.Visualize = { mapping; if (self.type == "RGraph") { + var i, l, startPos, endPos, topic, synapse; + self.mGraph.graph.eachNode(function (n) { topic = Metamaps.Topics.get(n.id); topic.set({ node: n }, { silent: true }); @@ -3671,8 +3672,7 @@ Metamaps.Topic = { }, centerOn: function (nodeid) { if (!Metamaps.Visualize.mGraph.busy) { - var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid); - Metamaps.Visualize.mGraph.onClick(node.id, { + Metamaps.Visualize.mGraph.onClick(nodeid, { hideLabels: false, duration: 1000, onComplete: function () { @@ -3681,6 +3681,66 @@ Metamaps.Topic = { }); } }, + fetchRelatives: function(node, metacode_id) { + + var topics = Metamaps.Topics.map(function(t){ return t.id }); + var topics_string = topics.join(); + + var creators = Metamaps.Creators.map(function(t){ return t.id }); + var creators_string = creators.join(); + + var topic = node.getData('topic'); + + var successCallback = function(data) { + if (data.creators.length > 0) Metamaps.Creators.add(data.creators); + if (data.topics.length > 0) Metamaps.Topics.add(data.topics); + if (data.synapses.length > 0) Metamaps.Synapses.add(data.synapses); + + var topicColl = new Metamaps.Backbone.TopicCollection(data.topics); + topicColl.add(topic); + var synapseColl = new Metamaps.Backbone.SynapseCollection(data.synapses); + + var graph = Metamaps.JIT.convertModelsToJIT(topicColl, synapseColl)[0]; + Metamaps.Visualize.mGraph.op.sum(graph, { + type: 'fade', + duration: 500, + hideLabels: false + }); + + var i, l, t, s; + + Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + t = Metamaps.Topics.get(n.id); + t.set({ node: n }, { silent: true }); + t.updateNode(); + + n.eachAdjacency(function (edge) { + if(!edge.getData('init')) { + edge.setData('init', true); + + l = edge.getData('synapseIDs').length; + for (i = 0; i < l; i++) { + s = Metamaps.Synapses.get(edge.getData('synapseIDs')[i]); + s.set({ edge: edge }, { silent: true }); + s.updateEdge(); + } + } + }); + }); + }; + + var paramsString = metacode_id ? "metacode=" + metacode_id + "&" : ""; + paramsString += "network=" + topics_string + "&creators=" + creators_string; + + $.ajax({ + type: "Get", + url: "/topics/" + topic.id + "/relatives.json?" + paramsString, + success: successCallback, + error: function () { + + } + }); + }, /* * * @@ -4739,8 +4799,6 @@ Metamaps.Account = { var destWidth = 84; var destHeight = 84; - //debugger; - context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight); $('.userImageDiv').prepend($canvas); }; diff --git a/app/assets/javascripts/src/codeleft.js b/app/assets/javascripts/src/codeleft.js deleted file mode 100644 index 413fc62a..00000000 --- a/app/assets/javascripts/src/codeleft.js +++ /dev/null @@ -1,34 +0,0 @@ -function fetchRelatives(node) { - var myA = $.ajax({ - type: "Get", - url: "/topics/" + node.id + "?format=json", - success: function (data) { - if (gType == "centered") { - Mconsole.busy = true; - Mconsole.op.sum(data, { - type: 'fade', - duration: 500, - hideLabels: false - }); - Mconsole.graph.eachNode(function (n) { - n.eachAdjacency(function (a) { - if (!a.getData('showDesc')) { - a.setData('alpha', 0.4, 'start'); - a.setData('alpha', 0.4, 'current'); - a.setData('alpha', 0.4, 'end'); - } - }); - }); - Mconsole.busy = false; - } else { - Mconsole.op.sum(data, { - type: 'nothing', - }); - Mconsole.plot(); - } - }, - error: function () { - alert('failure'); - } - }); -} \ No newline at end of file diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 259e8232..7849d889 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1244,7 +1244,9 @@ h3.realtimeBoxTitle { .rc-metacode li img { float: left; } -.rightclickmenu .rc-permission ul, .rightclickmenu .rc-metacode ul { +.rightclickmenu .rc-permission ul, +.rightclickmenu .rc-metacode ul, +.rightclickmenu .rc-siblings ul { display: none; background: white; top: 0; @@ -1255,7 +1257,9 @@ float: left; border-top-right-radius: 2px; box-shadow: 0px 3px 3px rgba(0,0,0,0.12), 0 3px 3px rgba(0,0,0,0.24); } -.rightclickmenu .rc-permission:hover > ul, .rightclickmenu .rc-metacode:hover > ul { +.rightclickmenu .rc-permission:hover > ul, +.rightclickmenu .rc-metacode:hover > ul, + .rightclickmenu .rc-siblings:hover > ul { display: block; } .rightclickmenu p { @@ -1283,20 +1287,24 @@ float: left; .rightclickmenu li.toPrivate .rc-perm-icon { background-position: -24px 0; } -.rightclickmenu .rc-metacode > ul > li { +.rightclickmenu .rc-metacode > ul > li, +.rightclickmenu .rc-siblings > ul > li { padding: 6px 10px 6px 8px; width: 100px; } -.rightclickmenu .rc-metacode ul ul { +.rightclickmenu .rc-metacode ul ul, +.rightclickmenu .rc-siblings ul ul { display: none; max-height: 270px; overflow-y: auto; overflow-x: hidden; } -.rightclickmenu .rc-metacode li:hover ul { +.rightclickmenu .rc-metacode li:hover ul, +.rightclickmenu .rc-siblings li:hover ul { display: block; } -.rightclickmenu .rc-metacode ul ul li { +.rightclickmenu .rc-metacode ul ul li, +.rightclickmenu .rc-siblings ul ul li { padding: 4px 10px 4px 8px; width: 120px; } @@ -1315,15 +1323,24 @@ float: left; display: block; } -.moveMenusUp .rc-metacode ul, .moveMenusUp .rc-permission ul { +.moveMenusUp .rc-metacode ul, +.moveMenusUp .rc-permission ul, +.moveMenusUp .rc-siblings ul { top: auto; bottom: 0; } -.moveMenusToLeft .rc-metacode ul, .moveMenusToLeft .rc-permission ul { +.moveMenusToLeft .rc-metacode ul, +.moveMenusToLeft .rc-permission ul, +.moveMenusToLeft .rc-siblings ul { left: auto; right: 100%; } +#loadingSiblings div { + width: 15px; + margin: 0 auto; +} + /* end right click menu */ diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index cd621db5..e39b67a8 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -61,7 +61,7 @@ class TopicsController < ApplicationController @topic = Topic.find(params[:id]).authorize_to_show(@current) if not @topic - redirect_to root_url and return + redirect_to root_url, notice: "Access denied. That topic is private." and return end @alltopics = @topic.relatives.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } @@ -90,6 +90,85 @@ class TopicsController < ApplicationController end end + # GET topics/:id/relative_numbers + def relative_numbers + @current = current_user + @topic = Topic.find(params[:id]).authorize_to_show(@current) + + if not @topic + redirect_to root_url, notice: "Access denied. That topic is private." and return + end + + @topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] + + @alltopics = @topic.relatives.delete_if {|t| + @topicsAlreadyHas.index(t.id.to_s) != nil || + (t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id))) + } + + @alltopics.uniq! + + @json = Hash.new() + @alltopics.each do |t| + if @json[t.metacode.id] + @json[t.metacode.id] += 1 + else + @json[t.metacode.id] = 1 + end + end + + respond_to do |format| + format.json { render json: @json } + end + end + + # GET topics/:id/relatives + def relatives + @current = current_user + @topic = Topic.find(params[:id]).authorize_to_show(@current) + + if not @topic + redirect_to root_url, notice: "Access denied. That topic is private." and return + end + + @topicsAlreadyHas = params[:network] ? params[:network].split(',') : [] + + @alltopics = @topic.relatives.delete_if {|t| + @topicsAlreadyHas.index(t.id.to_s) != nil || + (params[:metacode] && t.metacode_id.to_s != params[:metacode]) || + (t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id))) + } + + @alltopics.uniq! + + @allsynapses = @topic.synapses.delete_if {|s| + (s.topic1 == @topic && @alltopics.index(s.topic2) == nil) || + (s.topic2 == @topic && @alltopics.index(s.topic1) == nil) + } + + @creatorsAlreadyHas = params[:creators] ? params[:creators].split(',') : [] + @allcreators = [] + @alltopics.each do |t| + if @allcreators.index(t.user) == nil && @creatorsAlreadyHas.index(t.user_id.to_s) == nil + @allcreators.push(t.user) + end + end + @allsynapses.each do |s| + if @allcreators.index(s.user) == nil && @creatorsAlreadyHas.index(s.user_id.to_s) == nil + @allcreators.push(s.user) + end + end + + @json = Hash.new() + @json['topics'] = @alltopics + @json['synapses'] = @allsynapses + @json['creators'] = @allcreators + + respond_to do |format| + format.json { render json: @json } + end + end + # POST /topics # POST /topics.json def create diff --git a/config/routes.rb b/config/routes.rb index edc19576..f5ad183f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -22,6 +22,8 @@ Metamaps::Application.routes.draw do get :autocomplete_topic, :on => :collection end match 'topics/:id/network', to: 'topics#network', via: :get, as: :network + match 'topics/:id/relative_numbers', to: 'topics#relative_numbers', via: :get, as: :relative_numbers + match 'topics/:id/relatives', to: 'topics#relatives', via: :get, as: :relatives match 'explore/active', to: 'maps#index', via: :get, as: :activemaps match 'explore/featured', to: 'maps#index', via: :get, as: :featuredmaps