diff --git a/.eslintrc b/.eslintrc index 2535fa3fe..d4be26c7a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -22,6 +22,7 @@ "linebreak-style": ["error", "unix"], "no-caller": "error", "no-catch-shadow": "error", + "no-console": "warn", "no-div-regex": "error", "no-extend-native": "error", "no-extra-bind": "error", diff --git a/.gitignore b/.gitignore index f5504e01c..c3fd22f29 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ dist/*.js dist/*.css dist/*.map dist/img/*.svg +dist/mapillary-js/ node_modules/ npm-debug.log transifex.auth diff --git a/css/app.css b/css/app.css index 5ab11ea02..4d291387b 100644 --- a/css/app.css +++ b/css/app.css @@ -3331,15 +3331,6 @@ img.tile-removing { visibility: hidden; } -.mapillary-wrap .uil-ripple-css { - top: -9px; - left: -15px; -} - -.mapillary-wrap .uil-ripple-css div { - top: 38px; -} - .mapillary-wrap button.thumb-hide { border-radius: 0; padding: 5px; @@ -3350,11 +3341,13 @@ img.tile-removing { } .mly-wrapper { - visibility: hidden; + visibility: hidden; + width: 100%; + height: 100%; } .mly-wrapper.active { - visibility: visible; + visibility: visible; } /* Right-to-left localization settings */ diff --git a/css/map.css b/css/map.css index d26cfd4e5..250f23aed 100644 --- a/css/map.css +++ b/css/map.css @@ -1529,7 +1529,7 @@ text.gpx { pointer-events: none; } -.layer-mapillary-signs .icon-sign body { +.layer-mapillary-signs .icon-sign .icon-sign-body { min-width: 20px; height: 28px; width: 28px; @@ -1538,14 +1538,15 @@ text.gpx { cursor: pointer; /* Opera */ cursor: url(img/cursor-select-mapillary.png) 6 1, pointer; /* FF */ z-index: 70; + overflow: visible; } -.layer-mapillary-signs .icon-sign:hover body { +.layer-mapillary-signs .icon-sign:hover .icon-sign-body { border: 2px solid rgba(255,198,0,0.8); z-index: 80; } -.layer-mapillary-signs .icon-sign.selected body { +.layer-mapillary-signs .icon-sign.selected .icon-sign-body { border: 2px solid rgba(255,0,0,0.8); z-index: 80; } @@ -1553,7 +1554,6 @@ text.gpx { .layer-mapillary-signs .icon-sign .t { font-size: 28px; z-index: 70; - position: absolute; } .layer-mapillary-signs .icon-sign:hover .t, diff --git a/modules/services/mapillary.js b/modules/services/mapillary.js index e30ccd34c..c02bdd68b 100644 --- a/modules/services/mapillary.js +++ b/modules/services/mapillary.js @@ -11,8 +11,9 @@ import { utilQsString } from '../util/index'; var apibase = 'https://a.mapillary.com/v2/', - viewercss = 'https://unpkg.com/mapillary-js@1.3.0/dist/mapillary-js.min.css', - viewerjs = 'https://unpkg.com/mapillary-js@1.3.0/dist/mapillary-js.min.js', + viewercss = 'mapillary-js/mapillary.min.css', + viewerjs = 'mapillary-js/mapillary.min.js', + trafficocss = 'traffico/stylesheets/traffico.css', clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi', maxResults = 1000, maxPages = 10, @@ -25,31 +26,6 @@ var apibase = 'https://a.mapillary.com/v2/', mapillaryViewer; -function loadSignStyles(context) { - d3.select('head').selectAll('#traffico') - .data([0]) - .enter() - .append('link') - .attr('id', 'traffico') - .attr('rel', 'stylesheet') - .attr('href', context.asset('traffico/stylesheets/traffico.css')); -} - - -function loadSignDefs(context) { - if (mapillarySignDefs) return; - mapillarySignDefs = {}; - - _.each(['au', 'br', 'ca', 'de', 'us'], function(region) { - d3.json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) { - if (err) return; - if (region === 'de') region = 'eu'; - mapillarySignDefs[region] = data; - }); - }); -} - - function abortRequest(i) { i.abort(); } @@ -228,63 +204,6 @@ export default { }, - loadImages: function(projection, dimensions) { - var url = apibase + 'search/im/geojson?'; - loadTiles('images', url, projection, dimensions); - }, - - - loadSigns: function(context, projection, dimensions) { - var url = apibase + 'search/im/geojson/or?'; - loadSignStyles(context); - loadSignDefs(context); - loadTiles('signs', url, projection, dimensions); - }, - - - loadViewer: function() { - var that = this; - var wrap = d3.select('#content').selectAll('.mapillary-wrap') - .data([0]); - - var enter = wrap.enter() - .append('div') - .attr('class', 'mapillary-wrap') - .classed('al', true) // 'al'=left, 'ar'=right - .classed('hidden', true); - - enter - .append('button') - .attr('class', 'thumb-hide') - .on('click', function () { that.hideViewer(); }) - .append('div') - .call(svgIcon('#icon-close')); - - enter - .append('div') - .attr('id', 'mly') - .attr('class', 'mly-wrapper') - .classed('active', false); - - // mapillary-viewercss - d3.select('head').selectAll('#mapillary-viewercss') - .data([0]) - .enter() - .append('link') - .attr('id', 'mapillary-viewercss') - .attr('rel', 'stylesheet') - .attr('href', viewercss); - - // mapillary-viewerjs - d3.select('head').selectAll('#mapillary-viewerjs') - .data([0]) - .enter() - .append('script') - .attr('id', 'mapillary-viewerjs') - .attr('src', viewerjs); - }, - - images: function(projection, dimensions) { var psize = 16, limit = 3; return searchLimited(psize, limit, projection, dimensions, mapillaryCache.images.rtree); @@ -299,7 +218,9 @@ export default { signsSupported: function() { var detected = utilDetect(); - return (!(detected.ie || detected.browser.toLowerCase() === 'safari')); + if (detected.ie) return false; + if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false; + return true; }, @@ -314,11 +235,87 @@ export default { }, + loadImages: function(projection, dimensions) { + var url = apibase + 'search/im/geojson?'; + loadTiles('images', url, projection, dimensions); + }, + + + loadSigns: function(context, projection, dimensions) { + var url = apibase + 'search/im/geojson/or?'; + loadTiles('signs', url, projection, dimensions); + + // load traffico css + d3.select('head').selectAll('#traffico') + .data([0]) + .enter() + .append('link') + .attr('id', 'traffico') + .attr('rel', 'stylesheet') + .attr('href', context.asset(trafficocss)); + + // load traffico sign defs + if (!mapillarySignDefs) { + mapillarySignDefs = {}; + _.each(['au', 'br', 'ca', 'de', 'us'], function(region) { + d3.json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) { + if (err) return; + if (region === 'de') region = 'eu'; + mapillarySignDefs[region] = data; + }); + }); + } + }, + + + loadViewer: function(context) { + var that = this; + var wrap = d3.select('#content').selectAll('.mapillary-wrap') + .data([0]); + + var enter = wrap.enter() + .append('div') + .attr('class', 'mapillary-wrap') + .classed('al', true) // 'al'=left, 'ar'=right + .classed('hidden', true); + + enter + .append('button') + .attr('class', 'thumb-hide') + .on('click', function () { that.hideViewer(); }) + .append('div') + .call(svgIcon('#icon-close')); + + enter + .append('div') + .attr('id', 'mly') + .attr('class', 'mly-wrapper') + .classed('active', false); + + // load mapillary-viewercss + d3.select('head').selectAll('#mapillary-viewercss') + .data([0]) + .enter() + .append('link') + .attr('id', 'mapillary-viewercss') + .attr('rel', 'stylesheet') + .attr('href', context.asset(viewercss)); + + // load mapillary-viewerjs + d3.select('head').selectAll('#mapillary-viewerjs') + .data([0]) + .enter() + .append('script') + .attr('id', 'mapillary-viewerjs') + .attr('src', context.asset(viewerjs)); + }, + + showViewer: function() { d3.select('#content') - .selectAll('.mapillary-wrap') + .selectAll('.mapillary-wrap') .classed('hidden', false) - .selectAll('.mly-wrapper') + .selectAll('.mly-wrapper') .classed('active', true); return this; @@ -327,9 +324,9 @@ export default { hideViewer: function() { d3.select('#content') - .selectAll('.mapillary-wrap') + .selectAll('.mapillary-wrap') .classed('hidden', true) - .selectAll('.mly-wrapper') + .selectAll('.mly-wrapper') .classed('active', false); d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign') @@ -358,17 +355,14 @@ export default { if (Mapillary && imageKey) { var opts = { baseImageSize: 320, - cover: false, - cache: true, - debug: false, - imagePlane: true, - loading: true, - sequence: true + component: { + cover: false, + keyboard: false + } }; mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts); mapillaryViewer.on('nodechanged', nodeChanged); - mapillaryViewer.on('loadingchanged', loadingChanged); } function nodeChanged(node) { @@ -377,36 +371,11 @@ export default { if (index > -1) { // nodechange initiated from clicking on a marker.. clicks.splice(index, 1); } else { // nodechange initiated from the Mapillary viewer controls.. - var loc = node.apiNavImIm ? [node.apiNavImIm.lon, node.apiNavImIm.lat] : [node.latLon.lon, node.latLon.lat]; + var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat]; context.map().centerEase(loc); that.selectedImage(node.key, false); } } - - function loadingChanged(loading) { - var canvas = d3.select('#content') - .selectAll('.mly-wrapper canvas'); - - if (canvas.empty()) return; // viewer not loaded yet - - var cover = d3.select('#content') - .selectAll('.mly-wrapper .Cover'); - - cover.classed('CoverDone', !loading); - - var button = cover.selectAll('.CoverButton') - .data(loading ? [0] : []); - - button.exit() - .remove(); - - button.enter() - .append('div') - .attr('class', 'CoverButton') - .append('div') - .attr('class', 'uil-ripple-css') - .append('div'); - } }, diff --git a/modules/svg/mapillary_images.js b/modules/svg/mapillary_images.js index 653ac2410..47e5ede03 100644 --- a/modules/svg/mapillary_images.js +++ b/modules/svg/mapillary_images.js @@ -8,6 +8,7 @@ import { services } from '../services/index'; export function svgMapillaryImages(projection, context, dispatch) { var debouncedRedraw = _.debounce(function () { dispatch.call('change'); }, 1000), minZoom = 12, + minViewfieldZoom = 16, layer = d3.select(null), _mapillary; @@ -35,7 +36,7 @@ export function svgMapillaryImages(projection, context, dispatch) { var mapillary = getMapillary(); if (!mapillary) return; - mapillary.loadViewer(); + mapillary.loadViewer(context); editOn(); layer @@ -111,19 +112,30 @@ export function svgMapillaryImages(projection, context, dispatch) { .classed('selected', function(d) { return d.key === imageKey; }) .on('click', click); - enter.append('path') + markers + .merge(enter) + .attr('transform', transform); + + + var viewfields = markers.selectAll('.viewfield') + .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []); + + viewfields.exit() + .remove(); + + viewfields.enter() + .append('path') .attr('class', 'viewfield') .attr('transform', 'scale(1.5,1.5),translate(-8, -13)') .attr('d', 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z'); - enter.append('circle') + markers.selectAll('circle') + .data([0]) + .enter() + .append('circle') .attr('dx', '0') .attr('dy', '0') .attr('r', '6'); - - markers - .merge(enter) - .attr('transform', transform); } diff --git a/modules/svg/mapillary_signs.js b/modules/svg/mapillary_signs.js index db2cf004e..c0309b8a7 100644 --- a/modules/svg/mapillary_signs.js +++ b/modules/svg/mapillary_signs.js @@ -1,7 +1,6 @@ import * as d3 from 'd3'; import _ from 'lodash'; import { utilGetDimensions, utilSetDimensions } from '../util/dimensions'; -import { svgPointTransform } from './point_transform'; import { services } from '../services/index'; @@ -87,11 +86,13 @@ export function svgMapillarySigns(projection, context, dispatch) { enter .append('xhtml:body') + .attr('class', 'icon-sign-body') .html(mapillary.signHTML); signs .merge(enter) - .attr('transform', svgPointTransform(projection)); + .attr('x', function(d) { return projection(d.loc)[0] - 16; }) // offset by -16px to + .attr('y', function(d) { return projection(d.loc)[1] - 16; }); // center signs on loc } @@ -109,7 +110,6 @@ export function svgMapillarySigns(projection, context, dispatch) { .append('g') .attr('class', 'layer-mapillary-signs') .style('display', enabled ? 'block' : 'none') - .attr('transform', 'translate(-16, -16)') // center signs on loc .merge(layer); if (enabled) { diff --git a/package.json b/package.json index 25d5fd942..d7e3d64be 100644 --- a/package.json +++ b/package.json @@ -10,20 +10,21 @@ ], "license": "ISC", "scripts": { - "all": "npm run clean && npm run build-assets && npm run build && npm run build-min", + "all": "npm-run-all -s clean build dist", "build": "node build.js && node development_server.js", - "build-assets": "npm run build-css && npm run build-svg", - "build-css": "cat css/reset.css css/map.css css/app.css > dist/iD.css", - "build-min": "uglifyjs dist/iD.js -c -m -o dist/iD.min.js", - "build-svg": "npm run build-svg-maki && npm run build-svg-id", - "build-svg-maki": "svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/maki-sprite.svg node_modules/maki/src/*.svg", - "build-svg-id": "node svg/spriteify.js --svg svg/iD-sprite.src.svg --json svg/iD-sprite.json > dist/img/iD-sprite.svg", - "clean": "rm -f dist/*.js dist/*.map dist/*.css dist/img/*.svg", + "clean": "shx rm -f dist/*.js dist/*.map dist/*.css dist/img/*.svg", + "dist": "npm-run-all -p dist:**", + "dist:css": "shx cat css/reset.css css/map.css css/app.css > dist/iD.css", + "dist:mapillary": "shx mkdir -p dist/mapillary-js && shx cp -R node_modules/mapillary-js/dist/* dist/mapillary-js/", + "dist:min": "uglifyjs dist/iD.js -c -m -o dist/iD.min.js", + "dist:svg:maki": "svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/maki-sprite.svg node_modules/maki/src/*.svg", + "dist:svg:id": "node svg/spriteify.js --svg svg/iD-sprite.src.svg --json svg/iD-sprite.json > dist/img/iD-sprite.svg", "imagery": "node data/update_imagery", "lint": "eslint *.js js/id test/spec modules", "prepublish": "npm run all", "start": "node development_server.js develop", - "test": "npm run lint && npm run build && phantomjs node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js test/index.html spec", + "test": "npm-run-all -s lint build test:**", + "test:phantom": "phantomjs node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js test/index.html spec", "translations": "node data/update_locales" }, "dependencies": { @@ -41,7 +42,7 @@ "chai": "~3.5.0", "d3": "4.2.8", "ecstatic": "~2.1.0", - "editor-layer-index": "git://github.com/osmlab/editor-layer-index.git#gh-pages", + "editor-layer-index": "osmlab/editor-layer-index.git#gh-pages", "gaze": "~1.1.1", "eslint": "~3.9.0", "glob": "~7.1.0", @@ -49,16 +50,19 @@ "js-yaml": "~3.6.1", "jsonschema": "~1.1.0", "maki": "0.5.0", + "mapillary-js": "2.0.0", "minimist": "~1.2.0", "mocha": "~3.1.0", "mocha-phantomjs-core": "~2.0.1", "name-suggestion-index": "0.1.1", + "npm-run-all": "~3.1.1", "phantomjs-prebuilt": "~2.1.11", "request": "~2.76.0", "rollup": "0.36.2", "rollup-plugin-commonjs": "5.0.5", "rollup-plugin-json": "2.0.2", "rollup-plugin-node-resolve": "2.0.0", + "shx": "~0.1.4", "sinon": "~1.17.5", "sinon-chai": "~2.8.0", "smash": "0.0", diff --git a/test/spec/services/mapillary.js b/test/spec/services/mapillary.js index 5fa84f660..0b06c05d8 100644 --- a/test/spec/services/mapillary.js +++ b/test/spec/services/mapillary.js @@ -362,11 +362,17 @@ describe('iD.serviceMapillary', function() { expect(mapillary.signsSupported()).to.be.false; }); - it('returns false for Safari', function() { + it('returns false for Safari 9', function() { ua = 'Version/9.1 Safari/601'; iD.Detect(true); // force redetection expect(mapillary.signsSupported()).to.be.false; }); + + it('returns true for Safari 10', function() { + ua = 'Version/10.0 Safari/602'; + iD.Detect(true); // force redetection + expect(mapillary.signsSupported()).to.be.true; + }); }); describe('#signHTML', function() {