diff --git a/app/assets/images/.DS_Store b/app/assets/images/.DS_Store
index 5008ddfc..94ce050f 100644
Binary files a/app/assets/images/.DS_Store and b/app/assets/images/.DS_Store differ
diff --git a/app/assets/images/context_topicview_sprite.png b/app/assets/images/context_topicview_sprite.png
new file mode 100644
index 00000000..c611d392
Binary files /dev/null and b/app/assets/images/context_topicview_sprite.png differ
diff --git a/app/assets/images/icons/Open Data/OD_API.png b/app/assets/images/icons/Open Data/OD_API.png
new file mode 100644
index 00000000..c84c0f11
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_API.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Business Data.png b/app/assets/images/icons/Open Data/OD_Business Data.png
new file mode 100644
index 00000000..2658c658
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Business Data.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Cloud-hosted Data.png b/app/assets/images/icons/Open Data/OD_Cloud-hosted Data.png
new file mode 100644
index 00000000..c08ebbd6
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Cloud-hosted Data.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Creative Commons Data.png b/app/assets/images/icons/Open Data/OD_Creative Commons Data.png
new file mode 100644
index 00000000..29f428fb
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Creative Commons Data.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Data Analyst.png b/app/assets/images/icons/Open Data/OD_Data Analyst.png
new file mode 100644
index 00000000..8a9957ae
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Data Analyst.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Data Mining.png b/app/assets/images/icons/Open Data/OD_Data Mining.png
new file mode 100644
index 00000000..dd192bee
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Data Mining.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Data Scientist.png b/app/assets/images/icons/Open Data/OD_Data Scientist.png
new file mode 100644
index 00000000..71e71194
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Data Scientist.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Data.png b/app/assets/images/icons/Open Data/OD_Data.png
new file mode 100644
index 00000000..1ae5bd38
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Data.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Database.png b/app/assets/images/icons/Open Data/OD_Database.png
new file mode 100644
index 00000000..488f460e
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Database.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Geolocation.png b/app/assets/images/icons/Open Data/OD_Geolocation.png
new file mode 100644
index 00000000..20d1474c
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Geolocation.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Government Data.png b/app/assets/images/icons/Open Data/OD_Government Data.png
new file mode 100644
index 00000000..6981733b
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Government Data.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Hacker.png b/app/assets/images/icons/Open Data/OD_Hacker.png
new file mode 100644
index 00000000..923bfe0c
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Hacker.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Map Data.png b/app/assets/images/icons/Open Data/OD_Map Data.png
new file mode 100644
index 00000000..a51bbc31
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Map Data.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Mapper.png b/app/assets/images/icons/Open Data/OD_Mapper.png
new file mode 100644
index 00000000..028d36e3
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Mapper.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Metadata.png b/app/assets/images/icons/Open Data/OD_Metadata.png
new file mode 100644
index 00000000..5ab2065a
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Metadata.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Open Data.png b/app/assets/images/icons/Open Data/OD_Open Data.png
new file mode 100644
index 00000000..51ad11f9
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Open Data.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Open Innovation.png b/app/assets/images/icons/Open Data/OD_Open Innovation.png
new file mode 100644
index 00000000..d75b4aa9
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Open Innovation.png differ
diff --git a/app/assets/images/icons/Open Data/OD_Startup.png b/app/assets/images/icons/Open Data/OD_Startup.png
new file mode 100644
index 00000000..53845979
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_Startup.png differ
diff --git a/app/assets/images/icons/Open Data/OD_algorithm.png b/app/assets/images/icons/Open Data/OD_algorithm.png
new file mode 100644
index 00000000..1b5cbee7
Binary files /dev/null and b/app/assets/images/icons/Open Data/OD_algorithm.png differ
diff --git a/app/assets/images/linkedmedia.png b/app/assets/images/linkedmedia.png
deleted file mode 100755
index 2009b7a3..00000000
Binary files a/app/assets/images/linkedmedia.png and /dev/null differ
diff --git a/app/assets/images/missing-map.png b/app/assets/images/missing-map.png
index 5a51221a..54cbd843 100644
Binary files a/app/assets/images/missing-map.png and b/app/assets/images/missing-map.png differ
diff --git a/app/assets/images/screenshot_sprite.png b/app/assets/images/screenshot_sprite.png
new file mode 100644
index 00000000..d3c87c5a
Binary files /dev/null and b/app/assets/images/screenshot_sprite.png differ
diff --git a/app/assets/images/synapse32padded.png b/app/assets/images/synapse32padded.png
new file mode 100644
index 00000000..09e52fc0
Binary files /dev/null and b/app/assets/images/synapse32padded.png differ
diff --git a/app/assets/images/synapsestar.png b/app/assets/images/synapsestar.png
deleted file mode 100755
index ba9a7dd3..00000000
Binary files a/app/assets/images/synapsestar.png and /dev/null differ
diff --git a/app/assets/images/topic_description_signifier.png b/app/assets/images/topic_description_signifier.png
new file mode 100644
index 00000000..956db0a3
Binary files /dev/null and b/app/assets/images/topic_description_signifier.png differ
diff --git a/app/assets/images/topic_link_signifier.png b/app/assets/images/topic_link_signifier.png
new file mode 100644
index 00000000..a8b8b8e5
Binary files /dev/null and b/app/assets/images/topic_link_signifier.png differ
diff --git a/app/assets/javascripts/src/JIT.js b/app/assets/javascripts/src/JIT.js
index 743a7eef..498183ef 100644
--- a/app/assets/javascripts/src/JIT.js
+++ b/app/assets/javascripts/src/JIT.js
@@ -1,6 +1,3 @@
-
-var requestAnimId;
-
/*
Copyright (c) 2011 Sencha Inc. - Author: Nicolas Garcia Belmonte (http://philogb.github.com/)
diff --git a/app/assets/javascripts/src/Metamaps.JIT.js b/app/assets/javascripts/src/Metamaps.JIT.js
index faf895f2..88436a80 100644
--- a/app/assets/javascripts/src/Metamaps.JIT.js
+++ b/app/assets/javascripts/src/Metamaps.JIT.js
@@ -20,19 +20,26 @@ Metamaps.JIT = {
$(".zoomIn").click(self.zoomIn);
$(".zoomOut").click(self.zoomOut);
- $(".zoomExtents").click(self.zoomExtents);
- self.synapseStarImage = new Image();
- self.synapseStarImage.src = '/assets/synapsestar.png';
+ var zoomExtents = function (event) {
+ self.zoomExtents(event, Metamaps.Visualize.mGraph.canvas);
+ };
+ $(".zoomExtents").click(zoomExtents);
- self.topicMediaImage = new Image();
- self.topicMediaImage.src = '/assets/linkedmedia.png';
+ $(".takeScreenshot").click(Metamaps.Map.exportImage);
+
+ self.topicDescImage = new Image();
+ self.topicDescImage.src = '/assets/topic_description_signifier.png';
+
+ self.topicLinkImage = new Image();
+ self.topicLinkImage.src = '/assets/topic_link_signifier.png';
},
/**
* 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;
@@ -42,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);
}
@@ -83,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;
}
@@ -123,24 +140,45 @@ Metamaps.JIT = {
var directionCat = synapse.get("category");
//label placement on edges
- Metamaps.JIT.renderEdgeArrows($jit.Graph.Plot.edgeHelper, adj, synapse);
+ if (canvas.denySelected) {
+ var color = Metamaps.Settings.colors.synapses.normal;
+ canvas.getCtx().fillStyle = canvas.getCtx().strokeStyle = color;
+ }
+ Metamaps.JIT.renderEdgeArrows($jit.Graph.Plot.edgeHelper, adj, synapse, canvas);
//check for edge label in data
var desc = synapse.get("desc");
var showDesc = adj.getData("showDesc");
- var drawStar = function (context, x, y) {
- var starImage = Metamaps.JIT.synapseStarImage;
- var starImageLoaded = starImage.complete ||
- (typeof starImage.naturalWidth !== "undefined" &&
- starImage.naturalWidth !== 0)
- if (starImageLoaded) {
- context.drawImage(starImage, x, y, 16, 16);
- }
+ var drawSynapseCount = function (context, x, y, count) {
+ /*
+ circle size: 16x16px
+ positioning: overlay and center on top right corner of synapse label - 8px left and 8px down
+ color: #dab539
+ border color: #424242
+ border size: 1.5px
+ font: DIN medium
+ font-size: 14pt
+ font-color: #424242
+ */
+ context.beginPath();
+ context.arc(x, y, 8, 0, 2 * Math.PI, false);
+ context.fillStyle = '#DAB539';
+ context.strokeStyle = '#424242';
+ context.lineWidth = 1.5;
+ context.closePath();
+ context.fill();
+ context.stroke();
+
+ // add the synapse count
+ context.fillStyle = '#424242';
+ context.textAlign = 'center';
+ context.font = '14px din-medium';
+ context.fillText(count, x, y - 6);
};
- if (desc != "" && showDesc) {
+ if (!canvas.denySelected && desc != "" && showDesc) {
// '&' to '&'
desc = Metamaps.Util.decodeEntities(desc);
@@ -155,7 +193,7 @@ Metamaps.JIT = {
for (index = 0; index < arrayOfLabelLines.length; ++index) {
lineWidths.push(ctx.measureText(arrayOfLabelLines[index]).width)
}
- var width = Math.max.apply(null, lineWidths) + 8;
+ var width = Math.max.apply(null, lineWidths) + 16;
var height = (16 * arrayOfLabelLines.length) + 8;
var x = (pos.x + posChild.x - width) / 2;
@@ -177,23 +215,29 @@ Metamaps.JIT = {
ctx.closePath();
ctx.fill();
+ // get number of synapses
+ var synapseNum = adj.getData("synapses").length;
+
//render text
- ctx.fillStyle = '#222222';
+ ctx.fillStyle = '#424242';
ctx.textAlign = 'center';
for (index = 0; index < arrayOfLabelLines.length; ++index) {
- ctx.fillText(arrayOfLabelLines[index], x + (width / 2), y + 5 + (16 * index));
+ ctx.fillText(arrayOfLabelLines[index], x + (width / 2), y + 7 + (16 * index));
}
- if (adj.getData("synapses").length > 1) {
- drawStar(ctx, x + width, y);
+ if (synapseNum > 1) {
+ drawSynapseCount(ctx, x + width, y, synapseNum);
}
}
- else if (showDesc) {
- if (adj.getData("synapses").length > 1) {
+ else if (!canvas.denySelected && showDesc) {
+ // get number of synapses
+ var synapseNum = adj.getData("synapses").length;
+
+ if (synapseNum > 1) {
var ctx = canvas.getCtx();
var x = (pos.x + posChild.x) / 2;
var y = (pos.y + posChild.y) / 2;
- drawStar(ctx, x, y);
+ drawSynapseCount(ctx, x, y, synapseNum);
}
}
@@ -400,7 +444,7 @@ Metamaps.JIT = {
ctx = canvas.getCtx();
// if the topic is selected draw a circle around it
- if (node.selected) {
+ if (!canvas.denySelected && node.selected) {
ctx.beginPath();
ctx.arc(pos.x, pos.y, dim + 3, 0, 2 * Math.PI, false);
ctx.strokeStyle = Metamaps.Settings.colors.topics.selected;
@@ -423,12 +467,22 @@ Metamaps.JIT = {
// if the topic has a link, draw a small image to indicate that
var hasLink = topic && topic.get('link') !== "" && topic.get('link') !== null;
- var linkImage = Metamaps.JIT.topicMediaImage;
+ var linkImage = Metamaps.JIT.topicLinkImage;
var linkImageLoaded = linkImage.complete ||
(typeof linkImage.naturalWidth !== "undefined" &&
linkImage.naturalWidth !== 0)
if (hasLink && linkImageLoaded) {
- ctx.drawImage(linkImage, pos.x + dim / 2, pos.y - dim - 8, 16, 16);
+ ctx.drawImage(linkImage, pos.x - dim - 8, pos.y - dim - 8, 16, 16);
+ }
+
+ // if the topic has a desc, draw a small image to indicate that
+ var hasDesc = topic && topic.get('desc') !== "" && topic.get('desc') !== null;
+ var descImage = Metamaps.JIT.topicDescImage;
+ var descImageLoaded = descImage.complete ||
+ (typeof descImage.naturalWidth !== "undefined" &&
+ descImage.naturalWidth !== 0)
+ if (hasDesc && descImageLoaded) {
+ ctx.drawImage(descImage, pos.x + dim - 8, pos.y - dim - 8, 16, 16);
}
},
'contains': function (node, pos) {
@@ -469,7 +523,7 @@ Metamaps.JIT = {
if (-1 < pos.x && pos.x < 1) pos.x = 0;
if (-1 < pos.y && pos.y < 1) pos.y = 0;
- return $jit.Graph.Plot.edgeHelper.line.contains(from, to, pos, adj.Edge.epsilon);
+ return $jit.Graph.Plot.edgeHelper.line.contains(from, to, pos, adj.Edge.epsilon + 5);
}
}
}
@@ -865,6 +919,9 @@ Metamaps.JIT = {
};
}
}
+ else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && Metamaps.Active.Topic) {
+ Metamaps.GlobalUI.notifyUser("Cannot create in Topic view.");
+ }
else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && !authorized) {
Metamaps.GlobalUI.notifyUser("Cannot edit Public map.");
}
@@ -959,6 +1016,10 @@ Metamaps.JIT = {
Metamaps.GlobalUI.notifyUser("Cannot edit Public map.");
return;
}
+ else if (Metamaps.Active.Topic) {
+ Metamaps.GlobalUI.notifyUser("Cannot create in Topic view.");
+ return;
+ }
// DOUBLE CLICK
//pop up node creation :)
Metamaps.Create.newTopic.addSynapse = false;
@@ -1269,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
\
@@ -1283,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;
@@ -1376,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;
@@ -1595,12 +1730,10 @@ Metamaps.JIT = {
ctx.lineTo(v2.x, v2.y);
ctx.stroke();
}, // renderMidArrow
- renderEdgeArrows: function (edgeHelper, adj, synapse) {
+ renderEdgeArrows: function (edgeHelper, adj, synapse, canvas) {
var self = Metamaps.JIT;
- var canvas = Metamaps.Visualize.mGraph.canvas;
-
var directionCat = synapse.get('category');
var direction = synapse.getDirection();
@@ -1657,8 +1790,7 @@ Metamaps.JIT = {
Metamaps.Visualize.mGraph.canvas.scale(0.8,0.8);
$(document).trigger(Metamaps.JIT.events.zoom, [event]);
},
- centerMap: function () {
- var canvas = Metamaps.Visualize.mGraph.canvas;
+ centerMap: function (canvas) {
var offsetScale = canvas.scaleOffsetX;
canvas.scale(1/offsetScale,1/offsetScale);
@@ -1674,7 +1806,8 @@ Metamaps.JIT = {
eX = Metamaps.Mouse.boxEndCoordinates.x,
eY = Metamaps.Mouse.boxEndCoordinates.y;
- Metamaps.JIT.centerMap();
+ var canvas = Metamaps.Visualize.mGraph.canvas;
+ Metamaps.JIT.centerMap(canvas);
var height = $(document).height(),
width = $(document).width();
@@ -1686,8 +1819,6 @@ Metamaps.JIT = {
var newRatio = Math.min(ratioX,ratioY);
- var canvas = Metamaps.Visualize.mGraph.canvas;
-
if(canvas.scaleOffsetX *newRatio<= 5 && canvas.scaleOffsetX*newRatio >= 0.2){
canvas.scale(newRatio,newRatio);
}
@@ -1711,15 +1842,14 @@ Metamaps.JIT = {
Metamaps.Visualize.mGraph.plot();
},
- zoomExtents: function (event) {
- Metamaps.JIT.centerMap();
- var height = $(document).height(),
- width = $(document).width(),
+ zoomExtents: function (event, canvas, denySelected) {
+ Metamaps.JIT.centerMap(canvas);
+ var height = canvas.getSize().height,
+ width = canvas.getSize().width,
maxX, minX, maxY, minY, counter = 0;
- var canvas = Metamaps.Visualize.mGraph.canvas;
- if (Metamaps.Selected.Nodes.length > 0) {
+ if (!denySelected && Metamaps.Selected.Nodes.length > 0) {
var nodes = Metamaps.Selected.Nodes;
}
else {
diff --git a/app/assets/javascripts/src/Metamaps.Router.js b/app/assets/javascripts/src/Metamaps.Router.js
index aa4fa338..466326d2 100644
--- a/app/assets/javascripts/src/Metamaps.Router.js
+++ b/app/assets/javascripts/src/Metamaps.Router.js
@@ -125,7 +125,7 @@
if (Metamaps.Visualize.mGraph) {
Metamaps.Visualize.mGraph.graph.empty();
Metamaps.Visualize.mGraph.plot();
- Metamaps.JIT.centerMap();
+ Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas);
}
Metamaps.Famous.viz.show();
Metamaps.Topic.end();
@@ -156,7 +156,7 @@
if (Metamaps.Visualize.mGraph) {
Metamaps.Visualize.mGraph.graph.empty();
Metamaps.Visualize.mGraph.plot();
- Metamaps.JIT.centerMap();
+ Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas);
}
Metamaps.Famous.viz.show();
Metamaps.Map.end();
diff --git a/app/assets/javascripts/src/Metamaps.js b/app/assets/javascripts/src/Metamaps.js
index 0591b7d6..9f82b40e 100644
--- a/app/assets/javascripts/src/Metamaps.js
+++ b/app/assets/javascripts/src/Metamaps.js
@@ -82,6 +82,7 @@ Metamaps.Backbone.init = function () {
self.Metacode = Backbone.Model.extend({
initialize: function () {
var image = new Image();
+ image.crossOrigin = "Anonymous";
image.src = this.get('icon');
this.set('image',image);
},
@@ -218,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();
@@ -476,6 +476,9 @@ Metamaps.Backbone.init = function () {
Metamaps.Mappers = Metamaps.Mappers ? new self.MapperCollection(Metamaps.Mappers) : new self.MapperCollection();
+ // this is for topic view
+ Metamaps.Creators = Metamaps.Creators ? new self.MapperCollection(Metamaps.Creators) : new self.MapperCollection();
+
if (Metamaps.Active.Map) {
Metamaps.Mappings = Metamaps.Mappings ? new self.MappingCollection(Metamaps.Mappings) : new self.MappingCollection();
@@ -1504,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 });
@@ -3150,12 +3155,30 @@ Metamaps.Filter = {
var removed = [];
var added = [];
- Metamaps[collection].each(function(model) {
- var prop = model.get(propertyToCheck) ? model.get(propertyToCheck).toString() : false;
- if (prop && newList.indexOf(prop) === -1) {
- newList.push(prop);
- }
- });
+ // the first option enables us to accept
+ // ['Topics', 'Synapses'] as 'collection'
+ if (typeof collection === "object") {
+ Metamaps[collection[0]].each(function(model) {
+ var prop = model.get(propertyToCheck) ? model.get(propertyToCheck).toString() : false;
+ if (prop && newList.indexOf(prop) === -1) {
+ newList.push(prop);
+ }
+ });
+ Metamaps[collection[1]].each(function(model) {
+ var prop = model.get(propertyToCheck) ? model.get(propertyToCheck).toString() : false;
+ if (prop && newList.indexOf(prop) === -1) {
+ newList.push(prop);
+ }
+ });
+ }
+ else if (typeof collection === "string") {
+ Metamaps[collection].each(function(model) {
+ var prop = model.get(propertyToCheck) ? model.get(propertyToCheck).toString() : false;
+ if (prop && newList.indexOf(prop) === -1) {
+ newList.push(prop);
+ }
+ });
+ }
removed = _.difference(self.filters[filtersToUse], newList);
added = _.difference(newList, self.filters[filtersToUse]);
@@ -3198,7 +3221,14 @@ Metamaps.Filter = {
},
checkMappers: function () {
var self = Metamaps.Filter;
- self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper');
+ var onMap = Metamaps.Active.Map ? true : false;
+ if (onMap) {
+ self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper');
+ }
+ else {
+ // on topic view
+ self.updateFilters(['Topics', 'Synapses'], 'user_id', 'Creators', 'mappers', 'mapper');
+ }
},
checkSynapses: function () {
var self = Metamaps.Filter;
@@ -3279,7 +3309,11 @@ Metamaps.Filter = {
if (Metamaps.Active.Map) {
onMap = true;
}
- else passesMapper = true; // for when you're on a topic page
+ else if (Metamaps.Active.Topic) {
+ onMap = false;
+ }
+
+ var opacityForFilter = onMap ? 0 : 0.4;
Metamaps.Topics.each(function(topic) {
var n = topic.get('node');
@@ -3289,10 +3323,21 @@ Metamaps.Filter = {
else passesMetacode = true;
if (onMap) {
+ // when on a map,
+ // we filter by mapper according to the person who added the
+ // topic or synapse to the map
var user_id = topic.getMapping().get("user_id").toString();
if (visible.mappers.indexOf(user_id) == -1) passesMapper = false;
else passesMapper = true;
}
+ else {
+ // when on a topic view,
+ // we filter by mapper according to the person who created the
+ // topic or synapse
+ var user_id = topic.get("user_id").toString();
+ if (visible.mappers.indexOf(user_id) == -1) passesMapper = false;
+ else passesMapper = true;
+ }
if (passesMetacode && passesMapper) {
if (n) {
@@ -3303,7 +3348,7 @@ Metamaps.Filter = {
else {
if (n) {
Metamaps.Control.deselectNode(n, true);
- n.setData('alpha', 0, 'end');
+ n.setData('alpha', opacityForFilter, 'end');
n.eachAdjacency(function(e){
Metamaps.Control.deselectEdge(e, true);
});
@@ -3320,10 +3365,13 @@ Metamaps.Filter = {
else passesSynapse = true;
if (onMap) {
- var user_id = synapse.getMapping().get("user_id").toString();
- if (visible.mappers.indexOf(user_id) == -1) passesMapper = false;
- else passesMapper = true;
+ // when on a map,
+ // we filter by mapper according to the person who added the
+ // topic or synapse to the map
+ user_id = synapse.getMapping().get("user_id").toString();
}
+ if (visible.mappers.indexOf(user_id) == -1) passesMapper = false;
+ else passesMapper = true;
var color = Metamaps.Settings.colors.synapses.normal;
if (passesSynapse && passesMapper) {
@@ -3336,10 +3384,10 @@ Metamaps.Filter = {
else {
if (e) {
Metamaps.Control.deselectEdge(e, true);
- e.setData('alpha', 0, 'end');
+ e.setData('alpha', opacityForFilter, 'end');
}
else console.log(synapse);
- }
+ }
});
// run the animation
@@ -3389,7 +3437,7 @@ Metamaps.Listeners = {
case 69: //if e or E is pressed
if (e.ctrlKey){
e.preventDefault();
- Metamaps.JIT.zoomExtents();
+ Metamaps.JIT.zoomExtents(null, Metamaps.Visualize.mGraph.canvas);
}
break;
case 77: //if m or M is pressed
@@ -3590,10 +3638,14 @@ Metamaps.Topic = {
var bb = Metamaps.Backbone;
var start = function (data) {
Metamaps.Active.Topic = new bb.Topic(data.topic);
+ Metamaps.Creators = new bb.MapperCollection(data.creators);
Metamaps.Topics = new bb.TopicCollection([data.topic].concat(data.relatives));
Metamaps.Synapses = new bb.SynapseCollection(data.synapses);
Metamaps.Backbone.attachCollectionEvents();
+ // set filter mapper H3 text
+ $('#filter_by_mapper h3').html('CREATORS');
+
// build and render the visualization
Metamaps.Visualize.type = "RGraph";
Metamaps.JIT.prepareVizData();
@@ -3620,12 +3672,12 @@ Metamaps.Topic = {
$('.rightclickmenu').remove();
Metamaps.TopicCard.hideCard();
Metamaps.SynapseCard.hideCard();
+ Metamaps.Filter.close();
}
},
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 () {
@@ -3634,6 +3686,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 () {
+
+ }
+ });
+ },
/*
*
*
@@ -4048,6 +4160,9 @@ Metamaps.Map = {
$('.wrapper').addClass('commonsMap');
}
+ // set filter mapper H3 text
+ $('#filter_by_mapper h3').html('MAPPERS');
+
// build and render the visualization
Metamaps.Visualize.type = "ForceDirected";
Metamaps.JIT.prepareVizData();
@@ -4086,6 +4201,7 @@ Metamaps.Map = {
Metamaps.SynapseCard.hideCard();
Metamaps.Create.newTopic.hide();
Metamaps.Create.newSynapse.hide();
+ Metamaps.Filter.close();
Metamaps.Realtime.endActiveMap();
}
},
@@ -4094,31 +4210,37 @@ Metamaps.Map = {
var nodes_data = "",
synapses_data = "";
- var synapses_array = new Array();
+ var nodes_array = [];
+ var synapses_array = [];
+ // collect the unfiltered topics
Metamaps.Visualize.mGraph.graph.eachNode(function (n) {
- //don't add to the map if it was filtered out
- // TODO
- //if (categoryVisible[n.getData('metacode')] == false) {
- // return;
- //}
-
- var x, y;
- if (n.pos.x && n.pos.y) {
- x = n.pos.x;
- y = n.pos.y;
- } else {
- var x = Math.cos(n.pos.theta) * n.pos.rho;
- var y = Math.sin(n.pos.theta) * n.pos.rho;
+ // if the opacity is less than 1 then it's filtered
+ if (n.getData('alpha') === 1) {
+ var id = n.getData('topic').id;
+ nodes_array.push(id);
+ var x, y;
+ if (n.pos.x && n.pos.y) {
+ x = n.pos.x;
+ y = n.pos.y;
+ } else {
+ var x = Math.cos(n.pos.theta) * n.pos.rho;
+ var y = Math.sin(n.pos.theta) * n.pos.rho;
+ }
+ nodes_data += id + '/' + x + '/' + y + ',';
}
- nodes_data += n.id + '/' + x + '/' + y + ',';
- n.eachAdjacency(function (adj) {
- synapses_array.push(adj.getData("synapses")[0].id); // TODO
- });
});
+ // collect the unfiltered synapses
+ Metamaps.Synapses.each(function(synapse){
+ var desc = synapse.get("desc");
- //get unique values only
- synapses_array = $.grep(synapses_array, function (value, key) {
- return $.inArray(value, synapses_array) === key;
+ var descNotFiltered = Metamaps.Filter.visible.synapses.indexOf(desc) > -1;
+ // make sure that both topics are being added, otherwise, it
+ // doesn't make sense to add the synapse
+ var topicsNotFiltered = nodes_array.indexOf(synapse.get('node1_id')) > -1;
+ topicsNotFiltered = topicsNotFiltered && nodes_array.indexOf(synapse.get('node2_id')) > -1;
+ if (descNotFiltered && topicsNotFiltered) {
+ synapses_array.push(synapse.id);
+ }
});
synapses_data = synapses_array.join();
@@ -4209,6 +4331,131 @@ Metamaps.Map = {
Metamaps.Map.sideLength = 1;
Metamaps.Map.timeToTurn = 0;
Metamaps.Map.turnCount = 0;
+ },
+ exportImage: function() {
+
+ var canvas = {};
+
+ canvas.canvas = document.createElement("canvas");
+ canvas.canvas.width = 1880; // 960;
+ canvas.canvas.height = 1260; // 630
+
+ canvas.scaleOffsetX = 1;
+ canvas.scaleOffsetY = 1;
+ canvas.translateOffsetY = 0;
+ canvas.translateOffsetX = 0;
+ canvas.denySelected = true;
+
+ canvas.getSize = function() {
+ if(this.size) return this.size;
+ var canvas = this.canvas;
+ return this.size = {
+ width: canvas.width,
+ height: canvas.height
+ };
+ };
+ canvas.scale = function(x, y) {
+ var px = this.scaleOffsetX * x,
+ py = this.scaleOffsetY * y;
+ var dx = this.translateOffsetX * (x -1) / px,
+ dy = this.translateOffsetY * (y -1) / py;
+ this.scaleOffsetX = px;
+ this.scaleOffsetY = py;
+ this.getCtx().scale(x, y);
+ this.translate(dx, dy);
+ };
+ canvas.translate = function(x, y) {
+ var sx = this.scaleOffsetX,
+ sy = this.scaleOffsetY;
+ this.translateOffsetX += x*sx;
+ this.translateOffsetY += y*sy;
+ this.getCtx().translate(x, y);
+ };
+ canvas.getCtx = function() {
+ return this.canvas.getContext("2d");
+ };
+ // center it
+ canvas.getCtx().translate(1880/2, 1260/2);
+
+ var mGraph = Metamaps.Visualize.mGraph;
+
+ var id = mGraph.root;
+ var root = mGraph.graph.getNode(id);
+ var T = !!root.visited;
+
+ // pass true to avoid basing it on a selection
+ Metamaps.JIT.zoomExtents(null, canvas, true);
+
+ var c = canvas.canvas,
+ ctx = canvas.getCtx(),
+ scale = canvas.scaleOffsetX;
+
+ // draw a grey background
+ ctx.fillStyle = '#d8d9da';
+ var xPoint = (-(c.width/scale)/2) - (canvas.translateOffsetX/scale),
+ yPoint = (-(c.height/scale)/2) - (canvas.translateOffsetY/scale);
+ ctx.fillRect(xPoint,yPoint,c.width/scale,c.height/scale);
+
+ // draw the graph
+ mGraph.graph.eachNode(function(node) {
+ var nodeAlpha = node.getData('alpha');
+ node.eachAdjacency(function(adj) {
+ var nodeTo = adj.nodeTo;
+ if(!!nodeTo.visited === T && node.drawn && nodeTo.drawn) {
+ mGraph.fx.plotLine(adj, canvas);
+ }
+ });
+ if(node.drawn) {
+ mGraph.fx.plotNode(node, canvas);
+ }
+ if(!mGraph.labelsHidden) {
+ if(node.drawn && nodeAlpha >= 0.95) {
+ mGraph.labels.plotLabel(canvas, node);
+ } else {
+ mGraph.labels.hideLabel(node, false);
+ }
+ }
+ node.visited = !T;
+ });
+
+ var imageData = {
+ encoded_image: canvas.canvas.toDataURL()
+ };
+
+ console.log(imageData.encoded_image);
+ var map = Metamaps.Active.Map;
+
+ var today = new Date();
+ var dd = today.getDate();
+ var mm = today.getMonth()+1; //January is 0!
+ var yyyy = today.getFullYear();
+ if(dd<10) {
+ dd='0'+dd
+ }
+ if(mm<10) {
+ mm='0'+mm
+ }
+ today = mm+'/'+dd+'/'+yyyy;
+
+ var mapName = map.get("name").split(" ").join([separator = '-']);
+ var downloadMessage = "";
+ downloadMessage += "Captured map screenshot! ";
+ downloadMessage += "DOWNLOAD";
+ Metamaps.GlobalUI.notifyUser(downloadMessage);
+
+ $.ajax({
+ type: "POST",
+ dataType: 'json',
+ url: "/maps/" + Metamaps.Active.Map.id + "/upload_screenshot",
+ data: imageData,
+ success: function (data) {
+ console.log('successfully uploaded map screenshot');
+ },
+ error: function () {
+ console.log('failed to save map screenshot');
+ }
+ });
}
};
@@ -4559,8 +4806,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 e925ad4c..1c72ee8e 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -519,19 +519,19 @@ input[type="submit"]:active {
#new_topic .twitter-typeahead {
position: absolute !important;
- top: 40px;
- left: 35px;
+ top: 45px;
+ left: 41px;
z-index: 9999;
- width: 270px;
+ width: 256px;
height: 42px;
}
.new_topic #topic_name,
.new_topic .tt-hint {
- width: 254px;
+ width: 244px;
background: #FFFFFF;
height: 14px;
margin: 0;
- padding: 14px 8px;
+ padding: 10px 6px;
border: none;
border-radius: 2px;
outline: none;
@@ -581,11 +581,11 @@ input[type="submit"]:active {
}
.new_synapse #synapse_desc,
.new_synapse .tt-hint {
- width: 254px;
+ width: 244px;
background: #FFFFFF;
height: 14px;
margin: 0;
- padding: 14px 8px;
+ padding: 10px 6px;
border: none;
border-radius: 2px;
outline: none;
@@ -1170,8 +1170,9 @@ h3.realtimeBoxTitle {
.rightclickmenu {
position: absolute;
- width: 300px;
+ width: 260px;
background: #FFFFFF;
+ padding: 6px 0px 6px 0px;
z-index: 20;
border-radius: 2px;
color: black;
@@ -1184,8 +1185,8 @@ h3.realtimeBoxTitle {
list-style: none;
padding: 6px 10px 6px 32px;
font-family: helvetica, sans-serif;
- font-size: 12px;
- line-height: 12px;
+ font-size: 13px;
+ line-height: 15px;
position: relative;
}
.rightclickmenu li:hover {
@@ -1219,7 +1220,7 @@ h3.realtimeBoxTitle {
}
.rightclickmenu .rc-center .rc-icon {
-
+ background-image: url(context_topicview_sprite.png);
}
.rightclickmenu .rc-popout .rc-icon {
background-position: 0 -72px;
@@ -1230,6 +1231,10 @@ h3.realtimeBoxTitle {
.rightclickmenu .rc-metacode .rc-icon {
background-position: 0 -120px;
}
+.rightclickmenu .rc-siblings .rc-icon {
+ background-position: 0 -24px;
+ background-image: url(context_topicview_sprite.png);
+}
.rightclickmenu .expandLi {
position: absolute;
top: 4px;
@@ -1243,7 +1248,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;
@@ -1254,7 +1261,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 {
@@ -1282,20 +1291,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;
}
@@ -1314,15 +1327,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 */
@@ -1337,7 +1359,7 @@ float: left;
#new_topic .tt-suggestion,
#new_synapse .tt-suggestion {
background: #F5F5F5;
- width: 270px;
+ width: 256px;
position: relative;
}
#new_topic .autocompleteSection {
@@ -1606,7 +1628,7 @@ float: left;
background-position: 13px center;
}
.mapSynapses {
- background-image: url(synapse32.png);
+ background-image: url(synapse32padded.png);
background-position: 13px center;
}
.mapInfoBox .mapPermission {
@@ -1671,7 +1693,7 @@ float: left;
.mapInfoBox .mapInfoDesc {
font-family: helvetica, sans-serif;
color: #E0E0E0;
- margin: 8px;
+ margin: 16px;
padding-right: 16px;
height: 115px;
font-size: 14px;
diff --git a/app/assets/stylesheets/base.css b/app/assets/stylesheets/base.css
index 6cfa3d69..b894b317 100644
--- a/app/assets/stylesheets/base.css
+++ b/app/assets/stylesheets/base.css
@@ -110,7 +110,7 @@
display:block;
padding: 8px 0 8px 16px;
height: 152px;
- font-size: 12px;
+ font-size: 13px;
line-height:15px;
font-family: helvetica, sans-serif;
overflow-y: auto;
@@ -120,7 +120,7 @@
}
.CardOnGraph .best_in_place_desc textarea {
- font-size: 12px;
+ font-size: 13px;
line-height:15px;
font-family: helvetica, sans-serif;
color: #424242;
@@ -170,8 +170,8 @@ resize: none;
z-index: 1;
position: relative;
color: #424242;
- font-size: 12px;
- line-height:12px;
+ font-size: 14px;
+ line-height:14px;
height:12px;
padding:17px 0;
}
@@ -187,9 +187,9 @@ resize: none;
height: 48px;
}
.linkItem.contributor {
- margin-left:32px;
+ margin-left:40px;
z-index:1;
- padding:17px 16px 17px 32px;
+ padding:17px 16px 17px 30px;
position: relative;
}
.contributor .contributorIcon {
@@ -202,8 +202,9 @@ resize: none;
display:none;
}
.linkItem.mapCount {
+ margin-left: 12px;
width: 24px;
- padding:17px 0 17px 35px;
+ padding:17px 0 17px 36px;
}
.linkItem.mapCount .mapCountIcon {
position: absolute;
@@ -219,8 +220,9 @@ resize: none;
background-position: 0 -32px;
}
.linkItem.synapseCount {
+ margin-left: 2px;
width: 24px;
- padding:17px 0 17px 35px;
+ padding:17px 0 17px 32px;
}
.linkItem.synapseCount .synapseCountIcon {
position: absolute;
@@ -241,6 +243,7 @@ resize: none;
padding: 0;
min-width: 32px;
margin-top: 8px;
+ margin-left: 8px;
background-image: url(permissions32_sprite.png);
background-position: 0 0;
}
@@ -507,6 +510,8 @@ background-color: #E0E0E0;
width: 268px;
padding: 8px 16px 8px 16px;
position: relative;
+ border: none;
+ line-height: 14px;
}
#addLinkInput input{
diff --git a/app/assets/stylesheets/clean.css b/app/assets/stylesheets/clean.css
index 521f70c6..db90dd04 100644
--- a/app/assets/stylesheets/clean.css
+++ b/app/assets/stylesheets/clean.css
@@ -191,7 +191,7 @@
.explorePage .sidebarSearchField,
.explorePage .sidebarSearch .tt-hint {
width: 380px;
- padding: 7px 10px 3px 10px;
+ padding: 5px 10px 5px 10px;
}
.sidebarSearchField {
@@ -207,7 +207,7 @@
border-bottom: 1px solid #BDBDBD;
border-left: none;
border-right: none;
- padding: 7px 0 3px 0;
+ padding: 5px 0 5px 0;
width: 0px;
margin: 0;
outline: none;
@@ -218,7 +218,7 @@
}
.sidebarSearch .tt-dropdown-menu {
top: 40px !important;
- background: #FFF;
+ background: #F5F5F5;
width: 472px;
overflow-y: auto;
overflow-x: hidden;
@@ -577,7 +577,7 @@
top: 0;
}
-.topicPage .sidebarCollaborate, .topicPage .sidebarFilter {
+.topicPage .sidebarCollaborate {
display: none;
}
@@ -767,6 +767,20 @@
.mapControls:hover, .infoAndHelp:hover {
z-index: 4;
}
+
+.takeScreenshot {
+ margin-bottom: 5px;
+ border-radius: 2px;
+ background-image: url(screenshot_sprite.png);
+ display: none;
+}
+.takeScreenshot:hover {
+ background-position: -32px 0;
+}
+.canEditMap .takeScreenshot {
+ display: block;
+}
+
.zoomExtents {
margin-bottom:5px;
border-radius: 2px;
@@ -1026,6 +1040,10 @@
line-height:14px;
}
+.toast a {
+ color: #4fc059;
+}
+
/* end toast */
/* feedback */
diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb
index 0fbad24b..58f778d9 100644
--- a/app/controllers/maps_controller.rb
+++ b/app/controllers/maps_controller.rb
@@ -1,6 +1,6 @@
class MapsController < ApplicationController
- before_filter :require_user, only: [:create, :update, :destroy]
+ before_filter :require_user, only: [:create, :update, :screenshot, :destroy]
respond_to :html, :json
@@ -83,7 +83,14 @@ class MapsController < ApplicationController
@allmappers = @map.contributors
@alltopics = @map.topics.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) }
@allsynapses = @map.synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
- @allmappings = @map.mappings
+ @allmappings = @map.mappings.delete_if {|m|
+ if m.category == "Synapse"
+ object = m.synapse
+ elsif m.category == "Topic"
+ object = m.topic
+ end
+ !object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id)))
+ }
respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map)
}
@@ -104,7 +111,14 @@ class MapsController < ApplicationController
@allmappers = @map.contributors
@alltopics = @map.topics.delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) }
@allsynapses = @map.synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
- @allmappings = @map.mappings
+ @allmappings = @map.mappings.delete_if {|m|
+ if m.category == "Synapse"
+ object = m.synapse
+ elsif m.category == "Topic"
+ object = m.topic
+ end
+ !object || (object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id)))
+ }
@json = Hash.new()
@json['map'] = @map
@@ -183,6 +197,30 @@ class MapsController < ApplicationController
end
end
+ # POST maps/:id/upload_screenshot
+ def screenshot
+ @current = current_user
+ @map = Map.find(params[:id]).authorize_to_edit(@current)
+
+ if @map
+ png = Base64.decode64(params[:encoded_image]['data:image/png;base64,'.length .. -1])
+ StringIO.open(png) do |data|
+ data.class.class_eval { attr_accessor :original_filename, :content_type }
+ data.original_filename = "map-" + @map.id.to_s + "-screenshot.png"
+ data.content_type = "image/png"
+ @map.screenshot = data
+ end
+
+ if @map.save
+ render :json => {:message => "Successfully uploaded the map screenshot."}
+ else
+ render :json => {:message => "Failed to upload image."}
+ end
+ else
+ render :json => {:message => "Unauthorized to set map screenshot."}
+ end
+ end
+
# DELETE maps/:id
def destroy
@current = current_user
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
index e63bdc04..e39b67a8 100644
--- a/app/controllers/topics_controller.rb
+++ b/app/controllers/topics_controller.rb
@@ -29,7 +29,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
respond_to do |format|
@@ -37,7 +37,19 @@ class TopicsController < ApplicationController
@alltopics = ([@topic] + @topic.relatives).delete_if {|t| t.permission == "private" && (!authenticated? || (authenticated? && @current.id != t.user_id)) } # should limit to topics visible to user
@allsynapses = @topic.synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
- respond_with(@allsynapses, @alltopics, @topic)
+ @allcreators = []
+ @alltopics.each do |t|
+ if @allcreators.index(t.user) == nil
+ @allcreators.push(t.user)
+ end
+ end
+ @allsynapses.each do |s|
+ if @allcreators.index(s.user) == nil
+ @allcreators.push(s.user)
+ end
+ end
+
+ respond_with(@allsynapses, @alltopics, @allcreators, @topic)
}
format.json { render json: @topic }
end
@@ -49,14 +61,27 @@ 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)) }
@allsynapses = @topic.synapses.delete_if {|s| s.permission == "private" && (!authenticated? || (authenticated? && @current.id != s.user_id)) }
-
+ @allcreators = []
+ @allcreators.push(@topic.user)
+ @alltopics.each do |t|
+ if @allcreators.index(t.user) == nil
+ @allcreators.push(t.user)
+ end
+ end
+ @allsynapses.each do |s|
+ if @allcreators.index(s.user) == nil
+ @allcreators.push(s.user)
+ end
+ end
+
@json = Hash.new()
@json['topic'] = @topic
+ @json['creators'] = @allcreators
@json['relatives'] = @alltopics
@json['synapses'] = @allsynapses
@@ -65,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/app/models/map.rb b/app/models/map.rb
index fcfefc81..91bc0a11 100644
--- a/app/models/map.rb
+++ b/app/models/map.rb
@@ -8,12 +8,12 @@ class Map < ActiveRecord::Base
has_many :topics, :through => :topicmappings
has_many :synapses, :through => :synapsemappings
- after_touch :save_screenshot
+ #after_touch :save_screenshot
# This method associates the attribute ":image" with a file attachment
has_attached_file :screenshot, :styles => {
- :thumb => ['188x126#', :png],
- :full => ['940x630#', :png]
+ :thumb => ['188x126#', :png]
+ #:full => ['940x630#', :png]
},
:default_url => "/assets/missing-map.png"
diff --git a/app/views/layouts/_lightboxes.html.erb b/app/views/layouts/_lightboxes.html.erb
index e745bcd9..47fbd3f0 100644
--- a/app/views/layouts/_lightboxes.html.erb
+++ b/app/views/layouts/_lightboxes.html.erb
@@ -112,19 +112,20 @@
Asana
Invision App *
Docracy *
- Google Hangouts
Google Plus *
- Hipchat
Hackpad *
Loomio *
Twitter *
+ Hipchat
+ Google Hangouts
Vimeo
Youtube
- Development
+ Design & Development
+ Github*
+ Pixelapse*
+
Documentation
- Dropbox *
- Google Drive *
@@ -158,7 +159,7 @@
Donate!
-
The Metamaps.cc project has been bootstrapped through our own pockets, lots of time, and a couple of small grants which have gone to supporting our small full-time team. Some of us have used Metamaps.cc as a tool for our own freelance consulting practice, and we are starting to create hosted and customized installations of Metamaps for different clients as one business model.
+
The Metamaps.cc project has been bootstrapped through our own pockets, passion, and patrons - including a couple of small grants which have gone to supporting our core contributors. Some of us have used Metamaps.cc as a tool for our own freelance consulting practice, and we are starting to create hosted and customized installations of Metamaps for different clients as one business model.
We will continue to bootstrap this project and experiment with alternative business models that are aligned with our values and mission and do not involve exploitation of our users, exclusivity or privatization of the technology.
@@ -188,26 +189,25 @@
+
GET INVOLVED!
-
+
-
Want to help us with design, code, community building, and communications for Metamaps? We're an open value network, which for us means we want to invite and empower peers to participate in creating value together.
+
Want to help with design, code, community building, or communications for Metamaps? We're an open value network, which for us means we want to invite and empower peers to participate in creating value together.
-
To be a user, request an invite! We'll expect you to abide by our terms of service.
+
To be a USER, request an invite! We'll expect you to abide by our terms of service.
-
To be a contributor, simply enter our space and join the conversation! We'll expect you to behave well.
+
To be a CONTRIBUTOR, simply enter our space and join the conversation! We'll expect you to follow some guidelines.
-
Members are contributors who act as stewards and guardians of the collective and are responsible for maintaining our culture and purpose. We're working on a set of agreements to formalize what it means to be a member.
+
MEMBERS are contributors who act as stewards and guardians of the collective and are responsible for maintaining our culture and purpose. We're working on a set of agreements to formalize what it means to be a member.
We welcome people of all skillsets to create value within our network. There's open possibilities for designers, researchers, academics, strategists, and facilitators to contribute. If you're a developer, help us advance the code and take a look around our Github.
Thanks for your interest in helping out with Metamaps! Hopefully this gets you pointed in the right direction to get involved. The next step is to read the links on this page and then contribute!
-
-
@@ -225,7 +225,7 @@
SHARE INVITE
-The Metamaps platform is currently in an invite-only beta with the express purpose of creating a high value knowledge ecosystem, as well as building a community of contributors. As a valued beta tester, you have the ability to invite your peers, colleagues and collaborators onto the platform.
+The Metamaps platform is currently in an invite-only beta with the express purpose of creating a high value knowledge ecosystem, as well as building an active community of contributors and healthy culture. As a valued beta tester, you have the ability to invite your peers, colleagues and collaborators onto the platform.
Copy and send the link + access code below. The access code below is your personal code and can be used multiple times.
HTTP://METAMAPS.CC/JOIN
diff --git a/app/views/layouts/_lowermapelements.html.erb b/app/views/layouts/_lowermapelements.html.erb
index 8816d905..6c41d8df 100644
--- a/app/views/layouts/_lowermapelements.html.erb
+++ b/app/views/layouts/_lowermapelements.html.erb
@@ -1,4 +1,5 @@
+
diff --git a/app/views/shared/_filterBox.html.erb b/app/views/shared/_filterBox.html.erb
index 02f69477..67a8a61e 100644
--- a/app/views/shared/_filterBox.html.erb
+++ b/app/views/shared/_filterBox.html.erb
@@ -17,22 +17,41 @@
#and metacodes is filled with all the metacodes that are being used on the map.
if @map
- @map.topics.each_with_index do |topic, index|
+ @alltopics.each_with_index do |topic, index|
if @metacodes.index(topic.metacode) == nil
@metacodes.push(topic.metacode)
end
end
- @map.synapses.each_with_index do |synapse, index|
+ @allsynapses.each_with_index do |synapse, index|
if @synapses.index{|s| s.desc == synapse.desc} == nil
@synapses.push(synapse)
end
end
- @map.mappings.each_with_index do |mapping, index|
+ @allmappings.each_with_index do |mapping, index|
if @mappers.index(mapping.user) == nil
@mappers.push(mapping.user)
end
end
+ elsif @topic
+ @alltopics.each_with_index do |topic, index|
+ if @metacodes.index(topic.metacode) == nil
+ @metacodes.push(topic.metacode)
+ end
+ if @mappers.index(topic.user) == nil
+ @mappers.push(topic.user)
+ end
+ end
+ @allsynapses.each_with_index do |synapse, index|
+ if @synapses.index{|s| s.desc == synapse.desc} == nil
+ @synapses.push(synapse)
+ end
+ if @mappers.index(synapse.user) == nil
+ @mappers.push(synapse.user)
+ end
+ end
+ end
+ if @map || @topic
@metacodes.sort! {|x,y|
n1 = x.name || ""
n2 = y.name || ""
@@ -70,7 +89,7 @@
FILTER BY
-
MAPPERS
+
<%= @map ? "MAPPERS" : @topic ? "CREATORS" : "" %>
NONE
ALL
diff --git a/app/views/topics/show.html.erb b/app/views/topics/show.html.erb
index efe18fcf..33985bc9 100644
--- a/app/views/topics/show.html.erb
+++ b/app/views/topics/show.html.erb
@@ -19,6 +19,7 @@
Metamaps.currentSection = "topic";
Metamaps.currentPage = <%= @topic.id.to_s %>;
Metamaps.Active.Topic = <%= @topic.to_json.html_safe %>;
+ Metamaps.Creators = <%= @allcreators.to_json.html_safe %>;
Metamaps.Topics = <%= @alltopics.to_json.html_safe %>;
Metamaps.Synapses = <%= @allsynapses.to_json.html_safe %>;
Metamaps.Visualize.type = "RGraph";
diff --git a/config/routes.rb b/config/routes.rb
index 5031b431..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
@@ -30,6 +32,7 @@ Metamaps::Application.routes.draw do
match 'maps/topics/:id', to: 'maps#index', via: :get, as: :topicmaps
resources :maps, except: [:new, :edit]
match 'maps/:id/contains', to: 'maps#contains', via: :get, as: :contains
+ match 'maps/:id/upload_screenshot', to: 'maps#screenshot', via: :post, as: :screenshot
devise_for :users, controllers: { registrations: 'users/registrations', passwords: 'users/passwords', sessions: 'devise/sessions' }, :skip => [:sessions]
diff --git a/public/famous/templates.js b/public/famous/templates.js
index 3575e354..d38b0edc 100644
--- a/public/famous/templates.js
+++ b/public/famous/templates.js
@@ -6,7 +6,7 @@ t.logoContent = '
METAMAPS
';
t.logoContent += '
';
t.logoContent += '- About /
';
t.logoContent += '- Colophon /
';
-t.logoContent += '- Donate!
';
+t.logoContent += '- Donate! /
';
t.logoContent += '- Get Involved!
';
t.logoContent += '
';