Metamaps.Map
This commit is contained in:
parent
13d6ab56e5
commit
11a87582c7
3 changed files with 668 additions and 649 deletions
|
@ -25,6 +25,7 @@
|
||||||
//= require ./src/views/room
|
//= require ./src/views/room
|
||||||
//= require ./src/JIT
|
//= require ./src/JIT
|
||||||
//= require ./src/Metamaps
|
//= require ./src/Metamaps
|
||||||
|
//= require ./src/Metamaps.Map
|
||||||
//= require ./src/Metamaps.Account
|
//= require ./src/Metamaps.Account
|
||||||
//= require ./src/Metamaps.Mapper
|
//= require ./src/Metamaps.Mapper
|
||||||
//= require ./src/Metamaps.Admin
|
//= require ./src/Metamaps.Admin
|
||||||
|
|
667
app/assets/javascripts/src/Metamaps.Map.js.erb
Normal file
667
app/assets/javascripts/src/Metamaps.Map.js.erb
Normal file
|
@ -0,0 +1,667 @@
|
||||||
|
/* global Metamaps, $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metamaps.Map.js.erb
|
||||||
|
*
|
||||||
|
* Dependencies:
|
||||||
|
* Metamaps.Create
|
||||||
|
* Metamaps.Filter
|
||||||
|
* Metamaps.JIT
|
||||||
|
* Metamaps.Loading
|
||||||
|
* Metamaps.Maps
|
||||||
|
* Metamaps.Realtime
|
||||||
|
* Metamaps.Router
|
||||||
|
* Metamaps.Selected
|
||||||
|
* Metamaps.SynapseCard
|
||||||
|
* Metamaps.TopicCard
|
||||||
|
* Metamaps.Visualize
|
||||||
|
* - Metamaps.Active
|
||||||
|
* - Metamaps.Backbone
|
||||||
|
* - Metamaps.GlobalUI
|
||||||
|
* - Metamaps.Mappers
|
||||||
|
* - Metamaps.Mappings
|
||||||
|
* - Metamaps.Messages
|
||||||
|
* - Metamaps.Synapses
|
||||||
|
* - Metamaps.Topics
|
||||||
|
*
|
||||||
|
* Major sub-modules:
|
||||||
|
* - Metamaps.Map.CheatSheet
|
||||||
|
* - Metamaps.Map.InfoBox
|
||||||
|
*/
|
||||||
|
|
||||||
|
Metamaps.Map = {
|
||||||
|
events: {
|
||||||
|
editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper'
|
||||||
|
},
|
||||||
|
nextX: 0,
|
||||||
|
nextY: 0,
|
||||||
|
sideLength: 1,
|
||||||
|
turnCount: 0,
|
||||||
|
nextXshift: 1,
|
||||||
|
nextYshift: 0,
|
||||||
|
timeToTurn: 0,
|
||||||
|
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
|
||||||
|
})
|
||||||
|
|
||||||
|
$('.sidebarFork').click(function () {
|
||||||
|
self.fork()
|
||||||
|
})
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html()
|
||||||
|
|
||||||
|
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) {
|
||||||
|
Metamaps.Active.Map = new bb.Map(data.map)
|
||||||
|
Metamaps.Mappers = new bb.MapperCollection(data.mappers)
|
||||||
|
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.Backbone.attachCollectionEvents()
|
||||||
|
|
||||||
|
var map = Metamaps.Active.Map
|
||||||
|
var mapper = Metamaps.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')
|
||||||
|
}
|
||||||
|
|
||||||
|
// set filter mapper H3 text
|
||||||
|
$('#filter_by_mapper h3').html('MAPPERS')
|
||||||
|
|
||||||
|
// build and render the visualization
|
||||||
|
Metamaps.Visualize.type = 'ForceDirected'
|
||||||
|
Metamaps.JIT.prepareVizData()
|
||||||
|
|
||||||
|
// update filters
|
||||||
|
Metamaps.Filter.reset()
|
||||||
|
|
||||||
|
// reset selected arrays
|
||||||
|
Metamaps.Selected.reset()
|
||||||
|
|
||||||
|
// set the proper mapinfobox content
|
||||||
|
Metamaps.Map.InfoBox.load()
|
||||||
|
|
||||||
|
// these three update the actual filter box with the right list items
|
||||||
|
Metamaps.Filter.checkMetacodes()
|
||||||
|
Metamaps.Filter.checkSynapses()
|
||||||
|
Metamaps.Filter.checkMappers()
|
||||||
|
|
||||||
|
Metamaps.Realtime.startActiveMap()
|
||||||
|
Metamaps.Loading.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/maps/' + id + '/contains.json',
|
||||||
|
success: start
|
||||||
|
})
|
||||||
|
},
|
||||||
|
end: function () {
|
||||||
|
if (Metamaps.Active.Map) {
|
||||||
|
$('.wrapper').removeClass('canEditMap commonsMap')
|
||||||
|
Metamaps.Map.resetSpiral()
|
||||||
|
|
||||||
|
$('.rightclickmenu').remove()
|
||||||
|
Metamaps.TopicCard.hideCard()
|
||||||
|
Metamaps.SynapseCard.hideCard()
|
||||||
|
Metamaps.Create.newTopic.hide()
|
||||||
|
Metamaps.Create.newSynapse.hide()
|
||||||
|
Metamaps.Filter.close()
|
||||||
|
Metamaps.Map.InfoBox.close()
|
||||||
|
Metamaps.Realtime.endActiveMap()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fork: function () {
|
||||||
|
Metamaps.GlobalUI.openLightbox('forkmap')
|
||||||
|
|
||||||
|
var nodes_data = '',
|
||||||
|
synapses_data = ''
|
||||||
|
var nodes_array = []
|
||||||
|
var synapses_array = []
|
||||||
|
// collect the unfiltered topics
|
||||||
|
Metamaps.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 = Metamaps.Filter.visible.synapses.indexOf(desc) > -1
|
||||||
|
// make sure that both topics are being added, otherwise, it
|
||||||
|
// doesn't make sense to add the synapse
|
||||||
|
var topicsNotFiltered = nodes_array.indexOf(synapse.get('node1_id')) > -1
|
||||||
|
topicsNotFiltered = topicsNotFiltered && nodes_array.indexOf(synapse.get('node2_id')) > -1
|
||||||
|
if (descNotFiltered && topicsNotFiltered) {
|
||||||
|
synapses_array.push(synapse.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
synapses_data = synapses_array.join()
|
||||||
|
nodes_data = nodes_data.slice(0, -1)
|
||||||
|
|
||||||
|
Metamaps.GlobalUI.CreateMap.topicsToMap = nodes_data
|
||||||
|
Metamaps.GlobalUI.CreateMap.synapsesToMap = synapses_data
|
||||||
|
},
|
||||||
|
leavePrivateMap: function () {
|
||||||
|
var map = Metamaps.Active.Map
|
||||||
|
Metamaps.Maps.Active.remove(map)
|
||||||
|
Metamaps.Maps.Featured.remove(map)
|
||||||
|
Metamaps.Router.home()
|
||||||
|
Metamaps.GlobalUI.notifyUser('Sorry! That map has been changed to Private.')
|
||||||
|
},
|
||||||
|
commonsToPublic: function () {
|
||||||
|
Metamaps.Realtime.turnOff(true); // true is for 'silence'
|
||||||
|
Metamaps.GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.')
|
||||||
|
Metamaps.Active.Map.trigger('changeByOther')
|
||||||
|
},
|
||||||
|
publicToCommons: function () {
|
||||||
|
var confirmString = 'This map permission has been changed to Commons! '
|
||||||
|
confirmString += 'Do you want to reload and enable realtime collaboration?'
|
||||||
|
var c = confirm(confirmString)
|
||||||
|
if (c) {
|
||||||
|
Metamaps.Router.maps(Metamaps.Active.Map.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editedByActiveMapper: function () {
|
||||||
|
if (Metamaps.Active.Mapper) {
|
||||||
|
Metamaps.Mappers.add(Metamaps.Active.Mapper)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getNextCoord: function () {
|
||||||
|
var self = Metamaps.Map
|
||||||
|
var nextX = self.nextX
|
||||||
|
var nextY = self.nextY
|
||||||
|
|
||||||
|
var DISTANCE_BETWEEN = 120
|
||||||
|
|
||||||
|
self.nextX = self.nextX + DISTANCE_BETWEEN * self.nextXshift
|
||||||
|
self.nextY = self.nextY + DISTANCE_BETWEEN * self.nextYshift
|
||||||
|
|
||||||
|
self.timeToTurn += 1
|
||||||
|
// if true, it's time to turn
|
||||||
|
if (self.timeToTurn === self.sideLength) {
|
||||||
|
self.turnCount += 1
|
||||||
|
// if true, it's time to increase side length
|
||||||
|
if (self.turnCount % 2 === 0) {
|
||||||
|
self.sideLength += 1
|
||||||
|
}
|
||||||
|
self.timeToTurn = 0
|
||||||
|
|
||||||
|
// going right? turn down
|
||||||
|
if (self.nextXshift == 1 && self.nextYshift == 0) {
|
||||||
|
self.nextXshift = 0
|
||||||
|
self.nextYshift = 1
|
||||||
|
}
|
||||||
|
// going down? turn left
|
||||||
|
else if (self.nextXshift == 0 && self.nextYshift == 1) {
|
||||||
|
self.nextXshift = -1
|
||||||
|
self.nextYshift = 0
|
||||||
|
}
|
||||||
|
// going left? turn up
|
||||||
|
else if (self.nextXshift == -1 && self.nextYshift == 0) {
|
||||||
|
self.nextXshift = 0
|
||||||
|
self.nextYshift = -1
|
||||||
|
}
|
||||||
|
// going up? turn right
|
||||||
|
else if (self.nextXshift == 0 && self.nextYshift == -1) {
|
||||||
|
self.nextXshift = 1
|
||||||
|
self.nextYshift = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: nextX,
|
||||||
|
y: nextY
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetSpiral: function () {
|
||||||
|
Metamaps.Map.nextX = 0
|
||||||
|
Metamaps.Map.nextY = 0
|
||||||
|
Metamaps.Map.nextXshift = 1
|
||||||
|
Metamaps.Map.nextYshift = 0
|
||||||
|
Metamaps.Map.sideLength = 1
|
||||||
|
Metamaps.Map.timeToTurn = 0
|
||||||
|
Metamaps.Map.turnCount = 0
|
||||||
|
},
|
||||||
|
exportImage: function () {
|
||||||
|
var canvas = {}
|
||||||
|
|
||||||
|
canvas.canvas = document.createElement('canvas')
|
||||||
|
canvas.canvas.width = 1880 // 960
|
||||||
|
canvas.canvas.height = 1260 // 630
|
||||||
|
|
||||||
|
canvas.scaleOffsetX = 1
|
||||||
|
canvas.scaleOffsetY = 1
|
||||||
|
canvas.translateOffsetY = 0
|
||||||
|
canvas.translateOffsetX = 0
|
||||||
|
canvas.denySelected = true
|
||||||
|
|
||||||
|
canvas.getSize = function () {
|
||||||
|
if (this.size) return this.size
|
||||||
|
var canvas = this.canvas
|
||||||
|
return this.size = {
|
||||||
|
width: canvas.width,
|
||||||
|
height: canvas.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
canvas.scale = function (x, y) {
|
||||||
|
var px = this.scaleOffsetX * x,
|
||||||
|
py = this.scaleOffsetY * y
|
||||||
|
var dx = this.translateOffsetX * (x - 1) / px,
|
||||||
|
dy = this.translateOffsetY * (y - 1) / py
|
||||||
|
this.scaleOffsetX = px
|
||||||
|
this.scaleOffsetY = py
|
||||||
|
this.getCtx().scale(x, y)
|
||||||
|
this.translate(dx, dy)
|
||||||
|
}
|
||||||
|
canvas.translate = function (x, y) {
|
||||||
|
var sx = this.scaleOffsetX,
|
||||||
|
sy = this.scaleOffsetY
|
||||||
|
this.translateOffsetX += x * sx
|
||||||
|
this.translateOffsetY += y * sy
|
||||||
|
this.getCtx().translate(x, y)
|
||||||
|
}
|
||||||
|
canvas.getCtx = function () {
|
||||||
|
return this.canvas.getContext('2d')
|
||||||
|
}
|
||||||
|
// center it
|
||||||
|
canvas.getCtx().translate(1880 / 2, 1260 / 2)
|
||||||
|
|
||||||
|
var mGraph = Metamaps.Visualize.mGraph
|
||||||
|
|
||||||
|
var id = mGraph.root
|
||||||
|
var root = mGraph.graph.getNode(id)
|
||||||
|
var T = !!root.visited
|
||||||
|
|
||||||
|
// pass true to avoid basing it on a selection
|
||||||
|
Metamaps.JIT.zoomExtents(null, canvas, true)
|
||||||
|
|
||||||
|
var c = canvas.canvas,
|
||||||
|
ctx = canvas.getCtx(),
|
||||||
|
scale = canvas.scaleOffsetX
|
||||||
|
|
||||||
|
// draw a grey background
|
||||||
|
ctx.fillStyle = '#d8d9da'
|
||||||
|
var xPoint = (-(c.width / scale) / 2) - (canvas.translateOffsetX / scale),
|
||||||
|
yPoint = (-(c.height / scale) / 2) - (canvas.translateOffsetY / scale)
|
||||||
|
ctx.fillRect(xPoint, yPoint, c.width / scale, c.height / scale)
|
||||||
|
|
||||||
|
// draw the graph
|
||||||
|
mGraph.graph.eachNode(function (node) {
|
||||||
|
var nodeAlpha = node.getData('alpha')
|
||||||
|
node.eachAdjacency(function (adj) {
|
||||||
|
var nodeTo = adj.nodeTo
|
||||||
|
if (!!nodeTo.visited === T && node.drawn && nodeTo.drawn) {
|
||||||
|
mGraph.fx.plotLine(adj, canvas)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (node.drawn) {
|
||||||
|
mGraph.fx.plotNode(node, canvas)
|
||||||
|
}
|
||||||
|
if (!mGraph.labelsHidden) {
|
||||||
|
if (node.drawn && nodeAlpha >= 0.95) {
|
||||||
|
mGraph.labels.plotLabel(canvas, node)
|
||||||
|
} else {
|
||||||
|
mGraph.labels.hideLabel(node, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node.visited = !T
|
||||||
|
})
|
||||||
|
|
||||||
|
var imageData = {
|
||||||
|
encoded_image: canvas.canvas.toDataURL()
|
||||||
|
}
|
||||||
|
|
||||||
|
var map = Metamaps.Active.Map
|
||||||
|
|
||||||
|
var today = new Date()
|
||||||
|
var dd = today.getDate()
|
||||||
|
var mm = today.getMonth() + 1; // January is 0!
|
||||||
|
var yyyy = today.getFullYear()
|
||||||
|
if (dd < 10) {
|
||||||
|
dd = '0' + dd
|
||||||
|
}
|
||||||
|
if (mm < 10) {
|
||||||
|
mm = '0' + mm
|
||||||
|
}
|
||||||
|
today = mm + '/' + dd + '/' + yyyy
|
||||||
|
|
||||||
|
var mapName = map.get('name').split(' ').join([separator = '-'])
|
||||||
|
var downloadMessage = ''
|
||||||
|
downloadMessage += 'Captured map screenshot! '
|
||||||
|
downloadMessage += "<a href='" + imageData.encoded_image + "' "
|
||||||
|
downloadMessage += "download='metamap-" + map.id + '-' + mapName + '-' + today + ".png'>DOWNLOAD</a>"
|
||||||
|
Metamaps.GlobalUI.notifyUser(downloadMessage)
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
dataType: 'json',
|
||||||
|
url: '/maps/' + Metamaps.Active.Map.id + '/upload_screenshot',
|
||||||
|
data: imageData,
|
||||||
|
success: function (data) {
|
||||||
|
console.log('successfully uploaded map screenshot')
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
console.log('failed to save map screenshot')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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 = {
|
||||||
|
isOpen: false,
|
||||||
|
changing: false,
|
||||||
|
selectingPermission: false,
|
||||||
|
changePermissionText: "<div class='tooltips'>As the creator, you can change the permission of this map, but the permissions of the topics and synapses on it must be changed independently.</div>",
|
||||||
|
nameHTML: '<span class="best_in_place best_in_place_name" id="best_in_place_map_{{id}}_name" data-url="/maps/{{id}}" data-object="map" data-attribute="name" data-type="textarea" data-activator="#mapInfoName">{{name}}</span>',
|
||||||
|
descHTML: '<span class="best_in_place best_in_place_desc" id="best_in_place_map_{{id}}_desc" data-url="/maps/{{id}}" data-object="map" data-attribute="desc" data-nil="Click to add description..." data-type="textarea" data-activator="#mapInfoDesc">{{desc}}</span>',
|
||||||
|
init: function () {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
|
||||||
|
$('.mapInfoIcon').click(self.toggleBox)
|
||||||
|
$('.mapInfoBox').click(function (event) {
|
||||||
|
event.stopPropagation()
|
||||||
|
})
|
||||||
|
$('body').click(self.close)
|
||||||
|
|
||||||
|
self.attachEventListeners()
|
||||||
|
|
||||||
|
self.generateBoxHTML = Hogan.compile($('#mapInfoBoxTemplate').html())
|
||||||
|
},
|
||||||
|
toggleBox: function (event) {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
|
||||||
|
if (self.isOpen) self.close()
|
||||||
|
else self.open()
|
||||||
|
|
||||||
|
event.stopPropagation()
|
||||||
|
},
|
||||||
|
open: function () {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
$('.mapInfoIcon div').addClass('hide')
|
||||||
|
if (!self.isOpen && !self.changing) {
|
||||||
|
self.changing = true
|
||||||
|
$('.mapInfoBox').fadeIn(200, function () {
|
||||||
|
self.changing = false
|
||||||
|
self.isOpen = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
|
||||||
|
$('.mapInfoIcon div').removeClass('hide')
|
||||||
|
if (!self.changing) {
|
||||||
|
self.changing = true
|
||||||
|
$('.mapInfoBox').fadeOut(200, function () {
|
||||||
|
self.changing = false
|
||||||
|
self.isOpen = false
|
||||||
|
self.hidePermissionSelect()
|
||||||
|
$('.mapContributors .tip').hide()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
load: function () {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
|
||||||
|
var map = Metamaps.Active.Map
|
||||||
|
|
||||||
|
var obj = map.pick('permission', 'contributor_count', 'topic_count', 'synapse_count')
|
||||||
|
|
||||||
|
var isCreator = map.authorizePermissionChange(Metamaps.Active.Mapper)
|
||||||
|
var canEdit = map.authorizeToEdit(Metamaps.Active.Mapper)
|
||||||
|
var shareable = map.get('permission') !== 'private'
|
||||||
|
|
||||||
|
obj['name'] = canEdit ? Hogan.compile(self.nameHTML).render({id: map.id, name: map.get('name')}) : map.get('name')
|
||||||
|
obj['desc'] = canEdit ? Hogan.compile(self.descHTML).render({id: map.id, desc: map.get('desc')}) : map.get('desc')
|
||||||
|
obj['map_creator_tip'] = isCreator ? self.changePermissionText : ''
|
||||||
|
obj['contributors_class'] = Metamaps.Mappers.length > 1 ? 'multiple' : ''
|
||||||
|
obj['contributors_class'] += Metamaps.Mappers.length === 2 ? ' mTwo' : ''
|
||||||
|
obj['contributor_image'] = Metamaps.Mappers.length > 0 ? Metamaps.Mappers.models[0].get('image') : "<%= asset_path('user.png') %>"
|
||||||
|
obj['contributor_list'] = self.createContributorList()
|
||||||
|
obj['user_name'] = isCreator ? 'You' : map.get('user_name')
|
||||||
|
obj['created_at'] = map.get('created_at_clean')
|
||||||
|
obj['updated_at'] = map.get('updated_at_clean')
|
||||||
|
|
||||||
|
var classes = isCreator ? 'yourMap' : ''
|
||||||
|
classes += canEdit ? ' canEdit' : ''
|
||||||
|
classes += shareable ? ' shareable' : ''
|
||||||
|
$('.mapInfoBox').removeClass('shareable yourMap canEdit')
|
||||||
|
.addClass(classes)
|
||||||
|
.html(self.generateBoxHTML.render(obj))
|
||||||
|
|
||||||
|
self.attachEventListeners()
|
||||||
|
},
|
||||||
|
attachEventListeners: function () {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
|
||||||
|
$('.mapInfoBox.canEdit .best_in_place').best_in_place()
|
||||||
|
|
||||||
|
// because anyone who can edit the map can change the map title
|
||||||
|
var bipName = $('.mapInfoBox .best_in_place_name')
|
||||||
|
bipName.unbind('best_in_place:activate').bind('best_in_place:activate', function () {
|
||||||
|
var $el = bipName.find('textarea')
|
||||||
|
var el = $el[0]
|
||||||
|
|
||||||
|
$el.attr('maxlength', '140')
|
||||||
|
|
||||||
|
$('.mapInfoName').append('<div class="nameCounter forMap"></div>')
|
||||||
|
|
||||||
|
var callback = function (data) {
|
||||||
|
$('.nameCounter.forMap').html(data.all + '/140')
|
||||||
|
}
|
||||||
|
Countable.live(el, callback)
|
||||||
|
})
|
||||||
|
bipName.unbind('best_in_place:deactivate').bind('best_in_place:deactivate', function () {
|
||||||
|
$('.nameCounter.forMap').remove()
|
||||||
|
})
|
||||||
|
|
||||||
|
$('.mapInfoName .best_in_place_name').unbind('ajax:success').bind('ajax:success', function () {
|
||||||
|
var name = $(this).html()
|
||||||
|
Metamaps.Active.Map.set('name', name)
|
||||||
|
Metamaps.Active.Map.trigger('saved')
|
||||||
|
})
|
||||||
|
|
||||||
|
$('.mapInfoDesc .best_in_place_desc').unbind('ajax:success').bind('ajax:success', function () {
|
||||||
|
var desc = $(this).html()
|
||||||
|
Metamaps.Active.Map.set('desc', desc)
|
||||||
|
Metamaps.Active.Map.trigger('saved')
|
||||||
|
})
|
||||||
|
|
||||||
|
$('.yourMap .mapPermission').unbind().click(self.onPermissionClick)
|
||||||
|
// .yourMap in the unbind/bind is just a namespace for the events
|
||||||
|
// not a reference to the class .yourMap on the .mapInfoBox
|
||||||
|
$('.mapInfoBox.yourMap').unbind('.yourMap').bind('click.yourMap', self.hidePermissionSelect)
|
||||||
|
|
||||||
|
$('.yourMap .mapInfoDelete').unbind().click(self.deleteActiveMap)
|
||||||
|
|
||||||
|
$('.mapContributors span, #mapContribs').unbind().click(function (event) {
|
||||||
|
$('.mapContributors .tip').toggle()
|
||||||
|
event.stopPropagation()
|
||||||
|
})
|
||||||
|
$('.mapContributors .tip').unbind().click(function (event) {
|
||||||
|
event.stopPropagation()
|
||||||
|
})
|
||||||
|
$('.mapContributors .tip li a').click(Metamaps.Router.intercept)
|
||||||
|
|
||||||
|
$('.mapInfoBox').unbind('.hideTip').bind('click.hideTip', function () {
|
||||||
|
$('.mapContributors .tip').hide()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateNameDescPerm: function (name, desc, perm) {
|
||||||
|
$('.mapInfoName .best_in_place_name').html(name)
|
||||||
|
$('.mapInfoDesc .best_in_place_desc').html(desc)
|
||||||
|
$('.mapInfoBox .mapPermission').removeClass('commons public private').addClass(perm)
|
||||||
|
},
|
||||||
|
createContributorList: function () {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
|
||||||
|
var string = ''
|
||||||
|
string += '<ul>'
|
||||||
|
|
||||||
|
Metamaps.Mappers.each(function (m) {
|
||||||
|
string += '<li><a href="/explore/mapper/' + m.get('id') + '">' + '<img class="rtUserImage" width="25" height="25" src="' + m.get('image') + '" />' + m.get('name') + '</a></li>'
|
||||||
|
})
|
||||||
|
|
||||||
|
string += '</ul>'
|
||||||
|
return string
|
||||||
|
},
|
||||||
|
updateNumbers: function () {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
var mapper = Metamaps.Active.Mapper
|
||||||
|
|
||||||
|
var contributors_class = ''
|
||||||
|
if (Metamaps.Mappers.length === 2) contributors_class = 'multiple mTwo'
|
||||||
|
else if (Metamaps.Mappers.length > 2) contributors_class = 'multiple'
|
||||||
|
|
||||||
|
var contributors_image = "<%= asset_path('user.png') %>"
|
||||||
|
if (Metamaps.Mappers.length > 0) {
|
||||||
|
// get the first contributor and use their image
|
||||||
|
contributors_image = Metamaps.Mappers.models[0].get('image')
|
||||||
|
}
|
||||||
|
$('.mapContributors img').attr('src', contributors_image).removeClass('multiple mTwo').addClass(contributors_class)
|
||||||
|
$('.mapContributors span').text(Metamaps.Mappers.length)
|
||||||
|
$('.mapContributors .tip').html(self.createContributorList())
|
||||||
|
$('.mapTopics').text(Metamaps.Topics.length)
|
||||||
|
$('.mapSynapses').text(Metamaps.Synapses.length)
|
||||||
|
|
||||||
|
$('.mapEditedAt').html('<span>Last edited: </span>' + Metamaps.Util.nowDateFormatted())
|
||||||
|
},
|
||||||
|
onPermissionClick: function (event) {
|
||||||
|
var self = Metamaps.Map.InfoBox
|
||||||
|
|
||||||
|
if (!self.selectingPermission) {
|
||||||
|
self.selectingPermission = true
|
||||||
|
$(this).addClass('minimize') // this line flips the drop down arrow to a pull up arrow
|
||||||
|
if ($(this).hasClass('commons')) {
|
||||||
|
$(this).append('<ul class="permissionSelect"><li class="public"></li><li class="private"></li></ul>')
|
||||||
|
} else if ($(this).hasClass('public')) {
|
||||||
|
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="private"></li></ul>')
|
||||||
|
} else if ($(this).hasClass('private')) {
|
||||||
|
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="public"></li></ul>')
|
||||||
|
}
|
||||||
|
$('.mapPermission .permissionSelect li').click(self.selectPermission)
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hidePermissionSelect: function () {
|
||||||
|
var self = Metamaps.Map.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
|
||||||
|
|
||||||
|
self.selectingPermission = false
|
||||||
|
var permission = $(this).attr('class')
|
||||||
|
var permBefore = Metamaps.Active.Map.get('permission')
|
||||||
|
Metamaps.Active.Map.save({
|
||||||
|
permission: permission
|
||||||
|
})
|
||||||
|
Metamaps.Active.Map.updateMapWrapper()
|
||||||
|
if (permBefore !== 'commons' && permission === 'commons') {
|
||||||
|
Metamaps.Realtime.setupSocket()
|
||||||
|
Metamaps.Realtime.turnOn()
|
||||||
|
}
|
||||||
|
else if (permBefore === 'commons' && permission === 'public') {
|
||||||
|
Metamaps.Realtime.turnOff(true); // true is to 'silence'
|
||||||
|
// the notification that would otherwise be sent
|
||||||
|
}
|
||||||
|
shareable = permission === 'private' ? '' : 'shareable'
|
||||||
|
$('.mapPermission').removeClass('commons public private minimize').addClass(permission)
|
||||||
|
$('.mapPermission .permissionSelect').remove()
|
||||||
|
$('.mapInfoBox').removeClass('shareable').addClass(shareable)
|
||||||
|
event.stopPropagation()
|
||||||
|
},
|
||||||
|
deleteActiveMap: function () {
|
||||||
|
var confirmString = 'Are you sure you want to delete this map? '
|
||||||
|
confirmString += 'This action is irreversible. It will not delete the topics and synapses on the map.'
|
||||||
|
|
||||||
|
var doIt = confirm(confirmString)
|
||||||
|
var map = Metamaps.Active.Map
|
||||||
|
var mapper = Metamaps.Active.Mapper
|
||||||
|
var authorized = map.authorizePermissionChange(mapper)
|
||||||
|
|
||||||
|
if (doIt && authorized) {
|
||||||
|
Metamaps.Map.InfoBox.close()
|
||||||
|
Metamaps.Maps.Active.remove(map)
|
||||||
|
Metamaps.Maps.Featured.remove(map)
|
||||||
|
Metamaps.Maps.Mine.remove(map)
|
||||||
|
map.destroy()
|
||||||
|
Metamaps.Router.home()
|
||||||
|
Metamaps.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
|
|
@ -4729,652 +4729,3 @@ Metamaps.Synapse = {
|
||||||
self.renderSynapse(mapping, synapse, node1, node2, true);
|
self.renderSynapse(mapping, synapse, node1, node2, true);
|
||||||
}
|
}
|
||||||
}; // end Metamaps.Synapse
|
}; // end Metamaps.Synapse
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* MAP
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
Metamaps.Map = {
|
|
||||||
events: {
|
|
||||||
editedByActiveMapper: "Metamaps:Map:events:editedByActiveMapper"
|
|
||||||
},
|
|
||||||
nextX: 0,
|
|
||||||
nextY: 0,
|
|
||||||
sideLength: 1,
|
|
||||||
turnCount: 0,
|
|
||||||
nextXshift: 1,
|
|
||||||
nextYshift: 0,
|
|
||||||
timeToTurn: 0,
|
|
||||||
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;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.sidebarFork').click(function () {
|
|
||||||
self.fork();
|
|
||||||
});
|
|
||||||
|
|
||||||
Metamaps.GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html();
|
|
||||||
|
|
||||||
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) {
|
|
||||||
Metamaps.Active.Map = new bb.Map(data.map);
|
|
||||||
Metamaps.Mappers = new bb.MapperCollection(data.mappers);
|
|
||||||
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.Backbone.attachCollectionEvents();
|
|
||||||
|
|
||||||
var map = Metamaps.Active.Map;
|
|
||||||
var mapper = Metamaps.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');
|
|
||||||
}
|
|
||||||
|
|
||||||
// set filter mapper H3 text
|
|
||||||
$('#filter_by_mapper h3').html('MAPPERS');
|
|
||||||
|
|
||||||
// build and render the visualization
|
|
||||||
Metamaps.Visualize.type = "ForceDirected";
|
|
||||||
Metamaps.JIT.prepareVizData();
|
|
||||||
|
|
||||||
// update filters
|
|
||||||
Metamaps.Filter.reset();
|
|
||||||
|
|
||||||
// reset selected arrays
|
|
||||||
Metamaps.Selected.reset();
|
|
||||||
|
|
||||||
// set the proper mapinfobox content
|
|
||||||
Metamaps.Map.InfoBox.load();
|
|
||||||
|
|
||||||
// these three update the actual filter box with the right list items
|
|
||||||
Metamaps.Filter.checkMetacodes();
|
|
||||||
Metamaps.Filter.checkSynapses();
|
|
||||||
Metamaps.Filter.checkMappers();
|
|
||||||
|
|
||||||
Metamaps.Realtime.startActiveMap();
|
|
||||||
Metamaps.Loading.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "/maps/" + id + "/contains.json",
|
|
||||||
success: start
|
|
||||||
});
|
|
||||||
},
|
|
||||||
end: function () {
|
|
||||||
if (Metamaps.Active.Map) {
|
|
||||||
|
|
||||||
$('.wrapper').removeClass('canEditMap commonsMap');
|
|
||||||
Metamaps.Map.resetSpiral();
|
|
||||||
|
|
||||||
$('.rightclickmenu').remove();
|
|
||||||
Metamaps.TopicCard.hideCard();
|
|
||||||
Metamaps.SynapseCard.hideCard();
|
|
||||||
Metamaps.Create.newTopic.hide();
|
|
||||||
Metamaps.Create.newSynapse.hide();
|
|
||||||
Metamaps.Filter.close();
|
|
||||||
Metamaps.Map.InfoBox.close();
|
|
||||||
Metamaps.Realtime.endActiveMap();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fork: function () {
|
|
||||||
Metamaps.GlobalUI.openLightbox('forkmap');
|
|
||||||
|
|
||||||
var nodes_data = "",
|
|
||||||
synapses_data = "";
|
|
||||||
var nodes_array = [];
|
|
||||||
var synapses_array = [];
|
|
||||||
// collect the unfiltered topics
|
|
||||||
Metamaps.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 = Metamaps.Filter.visible.synapses.indexOf(desc) > -1;
|
|
||||||
// make sure that both topics are being added, otherwise, it
|
|
||||||
// doesn't make sense to add the synapse
|
|
||||||
var topicsNotFiltered = nodes_array.indexOf(synapse.get('node1_id')) > -1;
|
|
||||||
topicsNotFiltered = topicsNotFiltered && nodes_array.indexOf(synapse.get('node2_id')) > -1;
|
|
||||||
if (descNotFiltered && topicsNotFiltered) {
|
|
||||||
synapses_array.push(synapse.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
synapses_data = synapses_array.join();
|
|
||||||
nodes_data = nodes_data.slice(0, -1);
|
|
||||||
|
|
||||||
Metamaps.GlobalUI.CreateMap.topicsToMap = nodes_data;
|
|
||||||
Metamaps.GlobalUI.CreateMap.synapsesToMap = synapses_data;
|
|
||||||
|
|
||||||
},
|
|
||||||
leavePrivateMap: function(){
|
|
||||||
var map = Metamaps.Active.Map;
|
|
||||||
Metamaps.Maps.Active.remove(map);
|
|
||||||
Metamaps.Maps.Featured.remove(map);
|
|
||||||
Metamaps.Router.home();
|
|
||||||
Metamaps.GlobalUI.notifyUser('Sorry! That map has been changed to Private.');
|
|
||||||
},
|
|
||||||
commonsToPublic: function(){
|
|
||||||
Metamaps.Realtime.turnOff(true); // true is for 'silence'
|
|
||||||
Metamaps.GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.');
|
|
||||||
Metamaps.Active.Map.trigger('changeByOther');
|
|
||||||
},
|
|
||||||
publicToCommons: function(){
|
|
||||||
var confirmString = "This map permission has been changed to Commons! ";
|
|
||||||
confirmString += "Do you want to reload and enable realtime collaboration?";
|
|
||||||
var c = confirm(confirmString);
|
|
||||||
if (c) {
|
|
||||||
Metamaps.Router.maps(Metamaps.Active.Map.id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
editedByActiveMapper: function () {
|
|
||||||
if (Metamaps.Active.Mapper) {
|
|
||||||
Metamaps.Mappers.add(Metamaps.Active.Mapper);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getNextCoord: function() {
|
|
||||||
var self = Metamaps.Map;
|
|
||||||
var nextX = self.nextX;
|
|
||||||
var nextY = self.nextY;
|
|
||||||
|
|
||||||
var DISTANCE_BETWEEN = 120;
|
|
||||||
|
|
||||||
self.nextX = self.nextX + DISTANCE_BETWEEN * self.nextXshift;
|
|
||||||
self.nextY = self.nextY + DISTANCE_BETWEEN * self.nextYshift;
|
|
||||||
|
|
||||||
self.timeToTurn += 1;
|
|
||||||
// if true, it's time to turn
|
|
||||||
if (self.timeToTurn === self.sideLength) {
|
|
||||||
|
|
||||||
self.turnCount += 1;
|
|
||||||
// if true, it's time to increase side length
|
|
||||||
if (self.turnCount % 2 === 0) {
|
|
||||||
self.sideLength += 1;
|
|
||||||
}
|
|
||||||
self.timeToTurn = 0;
|
|
||||||
|
|
||||||
// going right? turn down
|
|
||||||
if (self.nextXshift == 1 && self.nextYshift == 0) {
|
|
||||||
self.nextXshift = 0;
|
|
||||||
self.nextYshift = 1;
|
|
||||||
}
|
|
||||||
// going down? turn left
|
|
||||||
else if (self.nextXshift == 0 && self.nextYshift == 1) {
|
|
||||||
self.nextXshift = -1;
|
|
||||||
self.nextYshift = 0;
|
|
||||||
}
|
|
||||||
// going left? turn up
|
|
||||||
else if (self.nextXshift == -1 && self.nextYshift == 0) {
|
|
||||||
self.nextXshift = 0;
|
|
||||||
self.nextYshift = -1;
|
|
||||||
}
|
|
||||||
// going up? turn right
|
|
||||||
else if (self.nextXshift == 0 && self.nextYshift == -1) {
|
|
||||||
self.nextXshift = 1;
|
|
||||||
self.nextYshift = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: nextX,
|
|
||||||
y: nextY
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetSpiral: function() {
|
|
||||||
Metamaps.Map.nextX = 0;
|
|
||||||
Metamaps.Map.nextY = 0;
|
|
||||||
Metamaps.Map.nextXshift = 1;
|
|
||||||
Metamaps.Map.nextYshift = 0;
|
|
||||||
Metamaps.Map.sideLength = 1;
|
|
||||||
Metamaps.Map.timeToTurn = 0;
|
|
||||||
Metamaps.Map.turnCount = 0;
|
|
||||||
},
|
|
||||||
exportImage: function() {
|
|
||||||
|
|
||||||
var canvas = {};
|
|
||||||
|
|
||||||
canvas.canvas = document.createElement("canvas");
|
|
||||||
canvas.canvas.width = 1880; // 960;
|
|
||||||
canvas.canvas.height = 1260; // 630
|
|
||||||
|
|
||||||
canvas.scaleOffsetX = 1;
|
|
||||||
canvas.scaleOffsetY = 1;
|
|
||||||
canvas.translateOffsetY = 0;
|
|
||||||
canvas.translateOffsetX = 0;
|
|
||||||
canvas.denySelected = true;
|
|
||||||
|
|
||||||
canvas.getSize = function() {
|
|
||||||
if(this.size) return this.size;
|
|
||||||
var canvas = this.canvas;
|
|
||||||
return this.size = {
|
|
||||||
width: canvas.width,
|
|
||||||
height: canvas.height
|
|
||||||
};
|
|
||||||
};
|
|
||||||
canvas.scale = function(x, y) {
|
|
||||||
var px = this.scaleOffsetX * x,
|
|
||||||
py = this.scaleOffsetY * y;
|
|
||||||
var dx = this.translateOffsetX * (x -1) / px,
|
|
||||||
dy = this.translateOffsetY * (y -1) / py;
|
|
||||||
this.scaleOffsetX = px;
|
|
||||||
this.scaleOffsetY = py;
|
|
||||||
this.getCtx().scale(x, y);
|
|
||||||
this.translate(dx, dy);
|
|
||||||
};
|
|
||||||
canvas.translate = function(x, y) {
|
|
||||||
var sx = this.scaleOffsetX,
|
|
||||||
sy = this.scaleOffsetY;
|
|
||||||
this.translateOffsetX += x*sx;
|
|
||||||
this.translateOffsetY += y*sy;
|
|
||||||
this.getCtx().translate(x, y);
|
|
||||||
};
|
|
||||||
canvas.getCtx = function() {
|
|
||||||
return this.canvas.getContext("2d");
|
|
||||||
};
|
|
||||||
// center it
|
|
||||||
canvas.getCtx().translate(1880/2, 1260/2);
|
|
||||||
|
|
||||||
var mGraph = Metamaps.Visualize.mGraph;
|
|
||||||
|
|
||||||
var id = mGraph.root;
|
|
||||||
var root = mGraph.graph.getNode(id);
|
|
||||||
var T = !!root.visited;
|
|
||||||
|
|
||||||
// pass true to avoid basing it on a selection
|
|
||||||
Metamaps.JIT.zoomExtents(null, canvas, true);
|
|
||||||
|
|
||||||
var c = canvas.canvas,
|
|
||||||
ctx = canvas.getCtx(),
|
|
||||||
scale = canvas.scaleOffsetX;
|
|
||||||
|
|
||||||
// draw a grey background
|
|
||||||
ctx.fillStyle = '#d8d9da';
|
|
||||||
var xPoint = (-(c.width/scale)/2) - (canvas.translateOffsetX/scale),
|
|
||||||
yPoint = (-(c.height/scale)/2) - (canvas.translateOffsetY/scale);
|
|
||||||
ctx.fillRect(xPoint,yPoint,c.width/scale,c.height/scale);
|
|
||||||
|
|
||||||
// draw the graph
|
|
||||||
mGraph.graph.eachNode(function(node) {
|
|
||||||
var nodeAlpha = node.getData('alpha');
|
|
||||||
node.eachAdjacency(function(adj) {
|
|
||||||
var nodeTo = adj.nodeTo;
|
|
||||||
if(!!nodeTo.visited === T && node.drawn && nodeTo.drawn) {
|
|
||||||
mGraph.fx.plotLine(adj, canvas);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if(node.drawn) {
|
|
||||||
mGraph.fx.plotNode(node, canvas);
|
|
||||||
}
|
|
||||||
if(!mGraph.labelsHidden) {
|
|
||||||
if(node.drawn && nodeAlpha >= 0.95) {
|
|
||||||
mGraph.labels.plotLabel(canvas, node);
|
|
||||||
} else {
|
|
||||||
mGraph.labels.hideLabel(node, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node.visited = !T;
|
|
||||||
});
|
|
||||||
|
|
||||||
var imageData = {
|
|
||||||
encoded_image: canvas.canvas.toDataURL()
|
|
||||||
};
|
|
||||||
|
|
||||||
var map = Metamaps.Active.Map;
|
|
||||||
|
|
||||||
var today = new Date();
|
|
||||||
var dd = today.getDate();
|
|
||||||
var mm = today.getMonth()+1; //January is 0!
|
|
||||||
var yyyy = today.getFullYear();
|
|
||||||
if(dd<10) {
|
|
||||||
dd='0'+dd
|
|
||||||
}
|
|
||||||
if(mm<10) {
|
|
||||||
mm='0'+mm
|
|
||||||
}
|
|
||||||
today = mm+'/'+dd+'/'+yyyy;
|
|
||||||
|
|
||||||
var mapName = map.get("name").split(" ").join([separator = '-']);
|
|
||||||
var downloadMessage = "";
|
|
||||||
downloadMessage += "Captured map screenshot! ";
|
|
||||||
downloadMessage += "<a href='" + imageData.encoded_image + "' ";
|
|
||||||
downloadMessage += "download='metamap-" + map.id + "-" + mapName + "-" + today + ".png'>DOWNLOAD</a>";
|
|
||||||
Metamaps.GlobalUI.notifyUser(downloadMessage);
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
dataType: 'json',
|
|
||||||
url: "/maps/" + Metamaps.Active.Map.id + "/upload_screenshot",
|
|
||||||
data: imageData,
|
|
||||||
success: function (data) {
|
|
||||||
console.log('successfully uploaded map screenshot');
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
console.log('failed to save map screenshot');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* 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 = {
|
|
||||||
isOpen: false,
|
|
||||||
changing: false,
|
|
||||||
selectingPermission: false,
|
|
||||||
changePermissionText: "<div class='tooltips'>As the creator, you can change the permission of this map, but the permissions of the topics and synapses on it must be changed independently.</div>",
|
|
||||||
nameHTML: '<span class="best_in_place best_in_place_name" id="best_in_place_map_{{id}}_name" data-url="/maps/{{id}}" data-object="map" data-attribute="name" data-type="textarea" data-activator="#mapInfoName">{{name}}</span>',
|
|
||||||
descHTML: '<span class="best_in_place best_in_place_desc" id="best_in_place_map_{{id}}_desc" data-url="/maps/{{id}}" data-object="map" data-attribute="desc" data-nil="Click to add description..." data-type="textarea" data-activator="#mapInfoDesc">{{desc}}</span>',
|
|
||||||
init: function () {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
|
|
||||||
$('.mapInfoIcon').click(self.toggleBox);
|
|
||||||
$('.mapInfoBox').click(function(event){
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
$('body').click(self.close);
|
|
||||||
|
|
||||||
self.attachEventListeners();
|
|
||||||
|
|
||||||
self.generateBoxHTML = Hogan.compile($('#mapInfoBoxTemplate').html());
|
|
||||||
},
|
|
||||||
toggleBox: function (event) {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
|
|
||||||
if (self.isOpen) self.close();
|
|
||||||
else self.open();
|
|
||||||
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
|
||||||
open: function () {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
$('.mapInfoIcon div').addClass('hide');
|
|
||||||
if (!self.isOpen && !self.changing) {
|
|
||||||
self.changing = true;
|
|
||||||
$('.mapInfoBox').fadeIn(200, function () {
|
|
||||||
self.changing = false;
|
|
||||||
self.isOpen = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close: function () {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
|
|
||||||
$('.mapInfoIcon div').removeClass('hide');
|
|
||||||
if (!self.changing) {
|
|
||||||
self.changing = true;
|
|
||||||
$('.mapInfoBox').fadeOut(200, function () {
|
|
||||||
self.changing = false;
|
|
||||||
self.isOpen = false;
|
|
||||||
self.hidePermissionSelect();
|
|
||||||
$('.mapContributors .tip').hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
load: function () {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
|
|
||||||
var map = Metamaps.Active.Map;
|
|
||||||
|
|
||||||
var obj = map.pick("permission","contributor_count","topic_count","synapse_count");
|
|
||||||
|
|
||||||
var isCreator = map.authorizePermissionChange(Metamaps.Active.Mapper);
|
|
||||||
var canEdit = map.authorizeToEdit(Metamaps.Active.Mapper);
|
|
||||||
var shareable = map.get('permission') !== 'private';
|
|
||||||
|
|
||||||
obj["name"] = canEdit ? Hogan.compile(self.nameHTML).render({id: map.id, name: map.get("name")}) : map.get("name");
|
|
||||||
obj["desc"] = canEdit ? Hogan.compile(self.descHTML).render({id: map.id, desc: map.get("desc")}) : map.get("desc");
|
|
||||||
obj["map_creator_tip"] = isCreator ? self.changePermissionText : "";
|
|
||||||
obj["contributors_class"] = Metamaps.Mappers.length > 1 ? "multiple" : "";
|
|
||||||
obj["contributors_class"] += Metamaps.Mappers.length === 2 ? " mTwo" : "";
|
|
||||||
obj["contributor_image"] = Metamaps.Mappers.length > 0 ? Metamaps.Mappers.models[0].get("image") : "<%= asset_path('user.png') %>";
|
|
||||||
obj["contributor_list"] = self.createContributorList();
|
|
||||||
obj["user_name"] = isCreator ? "You" : map.get("user_name");
|
|
||||||
obj["created_at"] = map.get("created_at_clean");
|
|
||||||
obj["updated_at"] = map.get("updated_at_clean");
|
|
||||||
|
|
||||||
var classes = isCreator ? "yourMap" : "";
|
|
||||||
classes += canEdit ? " canEdit" : "";
|
|
||||||
classes += shareable ? " shareable" : "";
|
|
||||||
$(".mapInfoBox").removeClass("shareable yourMap canEdit")
|
|
||||||
.addClass(classes)
|
|
||||||
.html(self.generateBoxHTML.render(obj));
|
|
||||||
|
|
||||||
self.attachEventListeners();
|
|
||||||
},
|
|
||||||
attachEventListeners: function () {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
|
|
||||||
$('.mapInfoBox.canEdit .best_in_place').best_in_place();
|
|
||||||
|
|
||||||
// because anyone who can edit the map can change the map title
|
|
||||||
var bipName = $('.mapInfoBox .best_in_place_name');
|
|
||||||
bipName.unbind("best_in_place:activate").bind("best_in_place:activate", function () {
|
|
||||||
var $el = bipName.find('textarea');
|
|
||||||
var el = $el[0];
|
|
||||||
|
|
||||||
$el.attr('maxlength', '140');
|
|
||||||
|
|
||||||
$('.mapInfoName').append('<div class="nameCounter forMap"></div>');
|
|
||||||
|
|
||||||
var callback = function (data) {
|
|
||||||
$('.nameCounter.forMap').html(data.all + '/140');
|
|
||||||
};
|
|
||||||
Countable.live(el, callback);
|
|
||||||
});
|
|
||||||
bipName.unbind("best_in_place:deactivate").bind("best_in_place:deactivate", function () {
|
|
||||||
$('.nameCounter.forMap').remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.mapInfoName .best_in_place_name').unbind("ajax:success").bind("ajax:success", function () {
|
|
||||||
var name = $(this).html();
|
|
||||||
Metamaps.Active.Map.set('name', name);
|
|
||||||
Metamaps.Active.Map.trigger('saved');
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.mapInfoDesc .best_in_place_desc').unbind("ajax:success").bind("ajax:success", function () {
|
|
||||||
var desc = $(this).html();
|
|
||||||
Metamaps.Active.Map.set('desc', desc);
|
|
||||||
Metamaps.Active.Map.trigger('saved');
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.yourMap .mapPermission').unbind().click(self.onPermissionClick);
|
|
||||||
// .yourMap in the unbind/bind is just a namespace for the events
|
|
||||||
// not a reference to the class .yourMap on the .mapInfoBox
|
|
||||||
$('.mapInfoBox.yourMap').unbind('.yourMap').bind('click.yourMap', self.hidePermissionSelect);
|
|
||||||
|
|
||||||
$('.yourMap .mapInfoDelete').unbind().click(self.deleteActiveMap);
|
|
||||||
|
|
||||||
$('.mapContributors span, #mapContribs').unbind().click(function(event){
|
|
||||||
$('.mapContributors .tip').toggle();
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
$('.mapContributors .tip').unbind().click(function(event){
|
|
||||||
event.stopPropagation();
|
|
||||||
});
|
|
||||||
$('.mapContributors .tip li a').click(Metamaps.Router.intercept);
|
|
||||||
|
|
||||||
$('.mapInfoBox').unbind('.hideTip').bind('click.hideTip', function(){
|
|
||||||
$('.mapContributors .tip').hide();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
updateNameDescPerm: function(name, desc, perm) {
|
|
||||||
$('.mapInfoName .best_in_place_name').html(name);
|
|
||||||
$('.mapInfoDesc .best_in_place_desc').html(desc);
|
|
||||||
$('.mapInfoBox .mapPermission').removeClass('commons public private').addClass(perm);
|
|
||||||
},
|
|
||||||
createContributorList: function () {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
|
|
||||||
var string = "";
|
|
||||||
string += "<ul>";
|
|
||||||
|
|
||||||
Metamaps.Mappers.each(function(m){
|
|
||||||
string += '<li><a href="/explore/mapper/' + m.get("id") + '">' + '<img class="rtUserImage" width="25" height="25" src="' + m.get("image") + '" />' + m.get("name") + '</a></li>';
|
|
||||||
});
|
|
||||||
|
|
||||||
string += "</ul>";
|
|
||||||
return string;
|
|
||||||
},
|
|
||||||
updateNumbers: function () {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
var mapper = Metamaps.Active.Mapper;
|
|
||||||
|
|
||||||
var contributors_class = "";
|
|
||||||
if (Metamaps.Mappers.length === 2) contributors_class = "multiple mTwo";
|
|
||||||
else if (Metamaps.Mappers.length > 2) contributors_class = "multiple";
|
|
||||||
|
|
||||||
var contributors_image = "<%= asset_path('user.png') %>";
|
|
||||||
if (Metamaps.Mappers.length > 0) {
|
|
||||||
// get the first contributor and use their image
|
|
||||||
contributors_image = Metamaps.Mappers.models[0].get("image");
|
|
||||||
}
|
|
||||||
$('.mapContributors img').attr('src', contributors_image).removeClass('multiple mTwo').addClass(contributors_class);
|
|
||||||
$('.mapContributors span').text(Metamaps.Mappers.length)
|
|
||||||
$('.mapContributors .tip').html(self.createContributorList());
|
|
||||||
$('.mapTopics').text(Metamaps.Topics.length);
|
|
||||||
$('.mapSynapses').text(Metamaps.Synapses.length);
|
|
||||||
|
|
||||||
$('.mapEditedAt').html('<span>Last edited: </span>' + Metamaps.Util.nowDateFormatted());
|
|
||||||
},
|
|
||||||
onPermissionClick: function (event) {
|
|
||||||
var self = Metamaps.Map.InfoBox;
|
|
||||||
|
|
||||||
if (!self.selectingPermission) {
|
|
||||||
self.selectingPermission = true;
|
|
||||||
$(this).addClass('minimize'); // this line flips the drop down arrow to a pull up arrow
|
|
||||||
if ($(this).hasClass('commons')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="public"></li><li class="private"></li></ul>');
|
|
||||||
} else if ($(this).hasClass('public')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="private"></li></ul>');
|
|
||||||
} else if ($(this).hasClass('private')) {
|
|
||||||
$(this).append('<ul class="permissionSelect"><li class="commons"></li><li class="public"></li></ul>');
|
|
||||||
}
|
|
||||||
$('.mapPermission .permissionSelect li').click(self.selectPermission);
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hidePermissionSelect: function () {
|
|
||||||
var self = Metamaps.Map.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;
|
|
||||||
|
|
||||||
self.selectingPermission = false;
|
|
||||||
var permission = $(this).attr('class');
|
|
||||||
var permBefore = Metamaps.Active.Map.get('permission');
|
|
||||||
Metamaps.Active.Map.save({
|
|
||||||
permission: permission
|
|
||||||
});
|
|
||||||
Metamaps.Active.Map.updateMapWrapper();
|
|
||||||
if (permBefore !== 'commons' && permission === 'commons') {
|
|
||||||
Metamaps.Realtime.setupSocket();
|
|
||||||
Metamaps.Realtime.turnOn();
|
|
||||||
}
|
|
||||||
else if (permBefore === 'commons' && permission === 'public') {
|
|
||||||
Metamaps.Realtime.turnOff(true); // true is to 'silence'
|
|
||||||
// the notification that would otherwise be sent
|
|
||||||
}
|
|
||||||
shareable = permission === 'private' ? '' : 'shareable';
|
|
||||||
$('.mapPermission').removeClass('commons public private minimize').addClass(permission);
|
|
||||||
$('.mapPermission .permissionSelect').remove();
|
|
||||||
$('.mapInfoBox').removeClass('shareable').addClass(shareable);
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
|
||||||
deleteActiveMap: function () {
|
|
||||||
var confirmString = 'Are you sure you want to delete this map? ';
|
|
||||||
confirmString += 'This action is irreversible. It will not delete the topics and synapses on the map.';
|
|
||||||
|
|
||||||
var doIt = confirm(confirmString);
|
|
||||||
var map = Metamaps.Active.Map;
|
|
||||||
var mapper = Metamaps.Active.Mapper;
|
|
||||||
var authorized = map.authorizePermissionChange(mapper);
|
|
||||||
|
|
||||||
if (doIt && authorized) {
|
|
||||||
Metamaps.Map.InfoBox.close();
|
|
||||||
Metamaps.Maps.Active.remove(map);
|
|
||||||
Metamaps.Maps.Featured.remove(map);
|
|
||||||
Metamaps.Maps.Mine.remove(map);
|
|
||||||
map.destroy();
|
|
||||||
Metamaps.Router.home();
|
|
||||||
Metamaps.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
|
|
||||||
|
|
Loading…
Reference in a new issue