From 75e41619ebe70bf99492730d367dea6229eb9503 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 30 Oct 2016 13:59:23 +0800 Subject: [PATCH 1/6] enable specifying scale/translate in query params for a map e.g. https://metamaps.cc/maps/12?scale=0.5&translate=-350,300 --- frontend/src/Metamaps/Util.js | 9 ++++++++- frontend/src/Metamaps/Visualize.js | 11 +++++++++++ frontend/src/patched/JIT.js | 3 --- frontend/test/Metamaps/Util.spec.js | 3 +++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/frontend/src/Metamaps/Util.js b/frontend/src/Metamaps/Util.js index 2bc49159..2cb70f8d 100644 --- a/frontend/src/Metamaps/Util.js +++ b/frontend/src/Metamaps/Util.js @@ -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,13 @@ 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 + }, {}) } } diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index aa0745da..b207d05c 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -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,16 @@ const Visualize = { self.mGraph.graph.empty() } + const queryParams = Util.queryParams() + if (typeof queryParams.scale === 'string') { + const scale = parseFloat(queryParams.scale) || 0 + self.mGraph.canvas.scale(scale, scale) + } + if (typeof queryParams.translate === 'string') { + const [x, y] = queryParams.translate.split(',').map(n => parseFloat(n) || 0) + self.mGraph.canvas.translate(x, y) + } + function runAnimation() { Loading.hide() // load JSON data, if it's not empty 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..e22329d3 100644 --- a/frontend/test/Metamaps/Util.spec.js +++ b/frontend/test/Metamaps/Util.spec.js @@ -129,4 +129,7 @@ describe('Metamaps.Util.js', function() { describe('resizeCanvas', function() { it.skip('TODO need a canvas') }) + describe('queryParams', function() { + it.skip('TODO need window') + }) }) From 7af59727658b86d411cdb005e6e0b5c8d3acbe02 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 11 Dec 2016 19:01:48 -0500 Subject: [PATCH 2/6] monkey patch scale/translate functions so they update the URL --- frontend/src/Metamaps/Util.js | 7 ++++++- frontend/src/Metamaps/Visualize.js | 23 +++++++++++++++++++++++ frontend/test/Metamaps/Util.spec.js | 3 +++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/frontend/src/Metamaps/Util.js b/frontend/src/Metamaps/Util.js index 2cb70f8d..4b55342a 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' @@ -236,6 +236,11 @@ const Util = { obj[item[0]] = item[1] return obj }, {}) + }, + updateQueryParams: function(newValues) { + 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, `${window.location.pathname}?${newString}`) } } diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index b207d05c..6aafb697 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -149,6 +149,29 @@ const Visualize = { self.mGraph.graph.empty() } + // monkey patch scale function + const oldScale = self.mGraph.canvas.scale + self.mGraph.canvas.scale = function(x, y, disablePlot) { + const returnValue = oldScale.apply(self.mGraph.canvas, arguments) + Util.updateQueryParams({ scale: self.mGraph.canvas.scaleOffsetX.toFixed(2) }) + return returnValue + } + + // monkey patch translate function + const oldTranslate = self.mGraph.canvas.translate + let translateTimeout = null + self.mGraph.canvas.translate = function(x, y, disablePlot) { + const returnValue = oldTranslate.apply(self.mGraph.canvas, arguments) + window.clearTimeout(translateTimeout) + translateTimeout = window.setTimeout(() => { + const newX = self.mGraph.canvas.translateOffsetX.toFixed(2) + const newY = self.mGraph.canvas.translateOffsetY.toFixed(2) + Util.updateQueryParams({ translate: `${newX},${newY}` }) + translateTimeout = null + return returnValue + }, 50) + } + const queryParams = Util.queryParams() if (typeof queryParams.scale === 'string') { const scale = parseFloat(queryParams.scale) || 0 diff --git a/frontend/test/Metamaps/Util.spec.js b/frontend/test/Metamaps/Util.spec.js index e22329d3..21996571 100644 --- a/frontend/test/Metamaps/Util.spec.js +++ b/frontend/test/Metamaps/Util.spec.js @@ -132,4 +132,7 @@ describe('Metamaps.Util.js', function() { describe('queryParams', function() { it.skip('TODO need window') }) + describe('updateQueryParams', function() { + it.skip('TODO need window') + }) }) From e30d05f71d87bdc9f1c7752f56eba78974ef6c97 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 18 Dec 2016 16:14:39 -0500 Subject: [PATCH 3/6] fix initial scale/translate algorithm --- frontend/src/Metamaps/Visualize.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index 6aafb697..1ae73da2 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -173,13 +173,13 @@ const Visualize = { } const queryParams = Util.queryParams() - if (typeof queryParams.scale === 'string') { - const scale = parseFloat(queryParams.scale) || 0 - self.mGraph.canvas.scale(scale, scale) - } + 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, y) + self.mGraph.canvas.translate(x / scale, y / scale) + } + if (typeof queryParams.scale === 'string') { + self.mGraph.canvas.scale(scale, scale) } function runAnimation() { From d219bde48dad5c9252e944fd5666a8400e8d7faf Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 18 Dec 2016 16:55:41 -0500 Subject: [PATCH 4/6] rework debouncing and lodash in Visualize.js --- frontend/src/Metamaps/Visualize.js | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index 1ae73da2..bacf7f03 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -1,6 +1,6 @@ /* global $ */ -import _ from 'lodash' +import { find as _find, indexOf as _indexOf, uniq as _uniq, debounce } from 'lodash' import $jit from '../patched/JIT' @@ -151,25 +151,25 @@ const Visualize = { // monkey patch scale function const oldScale = self.mGraph.canvas.scale + const updateScaleInUrl = debounce(() => { + Util.updateQueryParams({ scale: self.mGraph.canvas.scaleOffsetX.toFixed(2) }) + }, 200) self.mGraph.canvas.scale = function(x, y, disablePlot) { const returnValue = oldScale.apply(self.mGraph.canvas, arguments) - Util.updateQueryParams({ scale: self.mGraph.canvas.scaleOffsetX.toFixed(2) }) + updateScaleInUrl() return returnValue } // monkey patch translate function const oldTranslate = self.mGraph.canvas.translate - let translateTimeout = null + const updateTranslateInUrl = debounce(() => { + const newX = self.mGraph.canvas.translateOffsetX.toFixed(2) + const newY = self.mGraph.canvas.translateOffsetY.toFixed(2) + Util.updateQueryParams({ translate: `${newX},${newY}` }) + }, 200) self.mGraph.canvas.translate = function(x, y, disablePlot) { const returnValue = oldTranslate.apply(self.mGraph.canvas, arguments) - window.clearTimeout(translateTimeout) - translateTimeout = window.setTimeout(() => { - const newX = self.mGraph.canvas.translateOffsetX.toFixed(2) - const newY = self.mGraph.canvas.translateOffsetY.toFixed(2) - Util.updateQueryParams({ translate: `${newX},${newY}` }) - translateTimeout = null - return returnValue - }, 50) + updateTranslateInUrl() } const queryParams = Util.queryParams() @@ -189,10 +189,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. @@ -211,11 +211,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 From 6bbd35d644f7d3fd65d0ff465e246fe5024ebcc6 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sun, 18 Dec 2016 17:11:49 -0500 Subject: [PATCH 5/6] cache path name to avoid race conditions when updating url --- frontend/src/Metamaps/Util.js | 4 ++-- frontend/src/Metamaps/Visualize.js | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/frontend/src/Metamaps/Util.js b/frontend/src/Metamaps/Util.js index 4b55342a..9dfc8d3b 100644 --- a/frontend/src/Metamaps/Util.js +++ b/frontend/src/Metamaps/Util.js @@ -237,10 +237,10 @@ const Util = { return obj }, {}) }, - updateQueryParams: function(newValues) { + 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, `${window.location.pathname}?${newString}`) + history.replaceState({}, document.title, `${pathname}?${newString}`) } } diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index bacf7f03..ea337ba2 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -1,4 +1,4 @@ -/* global $ */ +/* global $, window */ import { find as _find, indexOf as _indexOf, uniq as _uniq, debounce } from 'lodash' @@ -151,8 +151,9 @@ const Visualize = { // 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) }) + Util.updateQueryParams({ scale: self.mGraph.canvas.scaleOffsetX.toFixed(2) }, pathname) }, 200) self.mGraph.canvas.scale = function(x, y, disablePlot) { const returnValue = oldScale.apply(self.mGraph.canvas, arguments) @@ -165,7 +166,7 @@ const Visualize = { const updateTranslateInUrl = debounce(() => { const newX = self.mGraph.canvas.translateOffsetX.toFixed(2) const newY = self.mGraph.canvas.translateOffsetY.toFixed(2) - Util.updateQueryParams({ translate: `${newX},${newY}` }) + Util.updateQueryParams({ translate: `${newX},${newY}` }, pathname) }, 200) self.mGraph.canvas.translate = function(x, y, disablePlot) { const returnValue = oldTranslate.apply(self.mGraph.canvas, arguments) From e0eb3e63339819e6f54ed8267e20618edbaa9780 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Sat, 31 Dec 2016 12:07:53 -0500 Subject: [PATCH 6/6] fix pathname --- frontend/src/Metamaps/Visualize.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index ea337ba2..d2cf576b 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -153,7 +153,7 @@ const Visualize = { const oldScale = self.mGraph.canvas.scale const cachedPathname = window.location.pathname const updateScaleInUrl = debounce(() => { - Util.updateQueryParams({ scale: self.mGraph.canvas.scaleOffsetX.toFixed(2) }, pathname) + 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) @@ -166,7 +166,7 @@ const Visualize = { const updateTranslateInUrl = debounce(() => { const newX = self.mGraph.canvas.translateOffsetX.toFixed(2) const newY = self.mGraph.canvas.translateOffsetY.toFixed(2) - Util.updateQueryParams({ translate: `${newX},${newY}` }, pathname) + Util.updateQueryParams({ translate: `${newX},${newY}` }, cachedPathname) }, 200) self.mGraph.canvas.translate = function(x, y, disablePlot) { const returnValue = oldTranslate.apply(self.mGraph.canvas, arguments)