enabled pulling in siblings through right click menus in topic view

This commit is contained in:
Connor Turland 2014-11-11 06:48:21 -05:00
parent 534bdae495
commit 8d3de3867f
6 changed files with 271 additions and 64 deletions

View file

@ -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 += '<li class="rc-delete ' + disabled + '"><div class="rc-icon"></div>Delete</li>';
if (Metamaps.Active.Topic) menustring += '<li class="rc-center"><div class="rc-icon"></div>Center this topic</li>';
if (Metamaps.Active.Topic) {
menustring += '<li class="rc-center"><div class="rc-icon"></div>Center this topic</li>';
}
menustring += '<li class="rc-popout"><div class="rc-icon"></div>Open in new tab</li>';
if (Metamaps.Active.Mapper) {
var options = '<ul><li class="changeP toCommons"><div class="rc-perm-icon"></div>commons</li> \
@ -1333,6 +1346,15 @@ Metamaps.JIT = {
menustring += '<li class="rc-metacode"><div class="rc-icon"></div>Change metacode' + metacodeOptions + '<div class="expandLi"></div></li>';
}
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 = '<ul id="fetchSiblingList"> \
<li class="fetchAll">All</li> \
<li id="loadingSiblings"></li> \
</ul>';
menustring += '<li class="rc-siblings"><div class="rc-icon"></div>Get siblings' + siblingMenu + '<div class="expandLi"></div></li>';
}
menustring += '</ul>';
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('<li class="getSiblings" data-id="' + key + '">' + string + '</li>');
}
$('.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;

View file

@ -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);
};

View file

@ -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');
}
});
}

View file

@ -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 */

View file

@ -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

View file

@ -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