diff --git a/frontend/src/Metamaps/Map/CheatSheet.js b/frontend/src/Metamaps/Map/CheatSheet.js
new file mode 100644
index 00000000..969ee159
--- /dev/null
+++ b/frontend/src/Metamaps/Map/CheatSheet.js
@@ -0,0 +1,27 @@
+const CheatSheet = {
+ init: function () {
+ // tab the cheatsheet
+ $('#cheatSheet').tabs()
+ $('#quickReference').tabs().addClass('ui-tabs-vertical ui-helper-clearfix')
+ $('#quickReference .ui-tabs-nav li').removeClass('ui-corner-top').addClass('ui-corner-left')
+
+ // id = the id of a vimeo video
+ var switchVideo = function (element, id) {
+ $('.tutorialItem').removeClass('active')
+ $(element).addClass('active')
+ $('#tutorialVideo').attr('src', '//player.vimeo.com/video/' + id)
+ }
+
+ $('#gettingStarted').click(function () {
+ // switchVideo(this,'88334167')
+ })
+ $('#upYourSkillz').click(function () {
+ // switchVideo(this,'100118167')
+ })
+ $('#advancedMapping').click(function () {
+ // switchVideo(this,'88334167')
+ })
+ }
+}
+
+export default CheatSheet
diff --git a/frontend/src/Metamaps/Map.js b/frontend/src/Metamaps/Map/InfoBox.js
similarity index 51%
rename from frontend/src/Metamaps/Map.js
rename to frontend/src/Metamaps/Map/InfoBox.js
index cd2c3d2e..eaceba29 100644
--- a/frontend/src/Metamaps/Map.js
+++ b/frontend/src/Metamaps/Map/InfoBox.js
@@ -1,405 +1,19 @@
/* global Metamaps, $ */
import Active from './Active'
-import AutoLayout from './AutoLayout'
-import Create from './Create'
-import Filter from './Filter'
-import GlobalUI from './GlobalUI'
-import JIT from './JIT'
-import Realtime from './Realtime'
-import Selected from './Selected'
-import SynapseCard from './SynapseCard'
-import TopicCard from './TopicCard'
-import Visualize from './Visualize'
+import GlobalUI from '../GlobalUI'
+import Router from '../Router'
/*
- * Metamaps.Map.js.erb
- *
- * Dependencies:
- * - Metamaps.Backbone
- * - Metamaps.Erb
- * - Metamaps.Loading
- * - Metamaps.Mappers
- * - Metamaps.Mappings
- * - Metamaps.Maps
- * - Metamaps.Messages
- * - Metamaps.Router
- * - Metamaps.Synapses
- * - Metamaps.Topics
- *
- * Major sub-modules:
- * - Metamaps.Map.CheatSheet
- * - Metamaps.Map.InfoBox
+ * Metamaps.Collaborators
+ * Metamaps.Erb
+ * Metamaps.Mappers
+ * Metamaps.Maps
+ * Metamaps.Synapses
+ * Metamaps.Topics
*/
-window.Metamaps = window.Metamaps || {}
-Metamaps.Map = {
- events: {
- editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper'
- },
- init: function () {
- var self = Metamaps.Map
-
- // prevent right clicks on the main canvas, so as to not get in the way of our right clicks
- $('#center-container').bind('contextmenu', function (e) {
- return false
- })
-
- $('.starMap').click(function () {
- if ($(this).is('.starred')) self.unstar()
- else self.star()
- })
-
- $('.sidebarFork').click(function () {
- self.fork()
- })
-
- GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html()
-
- self.updateStar()
- self.InfoBox.init()
- self.CheatSheet.init()
-
- $(document).on(Metamaps.Map.events.editedByActiveMapper, self.editedByActiveMapper)
- },
- launch: function (id) {
- var bb = Metamaps.Backbone
- var start = function (data) {
- Active.Map = new bb.Map(data.map)
- Metamaps.Mappers = new bb.MapperCollection(data.mappers)
- Metamaps.Collaborators = new bb.MapperCollection(data.collaborators)
- Metamaps.Topics = new bb.TopicCollection(data.topics)
- Metamaps.Synapses = new bb.SynapseCollection(data.synapses)
- Metamaps.Mappings = new bb.MappingCollection(data.mappings)
- Metamaps.Messages = data.messages
- Metamaps.Stars = data.stars
- Metamaps.Backbone.attachCollectionEvents()
-
- var map = Active.Map
- var mapper = Active.Mapper
-
- // add class to .wrapper for specifying whether you can edit the map
- if (map.authorizeToEdit(mapper)) {
- $('.wrapper').addClass('canEditMap')
- }
-
- // add class to .wrapper for specifying if the map can
- // be collaborated on
- if (map.get('permission') === 'commons') {
- $('.wrapper').addClass('commonsMap')
- }
-
- Metamaps.Map.updateStar()
-
- // set filter mapper H3 text
- $('#filter_by_mapper h3').html('MAPPERS')
-
- // build and render the visualization
- Visualize.type = 'ForceDirected'
- JIT.prepareVizData()
-
- // update filters
- Filter.reset()
-
- // reset selected arrays
- Selected.reset()
-
- // set the proper mapinfobox content
- Metamaps.Map.InfoBox.load()
-
- // these three update the actual filter box with the right list items
- Filter.checkMetacodes()
- Filter.checkSynapses()
- Filter.checkMappers()
-
- Realtime.startActiveMap()
- Metamaps.Loading.hide()
-
- // for mobile
- $('#header_content').html(map.get('name'))
- }
-
- $.ajax({
- url: '/maps/' + id + '/contains.json',
- success: start
- })
- },
- end: function () {
- if (Active.Map) {
- $('.wrapper').removeClass('canEditMap commonsMap')
- AutoLayout.resetSpiral()
-
- $('.rightclickmenu').remove()
- TopicCard.hideCard()
- SynapseCard.hideCard()
- Create.newTopic.hide(true) // true means force (and override pinned)
- Create.newSynapse.hide()
- Filter.close()
- Metamaps.Map.InfoBox.close()
- Realtime.endActiveMap()
- }
- },
- updateStar: function () {
- if (!Active.Mapper || !Metamaps.Stars) return
- // update the star/unstar icon
- if (Metamaps.Stars.find(function (s) { return s.user_id === Active.Mapper.id })) {
- $('.starMap').addClass('starred')
- $('.starMap .tooltipsAbove').html('Unstar')
- } else {
- $('.starMap').removeClass('starred')
- $('.starMap .tooltipsAbove').html('Star')
- }
- },
- star: function () {
- var self = Metamaps.Map
-
- if (!Active.Map) return
- $.post('/maps/' + Active.Map.id + '/star')
- Metamaps.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id })
- Metamaps.Maps.Starred.add(Active.Map)
- GlobalUI.notifyUser('Map is now starred')
- self.updateStar()
- },
- unstar: function () {
- var self = Metamaps.Map
-
- if (!Active.Map) return
- $.post('/maps/' + Active.Map.id + '/unstar')
- Metamaps.Stars = Metamaps.Stars.filter(function (s) { return s.user_id != Active.Mapper.id })
- Metamaps.Maps.Starred.remove(Active.Map)
- self.updateStar()
- },
- fork: function () {
- GlobalUI.openLightbox('forkmap')
-
- var nodes_data = '',
- synapses_data = ''
- var nodes_array = []
- var synapses_array = []
- // collect the unfiltered topics
- Visualize.mGraph.graph.eachNode(function (n) {
- // 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 + ','
- }
- })
- // collect the unfiltered synapses
- Metamaps.Synapses.each(function (synapse) {
- var desc = synapse.get('desc')
-
- var descNotFiltered = 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()
- nodes_data = nodes_data.slice(0, -1)
-
- GlobalUI.CreateMap.topicsToMap = nodes_data
- GlobalUI.CreateMap.synapsesToMap = synapses_data
- },
- leavePrivateMap: function () {
- var map = Active.Map
- Metamaps.Maps.Active.remove(map)
- Metamaps.Maps.Featured.remove(map)
- Metamaps.Router.home()
- GlobalUI.notifyUser('Sorry! That map has been changed to Private.')
- },
- cantEditNow: function () {
- Realtime.turnOff(true); // true is for 'silence'
- GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.')
- Active.Map.trigger('changeByOther')
- },
- canEditNow: function () {
- var confirmString = "You've been granted permission to edit this map. "
- confirmString += 'Do you want to reload and enable realtime collaboration?'
- var c = confirm(confirmString)
- if (c) {
- Metamaps.Router.maps(Active.Map.id)
- }
- },
- editedByActiveMapper: function () {
- if (Active.Mapper) {
- Metamaps.Mappers.add(Active.Mapper)
- }
- },
- 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 = 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
- 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()
- }
-
- var map = 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"
- GlobalUI.notifyUser(downloadMessage)
-
- $.ajax({
- type: 'POST',
- dataType: 'json',
- url: '/maps/' + 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')
- }
- })
- }
-}
-
-/*
- *
- * CHEATSHEET
- *
- */
-Metamaps.Map.CheatSheet = {
- init: function () {
- // tab the cheatsheet
- $('#cheatSheet').tabs()
- $('#quickReference').tabs().addClass('ui-tabs-vertical ui-helper-clearfix')
- $('#quickReference .ui-tabs-nav li').removeClass('ui-corner-top').addClass('ui-corner-left')
-
- // id = the id of a vimeo video
- var switchVideo = function (element, id) {
- $('.tutorialItem').removeClass('active')
- $(element).addClass('active')
- $('#tutorialVideo').attr('src', '//player.vimeo.com/video/' + id)
- }
-
- $('#gettingStarted').click(function () {
- // switchVideo(this,'88334167')
- })
- $('#upYourSkillz').click(function () {
- // switchVideo(this,'100118167')
- })
- $('#advancedMapping').click(function () {
- // switchVideo(this,'88334167')
- })
- }
-}; // end Metamaps.Map.CheatSheet
-
-/*
- *
- * INFOBOX
- *
- */
-Metamaps.Map.InfoBox = {
+const InfoBox = {
isOpen: false,
changing: false,
selectingPermission: false,
@@ -407,7 +21,7 @@ Metamaps.Map.InfoBox = {
nameHTML: '{{name}}',
descHTML: '{{desc}}',
init: function () {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
$('.mapInfoIcon').click(self.toggleBox)
$('.mapInfoBox').click(function (event) {
@@ -426,7 +40,7 @@ Metamaps.Map.InfoBox = {
}
},
toggleBox: function (event) {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
if (self.isOpen) self.close()
else self.open()
@@ -434,7 +48,7 @@ Metamaps.Map.InfoBox = {
event.stopPropagation()
},
open: function () {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
$('.mapInfoIcon div').addClass('hide')
if (!self.isOpen && !self.changing) {
self.changing = true
@@ -445,7 +59,7 @@ Metamaps.Map.InfoBox = {
}
},
close: function () {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
$('.mapInfoIcon div').removeClass('hide')
if (!self.changing) {
@@ -459,7 +73,7 @@ Metamaps.Map.InfoBox = {
}
},
load: function () {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
var map = Active.Map
@@ -494,7 +108,7 @@ Metamaps.Map.InfoBox = {
self.attachEventListeners()
},
attachEventListeners: function () {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
$('.mapInfoBox.canEdit .best_in_place').best_in_place()
@@ -547,7 +161,7 @@ Metamaps.Map.InfoBox = {
$('.mapContributors .tip').unbind().click(function (event) {
event.stopPropagation()
})
- $('.mapContributors .tip li a').click(Metamaps.Router.intercept)
+ $('.mapContributors .tip li a').click(Router.intercept)
$('.mapInfoBox').unbind('.hideTip').bind('click.hideTip', function () {
$('.mapContributors .tip').hide()
@@ -556,7 +170,7 @@ Metamaps.Map.InfoBox = {
self.addTypeahead()
},
addTypeahead: function () {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
if (!Active.Map) return
@@ -603,14 +217,14 @@ Metamaps.Map.InfoBox = {
}
},
removeCollaborator: function (collaboratorId) {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
Metamaps.Collaborators.remove(Metamaps.Collaborators.get(collaboratorId))
var mapperIds = Metamaps.Collaborators.models.map(function (mapper) { return mapper.id })
$.post('/maps/' + Active.Map.id + '/access', { access: mapperIds })
self.updateNumbers()
},
addCollaborator: function (newCollaboratorId) {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
if (Metamaps.Collaborators.get(newCollaboratorId)) {
GlobalUI.notifyUser('That user already has access')
@@ -629,7 +243,7 @@ Metamaps.Map.InfoBox = {
$.getJSON('/users/' + newCollaboratorId + '.json', callback)
},
handleResultClick: function (event, item) {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
self.addCollaborator(item.id)
$('.collaboratorSearchField').typeahead('val', '')
@@ -641,7 +255,7 @@ Metamaps.Map.InfoBox = {
$('.mapInfoBox .mapPermission').removeClass('commons public private').addClass(perm)
},
createContributorList: function () {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators
var activeMapperIsCreator = Active.Mapper && Active.Mapper.id === Active.Map.get('user_id')
var string = ''
@@ -666,7 +280,7 @@ Metamaps.Map.InfoBox = {
updateNumbers: function () {
if (!Active.Map) return
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
var mapper = Active.Mapper
var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators
@@ -689,10 +303,10 @@ Metamaps.Map.InfoBox = {
$('.mapTopics').text(Metamaps.Topics.length)
$('.mapSynapses').text(Metamaps.Synapses.length)
- $('.mapEditedAt').html('Last edited: ' + Metamaps.Util.nowDateFormatted())
+ $('.mapEditedAt').html('Last edited: ' + Util.nowDateFormatted())
},
onPermissionClick: function (event) {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
if (!self.selectingPermission) {
self.selectingPermission = true
@@ -709,14 +323,14 @@ Metamaps.Map.InfoBox = {
}
},
hidePermissionSelect: function () {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
self.selectingPermission = false
$('.mapPermission').removeClass('minimize') // this line flips the pull up arrow to a drop down arrow
$('.mapPermission .permissionSelect').remove()
},
selectPermission: function (event) {
- var self = Metamaps.Map.InfoBox
+ var self = InfoBox
self.selectingPermission = false
var permission = $(this).attr('class')
@@ -740,19 +354,19 @@ Metamaps.Map.InfoBox = {
var authorized = map.authorizePermissionChange(mapper)
if (doIt && authorized) {
- Metamaps.Map.InfoBox.close()
+ InfoBox.close()
Metamaps.Maps.Active.remove(map)
Metamaps.Maps.Featured.remove(map)
Metamaps.Maps.Mine.remove(map)
Metamaps.Maps.Shared.remove(map)
map.destroy()
- Metamaps.Router.home()
+ Router.home()
GlobalUI.notifyUser('Map eliminated!')
}
else if (!authorized) {
alert("Hey now. We can't just go around willy nilly deleting other people's maps now can we? Run off and find something constructive to do, eh?")
}
}
-}; // end Metamaps.Map.InfoBox
+}
-export default Metamaps.Map
+export default InfoBox
diff --git a/frontend/src/Metamaps/Map/index.js b/frontend/src/Metamaps/Map/index.js
new file mode 100644
index 00000000..84ee8b39
--- /dev/null
+++ b/frontend/src/Metamaps/Map/index.js
@@ -0,0 +1,365 @@
+/* global Metamaps, $ */
+
+import Active from './Active'
+import AutoLayout from './AutoLayout'
+import Create from './Create'
+import Filter from './Filter'
+import GlobalUI from './GlobalUI'
+import JIT from './JIT'
+import Realtime from './Realtime'
+import Router from './Router'
+import Selected from './Selected'
+import SynapseCard from './SynapseCard'
+import TopicCard from './TopicCard'
+import Visualize from './Visualize'
+
+import CheatSheet from './CheatSheet'
+import InfoBox from './InfoBox'
+
+/*
+ * Metamaps.Map.js.erb
+ *
+ * Dependencies:
+ * - Metamaps.Backbone
+ * - Metamaps.Erb
+ * - Metamaps.Loading
+ * - Metamaps.Mappers
+ * - Metamaps.Mappings
+ * - Metamaps.Maps
+ * - Metamaps.Messages
+ * - Metamaps.Synapses
+ * - Metamaps.Topics
+ */
+
+const Map = {
+ events: {
+ editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper'
+ },
+ init: function () {
+ var self = Map
+
+ // prevent right clicks on the main canvas, so as to not get in the way of our right clicks
+ $('#center-container').bind('contextmenu', function (e) {
+ return false
+ })
+
+ $('.starMap').click(function () {
+ if ($(this).is('.starred')) self.unstar()
+ else self.star()
+ })
+
+ $('.sidebarFork').click(function () {
+ self.fork()
+ })
+
+ GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html()
+
+ self.updateStar()
+ self.InfoBox.init()
+ CheatSheet.init()
+
+ $(document).on(Map.events.editedByActiveMapper, self.editedByActiveMapper)
+ },
+ launch: function (id) {
+ var bb = Metamaps.Backbone
+ var start = function (data) {
+ Active.Map = new bb.Map(data.map)
+ Metamaps.Mappers = new bb.MapperCollection(data.mappers)
+ Metamaps.Collaborators = new bb.MapperCollection(data.collaborators)
+ Metamaps.Topics = new bb.TopicCollection(data.topics)
+ Metamaps.Synapses = new bb.SynapseCollection(data.synapses)
+ Metamaps.Mappings = new bb.MappingCollection(data.mappings)
+ Metamaps.Messages = data.messages
+ Metamaps.Stars = data.stars
+ Metamaps.Backbone.attachCollectionEvents()
+
+ var map = Active.Map
+ var mapper = Active.Mapper
+
+ // add class to .wrapper for specifying whether you can edit the map
+ if (map.authorizeToEdit(mapper)) {
+ $('.wrapper').addClass('canEditMap')
+ }
+
+ // add class to .wrapper for specifying if the map can
+ // be collaborated on
+ if (map.get('permission') === 'commons') {
+ $('.wrapper').addClass('commonsMap')
+ }
+
+ Map.updateStar()
+
+ // set filter mapper H3 text
+ $('#filter_by_mapper h3').html('MAPPERS')
+
+ // build and render the visualization
+ Visualize.type = 'ForceDirected'
+ JIT.prepareVizData()
+
+ // update filters
+ Filter.reset()
+
+ // reset selected arrays
+ Selected.reset()
+
+ // set the proper mapinfobox content
+ Map.InfoBox.load()
+
+ // these three update the actual filter box with the right list items
+ Filter.checkMetacodes()
+ Filter.checkSynapses()
+ Filter.checkMappers()
+
+ Realtime.startActiveMap()
+ Metamaps.Loading.hide()
+
+ // for mobile
+ $('#header_content').html(map.get('name'))
+ }
+
+ $.ajax({
+ url: '/maps/' + id + '/contains.json',
+ success: start
+ })
+ },
+ end: function () {
+ if (Active.Map) {
+ $('.wrapper').removeClass('canEditMap commonsMap')
+ AutoLayout.resetSpiral()
+
+ $('.rightclickmenu').remove()
+ TopicCard.hideCard()
+ SynapseCard.hideCard()
+ Create.newTopic.hide(true) // true means force (and override pinned)
+ Create.newSynapse.hide()
+ Filter.close()
+ Map.InfoBox.close()
+ Realtime.endActiveMap()
+ }
+ },
+ updateStar: function () {
+ if (!Active.Mapper || !Metamaps.Stars) return
+ // update the star/unstar icon
+ if (Metamaps.Stars.find(function (s) { return s.user_id === Active.Mapper.id })) {
+ $('.starMap').addClass('starred')
+ $('.starMap .tooltipsAbove').html('Unstar')
+ } else {
+ $('.starMap').removeClass('starred')
+ $('.starMap .tooltipsAbove').html('Star')
+ }
+ },
+ star: function () {
+ var self = Map
+
+ if (!Active.Map) return
+ $.post('/maps/' + Active.Map.id + '/star')
+ Metamaps.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id })
+ Metamaps.Maps.Starred.add(Active.Map)
+ GlobalUI.notifyUser('Map is now starred')
+ self.updateStar()
+ },
+ unstar: function () {
+ var self = Map
+
+ if (!Active.Map) return
+ $.post('/maps/' + Active.Map.id + '/unstar')
+ Metamaps.Stars = Metamaps.Stars.filter(function (s) { return s.user_id != Active.Mapper.id })
+ Metamaps.Maps.Starred.remove(Active.Map)
+ self.updateStar()
+ },
+ fork: function () {
+ GlobalUI.openLightbox('forkmap')
+
+ var nodes_data = '',
+ synapses_data = ''
+ var nodes_array = []
+ var synapses_array = []
+ // collect the unfiltered topics
+ Visualize.mGraph.graph.eachNode(function (n) {
+ // 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 + ','
+ }
+ })
+ // collect the unfiltered synapses
+ Metamaps.Synapses.each(function (synapse) {
+ var desc = synapse.get('desc')
+
+ var descNotFiltered = 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()
+ nodes_data = nodes_data.slice(0, -1)
+
+ GlobalUI.CreateMap.topicsToMap = nodes_data
+ GlobalUI.CreateMap.synapsesToMap = synapses_data
+ },
+ leavePrivateMap: function () {
+ var map = Active.Map
+ Metamaps.Maps.Active.remove(map)
+ Metamaps.Maps.Featured.remove(map)
+ Router.home()
+ GlobalUI.notifyUser('Sorry! That map has been changed to Private.')
+ },
+ cantEditNow: function () {
+ Realtime.turnOff(true); // true is for 'silence'
+ GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.')
+ Active.Map.trigger('changeByOther')
+ },
+ canEditNow: function () {
+ var confirmString = "You've been granted permission to edit this map. "
+ confirmString += 'Do you want to reload and enable realtime collaboration?'
+ var c = confirm(confirmString)
+ if (c) {
+ Router.maps(Active.Map.id)
+ }
+ },
+ editedByActiveMapper: function () {
+ if (Active.Mapper) {
+ Metamaps.Mappers.add(Active.Mapper)
+ }
+ },
+ 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 = 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
+ 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()
+ }
+
+ var map = 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"
+ GlobalUI.notifyUser(downloadMessage)
+
+ $.ajax({
+ type: 'POST',
+ dataType: 'json',
+ url: '/maps/' + 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')
+ }
+ })
+ }
+}
+
+export CheatSheet, InfoBox
+export default Map
diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js
index 9fe8925b..7b431d1f 100644
--- a/frontend/src/Metamaps/index.js
+++ b/frontend/src/Metamaps/index.js
@@ -13,7 +13,7 @@ import GlobalUI from './GlobalUI'
import Import from './Import'
import JIT from './JIT'
import Listeners from './Listeners'
-import Map from './Map'
+import Map, { CheatSheet, InfoBox } from './Map'
import Mapper from './Mapper'
import Mobile from './Mobile'
import Mouse from './Mouse'
@@ -46,6 +46,8 @@ Metamaps.Import = Import
Metamaps.JIT = JIT
Metamaps.Listeners = Listeners
Metamaps.Map = Map
+Metamaps.Map.CheatSheet = CheatSheet
+Metamaps.Map.InfoBox = InfoBox
Metamaps.Maps = {}
Metamaps.Mapper = Mapper
Metamaps.Mobile = Mobile