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 = '- commons
\
@@ -1333,6 +1346,15 @@ Metamaps.JIT = {
menustring += '- Change metacode' + metacodeOptions + '
';
}
+ if (Metamaps.Active.Topic) {
+ // set up the get sibling menu as a "lazy load"
+ // only fill in the submenu when they hover over the get siblings list item
+ var siblingMenu = '';
+ menustring += '- Get siblings' + siblingMenu + '
';
+ }
menustring += '
';
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