diff --git a/frontend/src/Metamaps/Util.js b/frontend/src/Metamaps/Util.js index 2bc49159..9dfc8d3b 100644 --- a/frontend/src/Metamaps/Util.js +++ b/frontend/src/Metamaps/Util.js @@ -1,4 +1,4 @@ -/* global $ */ +/* global $, window, document, history */ import { Parser, HtmlRenderer, Node } from 'commonmark' import { emojiIndex } from 'emoji-mart' @@ -172,7 +172,7 @@ const Util = { canvas.resize($(window).width(), $(window).height()) // Return the map to the original scale, and then put the previous central map-coordinate back to the centre of user's newly resized screen - canvas.scale(oldAttr.scaleX, oldAttr.scaleY) + canvas.scale(oldAttr.scaleX, oldAttr.scaleY) // should be equal const newAttr = Util.logCanvasAttributes(canvas) canvas.translate(newAttr.centreCoords.x - oldAttr.centreCoords.x, newAttr.centreCoords.y - oldAttr.centreCoords.y) }, @@ -229,6 +229,18 @@ const Util = { // Translate the canvas to put the pointer back over top the same coordinate it was over before graph.canvas.translate(newX - pointerCoordX, newY - pointerCoordY) + }, + queryParams: function() { + return window.location.search.replace(/(^\?)/, '').split('&').reduce((obj, item) => { + item = item.split('=') + obj[item[0]] = item[1] + return obj + }, {}) + }, + updateQueryParams: function(newValues, pathname = window.location.pathname) { + const qp = Object.assign({}, Util.queryParams(), newValues) + const newString = Object.keys(qp).filter(key => !!key).map(key => `${key}=${qp[key]}`).join('&') + history.replaceState({}, document.title, `${pathname}?${newString}`) } } diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index aa0745da..d2cf576b 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -1,6 +1,6 @@ -/* global $ */ +/* global $, window */ -import _ from 'lodash' +import { find as _find, indexOf as _indexOf, uniq as _uniq, debounce } from 'lodash' import $jit from '../patched/JIT' @@ -9,6 +9,7 @@ import DataModel from './DataModel' import JIT from './JIT' import Loading from './Loading' import TopicCard from './Views/TopicCard' +import Util from './Util' const Visualize = { mGraph: null, // a reference to the graph object. @@ -148,6 +149,40 @@ const Visualize = { self.mGraph.graph.empty() } + // monkey patch scale function + const oldScale = self.mGraph.canvas.scale + const cachedPathname = window.location.pathname + const updateScaleInUrl = debounce(() => { + Util.updateQueryParams({ scale: self.mGraph.canvas.scaleOffsetX.toFixed(2) }, cachedPathname) + }, 200) + self.mGraph.canvas.scale = function(x, y, disablePlot) { + const returnValue = oldScale.apply(self.mGraph.canvas, arguments) + updateScaleInUrl() + return returnValue + } + + // monkey patch translate function + const oldTranslate = self.mGraph.canvas.translate + const updateTranslateInUrl = debounce(() => { + const newX = self.mGraph.canvas.translateOffsetX.toFixed(2) + const newY = self.mGraph.canvas.translateOffsetY.toFixed(2) + Util.updateQueryParams({ translate: `${newX},${newY}` }, cachedPathname) + }, 200) + self.mGraph.canvas.translate = function(x, y, disablePlot) { + const returnValue = oldTranslate.apply(self.mGraph.canvas, arguments) + updateTranslateInUrl() + } + + const queryParams = Util.queryParams() + const scale = parseFloat(queryParams.scale) || 1.0 + if (typeof queryParams.translate === 'string') { + const [x, y] = queryParams.translate.split(',').map(n => parseFloat(n) || 0) + self.mGraph.canvas.translate(x / scale, y / scale) + } + if (typeof queryParams.scale === 'string') { + self.mGraph.canvas.scale(scale, scale) + } + function runAnimation() { Loading.hide() // load JSON data, if it's not empty @@ -155,10 +190,10 @@ const Visualize = { // load JSON data. var rootIndex = 0 if (Active.Topic) { - var node = _.find(JIT.vizData, function(node) { + var node = _find(JIT.vizData, function(node) { return node.id === Active.Topic.id }) - rootIndex = _.indexOf(JIT.vizData, node) + rootIndex = _indexOf(JIT.vizData, node) } self.mGraph.loadJSON(JIT.vizData, rootIndex) // compute positions and plot. @@ -177,11 +212,11 @@ const Visualize = { // hold for a maximum of 80 passes, or 4 seconds of waiting time var tries = 0 function hold() { - const unique = _.uniq(DataModel.Topics.models, function(metacode) { return metacode.get('metacode_id') }) - const requiredMetacodes = _.map(unique, function(metacode) { return metacode.get('metacode_id') }) + const unique = _uniq(DataModel.Topics.models, function(metacode) { return metacode.get('metacode_id') }) + const requiredMetacodes = unique.map(metacode => metacode.get('metacode_id')) let loadedCount = 0 - _.each(requiredMetacodes, function(metacodeId) { + requiredMetacodes.forEach(metacodeId => { const metacode = DataModel.Metacodes.get(metacodeId) const img = metacode ? metacode.get('image') : false diff --git a/frontend/src/patched/JIT.js b/frontend/src/patched/JIT.js index 5ea04ce1..fbe34c4f 100644 --- a/frontend/src/patched/JIT.js +++ b/frontend/src/patched/JIT.js @@ -2581,10 +2581,7 @@ Extras.Classes.Navigation = new Class({ // START METAMAPS CODE if (Metamaps.Mouse.didPan) Metamaps.JIT.SmoothPanning(); - - // END METAMAPS CODE - }, // START METAMAPS CODE diff --git a/frontend/test/Metamaps/Util.spec.js b/frontend/test/Metamaps/Util.spec.js index 3cfe05d8..21996571 100644 --- a/frontend/test/Metamaps/Util.spec.js +++ b/frontend/test/Metamaps/Util.spec.js @@ -129,4 +129,10 @@ describe('Metamaps.Util.js', function() { describe('resizeCanvas', function() { it.skip('TODO need a canvas') }) + describe('queryParams', function() { + it.skip('TODO need window') + }) + describe('updateQueryParams', function() { + it.skip('TODO need window') + }) })