fixed merges from develop

This commit is contained in:
Connor Turland 2014-11-11 07:05:31 -05:00
commit 70cf1426d7
36 changed files with 1314 additions and 495 deletions

View file

@ -4,9 +4,9 @@ install homebrew
\curl -sSL https://get.rvm.io | bash -s stable --rails
rvm install 1.9.3 --with-gcc=clang
rvm install 2.1.3 --with-gcc=clang
rvm use 1.9.3
rvm use 2.1.3
gem install lunchy

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

View file

@ -2477,7 +2477,6 @@ Extras.Classes.Navigation = new Class({
// START METAMAPS CODE
jQuery(document).trigger(Metamaps.JIT.events.zoom, [e]);
// END METAMAPS CODE
},
onMouseDown: function(e, win, eventInfo) {
@ -7097,7 +7096,7 @@ Graph.Plot = {
ctx.restore();
}
//END METAMAPS CODE
aGraph.eachNode(function(node) {
var nodeAlpha = node.getData('alpha');
node.eachAdjacency(function(adj) {
@ -7427,6 +7426,7 @@ Graph.Label.Native = new Class({
(end code)
*/
plotLabel: function(canvas, node, controller) {
var ctx = canvas.getCtx();
var pos = node.pos.getc(true);
@ -7493,7 +7493,7 @@ Graph.Label.Native = new Class({
// START METAMAPS CODE
var index;
for (index = 0; index < customLabel.length; ++index) {
ctx.fillText(customLabel[index], pos.x, pos.y + node.getData("height") + 8 + (25*index));
ctx.fillText(customLabel[index], pos.x, pos.y + node.getData("height") + 9 + (25*index));
}
// END METAMAPS CODE
},

View file

@ -5,6 +5,34 @@ Metamaps.Backbone.Map = Backbone.Model.extend({
toJSON: function (options) {
return _.omit(this.attributes, this.blacklist);
},
save: function (key, val, options) {
var attrs;
// Handle both `"key", value` and `{key: value}` -style arguments.
if (key == null || typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
var newOptions = options || {};
var s = newOptions.success;
newOptions.success = function (model, response, opt) {
if (s) s(model, response, opt);
model.trigger('saved');
};
return Backbone.Model.prototype.save.call(this, attrs, newOptions);
},
initialize: function () {
this.on('changeByOther', this.updateView);
this.on('saved', this.savedEvent);
},
savedEvent: function() {
Metamaps.Realtime.sendMapChange(this);
},
authorizeToEdit: function (mapper) {
if (mapper && (this.get('permission') === "commons" || this.get('user_id') === mapper.get('id'))) return true;
else return false;
@ -24,11 +52,12 @@ Metamaps.Backbone.Map = Backbone.Model.extend({
that.set('topics', new bb.TopicCollection(data.topics));
that.set('synapses', new bb.SynapseCollection(data.synapses));
that.set('mappings', new bb.MappingCollection(data.mappings));
}
};
$.ajax({
var e = $.ajax({
url: "/maps/" + this.id + "/contains.json",
success: start,
error: errorFunc,
async: false
});
},
@ -75,6 +104,25 @@ Metamaps.Backbone.Map = Backbone.Model.extend({
screenshot: '<img src="' + this.get('screenshot_url') + '" />'
};
return obj;
},
updateView: function() {
var map = Metamaps.Active.Map;
var isActiveMap = this.id === map.id;
var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '';
var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '';
if (isActiveMap) {
Metamaps.Map.InfoBox.updateNameDescPerm(this.get('name'), this.get('desc'), this.get('permission'));
this.updateMapWrapper();
}
},
updateMapWrapper: function() {
var map = Metamaps.Active.Map;
var isActiveMap = this.id === map.id;
var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '';
var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '';
if (isActiveMap) {
$('.wrapper').removeClass('canEditMap commonsMap').addClass(authorized + ' ' + commonsMap);
}
}
});
Metamaps.Backbone.MapsCollection = Backbone.Collection.extend({

View file

@ -223,7 +223,7 @@ Metamaps.GlobalUI.CreateMap = {
$(this).parents('.new_map').find('.permText').html(permText);
},
submit: function (event) {
event.preventDefault();
if (event) event.preventDefault();
var self = Metamaps.GlobalUI.CreateMap;
@ -233,23 +233,15 @@ Metamaps.GlobalUI.CreateMap = {
}
var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map';
var form = $(formId)
var $form = $(formId);
self.newMap.set('name', form.find('#map_name').val());
self.newMap.set('desc', form.find('#map_desc').val());
self.newMap.set('name', $form.find('#map_name').val());
self.newMap.set('desc', $form.find('#map_desc').val());
// TODO validate map attributes
if (self.newMap.get('name').length===0){
console.log('Empty map name.');
Metamaps.GlobalUI.notifyUser('map name is mandatory.');
return;
} else if (self.newMap.get('name').length>140){
console.log('map name cannot exceed 140 characteres.');
Metamaps.GlobalUI.notifyUser('map name cannot exceed 140 characteres.');
self.throwMapNameError();
return;
}
//console.log('self.newMap.get("name").length='+self.newMap.get("name").length.toString());
self.newMap.save(null, {
success: self.success
@ -259,6 +251,21 @@ Metamaps.GlobalUI.CreateMap = {
Metamaps.GlobalUI.closeLightbox();
Metamaps.GlobalUI.notifyUser('Working...');
},
throwMapNameError: function () {
var self = Metamaps.GlobalUI.CreateMap;
var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map';
var $form = $(formId);
var message = $("<div class='feedback_message'>Please enter a map name...</div>");
$form.find('#map_name').after(message);
setTimeout(function(){
message.fadeOut('fast', function(){
message.remove();
});
}, 5000);
},
success: function (model) {
var self = Metamaps.GlobalUI.CreateMap;

View file

@ -1,6 +1,5 @@
Metamaps.JIT = {
events: {
mouseMove: 'Metamaps:JIT:events:mouseMove',
topicDrag: 'Metamaps:JIT:events:topicDrag',
newTopic: 'Metamaps:JIT:events:newTopic',
deleteTopic: 'Metamaps:JIT:events:deleteTopic',
@ -21,13 +20,26 @@ Metamaps.JIT = {
$(".zoomIn").click(self.zoomIn);
$(".zoomOut").click(self.zoomOut);
$(".zoomExtents").click(self.zoomExtents);
var zoomExtents = function (event) {
self.zoomExtents(event, Metamaps.Visualize.mGraph.canvas);
};
$(".zoomExtents").click(zoomExtents);
$(".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;
@ -37,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);
}
@ -78,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;
}
@ -118,14 +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");
if (desc != "" && showDesc) {
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 (!canvas.denySelected && desc != "" && showDesc) {
// '&amp;' to '&'
desc = Metamaps.Util.decodeEntities(desc);
@ -140,11 +193,12 @@ 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;
var y = ((pos.y + posChild.y) / 2) - height / 2;
var radius = 5;
//render background
@ -161,70 +215,33 @@ 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 (synapseNum > 1) {
drawSynapseCount(ctx, x + width, y, synapseNum);
}
}
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;
drawSynapseCount(ctx, x, y, synapseNum);
}
}
}, // edgeRender
edgeRenderEmbed: function (adj, canvas) {
//get nodes cartesian coordinates
var pos = adj.nodeFrom.pos.getc(true);
var posChild = adj.nodeTo.pos.getc(true);
var directionCat = adj.getData("category");
//label placement on edges
Metamaps.JIT.renderEdgeArrows(this.edgeHelper, adj);
//check for edge label in data
var desc = adj.getData("desc");
var showDesc = adj.getData("showDesc");
if (desc != "" && showDesc) {
// '&amp;' to '&'
desc = Metamaps.Util.decodeEntities(desc);
//now adjust the label placement
var ctx = canvas.getCtx();
ctx.font = 'bold 14px arial';
ctx.fillStyle = '#FFF';
ctx.textBaseline = 'hanging';
var arrayOfLabelLines = Metamaps.Util.splitLine(desc, 30).split('\n');
var index, lineWidths = [];
for (index = 0; index < arrayOfLabelLines.length; ++index) {
lineWidths.push(ctx.measureText(arrayOfLabelLines[index]).width)
}
var width = Math.max.apply(null, lineWidths) + 8;
var height = (16 * arrayOfLabelLines.length) + 8;
var x = (pos.x + posChild.x - width) / 2;
var y = ((pos.y + posChild.y) / 2) - height / 2;
var radius = 5;
//render background
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
ctx.fill();
//render text
ctx.fillStyle = '#222222';
ctx.textAlign = 'center';
for (index = 0; index < arrayOfLabelLines.length; ++index) {
ctx.fillText(arrayOfLabelLines[index], x + (width / 2), y + 5 + (16 * index));
}
}
}, // edgeRenderEmbed
ForceDirected: {
animateSavedLayout: {
modes: ['linear'],
@ -427,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;
@ -447,6 +464,26 @@ Metamaps.JIT = {
} else {
ctx.drawImage(metacode.get('image'), pos.x - dim, pos.y - dim, dim * 2, dim * 2);
}
// 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.topicLinkImage;
var linkImageLoaded = linkImage.complete ||
(typeof linkImage.naturalWidth !== "undefined" &&
linkImage.naturalWidth !== 0)
if (hasLink && linkImageLoaded) {
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) {
var npos = node.pos.getc(true),
@ -486,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);
}
}
}
@ -677,15 +714,18 @@ Metamaps.JIT = {
if (!node && !edge) {
$('canvas').css('cursor', 'default');
}
var pos = eventInfo.getPos();
$(document).trigger(Metamaps.JIT.events.mouseMove, [pos]);
}, // onMouseMoveHandler
enterKeyHandler: function () {
var creatingMap = Metamaps.GlobalUI.lightbox;
if (creatingMap === "newmap" || creatingMap === "forkmap") {
Metamaps.GlobalUI.CreateMap.submit();
}
// this is to submit new topic creation
if (Metamaps.Create.newTopic.beingCreated) {
else if (Metamaps.Create.newTopic.beingCreated) {
Metamaps.Topic.createTopicLocally();
} else if (Metamaps.Create.newSynapse.beingCreated) {
}
// to submit new synapse creation
else if (Metamaps.Create.newSynapse.beingCreated) {
Metamaps.Synapse.createSynapseLocally();
}
}, //enterKeyHandler
@ -751,6 +791,8 @@ Metamaps.JIT = {
var positionsToSend = {};
var topic;
var authorized = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper);
if (node && !node.nodeFrom) {
var pos = eventInfo.getPos();
// if it's a left click, or a touch, move the node
@ -773,7 +815,6 @@ Metamaps.JIT = {
// maps
positionsToSend[topic.id] = pos;
$(document).trigger(Metamaps.JIT.events.topicDrag, [positionsToSend]);
$(document).trigger(Metamaps.JIT.events.mouseMove, [pos]);
}
} else {
var len = Metamaps.Selected.Nodes.length;
@ -805,7 +846,6 @@ Metamaps.JIT = {
if (Metamaps.Active.Map) {
$(document).trigger(Metamaps.JIT.events.topicDrag, [positionsToSend]);
$(document).trigger(Metamaps.JIT.events.mouseMove, [pos]);
}
} //if
@ -815,7 +855,7 @@ Metamaps.JIT = {
Metamaps.Visualize.mGraph.plot();
}
// if it's a right click or holding down alt, start synapse creation ->third option is for firefox
else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && Metamaps.Active.Mapper) {
else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && authorized) {
if (tempInit == false) {
tempNode = node;
tempInit = true;
@ -877,9 +917,14 @@ Metamaps.JIT = {
x: pos.x,
y: pos.y
};
$(document).trigger(Metamaps.JIT.events.mouseMove, [pos]);
}
}
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.");
}
}
}, // onDragMoveTopicHandler
onDragCancelHandler: function (node, eventInfo, e) {
@ -921,6 +966,9 @@ Metamaps.JIT = {
// check whether to save mappings
var checkWhetherToSave = function() {
var map = Metamaps.Active.Map;
if (!map) return false;
var mapper = Metamaps.Active.Mapper;
// this case
// covers when it is a public map owned by you
@ -961,7 +1009,17 @@ Metamaps.JIT = {
var now = Date.now(); //not compatible with IE8 FYI
Metamaps.Mouse.lastCanvasClick = now;
var authorized = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper);
if (now - storedTime < Metamaps.Mouse.DOUBLE_CLICK_TOLERANCE && !Metamaps.Mouse.didPan) {
if (Metamaps.Active.Map && !authorized) {
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;
@ -1263,12 +1321,18 @@ Metamaps.JIT = {
// add the proper options to the menu
var menustring = '<ul>';
menustring += '<li class="rc-hide"><div class="rc-icon"></div>Hide until refresh</li>';
if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '<li class="rc-remove"><div class="rc-icon"></div>Remove from map</li>';
if (Metamaps.Active.Mapper) menustring += '<li class="rc-delete"><div class="rc-icon"></div>Delete</li>';
var authorized = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper);
var disabled = authorized ? "" : "disabled";
if (Metamaps.Active.Map) menustring += '<li class="rc-hide"><div class="rc-icon"></div>Hide until refresh</li>';
if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '<li class="rc-remove ' + disabled + '"><div class="rc-icon"></div>Remove from map</li>';
if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '<li class="rc-delete ' + disabled + '"><div class="rc-icon"></div>Delete</li>';
if (!Metamaps.Active.Map) 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> \
@ -1282,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;
@ -1325,17 +1398,21 @@ Metamaps.JIT = {
// attach events to clicks on the list items
// delete the selected things from the database
$('.rc-delete').click(function () {
$('.rightclickmenu').remove();
Metamaps.Control.deleteSelected();
});
if (authorized) {
$('.rc-delete').click(function () {
$('.rightclickmenu').remove();
Metamaps.Control.deleteSelected();
});
}
// remove the selected things from the map
$('.rc-remove').click(function () {
$('.rightclickmenu').remove();
Metamaps.Control.removeSelectedEdges();
Metamaps.Control.removeSelectedNodes();
});
if (authorized) {
$('.rc-remove').click(function () {
$('.rightclickmenu').remove();
Metamaps.Control.removeSelectedEdges();
Metamaps.Control.removeSelectedNodes();
});
}
// hide selected nodes and synapses until refresh
$('.rc-hide').click(function () {
@ -1371,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;
@ -1439,11 +1579,13 @@ Metamaps.JIT = {
// add the proper options to the menu
var menustring = '<ul>';
menustring += '<li class="rc-hide"><div class="rc-icon"></div>Hide until refresh</li>';
if (Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper)) {
menustring += '<li class="rc-remove"><div class="rc-icon"></div>Remove from map</li>';
}
if (Metamaps.Active.Mapper) menustring += '<li class="rc-delete"><div class="rc-icon"></div>Delete</li>';
var authorized = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper);
var disabled = authorized ? "" : "disabled";
if (Metamaps.Active.Map) menustring += '<li class="rc-hide"><div class="rc-icon"></div>Hide until refresh</li>';
if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '<li class="rc-remove ' + disabled + '"><div class="rc-icon"></div>Remove from map</li>';
if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '<li class="rc-delete ' + disabled + '"><div class="rc-icon"></div>Delete</li>';
if (Metamaps.Active.Mapper) {
var permOptions = '<ul><li class="changeP toCommons"><div class="rc-perm-icon"></div>commons</li> \
@ -1494,17 +1636,21 @@ Metamaps.JIT = {
// attach events to clicks on the list items
// delete the selected things from the database
$('.rc-delete').click(function () {
$('.rightclickmenu').remove();
Metamaps.Control.deleteSelected();
});
if (authorized) {
$('.rc-delete').click(function () {
$('.rightclickmenu').remove();
Metamaps.Control.deleteSelected();
});
}
// remove the selected things from the map
$('.rc-remove').click(function () {
$('.rightclickmenu').remove();
Metamaps.Control.removeSelectedEdges();
Metamaps.Control.removeSelectedNodes();
});
if (authorized) {
$('.rc-remove').click(function () {
$('.rightclickmenu').remove();
Metamaps.Control.removeSelectedEdges();
Metamaps.Control.removeSelectedNodes();
});
}
// hide selected nodes and synapses until refresh
$('.rc-hide').click(function () {
@ -1584,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();
@ -1646,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);
@ -1663,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();
@ -1675,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);
}
@ -1700,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 {

View file

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

File diff suppressed because it is too large Load diff

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

@ -293,7 +293,7 @@ input[type="submit"]:active {
margin-top: 32px;
cursor: pointer;
}
.edit_user .userImage img {
.edit_user .userImage img, .edit_user .userImage canvas {
border-radius: 42px;
}
.edit_user .editPhoto {
@ -448,6 +448,13 @@ input[type="submit"]:active {
}
#accountPageLoading {
display: none;
position: absolute;
bottom: 16px;
right: 120px;
}
.centerGreyForm input[type="text"],
.centerGreyForm input[type="email"],
.centerGreyForm input[type="password"] {
@ -512,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;
@ -574,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;
@ -1111,7 +1118,7 @@ h3.realtimeBoxTitle {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 9px 32px;
padding: 10px 34px;
display: block;
height: 14px;
font-family: 'din-regular', helvetica, sans-serif;
@ -1119,11 +1126,16 @@ h3.realtimeBoxTitle {
line-height: 14px;
position: relative;
}
.rtMapperSelf img {
border: 2px solid #424242;
}
.rtUserImage {
position: absolute;
top: 4px;
left: 0;
border-radius: 12px;
border-radius: 14px;
}
.littleJuntoIcon {
width: 24px;
@ -1158,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;
@ -1172,14 +1185,21 @@ 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 {
background-color: #E0E0E0;
cursor: pointer;
}
.rightclickmenu li.disabled {
opacity: 0.4;
}
.rightclickmenu li.disabled:hover {
background-color: transparent;
cursor: default;
}
.rightclickmenu > ul > li .rc-icon {
position: absolute;
top: 0;
@ -1224,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;
@ -1235,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 {
@ -1263,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;
}
@ -1295,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 */
@ -1318,7 +1355,7 @@ float: left;
#new_topic .tt-suggestion,
#new_synapse .tt-suggestion {
background: #F5F5F5;
width: 270px;
width: 256px;
position: relative;
}
#new_topic .autocompleteSection {
@ -1587,7 +1624,7 @@ float: left;
background-position: 13px center;
}
.mapSynapses {
background-image: url(synapse32.png);
background-image: url(synapse32padded.png);
background-position: 13px center;
}
.mapInfoBox .mapPermission {
@ -1652,7 +1689,7 @@ float: left;
.mapInfoBox .mapInfoDesc {
font-family: helvetica, sans-serif;
color: #E0E0E0;
margin: 8px;
margin: 16px;
padding-right: 16px;
height: 115px;
font-size: 14px;
@ -1976,6 +2013,8 @@ and it won't be important on password protected instances */
font-family: 'din-medium', helvetica, sans-serif;
color: #424242;
font-size: 14px;
text-align: justify;
padding-right: 16px;
}
#switchMetacodes > p {
margin: 16px 0 16px 0;
@ -1990,10 +2029,17 @@ and it won't be important on password protected instances */
#metacodeSwitchTabs li.ui-state-active a {
color: #00BCD4;
}
.metacodeSwitchTab {
max-height: 300px;
overflow-y: auto;
margin-bottom: 16px;
}
.customMetacodeList {
overflow-y: auto;
}
.customMetacodeList,
.metacodeSetList {
height: 301px;
overflow-y: auto;
margin: 5px 0 15px 0;
}
.customMetacodeList ul li {
@ -2191,6 +2237,16 @@ and it won't be important on password protected instances */
margin: 15px 0 5px;
position: relative;
}
.new_map .feedback_message {
float: right;
width: 388px;
background: #c04f4f;
margin: 5px 1px;
padding: 2px 5px;
border-radius: 2px;
color: #FFF;
}
.new_map label {
float: left;
width: 100px;

View file

@ -110,16 +110,17 @@
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;
}
.CardOnGraph.hasAttachment .scroll {
height: auto;
}
.CardOnGraph .best_in_place_desc textarea {
font-size: 12px;
font-size: 13px;
line-height:15px;
font-family: helvetica, sans-serif;
color: #424242;
@ -169,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;
}
@ -186,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 {
@ -201,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;
@ -218,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;
@ -240,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;
}
@ -506,6 +510,8 @@ background-color: #E0E0E0;
width: 268px;
padding: 8px 16px 8px 16px;
position: relative;
border: none;
line-height: 14px;
}
#addLinkInput input{
@ -547,6 +553,28 @@ font-family: 'din-regular', helvetica, sans-serif;
background-position: center center;
}
.embeds.nonEmbedlyLink {
padding-top: 24px;
}
#embedlyLink {
border-left: 8px solid #CCC;
overflow: hidden;
padding: 8px;
padding-left: 12px;
-moz-box-shadow: 1px 1px 5px 0 #ccc;
-webkit-box-shadow: 1px 1px 5px 0 #ccc;
box-shadow: 1px 1px 5px 0 #ccc;
-moz-border-radius-topright: 5px;
-webkit-border-top-right-radius: 5px;
border-top-right-radius: 5px;
-moz-border-radius-bottomright: 8px;
-webkit-border-bottom-right-radius: 8px;
border-bottom-right-radius: 8px;
display: none;
margin: 8px;
}
.linkActions {
position: relative;
}

View file

@ -185,7 +185,7 @@
.explorePage .sidebarSearchField,
.explorePage .sidebarSearch .tt-hint {
width: 380px;
padding: 7px 10px 3px 10px;
padding: 5px 10px 5px 10px;
}
.sidebarSearchField {
@ -201,7 +201,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;
@ -212,7 +212,7 @@
}
.sidebarSearch .tt-dropdown-menu {
top: 40px !important;
background: #FFF;
background: #F5F5F5;
width: 472px;
overflow-y: auto;
overflow-x: hidden;
@ -571,7 +571,7 @@
top: 0;
}
.topicPage .sidebarCollaborate, .topicPage .sidebarFilter {
.topicPage .sidebarCollaborate {
display: none;
}
@ -798,6 +798,18 @@
background-position: 0 0;
cursor:pointer;
}
.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;
@ -918,6 +930,10 @@
line-height:14px;
}
.toast a {
color: #4fc059;
}
/* end toast */
/* feedback */

View file

@ -79,9 +79,16 @@ class MapsController < ApplicationController
respond_to do |format|
format.html {
@allmappers = @map.contributors
@alltopics = @map.topics # should limit to topics visible to user
@allsynapses = @map.synapses # should also be limited
@allmappings = @map.mappings
@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.delete_if {|m|
if m.category == "Synapse"
object = m.synapse
elsif m.category == "Topic"
object = m.topic
end
object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id))
}
respond_with(@allmappers, @allmappings, @allsynapses, @alltopics, @map)
}
@ -100,9 +107,16 @@ class MapsController < ApplicationController
end
@allmappers = @map.contributors
@alltopics = @map.topics # should limit to topics visible to user
@allsynapses = @map.synapses # should also be limited
@allmappings = @map.mappings
@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.delete_if {|m|
if m.category == "Synapse"
object = m.synapse
elsif m.category == "Topic"
object = m.topic
end
object.permission == "private" && (!authenticated? || (authenticated? && @current.id != object.user_id))
}
@json = Hash.new()
@json['map'] = @map
@ -116,27 +130,6 @@ class MapsController < ApplicationController
end
end
# GET maps/:id/embed
def embed
@current = current_user
@map = Map.find(params[:id]).authorize_to_show(@current)
if not @map
redirect_to root_url and return
end
@alltopics = @map.topics # should limit to topics visible to user
@allsynapses = @map.synapses # should also be limited
@allmappings = @map.mappings
@allmetacodes = Metacode.all
respond_to do |format|
format.html { respond_with(@allmetacodes, @allmappings, @allsynapses, @alltopics, @map, @user) }
format.json { render json: @map }
end
end
# POST maps
def create
@ -202,6 +195,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

View file

@ -27,15 +27,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
respond_to do |format|
format.html {
@alltopics = [@topic] + @topic.relatives # should limit to topics visible to user
@allsynapses = @topic.synapses # should also be limited
@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
@ -47,14 +59,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 # should limit to topics visible to user
@allsynapses = @topic.synapses # should also be limited
@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
@ -63,6 +88,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

@ -8,7 +8,7 @@ module UsersHelper
user['id'] = u.id
user['label'] = u.name
user['value'] = u.name
user['profile'] = u.image.url(:thumb)
user['profile'] = u.image.url(:square)
user['mapCount'] = u.maps.count
user['created_at'] = u.created_at.strftime("%m/%d/%Y")
user['rtype'] = "mapper"

View file

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

View file

@ -37,30 +37,17 @@ class User < ActiveRecord::Base
# This method associates the attribute ":image" with a file attachment
has_attached_file :image, :styles => {
:thumb => ['100x100>', :png],
:square => ['200x200#', :png],
:round => ['200x200#', :png]
:square => ['84x84#', :png]
},
:default_url => "/assets/user.png"
#, :convert_options => {:round => Proc.new{self.convert_options}}
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
def self.convert_options
trans = ''
trans << ' ( +clone -alpha extract '
trans << '-draw "fill black polygon 0,0 0,100 100,0 fill white circle 100,100 100,0" '
trans << '( +clone -flip ) -compose multiply -composite '
trans << '( +clone -flop ) -compose multiply -composite '
trans << ') -alpha off -compose copy_opacity -composite '
end
def as_json(options={})
{ :id => self.id,
:name => self.name,
:image => self.image.url
:image => self.image.url(:square)
}
end

View file

@ -4,7 +4,7 @@
#%>
<% account = current_user %>
<%= image_tag user.image.url(:thumb), :size => "48x48", :class => "sidebarAccountImage" %>
<%= image_tag user.image.url(:square), :size => "48x48", :class => "sidebarAccountImage" %>
<h3 class="accountHeader"><%= account.name.split[0...1][0] %></h3>
<ul>
<li class="accountListItem accountSettings">
@ -21,4 +21,4 @@
<div class="accountIcon"></div>
<%= link_to "Sign Out", "/logout", id: "Logout", :data => { :bypass => 'true'} %>
</li>
</ul>
</ul>

View file

@ -114,7 +114,6 @@
Underscore.js<br>
Famo.us<br>
Typeahead.js</p><br>
<div class="clearfloat"></div>
</div>

View file

@ -1,4 +1,5 @@
<div class="mapControls mapElement">
<div class="takeScreenshot mapControl"></div>
<div class="zoomExtents mapControl"></div>
<div class="zoomIn mapControl"></div>
<div class="zoomOut mapControl"></div>

View file

@ -8,7 +8,7 @@
<div class="inputGroup">
<label for="map_name">Name: </label>
<%= form.text_field :name %>
<%= form.text_field :name, :maxlength => 140 %>
<div class="clearfloat"></div>
</div>

View file

@ -30,7 +30,7 @@
<div class="realtimeMapperList">
<ul>
<li class="rtMapper littleRtOn rtMapperSelf">
<%= image_tag user.image.url(:thumb), :size => "24x24", :class => "rtUserImage" %>
<%= image_tag user.image.url(:square), :size => "24x24", :class => "rtUserImage" %>
<%= user.name %> (me)
<div class="littleJuntoIcon"></div>
</li>
@ -62,7 +62,7 @@
<!-- Account / Sign in -->
<div class="sidebarAccount upperRightEl">
<div class="sidebarAccountIcon">
<%= image_tag user.image.url(:thumb), :size => "32x32" %>
<%= image_tag user.image.url(:square), :size => "32x32" %>
</div>
<div class="sidebarAccountBox upperRightBox">
<%= render :partial => 'layouts/account' %>

View file

@ -24,6 +24,46 @@
require.config({baseUrl: '/famous/'});
require(['main']);
</script>
<!--[if (IE)]>
<style type="text/css">
#lightbox_overlay {
display: block;
}
#lightbox_main {
top: 50%;
margin-top: -281px;
}
#lightbox_screen {
height: 100%;
opacity: 0.42;
}
.lightboxContent {
display: none;
}
#noIE {
display: block;
}
#lightbox_close {
display: none;
}
</style>
<script type="text/javascript">
$(document).ready(function(){
$("#lightbox_screen").unbind().click(function(event){
event.preventDefault();
event.stopPropagation();
return false;
});
});
</script>
<![endif]-->
</head>
<body data-env="<%= Rails.env %>">

View file

@ -15,11 +15,11 @@
<% if @map.contributors.count == 0 %>
<img id="mapContribs" width="25" height="25" src="/assets/user.png" />
<% elsif @map.contributors.count == 1 %>
<img id="mapContribs" width="25" height="25" src="<%= @map.contributors[0].image.url %>" />
<img id="mapContribs" width="25" height="25" src="<%= @map.contributors[0].image.url(:square) %>" />
<% elsif @map.contributors.count == 2 %>
<img id="mapContribs" width="25" height="25" src="<%= @map.contributors[0].image.url %>" class="multiple mTwo" />
<img id="mapContribs" width="25" height="25" src="<%= @map.contributors[0].image.url(:square) %>" class="multiple mTwo" />
<% elsif @map.contributors.count > 2 %>
<img id="mapContribs" width="25" height="25" src="<%= @map.contributors[0].image.url %>" class="multiple" />
<img id="mapContribs" width="25" height="25" src="<%= @map.contributors[0].image.url(:square) %>" class="multiple" />
<% end %>
<span><%= @map.contributors.count %></span>
<% contributorList = ''

View file

@ -1,83 +0,0 @@
<%#
# @file
# Code to display a map
# /maps/:id
#%>
<% content_for :title, @map.name + " | Metamaps" %>
<div id="preloaded-images">
<img src="/assets/MMCCicon_realtime_blue.png" />
</div>
<% if authenticated? %>
<div class="sidebarFork">
<div class="sidebarForkIcon">
</div>
<div class="sidebarForkBox"></div>
</div>
<% if @map.permission == "commons" || @map.user == user %>
<div class="sidebarCollaborate">
<div class="sidebarCollaborateIcon blue"></div>
<div class="sidebarCollaborateBox">
<h3 class="realtimeBoxTitle">Realtime: </h3>
<span class="realtimeOnOff rtOn">ON</span>
<div class="clearfloat"></div>
<div class="realtimeMapperList">
<ul>
<li class="rtMapper littleRtOn rtMapperSelf">
<%= user.name %> (me)
</li>
</ul>
</div>
</div>
</div>
<% end %>
<% end %>
<div class="sidebarFilter <%= authenticated? ? 'loggedin' : 'loggedout' %>">
<div class="sidebarFilterIcon"></div>
<div class="sidebarFilterBox">
<h3 class="filterByMetacode">Filter By Metacode</h3><span class="showAll">all</span><span class="hideAll">none</span>
<div class="clearfloat"></div>
<%= render :partial => 'shared/filterbymetacode' %>
</div>
</div>
<div class="index">
<div class="openCheatsheet openLightbox" data-open="cheatsheet"></div>
<span class="mapInfo"></span>
<div class="clearfloat"></div>
<%= render :partial => 'maps/mapinfobox' %>
</div>
<div class="maps onMap" id="container">
<div id="center-container">
<div id="infovis"></div>
</div>
<div class="showcard" id="showcard"></div>
</div>
<div class="clearfloat"></div>
<% if authenticated? %>
<% # add these if you have edit permissions on the map %>
<% if @map.permission == "commons" || @map.user == user %>
<% # for creating and pulling in topics and synapses %>
<%= render :partial => 'newtopic' %>
<%= render :partial => 'newsynapse' %>
<% end %>
<% # for populating the change metacode list on the topic card %>
<%= render :partial => 'shared/metacodeoptions' %>
<% end %>
<script>
Metamaps.Active.Map = <%= @map.to_json.html_safe %>;
Metamaps.Metacodes = <%= @allmetacodes.to_json.html_safe %>;
Metamaps.Topics = <%= @alltopics.to_json.html_safe %>;
Metamaps.Synapses = <%= @allsynapses.to_json.html_safe %>;
Metamaps.Mappings = <%= @allmappings.to_json.html_safe %>;
Metamaps.Settings.embed = true;
</script>

View file

@ -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 || ""
@ -62,7 +81,7 @@
end
@mappers.each_with_index do |mapper, index|
@mapperlist += '<li data-id="' + mapper.id.to_s + '">'
@mapperlist += '<img src="' + mapper.image.url(:thumb) + '" data-id="' + mapper.id.to_s + '" alt="' + mapper.name + '" />'
@mapperlist += '<img src="' + mapper.image.url(:square) + '" data-id="' + mapper.id.to_s + '" alt="' + mapper.name + '" />'
@mapperlist += '<p>' + mapper.name + '</p></li>'
end
end
@ -70,7 +89,7 @@
<div class="filterBox">
<h2>FILTER BY</h2>
<div id="filter_by_mapper" class="filterBySection">
<h3>MAPPERS</h3>
<h3><%= @map ? "MAPPERS" : @topic ? "CREATORS" : "" %></h3>
<span class="hideAll hideAllMappers">NONE</span>
<span class="showAll showAllMappers">ALL</span>
<div class="clearfloat"></div>

View file

@ -9,7 +9,7 @@
<div class="inputGroup">
<label for="map_name">Name: </label>
<%= form.text_field :name %>
<%= form.text_field :name, :maxlength => 140 %>
<div class="clearfloat"></div>
</div>

View file

@ -24,18 +24,20 @@
<li><a href="#metacodeSwitchTabsCustom" data-set-id="custom" id="metacodeSetCustom">CUSTOM SELECTION</a></li>
</ul>
<% allMetacodeSets.each_with_index do |m, localindex| %>
<div id="metacodeSwitchTabs<%= m.id %>"
<div id="metacodeSwitchTabs<%= m.id %>"
data-metacodes="<%= m.metacodes.map(&:id).join(',') %>">
<% @list = '' %>
<% m.metacodes.sort{|x,y| x.name <=> y.name }.each_with_index do |m, index| %>
<% @list += '<li><img src="' + m.icon + '" alt="' + m.name + '" /><p>' + m.name.downcase + '</p><div class="clearfloat"></div></li>' %>
<% end %>
<p class="setDesc"><%= m.desc %></p>
<div class="metacodeSetList">
<ul>
<%= @list.html_safe %>
</ul>
<div class="clearfloat"></div>
<div class="metacodeSwitchTab">
<p class="setDesc"><%= m.desc %></p>
<div class="metacodeSetList">
<ul>
<%= @list.html_safe %>
</ul>
<div class="clearfloat"></div>
</div>
</div>
<button class="button" onclick="Metamaps.Create.updateMetacodeSet(<%= m.id %>, <%= localindex %>, false);">
Switch Set

View file

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

View file

@ -10,7 +10,7 @@
<h3>Edit Account</h3>
<div class="userImage">
<div class="userImageDiv" onclick="Metamaps.Account.toggleChangePicture()">
<%= image_tag @user.image.url(:round), :size => "84x84" %>
<%= image_tag @user.image.url(:square), :size => "84x84" %>
<div class="editPhoto"></div>
</div>
<div class="userImageMenu">
@ -49,6 +49,7 @@
<%= form.password_field :password_confirmation, :autocomplete => :off%></div>
<div class="noChangePass" onclick="Metamaps.Account.hidePass()">Oops, don't change password</div>
</div>
<%= form.submit "Update", class: "update" %>
<div id="accountPageLoading"></div>
<%= form.submit "Update", class: "update", onclick: "Metamaps.Account.showLoading()" %>
<% end %>
</div>

View file

@ -20,6 +20,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
@ -27,8 +29,8 @@ Metamaps::Application.routes.draw do
match 'maps/mappers/:id', to: 'maps#index', via: :get, as: :usermaps
match 'maps/topics/:id', to: 'maps#index', via: :get, as: :topicmaps
resources :maps, except: [:new, :edit]
match 'maps/:id/embed', to: 'maps#embed', via: :get, as: :embed
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]