This commit is contained in:
Connor Turland 2014-10-27 12:03:55 -04:00
parent cbf71ca2da
commit f58db49bc1
6 changed files with 446 additions and 65 deletions

View file

@ -1,3 +1,7 @@
## 2.6
- Backbone.js in use for client side models
- Realtime depends entirely on sockets for transmitting changes, rather than server using redis to push
## 2.5
- Initial release

View file

@ -3,8 +3,10 @@ Metamaps.JIT = {
mouseMove: 'Metamaps:JIT:events:mouseMove',
topicDrag: 'Metamaps:JIT:events:topicDrag',
newTopic: 'Metamaps:JIT:events:newTopic',
deleteTopic: 'Metamaps:JIT:events:deleteTopic',
removeTopic: 'Metamaps:JIT:events:removeTopic',
newSynapse: 'Metamaps:JIT:events:newSynapse',
deleteSynapse: 'Metamaps:JIT:events:deleteSynapse',
removeSynapse: 'Metamaps:JIT:events:removeSynapse',
pan: 'Metamaps:JIT:events:pan',
zoom: 'Metamaps:JIT:events:zoom',
@ -915,7 +917,24 @@ Metamaps.JIT = {
tempInit = false;
} else if (!tempInit && node && !node.nodeFrom) {
// this means you dragged an existing node, autosave that to the database
if (Metamaps.Active.Map) {
// check whether to save mappings
var checkWhetherToSave = function() {
var map = Metamaps.Active.Map;
var mapper = Metamaps.Active.Mapper;
// this case
// covers when it is a public map owned by you
// and also when it's a private map
var activeMappersMap = map.authorizePermissionChange(mapper);
var commonsMap = map.get('permission') === 'commons';
var realtimeOn = Metamaps.Realtime.status;
// don't save if commons map, and you have realtime off,
// even if you're map creator
return map && mapper && ((commonsMap && realtimeOn) || (activeMappersMap && !commonsMap));
}
if (checkWhetherToSave()) {
mapping = node.getData('mapping');
mapping.save({
xloc: node.getPos().x,

View file

@ -65,7 +65,7 @@ Metamaps.Selected = {
var self = Metamaps.Selected;
self.Nodes = [];
self.edges = [];
self.Edges = [];
},
Nodes: [],
Edges: []
@ -111,6 +111,36 @@ Metamaps.Backbone.init = function () {
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;
var permBefore = this.get('permission');
newOptions.success = function (model, response, opt) {
if (s) s(model, response, opt);
model.trigger('saved');
if (permBefore === 'private' && model.get('permission') !== 'private') {
model.trigger('noLongerPrivate');
}
else if (permBefore !== 'private' && model.get('permission') === 'private') {
model.trigger('nowPrivate');
}
};
return Backbone.Model.prototype.save.call(this, attrs, newOptions);
},
initialize: function () {
if (this.isNew()) {
this.set({
@ -121,13 +151,27 @@ Metamaps.Backbone.init = function () {
});
}
this.on('changeByOther', this.updateCardView);
this.on('change', this.updateNodeView);
this.on('saved', this.savedEvent);
this.on('nowPrivate', function(){
var removeTopicData = {
topicid: this.id
};
$(document).trigger(Metamaps.JIT.events.removeTopic, [removeTopicData]);
});
this.on('noLongerPrivate', function(){
var newTopicData = {
mappingid: this.getMapping().id,
topicid: this.id
};
$(document).trigger(Metamaps.JIT.events.newTopic, [newTopicData]);
});
this.on('change:metacode_id', Metamaps.Filter.checkMetacodes, this);
var updateName = function () {
if (this.get('node')) this.get('node').name = this.get('name');
if (Metamaps.Visualize) Metamaps.Visualize.mGraph.plot();
};
this.on('change:name', updateName, this);
},
authorizeToEdit: function (mapper) {
if (mapper && (this.get('permission') === "commons" || this.get('user_id') === mapper.get('id'))) return true;
@ -183,6 +227,41 @@ Metamaps.Backbone.init = function () {
return node;
},
savedEvent: function() {
Metamaps.Realtime.sendTopicChange(this);
},
updateViews: function() {
var onPageWithTopicCard = Metamaps.Active.Map || Metamaps.Active.Topic;
var node = this.get('node');
// update topic card, if this topic is the one open there
if (onPageWithTopicCard && this == Metamaps.TopicCard.openTopicCard) {
Metamaps.TopicCard.showCard(node);
}
// update the node on the map
if (onPageWithTopicCard && node) {
node.name = this.get('name');
Metamaps.Visualize.mGraph.plot();
}
},
updateCardView: function() {
var onPageWithTopicCard = Metamaps.Active.Map || Metamaps.Active.Topic;
var node = this.get('node');
// update topic card, if this topic is the one open there
if (onPageWithTopicCard && this == Metamaps.TopicCard.openTopicCard) {
Metamaps.TopicCard.showCard(node);
}
},
updateNodeView: function() {
var onPageWithTopicCard = Metamaps.Active.Map || Metamaps.Active.Topic;
var node = this.get('node');
// update the node on the map
if (onPageWithTopicCard && node) {
node.name = this.get('name');
Metamaps.Visualize.mGraph.plot();
}
}
});
self.TopicCollection = Backbone.Collection.extend({
@ -196,6 +275,36 @@ Metamaps.Backbone.init = function () {
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;
var permBefore = this.get('permission');
newOptions.success = function (model, response, opt) {
if (s) s(model, response, opt);
model.trigger('saved');
if (permBefore === 'private' && model.get('permission') !== 'private') {
model.trigger('noLongerPrivate');
}
else if (permBefore !== 'private' && model.get('permission') === 'private') {
model.trigger('nowPrivate');
}
};
return Backbone.Model.prototype.save.call(this, attrs, newOptions);
},
initialize: function () {
if (this.isNew()) {
this.set({
@ -204,6 +313,24 @@ Metamaps.Backbone.init = function () {
"category": "from-to"
});
}
this.on('changeByOther', this.updateCardView);
this.on('change', this.updateEdgeView);
this.on('saved', this.savedEvent);
this.on('noLongerPrivate', function(){
var newSynapseData = {
mappingid: this.getMapping().id,
synapseid: this.id
};
$(document).trigger(Metamaps.JIT.events.newSynapse, [newSynapseData]);
});
this.on('nowPrivate', function(){
$(document).trigger(Metamaps.JIT.events.removeSynapse, [{
synapseid: this.id
}]);
});
this.on('change:desc', Metamaps.Filter.checkSynapses, this);
},
prepareLiForFilter: function () {
@ -277,6 +404,31 @@ Metamaps.Backbone.init = function () {
return edge;
},
savedEvent: function() {
Metamaps.Realtime.sendSynapseChange(this);
},
updateViews: function() {
this.updateCardView();
this.updateEdgeView();
},
updateCardView: function() {
var onPageWithSynapseCard = Metamaps.Active.Map || Metamaps.Active.Topic;
var edge = this.get('edge');
// update synapse card, if this synapse is the one open there
if (onPageWithSynapseCard && edge == Metamaps.SynapseCard.openSynapseCard) {
Metamaps.SynapseCard.showCard(edge);
}
},
updateEdgeView: function() {
var onPageWithSynapseCard = Metamaps.Active.Map || Metamaps.Active.Topic;
var edge = this.get('edge');
// update the edge on the map
if (onPageWithSynapseCard && edge) {
Metamaps.Visualize.mGraph.plot();
}
}
});
self.SynapseCollection = Backbone.Collection.extend({
@ -850,7 +1002,6 @@ Metamaps.TopicCard = {
$('.metacodeSelect li li').click(metacodeLiClick);
var bipName = $(showCard).find('.best_in_place_name');
bipName.best_in_place();
bipName.bind("best_in_place:activate", function () {
var $el = bipName.find('textarea');
var el = $el[0];
@ -872,12 +1023,14 @@ Metamaps.TopicCard = {
bipName.bind("ajax:success", function () {
var name = Metamaps.Util.decodeEntities($(this).html());
topic.set("name", name);
topic.trigger('saved');
});
$(showCard).find('.best_in_place_desc').bind("ajax:success", function () {
this.innerHTML = this.innerHTML.replace(/\r/g, '')
var desc = $(this).html();
topic.set("desc", desc);
topic.trigger('saved');
});
}
@ -1108,6 +1261,7 @@ Metamaps.SynapseCard = {
} else {
synapse.set("desc", desc);
}
synapse.trigger('saved');
Metamaps.Control.selectEdge(synapse.get('edge'));
Metamaps.Visualize.mGraph.plot();
});
@ -1333,7 +1487,7 @@ Metamaps.Visualize = {
if (self.type == "RGraph") {
self.mGraph.graph.eachNode(function (n) {
topic = Metamaps.Topics.get(n.id);
topic.set('node', n);
topic.set({ node: n }, { silent: true });
topic.updateNode();
n.eachAdjacency(function (edge) {
@ -1343,7 +1497,7 @@ Metamaps.Visualize = {
l = edge.getData('synapseIDs').length;
for (i = 0; i < l; i++) {
synapse = Metamaps.Synapses.get(edge.getData('synapseIDs')[i]);
synapse.set('edge', edge);
synapse.set({ edge: edge }, { silent: true });
synapse.updateEdge();
}
}
@ -1358,7 +1512,7 @@ Metamaps.Visualize = {
self.mGraph.graph.eachNode(function (n) {
topic = Metamaps.Topics.get(n.id);
topic.set('node', n);
topic.set({ node: n }, { silent: true });
topic.updateNode();
mapping = topic.getMapping();
@ -1369,7 +1523,7 @@ Metamaps.Visualize = {
l = edge.getData('synapseIDs').length;
for (i = 0; i < l; i++) {
synapse = Metamaps.Synapses.get(edge.getData('synapseIDs')[i]);
synapse.set('edge', edge);
synapse.set({ edge: edge }, { silent: true });
synapse.updateEdge();
}
}
@ -1510,18 +1664,26 @@ Metamaps.Util = {
return Math.sqrt(Math.pow((p2.x - p1.x), 2) + Math.pow((p2.y - p1.y), 2));
},
coordsToPixels: function (coords) {
var canvas = Metamaps.Visualize.mGraph.canvas,
s = canvas.getSize(),
p = canvas.getPos(),
ox = canvas.translateOffsetX,
oy = canvas.translateOffsetY,
sx = canvas.scaleOffsetX,
sy = canvas.scaleOffsetY;
var pixels = {
x: (coords.x / (1/sx)) + p.x + s.width/2 + ox,
y: (coords.y / (1/sy)) + p.y + s.height/2 + oy
};
return pixels;
if (Metamaps.Visualize.mGraph) {
var canvas = Metamaps.Visualize.mGraph.canvas,
s = canvas.getSize(),
p = canvas.getPos(),
ox = canvas.translateOffsetX,
oy = canvas.translateOffsetY,
sx = canvas.scaleOffsetX,
sy = canvas.scaleOffsetY;
var pixels = {
x: (coords.x / (1/sx)) + p.x + s.width/2 + ox,
y: (coords.y / (1/sy)) + p.y + s.height/2 + oy
};
return pixels;
}
else {
return {
x: 0,
y: 0
};
}
},
pixelsToCoords: function (pixels) {
var canvas = Metamaps.Visualize.mGraph.canvas,
@ -1597,10 +1759,10 @@ Metamaps.Realtime = {
init: function () {
var self = Metamaps.Realtime;
var turnOn = function () {
self.turnOn(true);
}
$(".rtOn").click(turnOn);
var reenableRealtime = function () {
self.reenableRealtime();
};
$(".rtOn").click(reenableRealtime);
$(".rtOff").click(self.turnOff);
$('.sidebarCollaborateIcon').click(self.toggleBox);
@ -1612,7 +1774,9 @@ Metamaps.Realtime = {
var railsEnv = $('body').data('env');
var whichToConnect = railsEnv === 'development' ? self.stringForLocalhost : self.stringForHeroku;
self.socket = io.connect(whichToConnect);
self.startActiveMap();
self.socket.on('connect', function () {
self.startActiveMap();
});
},
toggleBox: function (event) {
var self = Metamaps.Realtime;
@ -1650,31 +1814,34 @@ Metamaps.Realtime = {
startActiveMap: function () {
var self = Metamaps.Realtime;
var mapperm = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper);
if (Metamaps.Active.Map) {
var commonsMap = Metamaps.Active.Map.get('permission') === 'commons';
var start = function() {
if (mapperm) {
if (commonsMap) {
self.turnOn();
self.setupSocket();
}
}
if (!self.socket.connected) {
self.socket.socket.connect();
}
self.socket.on('connect', function () {
start();
});
},
endActiveMap: function () {
var self = Metamaps.Realtime;
$(document).off(Metamaps.JIT.events.mouseMove);
self.socket.disconnect();
self.socket.removeAllListeners();
self.socket.emit('endMapperNotify');
$(".collabCompass").remove();
self.status = false;
},
reenableRealtime: function() {
var confirmString = "The layout of your map has fallen out of sync with the saved copy. ";
confirmString += "To save your changes without overwriting the map, hit 'Cancel' and ";
confirmString += "then use 'Save to new map'. ";
confirmString += "Do you want to discard your changes and enable realtime?";
var c = confirm(confirmString);
if (c) {
Metamaps.Router.maps(Metamaps.Active.Map.id);
}
},
turnOn: function (notify) {
var self = Metamaps.Realtime;
@ -1742,6 +1909,14 @@ Metamaps.Realtime = {
// update mapper compass position
socket.on('maps-' + Metamaps.Active.Map.id + '-updatePeerCoords', self.updatePeerCoords);
// deletions
socket.on('deleteTopicFromServer', self.removeTopic);
socket.on('deleteSynapseFromServer', self.removeSynapse);
socket.on('topicChangeFromServer', self.topicChange);
socket.on('synapseChangeFromServer', self.synapseChange);
socket.on('mapChangeFromServer', self.mapChange);
// local event listeners that trigger events
var sendCoords = function (event, coords) {
self.sendCoords(coords);
@ -1773,6 +1948,11 @@ Metamaps.Realtime = {
};
$(document).on(Metamaps.JIT.events.newTopic, sendNewTopic);
var sendDeleteTopic = function (event, data) {
self.sendDeleteTopic(data);
};
$(document).on(Metamaps.JIT.events.deleteTopic, sendDeleteTopic);
var sendRemoveTopic = function (event, data) {
self.sendRemoveTopic(data);
};
@ -1783,6 +1963,11 @@ Metamaps.Realtime = {
};
$(document).on(Metamaps.JIT.events.newSynapse, sendNewSynapse);
var sendDeleteSynapse = function (event, data) {
self.sendDeleteSynapse(data);
};
$(document).on(Metamaps.JIT.events.deleteSynapse, sendDeleteSynapse);
var sendRemoveSynapse = function (event, data) {
self.sendRemoveSynapse(data);
};
@ -1849,7 +2034,7 @@ Metamaps.Realtime = {
$('.realtimeMapperList ul').append(mapperListItem);
// create a div for the collaborators compass
self.createCompass(data.username, data.userid, data.userimage, self.mappersOnMap[data.userid].color);
self.createCompass(data.username, data.userid, data.userimage, self.mappersOnMap[data.userid].color, !self.status);
}
},
newPeerOnMap: function (data) {
@ -1883,7 +2068,7 @@ Metamaps.Realtime = {
$('.realtimeMapperList ul').append(mapperListItem);
// create a div for the collaborators compass
self.createCompass(data.username, data.userid, data.userimage, self.mappersOnMap[data.userid].color);
self.createCompass(data.username, data.userid, data.userimage, self.mappersOnMap[data.userid].color, !self.status);
Metamaps.GlobalUI.notifyUser(data.username + ' just joined the map');
@ -1899,7 +2084,7 @@ Metamaps.Realtime = {
socket.emit('updateNewMapperList', update);
}
},
createCompass: function(name, id, image, color) {
createCompass: function(name, id, image, color, hide) {
var str = '<img width="28" height="28" src="'+image+'" /><p>'+name+'</p>';
str += '<div id="compassArrow'+id+'" class="compassArrow"></div>';
$('#compass' + id).remove();
@ -1907,6 +2092,9 @@ Metamaps.Realtime = {
id: 'compass' + id,
class: 'collabCompass'
}).html(str).appendTo('#wrapper');
if (hide) {
$('#compass' + id).hide();
}
$('#compass' + id + ' img').css({
'border': '2px solid ' + color
});
@ -2071,6 +2259,75 @@ Metamaps.Realtime = {
Metamaps.Visualize.mGraph.plot();
}
},
sendTopicChange: function (topic) {
var self = Metamaps.Realtime;
var socket = self.socket;
var data = {
topicId: topic.id
}
socket.emit('topicChangeFromClient', data);
},
topicChange: function (data) {
var topic = Metamaps.Topics.get(data.topicId);
if (topic) {
var node = topic.get('node');
topic.fetch({
success: function (model) {
model.set({ node: node });
model.trigger('changeByOther');
}
});
}
},
sendSynapseChange: function (synapse) {
var self = Metamaps.Realtime;
var socket = self.socket;
var data = {
synapseId: synapse.id
}
socket.emit('synapseChangeFromClient', data);
},
synapseChange: function (data) {
var synapse = Metamaps.Synapses.get(data.synapseId);
if (synapse) {
// edge reset necessary because fetch causes model reset
var edge = synapse.get('edge');
synapse.fetch({
success: function (model) {
model.set({ edge: edge });
model.trigger('changeByOther');
}
});
}
},
sendMapChange: function (map) {
var self = Metamaps.Realtime;
var socket = self.socket;
var data = {
mapId: map.id
}
socket.emit('mapChangeFromClient', data);
},
mapChange: function (data) {
/*var map = Metamaps.Topics.get(data.topicId);
if (map) {
var node = topic.get('node');
topic.fetch({
success: function (model) {
// must be set using silent:true otherwise
// will trigger a change event and an infinite
// loop with other clients of change events
model.set({ node: node });
}
});
}*/
},
// newTopic
sendNewTopic: function (data) {
var self = Metamaps.Realtime;
@ -2085,6 +2342,11 @@ Metamaps.Realtime = {
newTopic: function (data) {
var topic, mapping, mapper, mapperCallback, cancel;
var self = Metamaps.Realtime;
var socket = self.socket;
if (!self.status) return;
function test() {
if (topic && mapping && mapper) {
Metamaps.Topic.renderTopic(mapping, topic, false, false);
@ -2126,24 +2388,45 @@ Metamaps.Realtime = {
test();
},
// removeTopic
sendDeleteTopic: function (data) {
var self = Metamaps.Realtime;
var socket = self.socket;
if (Metamaps.Active.Map) {
socket.emit('deleteTopicFromClient', data);
}
},
// removeTopic
sendRemoveTopic: function (data) {
var self = Metamaps.Realtime;
var socket = self.socket;
if (Metamaps.Active.Map && self.status) {
if (Metamaps.Active.Map) {
data.mapid = Metamaps.Active.Map.id;
socket.emit('removeTopic', data);
}
},
removeTopic: function (data) {
var self = Metamaps.Realtime;
var socket = self.socket;
if (!self.status) return;
var topic = Metamaps.Topics.get(data.topicid);
if (topic) {
var node = topic.get('node');
var mapping = topic.getMapping();
Metamaps.Control.hideNode(node.id);
Metamaps.Topics.remove(topic);
Metamaps.Mappings.remove(mapping);
}
},
// newSynapse
sendNewSynapse: function (data) {
var self = Metamaps.Realtime;
var socket = self.socket;
if (Metamaps.Active.Map && self.status) {
if (Metamaps.Active.Map) {
data.mapperid = Metamaps.Active.Mapper.id;
data.mapid = Metamaps.Active.Map.id;
socket.emit('newSynapse', data);
@ -2152,6 +2435,11 @@ Metamaps.Realtime = {
newSynapse: function (data) {
var topic1, topic2, node1, node2, synapse, mapping, cancel;
var self = Metamaps.Realtime;
var socket = self.socket;
if (!self.status) return;
function test() {
if (synapse && mapping && mapper) {
topic1 = synapse.getTopic1();
@ -2196,18 +2484,49 @@ Metamaps.Realtime = {
});
test();
},
// deleteSynapse
sendDeleteSynapse: function (data) {
var self = Metamaps.Realtime;
var socket = self.socket;
if (Metamaps.Active.Map) {
data.mapid = Metamaps.Active.Map.id;
socket.emit('deleteSynapseFromClient', data);
}
},
// removeSynapse
sendRemoveSynapse: function (data) {
var self = Metamaps.Realtime;
var socket = self.socket;
if (Metamaps.Active.Map && self.status) {
if (Metamaps.Active.Map) {
data.mapid = Metamaps.Active.Map.id;
socket.emit('removeSynapse', data);
}
},
removeSynapse: function (data) {
var self = Metamaps.Realtime;
var socket = self.socket;
if (!self.status) return;
var synapse = Metamaps.Synapses.get(data.synapseid);
if (synapse) {
var edge = synapse.get('edge');
var mapping = synapse.getMapping();
if (edge.getData("mappings").length - 1 === 0) {
Metamaps.Control.hideEdge(edge);
}
var index = _.indexOf(edge.getData("synapses"), synapse);
edge.getData("mappings").splice(index, 1);
edge.getData("synapses").splice(index, 1);
if (edge.getData("displayIndex")) {
delete edge.data.$displayIndex;
}
Metamaps.Synapses.remove(synapse);
Metamaps.Mappings.remove(mapping);
}
},
}; // end Metamaps.Realtime
@ -2267,8 +2586,14 @@ Metamaps.Control = {
},
deleteNode: function (nodeid) { // refers to deleting topics permanently
var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid);
Metamaps.Control.deselectNode(node);
Metamaps.Topics.get(nodeid).destroy();
var topic = node.getData('topic');
var topicid = topic.id;
var mapping = node.getData('mapping');
topic.destroy();
Metamaps.Mappings.remove(mapping);
$(document).trigger(Metamaps.JIT.events.deleteTopic, [{
topicid: topicid
}]);
Metamaps.Control.hideNode(nodeid);
},
removeSelectedNodes: function () { // refers to removing topics permanently from a map
@ -2289,8 +2614,14 @@ Metamaps.Control = {
var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid);
if (mapperm) {
Metamaps.Control.deselectNode(node);
node.getData('mapping').destroy();
var topic = node.getData('topic');
var topicid = topic.id;
var mapping = node.getData('mapping');
mapping.destroy();
Metamaps.Topics.remove(topic);
$(document).trigger(Metamaps.JIT.events.removeTopic, [{
topicid: topicid
}]);
Metamaps.Control.hideNode(nodeid);
}
},
@ -2306,9 +2637,10 @@ Metamaps.Control = {
},
hideNode: function (nodeid) {
var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid);
var graph = Metamaps.Visualize.mGraph;
if (nodeid == Metamaps.Visualize.mGraph.root) { // && Metamaps.Visualize.type === "RGraph"
alert("You can't hide this topic, it is the root of your graph.");
return;
var newroot = _.find(graph.graph.nodes, function(n){ return n.id !== nodeid; });
graph.root = newroot ? newroot.id : null;
}
Metamaps.Control.deselectNode(node);
@ -2383,8 +2715,6 @@ Metamaps.Control = {
},
deleteEdge: function (edge) {
// TODO make it so that you select which one, of multiple possible synapses you want to delete
if (edge.getData("synapses").length - 1 === 0) {
Metamaps.Control.hideEdge(edge);
}
@ -2393,6 +2723,7 @@ Metamaps.Control = {
var synapse = edge.getData("synapses")[index];
var mapping = edge.getData("mappings")[index];
var synapseid = synapse.id;
synapse.destroy();
// the server will destroy the mapping, we just need to remove it here
@ -2402,6 +2733,9 @@ Metamaps.Control = {
if (edge.getData("displayIndex")) {
delete edge.data.$displayIndex;
}
$(document).trigger(Metamaps.JIT.events.deleteSynapse, [{
synapseid: synapseid
}]);
},
removeSelectedEdges: function () {
var l = Metamaps.Selected.Edges.length,
@ -2418,8 +2752,6 @@ Metamaps.Control = {
},
removeEdge: function (edge) {
// TODO make it so that you select which one, of multiple possible synapses you want
if (edge.getData("mappings").length - 1 === 0) {
Metamaps.Control.hideEdge(edge);
}
@ -2428,6 +2760,7 @@ Metamaps.Control = {
var synapse = edge.getData("synapses")[index];
var mapping = edge.getData("mappings")[index];
var synapseid = synapse.id;
mapping.destroy();
Metamaps.Synapses.remove(synapse);
@ -2437,6 +2770,9 @@ Metamaps.Control = {
if (edge.getData("displayIndex")) {
delete edge.data.$displayIndex;
}
$(document).trigger(Metamaps.JIT.events.removeSynapse, [{
synapseid: synapseid
}]);
},
hideSelectedEdges: function () {
var edge,
@ -3857,6 +4193,7 @@ Metamaps.Map.InfoBox = {
var name = $(this).html();
$('.mapName').html(name);
Metamaps.Active.Map.set('name', name);
Metamaps.Active.Map.trigger('saved');
});
$('.yourMap .mapPermission').unbind().click(self.onPermissionClick);

View file

@ -3,14 +3,13 @@
div.uv-icon.uv-bottom-left {
background-image:url(feedback_sprite.png);
background-color:#222222;
color:#FFFFFF;
cursor:pointer;
height:108px;
left:0;
margin-left:0px;
text-indent:-100000px;
top:25%;
top:65%;
width:25px;
z-index:100000;
opacity: 1;

View file

@ -75,7 +75,7 @@ class MapsController < ApplicationController
@map = Map.find(params[:id]).authorize_to_show(@current)
if not @map
redirect_to root_url and return
redirect_to root_url, notice: "Access denied. That map is private." and return
end
respond_to do |format|
@ -98,7 +98,7 @@ class MapsController < ApplicationController
@map = Map.find(params[:id]).authorize_to_show(@current)
if not @map
redirect_to root_url and return
redirect_to root_url, notice: "Access denied. That map is private." and return
end
@allmappers = @map.contributors

View file

@ -66,8 +66,7 @@ function start() {
socket.broadcast.emit('maps-' + data.mapid + '-newmapper', newUser);
});
// this will ping everyone on a map that there's a person just left the map
socket.on('disconnect', function () {
var end = function () {
var socketUserName, socketUserID;
socket.get('userid', function (err, id) {
socketUserID = id;
@ -82,7 +81,10 @@ function start() {
socket.get('mapid', function (err, mapid) {
socket.broadcast.emit('maps-' + mapid + '-lostmapper', data);
});
});
};
// this will ping everyone on a map that there's a person just left the map
socket.on('disconnect', end);
socket.on('endMapperNotify', end);
// this will ping everyone on a map that someone just turned on realtime
socket.on('notifyStartRealtime', function (data) {
@ -127,6 +129,22 @@ function start() {
socket.broadcast.emit('maps-' + mapId + '-newTopic', data);
});
socket.on('topicChangeFromClient', function (data) {
socket.broadcast.emit('topicChangeFromServer', data);
});
socket.on('synapseChangeFromClient', function (data) {
socket.broadcast.emit('synapseChangeFromServer', data);
});
socket.on('mapChangeFromClient', function (data) {
socket.broadcast.emit('mapChangeFromServer', data);
});
socket.on('deleteTopicFromClient', function (data) {
socket.broadcast.emit('deleteTopicFromServer', data);
});
socket.on('removeTopic', function (data) {
var mapId = data.mapid;
delete data.mapid;
@ -141,6 +159,10 @@ function start() {
socket.broadcast.emit('maps-' + mapId + '-newSynapse', data);
});
socket.on('deleteSynapseFromClient', function (data) {
socket.broadcast.emit('deleteSynapseFromServer', data);
});
socket.on('removeSynapse', function (data) {
var mapId = data.mapid;
delete data.mapid;