/* 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.') }, cantEditNow: 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') }, 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(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 += "DOWNLOAD" Metamaps.GlobalUI.notifyUser(downloadMessage) $.ajax({ type: 'POST', dataType: 'json', url: '/maps/' + Metamaps.Active.Map.id + '/upload_screenshot', data: imageData, success: function (data) { console.log('successfully uploaded map screenshot') }, error: function () { console.log('failed to save map screenshot') } }) } } /* * * 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: "