From ca87996f29e5bbde862d5c1da47e6c79de9923f5 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 5 Jul 2016 16:25:49 +0200 Subject: [PATCH 01/34] Update misc files --- include/index.php | 9 ++++++++- readme.txt | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 readme.txt diff --git a/include/index.php b/include/index.php index 3092985..11ef5ae 100644 --- a/include/index.php +++ b/include/index.php @@ -10,7 +10,14 @@ header('HTTP/1.1 400 Bad Request'); die; } -$data = file_get_contents('../../output/' . trim($id, '/') . '/map.json'); +$path = "../../output/"; +if(!!preg_match("/^(online|beta)\\.maps4news\\.com$/i", $_SERVER['HTTP_HOST'])) { + $path = "/mnt/data/production/output/"; +} else if("/^staging\\.maps4news\\.com$/i") { + $path = "/mnt/data/staging/output/"; +} + +$data = file_get_contents($path . trim($id, '/') . '/map.json'); header("Content-type: application/javascript; charset=utf-8"); diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..cab319a --- /dev/null +++ b/readme.txt @@ -0,0 +1,10 @@ +------------------------------------------------------------------------ +Copyright (C) @maps4news interactive maps (v2.0) +------------------------------------------------------------------------ +x Upload this folder to a directory on your server. +x Add m4n.js to your page. +x Add the following HTML to your webpage +
+ +
+x Replace the two [id]'s with both the same unique id and [path] with a relative reference to the tile directory. \ No newline at end of file From d8cfdac30b1dc5960aeaea0a410b8fa0bc3663c2 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 5 Jul 2016 16:26:56 +0200 Subject: [PATCH 02/34] Rename init to options & rework debug --- app/js/main.js | 2 +- app/js/{init.js => options.js} | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) rename app/js/{init.js => options.js} (87%) diff --git a/app/js/main.js b/app/js/main.js index d95be15..92ca60a 100644 --- a/app/js/main.js +++ b/app/js/main.js @@ -8,7 +8,7 @@ var M4nInteractive = (function(options, container, callback) { "use strict"; var main = this; - ""; + ""; ""; diff --git a/app/js/init.js b/app/js/options.js similarity index 87% rename from app/js/init.js rename to app/js/options.js index 70557e3..06258a2 100644 --- a/app/js/init.js +++ b/app/js/options.js @@ -12,9 +12,14 @@ main.zoomControls = typeof options.zoomControls !== 'undefined' ? options.zoomControls : true; main.homeButton = typeof options.homeButton !== 'undefined' ? options.homeButton : true; - main.version = { map: '2.0', code: '2.0.5' }; // TODO Add version to json for verification + main.version = { map: '2.0', code: '2.0.5' }; - main.dev = main.environment == 'development' || (options.debug && options.debug == "true"); + main.dev = (function() { + if(typeof options.debug !== 'undefined') { + return options.debug; + } + return main.environment === 'development'; + })(); main.isMobile = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); main.isIframe = window.location !== window.parent.location; From c1eea5195e0d39830fdb9d2911e44bfdcfa7b61e Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 5 Jul 2016 16:28:08 +0200 Subject: [PATCH 03/34] Cleanup api --- app/js/api.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/app/js/api.js b/app/js/api.js index 98ed42a..db59839 100644 --- a/app/js/api.js +++ b/app/js/api.js @@ -11,10 +11,7 @@ main.api = { */ popup: function(i) { var popup = main.object.popups.get(i); - if(popup === null) { - throw "Popup " + i + " not found"; - } - return popup.getApiObject(); + return popup.getApiObject() || null; }, /** @@ -93,14 +90,14 @@ main.api = { * Zoom in 1 level */ in: function() { - this.to(main.object.levels.current + 1); + main.api.zoom.to(main.object.levels.current + 1); }, /** * Zoom out 1 level */ out: function() { - this.to(main.object.levels.current - 1); + main.api.zoom.to(main.object.levels.current - 1); } }, @@ -154,14 +151,14 @@ main.api = { /** * Array of controls to add - * @param {Array|Object} objects + * @param {Array|Object} buttons */ - add: function(objects) { - if(!Array.isArray(objects)) { - objects = [objects]; + add: function(buttons) { + if(!Array.isArray(buttons)) { + buttons = [buttons]; } var control_container = helpers.createElement('div', 'm4n-custom-control-container'); - objects.forEach(function(object) { + buttons.forEach(function(object) { var isDisabled = false; From ea80ef61b74d514e942355669b30e0e144b39f1d Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 5 Jul 2016 16:30:29 +0200 Subject: [PATCH 04/34] Let controls use the new api --- app/js/home_button.js | 17 ----------------- app/js/setup.js | 30 +++++++++++++++++++++++++++--- app/js/zoom_controls.js | 40 ---------------------------------------- app/less/controls.less | 15 --------------- 4 files changed, 27 insertions(+), 75 deletions(-) delete mode 100644 app/js/home_button.js delete mode 100644 app/js/zoom_controls.js diff --git a/app/js/home_button.js b/app/js/home_button.js deleted file mode 100644 index ffdd42e..0000000 --- a/app/js/home_button.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - - **/ -function createHomeButton() { - - var home_container = helpers.createElement('div', 'm4n-home-container'); - var home_button = helpers.createElement('div', 'm4n-control-button', { - 'click': function() { - main.api.reset(); - } - }); - - home_container.appendChild(home_button); - home_container.appendChild(helpers.createElement('div', 'm4n-control-separator')); - - main.controlContainer.appendChild(home_container); -} diff --git a/app/js/setup.js b/app/js/setup.js index 2b9c41f..6ae4a9f 100644 --- a/app/js/setup.js +++ b/app/js/setup.js @@ -23,16 +23,40 @@ function initializeM4n(mapJson) { main.object = revive(mapJson); main.controlContainer = helpers.createElement('div', 'm4n-control-container'); + main.controlContainer.style.zIndex = main.object.canvas.style.zIndex +1; if(main.object.levels.count() > 1 && main.zoomControls) { - createZoomControls(); + main.api.controls.add([ + { + text: '+', + click: main.api.zoom.in, + disabled: { + event: 'level_changed', + callback: function() { + return main.object.levels.current == main.object.levels.getLowest().level; + } + } + }, + { + text: "\u2013", + click: main.api.zoom.out, + disabled: { + event: 'level_changed', + callback: function() { + return main.object.levels.current == main.object.levels.getHighest().level; + } + } + } + ]); } if(main.homeButton) { - createHomeButton(); + main.api.controls.add({ + 'text': "\u2302", + 'click': main.api.reset + }); } - main.controlContainer.style.zIndex = main.object.canvas.style.zIndex +1; container.appendChild(main.controlContainer); if(!container.hasPredefinedHeight) { diff --git a/app/js/zoom_controls.js b/app/js/zoom_controls.js deleted file mode 100644 index 5c061ae..0000000 --- a/app/js/zoom_controls.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Create the zoom controls - */ -function createZoomControls() { - // Zoom controls - var zoom_container = helpers.createElement('div', 'm4n-zoom-container'); - var zoom_control_in = helpers.createElement('div', 'm4n-control-button', { - 'click': function() { - if(!zoom_control_in.classList.contains('disabled')) { - main.api.zoom.in(); - } - } - }); - var zoom_control_out = helpers.createElement('div', 'm4n-control-button', { - 'click': function() { - if(!zoom_control_out.classList.contains('disabled')) { - main.api.zoom.out(); - } - } - }); - - addEventListener("level_changed", function() { - var currentLevel = main.object.levels.getCurrent(); - - zoom_control_out.classList.remove('disabled'); - zoom_control_in.classList.remove('disabled'); - - if(currentLevel.level == main.object.levels.getHighest().level) { - zoom_control_out.classList.add('disabled'); - } else if(currentLevel.level == main.object.levels.getLowest().level) { - zoom_control_in.classList.add('disabled'); - } - }); - - zoom_container.appendChild(zoom_control_in); - zoom_container.appendChild(zoom_control_out); - zoom_container.appendChild(helpers.createElement('div', 'm4n-control-separator')); - - main.controlContainer.appendChild(zoom_container); -} diff --git a/app/less/controls.less b/app/less/controls.less index dd27033..162a493 100644 --- a/app/less/controls.less +++ b/app/less/controls.less @@ -41,21 +41,6 @@ cursor: not-allowed; } -//// -// Button icons - -.m4n-zoom-container div.m4n-control-button:nth-child(1)::before { - content: '+'; -} - -.m4n-zoom-container div.m4n-control-button:nth-child(2)::before { - content: '\2013'; -} - -.m4n-home-container div.m4n-control-button:first-child::before { - content: '\2302'; -} - .m4n-custom-control-container div.m4n-control-button::before { content: attr(data-content); } \ No newline at end of file From 8f4c42b6e23cc24a159c23a6a84c0fefc22cae69 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 5 Jul 2016 16:32:32 +0200 Subject: [PATCH 05/34] Move custom style code --- app/js/custom_style.js | 27 --------------------------- app/js/setup.js | 34 ++++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 33 deletions(-) delete mode 100644 app/js/custom_style.js diff --git a/app/js/custom_style.js b/app/js/custom_style.js deleted file mode 100644 index 54d95a8..0000000 --- a/app/js/custom_style.js +++ /dev/null @@ -1,27 +0,0 @@ -// Reload custom css file -var customStyle = document.getElementById("m4n-style-custom"); -if(customStyle !== null) { - var newCustomStyle = document.createElement("link"); - newCustomStyle.id = "m4n-style-custom"; - newCustomStyle.rel = "stylesheet"; - newCustomStyle.type = "text/css"; - newCustomStyle.href = customStyle.href; - - document.head.removeChild(customStyle); - document.head.appendChild(newCustomStyle); -} - -// Create the canvas -var canvas = document.getElementById(main.canvas); -if(canvas !== null) { - if(canvas.classList.contains("m4n-canvas")) { - throw "Map already initialized for " + main.canvas; - } else { - main.canvas = main.canvas + "-" + Math.random().toString(36).substring(7); - canvas = helpers.createElement("canvas", "m4n-canvas"); - canvas.id = main.canvas; - } -} else { - canvas = helpers.createElement("canvas", "m4n-canvas"); - canvas.id = main.canvas; -} \ No newline at end of file diff --git a/app/js/setup.js b/app/js/setup.js index 6ae4a9f..5e29897 100644 --- a/app/js/setup.js +++ b/app/js/setup.js @@ -112,7 +112,7 @@ function enableEventListeners() { function trackTransforms(ctx) { var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg'); var xform = svg.createSVGMatrix(); - ctx.getTransform = function(){ return xform; }; + ctx.getTransform = function() { return xform; }; var savedTransforms = []; var save = ctx.save; @@ -245,7 +245,33 @@ function createHtmlElements() { document.head.appendChild(style); } - ""; + // Reload custom css file + var customStyle = document.getElementById("m4n-style-custom"); + if(customStyle !== null) { + var newCustomStyle = document.createElement("link"); + newCustomStyle.id = "m4n-style-custom"; + newCustomStyle.rel = "stylesheet"; + newCustomStyle.type = "text/css"; + newCustomStyle.href = customStyle.href; + + document.head.removeChild(customStyle); + document.head.appendChild(newCustomStyle); + } + + // Create the canvas + var canvas = document.getElementById(main.canvas); + if(canvas !== null) { + if(canvas.classList.contains("m4n-canvas")) { + throw "Map already initialized for " + main.canvas; + } else { + main.canvas = main.canvas + "-" + Math.random().toString(36).substring(7); + canvas = helpers.createElement("canvas", "m4n-canvas"); + canvas.id = main.canvas; + } + } else { + canvas = helpers.createElement("canvas", "m4n-canvas"); + canvas.id = main.canvas; + } ""; @@ -265,8 +291,4 @@ function createHtmlElements() { canvas.width = container.clientWidth; } -""; - -""; - ""; \ No newline at end of file From 3892e0926597ef009cecb44a4608de43750678ca Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 5 Jul 2016 16:35:54 +0200 Subject: [PATCH 06/34] Cleanup --- app/js/event_listener.js | 42 ++++++++++++++++++++++++++++++---------- app/js/helpers.js | 32 ++++++++++++++++++++---------- app/js/smart_overlay.js | 8 ++++---- app/less/main.less | 1 + 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/app/js/event_listener.js b/app/js/event_listener.js index 2f2dc0b..de15e11 100644 --- a/app/js/event_listener.js +++ b/app/js/event_listener.js @@ -5,12 +5,21 @@ * @returns {number} The listener id */ function addEventListener(event, callback) { - if(typeof event !== 'string') { throw "event must be a string; " + event + " given"; } - if(typeof callback !== 'function') { throw "callback must be a function"; } + if(typeof event !== 'string') { + throw "event must be a string; " + event + " given"; + } + + if(typeof callback !== 'function') { + throw "callback must be a function"; + } - if(!main.dispatchEvents[event]) { main.dispatchEvents[event] = []; } + if(!main.dispatchEvents[event]) { + main.dispatchEvents[event] = []; + } - if(main.dev) { console.log("Event listener for event \"" + event + "\" added", callback); } + if(main.dev) { + console.log("Event listener for event \"" + event + "\" added", callback); + } return main.dispatchEvents[event].push(callback); } @@ -21,13 +30,26 @@ function addEventListener(event, callback) { * @param {number} id - the id of the listener */ function removeEventListener(event, id) { - if(typeof event !== 'string') { throw "event must be a string; " + event + " given"; } - if(typeof id !== 'number') { throw "id must be a number; " + id + " given"; } + if(typeof event !== 'string') { + throw "event must be a string; " + event + " given"; + } - if(!main.dispatchEvents[event]) { throw "unknown event"; } - if(!main.dispatchEvents[event][id -1]) { throw "unknown listener"; } + if(typeof id !== 'number') { + throw "id must be a number; " + id + " given"; + } + + if(!main.dispatchEvents[event]) { + throw "unknown event"; + } - if(main.dev) { console.log("Event listener for event \"" + event + "\" removed", main.dispatchEvents[event][id -1]); } + var listener = main.dispatchEvents[event][id -1]; + if(!listener) { + throw "unknown listener"; + } + + if(main.dev) { + console.log("Event listener for event \"" + event + "\" removed", listener); + } delete main.dispatchEvents[event][id -1]; } @@ -35,7 +57,7 @@ function removeEventListener(event, id) { /** * Trigger a custom event * @param {string} event - the name of the event that should be triggered - * @param {object} object - the parameter for the callback function + * @param {object} object - the parameter for the listener */ function triggerEvent(event, object) { if(main.dispatchEvents[event]) { diff --git a/app/js/helpers.js b/app/js/helpers.js index f47081d..7a5317a 100644 --- a/app/js/helpers.js +++ b/app/js/helpers.js @@ -32,9 +32,11 @@ var helpers = { * Help set value of double (tap|click) */ doubleTap: function() { - main.globals.doubleTap = - main.globals.doubleTap !== null && new Date().getTime() - main.globals.doubleTap <= 250 ? - true : new Date().getTime(); + if(main.globals.doubleTap !== null && new Date().getTime() - main.globals.doubleTap <= 250) { + main.globals.doubleTap = true; + } else { + main.globals.doubleTap = new Date().getTime(); + } }, /** @@ -74,7 +76,7 @@ var helpers = { /** * Create an html element * @param {string} tag - the tag of the element - * @param {string|string[]} classes - the classes for the element + * @param {string|Array} [classes] - the classes for the element * @param {Object|null} [events] - the event listeners * @returns {Element} the new element */ @@ -82,7 +84,13 @@ var helpers = { var element = document.createElement(tag); if(classes !== null) { - element.classList.add(classes); + if(!Array.isArray(classes)) { + classes = [classes]; + } + + classes.forEach(function(item) { + element.classList.add(item); + }); } for(var event in events) { @@ -90,6 +98,7 @@ var helpers = { element.addEventListener(event, events[event]); } } + return element; }, @@ -120,21 +129,24 @@ var helpers = { * Checks if the finger moved with a margin of 2 pixels * @param {object} a * @param {object} b - * @returns {boolean} + * @returns {boolean} if the click was within the margin */ validateTouchMoveClickMargin: function(a, b) { - return( + return ( (a.x > b.x -2 && a.x < b.x +2) && (a.y > b.y -2 && a.y < b.y +2) ); }, /** - * + * Checks if the clicked object is a sibling of m4n-container + * @returns {boolean} if one of the parents is the m4n-container */ clickedInCanvas: function(target) { - while (target = target.parentElement) { - if (target.classList.contains('m4n-container')) { return true } + while(target = target.parentElement) { + if(target.classList.contains('m4n-container')) { + return true; + } } return false; } diff --git a/app/js/smart_overlay.js b/app/js/smart_overlay.js index b4b7596..6fbab88 100644 --- a/app/js/smart_overlay.js +++ b/app/js/smart_overlay.js @@ -1,14 +1,14 @@ if(main.interact == "smart") { main.timeoutOverlay = helpers.createElement("div", "m4n-timeout-overlay", { - "click": helpers.hideTimeoutOverlay, - "touchstart": function(e) { + click: helpers.hideTimeoutOverlay, + touchstart: function(e) { main.globals.dragPosition = { x: e.touches[0].clientX, y: e.touches[0].clientY }; main.globals.clickStart = { x: e.touches[0].clientX, y: e.touches[0].clientY }; }, - "touchmove": function(e) { + touchmove: function(e) { main.globals.dragPosition = { x: e.touches[0].clientX, y: e.touches[0].clientY }; }, - "touchend": function() { + touchend: function() { if(helpers.validateTouchMoveClickMargin(main.globals.clickStart, main.globals.dragPosition)) { helpers.hideTimeoutOverlay(); } diff --git a/app/less/main.less b/app/less/main.less index 9266936..62179b1 100644 --- a/app/less/main.less +++ b/app/less/main.less @@ -21,6 +21,7 @@ } .m4n-canvas.grabbing { + cursor: move; cursor: grabbing; cursor: -moz-grabbing; cursor: -webkit-grabbing; From a0991afde15a3dc5e87d5b16a3bd9d3e72404287 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 5 Jul 2016 16:53:50 +0200 Subject: [PATCH 07/34] Fix offset popover --- app/js/classes/popup.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index c5149d8..feaf8c3 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -55,7 +55,7 @@ Popup.prototype.show = function(center) { var point = main.object.levels.getCurrent().points.get(this.number); // Center the map - if(center === true) { + if(center) { helpers.moveTo(point.position.left + (point.size.width / 2), point.position.top + (point.size.height / 2)); } else { var object = { x: 0, y: 0 }; @@ -169,9 +169,9 @@ Popup.prototype.onHide = function(force) { */ Popup.prototype.toggle = function(center, force) { if(this.on_screen) { - this.hide(force); + this.hide(force || false); } else { - this.show(center); + this.show(center || false); } }; @@ -229,7 +229,7 @@ Popup.prototype.startVideo = function() { Popup.prototype.generateHTML = function() { var title = typeof this.title !== "undefined" ? this.title : ""; var media = typeof this.media !== "undefined" ? this.media : null; - var info = typeof this.info !== "undefined" ? this.info : null; + var info = typeof this.info !== "undefined" ? this.info : ""; var popup = document.createElement("div"); popup.id = this.html_id; @@ -369,26 +369,26 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h var show = { above: function() { triangle.classList.add("bottom"); - popup.style.top = main.globals.offset.get().y + point.position.top - popup.clientHeight - heightTriangle + 'px'; + popup.style.top = main.globals.offset.get().y + point.position.top - popup.clientHeight - heightTriangle + 10 + 'px'; popup.style.left = main.globals.offset.get().x + point.position.left + (point.size.width / 2) - (popup.clientWidth * left) + 'px'; triangle.style.left = (left * 100) + "%"; }, beneath: function() { triangle.classList.add("top"); - popup.style.top = main.globals.offset.get().y + point.position.top + point.size.height + heightTriangle + 'px'; + popup.style.top = main.globals.offset.get().y + point.position.top + point.size.height + heightTriangle - 10 + 'px'; popup.style.left = main.globals.offset.get().x + point.position.left + (point.size.width / 2) - (popup.clientWidth * left) + 'px'; triangle.style.left = (left * 100) + "%"; }, left: function() { triangle.classList.add("right"); popup.style.top = (main.globals.offset.get().y + point.position.top + (point.size.height / 2) - (popup.clientHeight * top) - 10) + 'px'; - popup.style.left = main.globals.offset.get().x + point.position.left - popup.clientWidth - heightTriangle + 'px'; + popup.style.left = main.globals.offset.get().x + point.position.left - popup.clientWidth - heightTriangle - 10 + 'px'; triangle.style.top = (top * 100) + "%"; }, right: function() { triangle.classList.add("left"); popup.style.top = (main.globals.offset.get().y + point.position.top + (point.size.height / 2) - (popup.clientHeight * top) - 10) + 'px'; - popup.style.left = main.globals.offset.get().x + point.position.left + point.size.width + heightTriangle + 'px'; + popup.style.left = main.globals.offset.get().x + point.position.left + point.size.width + heightTriangle + 10 + 'px'; triangle.style.top = (top * 100) + "%"; } }; From 099e9004cd48b95677f7e8d1a08986c3efa13443 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 7 Jul 2016 10:16:00 +0200 Subject: [PATCH 08/34] Fix offset left and right --- app/js/classes/popup.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index feaf8c3..00c27aa 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -382,13 +382,13 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h left: function() { triangle.classList.add("right"); popup.style.top = (main.globals.offset.get().y + point.position.top + (point.size.height / 2) - (popup.clientHeight * top) - 10) + 'px'; - popup.style.left = main.globals.offset.get().x + point.position.left - popup.clientWidth - heightTriangle - 10 + 'px'; + popup.style.left = main.globals.offset.get().x + point.position.left - popup.clientWidth - heightTriangle + 10 + 'px'; triangle.style.top = (top * 100) + "%"; }, right: function() { triangle.classList.add("left"); popup.style.top = (main.globals.offset.get().y + point.position.top + (point.size.height / 2) - (popup.clientHeight * top) - 10) + 'px'; - popup.style.left = main.globals.offset.get().x + point.position.left + point.size.width + heightTriangle + 10 + 'px'; + popup.style.left = main.globals.offset.get().x + point.position.left + point.size.width + heightTriangle - 10 + 'px'; triangle.style.top = (top * 100) + "%"; } }; From 99af683c4233d36efac484b4ad088b01734aff30 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 7 Jul 2016 10:16:29 +0200 Subject: [PATCH 09/34] Fix errors on IE --- app/js/external_apis.js | 8 +++++++- app/js/setup.js | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/js/external_apis.js b/app/js/external_apis.js index b3f9984..84e197a 100644 --- a/app/js/external_apis.js +++ b/app/js/external_apis.js @@ -50,5 +50,11 @@ document.addEventListener("onYouTubeIframeAPIReady", externalAPIs.youtube.enable * "onYouTubeIframeAPIReady" is a core function from the youtube api */ window.onYouTubeIframeAPIReady = function() { - document.dispatchEvent(new CustomEvent("onYouTubeIframeAPIReady", null)); + if(document.createEvent) { + var event = document.createEvent("Event"); + event.initEvent("onYouTubeIframeAPIReady", false, false); + document.dispatchEvent(event); + } else { + document.dispatchEvent(new Event("onYouTubeIframeAPIReady")); + } }; \ No newline at end of file diff --git a/app/js/setup.js b/app/js/setup.js index 5e29897..e6c58ae 100644 --- a/app/js/setup.js +++ b/app/js/setup.js @@ -6,7 +6,7 @@ request.open('GET', main.json, true); request.onreadystatechange = function() { if(request.readyState == 4 && request.status == 200) { initializeM4n(request.responseText); - } else if(request.status !== 200) { + } else if([0, 200].indexOf(request.status) == -1) { console.error("Something went wrong!", request); } }; From 5525a3877b16219cd86e61f63e4bc1537084f73c Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 7 Jul 2016 10:57:53 +0200 Subject: [PATCH 10/34] Call desktop method as default --- app/js/classes/popup.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index 00c27aa..bee290b 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -114,7 +114,7 @@ Popup.prototype.show = function(center) { */ Popup.prototype.onShowMobile = function(point) { // Overwrite with popup specific code - return false; + return this.onShowDesktop(); }; /** @@ -451,7 +451,7 @@ Popup.prototype.generateOverlay = function(popup, title_html, info_html, media_h return true; }; - this.onShowDesktop = this.onShowMobile = function() { + this.onShowDesktop = function() { popup.style.display = "block"; popup.style.left = main.object.canvas.clientLeft + "px"; popup.style.top = main.object.canvas.clientTop + "px"; @@ -547,7 +547,7 @@ Popup.prototype.generateSidebar = function(popup, title_html, info_html, media_h return false; }; - this.onShowDesktop = this.onShowMobile = function() { + this.onShowDesktop = function() { popup.style.removeProperty("display"); return true; }; From 9bd055acc83c5e3e0a93b84326c77d12fe59b608 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 7 Jul 2016 13:59:29 +0200 Subject: [PATCH 11/34] Update readme --- readme.txt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/readme.txt b/readme.txt index cab319a..67bc031 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,17 @@ ------------------------------------------------------------------------ -Copyright (C) @maps4news interactive maps (v2.0) +Copyright © @maps4news interactive maps (v2.0) ------------------------------------------------------------------------ x Upload this folder to a directory on your server. -x Add m4n.js to your page. -x Add the following HTML to your webpage +x Add the following HTML to your web page
- + +
-x Replace the two [id]'s with both the same unique id and [path] with a relative reference to the tile directory. \ No newline at end of file +x Replace the two [id]s with both the same unique id, e.g. m4n-map +x Replace [script path] with the url to the m4n.js script found in the zip file +x Replace [path] with a relative path to the directory with the tiles found in the zip file. From 1bba046601438bf4d35ba7a9b6ce238fcb817930 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 7 Jul 2016 14:25:28 +0200 Subject: [PATCH 12/34] Update docs --- docs.md | 14 ++++++++++---- readme.txt | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs.md b/docs.md index a4ec38c..ab48da3 100644 --- a/docs.md +++ b/docs.md @@ -61,7 +61,7 @@ The M4nInteractive class accepts the following parameters: | online | The default environment of a map. | | beta | For maps generated with the M4N beta tool. | | bleeding | For maps generated with the M4N bleeding tool. | - | download | This should be used when a user wants to self-host their map. | + | local | This should be used when a user wants to self-host their map. | | development | Used by M4N employees during development. (will enable debugging mode) | - __interact__. (optional; default "scroll") The way interaction with the map works. @@ -69,7 +69,7 @@ The M4nInteractive class accepts the following parameters: | -------- | ----------- | | scroll | allow scrolling the map to zoom it in or out (holding ctrl will __disable__ scroll zooming) | | controls | use the on-screen controls and the mouse buttons to zoom in or out (holding ctrl will __enable__ scroll zooming) | - | smart | an overlay will be placed over the map when the user is not working with the map and disables the events to the map (timeout of 3 seconds; will not disable when a popup is active) | + | smart | an overlay will be placed over the map when the user is not interacting with the map and disables the events to the map (the overaly will reappear when the user clicks outside the map) | - __zoomControls__. (optional; default true) Enable or disable the zoom controls for maps with more than 1 level. @@ -333,12 +333,18 @@ var levels = []; map.api.levels().levels.forEach(function(level) { levels.push({ 'text': level.level, - 'click': level.changeTo + 'click': level.changeTo, + 'disabled': { + 'event': 'level_changed', + 'callback': function() { + return map.api.levels().current == level.level; + } + } }); }); map.api.controls.add(levels); ``` -The code in the example will add a cluster of all levels to the control container and when they're clicked the map will change to that level. +The code in the example will add a cluster of all levels to the control container, the button for the current level will be disabled and when a button is clicked the map will change to that level. ### addEventListener The `addEventListener` method is used to add an eventListener to an event. diff --git a/readme.txt b/readme.txt index 67bc031..fe9a82a 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Copyright © @maps4news interactive maps (v2.0) ------------------------------------------------------------------------ x Upload this folder to a directory on your server. -x Add the following HTML to your web page +x Add the following HTML to your web page.
-x Replace the two [id]s with both the same unique id, e.g. m4n-map -x Replace [script path] with the url to the m4n.js script found in the zip file +x Replace the two [id]s with both the same unique id, e.g. m4n-map. +x Replace [script path] with the url to the m4n.js script found in the zip file. x Replace [path] with a relative path to the directory with the tiles found in the zip file. From 1541841dea3cf7b834bbd243f181bb90ff69072c Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 7 Jul 2016 15:51:29 +0200 Subject: [PATCH 13/34] Show single object can be passed as button --- docs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs.md b/docs.md index ab48da3..7d62599 100644 --- a/docs.md +++ b/docs.md @@ -186,9 +186,9 @@ In the API you will find a number of functions which can be used to interact wit controls: { /** * Array of controls to add - * @param {Array} objects - The array object + * @param {Array|Object} buttons - The button or array of buttons to add */ - add: function(objects) {} + add: function(buttons) {} } } ``` From 97fcf0c901af845d85be27c6072c975ebe48fd83 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 19 Jul 2016 10:58:16 +0200 Subject: [PATCH 14/34] Allow inline map object loading --- app/js/options.js | 3 ++- app/js/setup.js | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/app/js/options.js b/app/js/options.js index 06258a2..b01f9dc 100644 --- a/app/js/options.js +++ b/app/js/options.js @@ -11,6 +11,7 @@ main.environment = options.environment || "online"; main.zoomControls = typeof options.zoomControls !== 'undefined' ? options.zoomControls : true; main.homeButton = typeof options.homeButton !== 'undefined' ? options.homeButton : true; + main.inlineObject = main.environment === 'development' && typeof options.object !== 'undefined'; main.version = { map: '2.0', code: '2.0.5' }; @@ -30,7 +31,7 @@ switch(main.environment) { case 'development': main.url = location.href.split("/").slice(0, -1).join("/") + '/output/' + options.path + '/'; - main.json = main.url + 'map.json'; + main.json = main.inlineObject ? options.object : main.url + 'map.json'; break; case 'local': main.url = options.path.replace(/\/$/, '') + '/'; // Path to images diff --git a/app/js/setup.js b/app/js/setup.js index e6c58ae..9e13a43 100644 --- a/app/js/setup.js +++ b/app/js/setup.js @@ -1,16 +1,25 @@ /** * Download the JSON file */ -var request = new XMLHttpRequest(); -request.open('GET', main.json, true); -request.onreadystatechange = function() { - if(request.readyState == 4 && request.status == 200) { - initializeM4n(request.responseText); - } else if([0, 200].indexOf(request.status) == -1) { - console.error("Something went wrong!", request); +if(main.inlineObject) { + if(typeof main.json !== "string") { + main.json = JSON.stringify(main.json); } -}; -request.send(); + setTimeout(function() { + initializeM4n(main.json); + }, 0); // I'm lovin' it. +} else { + var request = new XMLHttpRequest(); + request.open('GET', main.json, true); + request.onreadystatechange = function() { + if(request.readyState == 4 && request.status == 200) { + initializeM4n(request.responseText); + } else if([0, 200].indexOf(request.status) == -1) { + console.error("Something went wrong!", request); + } + }; + request.send(); +} /** * Initialize the map From ce8a765e322527eec2e0de40211ef241bb51b796 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 19 Jul 2016 12:10:37 +0200 Subject: [PATCH 15/34] Added object docs #21 --- docs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs.md b/docs.md index 7d62599..a0fdc07 100644 --- a/docs.md +++ b/docs.md @@ -76,6 +76,7 @@ The M4nInteractive class accepts the following parameters: - __homeButton__. (optional; default true) Enable or disable the home button - __debug__. (not recommended) true or false, this allows the map object to be returned from the browser's console. + - __object__. (only with environment "development") Add your map object inline for debugging without a webserver. 2. The div container node (in this case the `div` with id `m4n-map`). 3. The callback (optional), this will be called after the map has finished initializing. Best used for subscribing to custom events. The callback function has 1 parameter, the map object, as described below. From cfa95413c5579f6042b5c54e6aee4511dc29958f Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 19 Jul 2016 12:57:55 +0200 Subject: [PATCH 16/34] Added close button for popovers #14 --- app/js/classes/popup.js | 10 +++++++++- app/less/popups/popover.less | 20 +++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index bee290b..f062b33 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -303,9 +303,17 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h popup.classList.add("m4n-popover"); var triangle = helpers.createElement("div", "m4n-popover-triangle"); + var header = helpers.createElement("div", "m4n-popover-header"); + var close = helpers.createElement("div", "m4n-popover-close", { + "click": function() { this.hide(true); }.bind(this), + "touchend": function() { this.hide(true); }.bind(this) + }); + + header.appendChild(close); + header.appendChild(title_html); popup.appendChild(triangle); - popup.appendChild(title_html); + popup.appendChild(header); popup.appendChild(media_html); popup.appendChild(info_html); diff --git a/app/less/popups/popover.less b/app/less/popups/popover.less index ba716ee..f1602e7 100644 --- a/app/less/popups/popover.less +++ b/app/less/popups/popover.less @@ -15,7 +15,7 @@ display: none; } -.m4n-popover .m4n-title { +.m4n-popover .m4n-popover-header { font-size: 14px; line-height: 1.5; padding: 10px; @@ -83,4 +83,22 @@ background: white; box-shadow: -1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); z-index: -1; +} + +.m4n-popover-close { + float: right; + color: #888; + text-align: center; + font-family: "Arial", serif; + font-weight: bold; + cursor: pointer; + top: 0; +} + +.m4n-popover-close:hover { + color: #555; +} + +.m4n-popover-close::before { + content: '✕'; } \ No newline at end of file From 8bded39a9d715aa5e3c9e20a55a3f68f2eaece38 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 19 Jul 2016 13:25:23 +0200 Subject: [PATCH 17/34] Allow children to be passed to the createElement helper --- app/js/helpers.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/js/helpers.js b/app/js/helpers.js index 7a5317a..09e97f6 100644 --- a/app/js/helpers.js +++ b/app/js/helpers.js @@ -78,12 +78,13 @@ var helpers = { * @param {string} tag - the tag of the element * @param {string|Array} [classes] - the classes for the element * @param {Object|null} [events] - the event listeners + * @param {Array} [children] - array of child elements * @returns {Element} the new element */ - createElement: function(tag, classes, events) { + createElement: function(tag, classes, events, children) { var element = document.createElement(tag); - if(classes !== null) { + if(!!classes) { if(!Array.isArray(classes)) { classes = [classes]; } @@ -93,9 +94,19 @@ var helpers = { }); } - for(var event in events) { - if(events.hasOwnProperty(event)) { - element.addEventListener(event, events[event]); + if(!!events) { + for(var event in events) { + if(events.hasOwnProperty(event)) { + element.addEventListener(event, events[event]); + } + } + } + + if(!!children) { + for(var child in children) { + if(children.hasOwnProperty(child)) { + element.appendChild(children[child]); + } } } From 6895cce7680465e591ebd1ab7c2df75e6d99e1ce Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 19 Jul 2016 15:04:48 +0200 Subject: [PATCH 18/34] Reformat popup html, cleanup & reformat --- .gitignore | 1 - .idea/.gitignore | 5 ++ .idea/codeStyleSettings.xml | 61 ++++++++++++++ .idea/encodings.xml | 6 ++ app/js/classes/level.js | 1 - app/js/classes/popup.js | 158 +++++++++++++++-------------------- app/js/classes/popups.js | 2 +- app/js/event_listener.js | 4 +- app/js/events.js | 18 ++-- app/js/globals.js | 74 ++++++++-------- app/js/helpers.js | 4 +- app/js/options.js | 8 +- app/js/setup.js | 11 ++- app/less/controls.less | 48 +++++------ app/less/main.less | 50 +++++------ app/less/popups/overlay.less | 77 +++++++++-------- app/less/popups/popover.less | 121 +++++++++++++-------------- app/less/popups/sidebar.less | 117 +++++++++++++------------- 18 files changed, 410 insertions(+), 356 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyleSettings.xml create mode 100644 .idea/encodings.xml diff --git a/.gitignore b/.gitignore index d4e0572..76add87 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ node_modules -.idea dist \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..cd31c92 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +* +!.gitignore +!codeStyleSettings.xml +!jsLinters +!encodings.xml \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 0000000..a8d6ce5 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,61 @@ + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/js/classes/level.js b/app/js/classes/level.js index 59b927c..63e16d1 100644 --- a/app/js/classes/level.js +++ b/app/js/classes/level.js @@ -60,7 +60,6 @@ Level.prototype.checkLoaded = function() { Level.prototype.draw = function() { main.object.popups.hideAll(); - main.object.context.save(); main.object.context.setTransform(1, 0, 0, 1, 0, 0); diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index f062b33..80b206d 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -233,7 +233,7 @@ Popup.prototype.generateHTML = function() { var popup = document.createElement("div"); popup.id = this.html_id; - popup.style.zIndex = main.object.canvas.style.zIndex +1; + popup.style.zIndex = main.object.canvas.style.zIndex + 2; var title_html = helpers.createElement("div", "m4n-title"); title_html.innerHTML = title; @@ -302,18 +302,14 @@ Popup.prototype.generateHTML = function() { Popup.prototype.generatePopover = function(popup, title_html, info_html, media_html) { popup.classList.add("m4n-popover"); - var triangle = helpers.createElement("div", "m4n-popover-triangle"); - var header = helpers.createElement("div", "m4n-popover-header"); - var close = helpers.createElement("div", "m4n-popover-close", { - "click": function() { this.hide(true); }.bind(this), - "touchend": function() { this.hide(true); }.bind(this) - }); - - header.appendChild(close); - header.appendChild(title_html); - - popup.appendChild(triangle); - popup.appendChild(header); + popup.appendChild(helpers.createElement("div", "m4n-popover-triangle")); + popup.appendChild(helpers.createElement("div", "m4n-popover-header", null, [ + helpers.createElement("div", "m4n-popover-close", { + "click": this.hide.bind(this), + "touchend": this.hide.bind(this) + }), + title_html + ])); popup.appendChild(media_html); popup.appendChild(info_html); @@ -435,24 +431,17 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h Popup.prototype.generateOverlay = function(popup, title_html, info_html, media_html) { popup.classList.add("m4n-overlay"); - var info_container = document.createElement("div"); - info_container.appendChild(title_html); - info_container.appendChild(media_html); - info_container.appendChild(info_html); - - var cell = document.createElement("div"); - var aligner = document.createElement("div"); - - var close_button = helpers.createElement("span", "close_overlay", { - "click": function() { this.hide(); }.bind(this), - "touchend": function() { this.hide(); }.bind(this) - }); - - aligner.appendChild(info_container); - cell.appendChild(aligner); - - popup.appendChild(cell); - popup.appendChild(close_button); + // Content + popup.appendChild(helpers.createElement("div", null, null, [ + helpers.createElement("div", null, null, [ + helpers.createElement("div", null, null, [title_html, media_html, info_html]) + ]) + ])); + // Close button + popup.appendChild(helpers.createElement("span", "close-overlay", { + "click": this.hide.bind(this), + "touchend": this.hide.bind(this) + })); this.onHide = function() { popup.style.display = "none"; @@ -485,65 +474,54 @@ Popup.prototype.generateSidebar = function(popup, title_html, info_html, media_h popup.classList.add("m4n-sidebar-container"); - var sidebar = helpers.createElement("div", "m4n-sidebar"); - var header = helpers.createElement("div", "m4n-sidebar-header"); - var close = helpers.createElement("div", "m4n-sidebar-close", { - "click": function() { this.hide(true); }.bind(this), - "touchend": function() { this.hide(true); }.bind(this) - }); - - header.appendChild(close); - header.appendChild(title_html); - - var content = helpers.createElement("div", "m4n-sidebar-content"); - content.appendChild(media_html); - content.appendChild(info_html); - - var footer = helpers.createElement("div", "m4n-sidebar-footer"); - var pagination = helpers.createElement("ul", "m4n-pagination"); - - var previous = helpers.createElement("li", null, { - "click": function() { - this.hide(true); - var new_popup; - if(this.number != main.object.popups.getFirst().number) { - new_popup = main.api.popup(this.number -1); - } else { - new_popup = main.api.popup(main.object.popups.getLast().number); - } - if(new_popup !== null) { - new_popup.show(true); - } - }.bind(this) - }); - - var next = helpers.createElement("li", null, { - "click": function() { - this.hide(true); - var new_popup; - if(this.number != main.object.popups.getLast().number) { - new_popup = main.api.popup(this.number + 1); - } else { - new_popup = main.api.popup(main.object.popups.getFirst().number); - } - if(new_popup !== null) { - new_popup.show(true); - } - }.bind(this) - }); - - var clear = document.createElement("div"); - clear.style.clear = "both"; - - pagination.appendChild(previous); - pagination.appendChild(next); - - footer.appendChild(pagination); - footer.appendChild(clear); - - sidebar.appendChild(header); - sidebar.appendChild(content); - sidebar.appendChild(footer); + var sidebar = helpers.createElement("div", "m4n-sidebar", null, [ + // Header + helpers.createElement("div", "m4n-sidebar-header", null, [ + // Close button + helpers.createElement("div", "m4n-sidebar-close", { + "click": function() { this.hide(true); }.bind(this), + "touchend": function() { this.hide(true); }.bind(this) + }), + // Title + title_html + ]), + // Content + helpers.createElement("div", "m4n-sidebar-content", null, [media_html, info_html]), + // Footer + helpers.createElement("div", "m4n-sidebar-footer", null, [ + // Pagination + helpers.createElement("ul", "m4n-pagination", null, [ + // Previous + helpers.createElement("li", null, { + "click": function() { + this.hide(true); + var new_popup; + if(this.number != main.object.popups.getFirst().number) { + new_popup = main.api.popup(this.number - 1); + } else { + new_popup = main.api.popup(main.object.popups.getLast().number); + } + if(!!new_popup) { + new_popup.show(true); + } + }.bind(this) + }), + // Next + helpers.createElement("li", null, { + "click": function() { + this.hide(true); + var new_popup; + if(this.number != main.object.popups.getLast().number) { + new_popup = main.api.popup(this.number + 1); + } else { + new_popup = main.api.popup(main.object.popups.getFirst().number); + } + if(!!new_popup) { new_popup.show(true); } + }.bind(this) + }) + ]) + ]) + ]); popup.appendChild(sidebar); diff --git a/app/js/classes/popups.js b/app/js/classes/popups.js index 8f5b30d..5ccc65d 100644 --- a/app/js/classes/popups.js +++ b/app/js/classes/popups.js @@ -67,7 +67,7 @@ Popups.prototype.getFirst = function() { * @returns {Popup} */ Popups.prototype.getLast = function() { - return this.list[this.list.length -1]; + return this.list[this.list.length - 1]; }; /** diff --git a/app/js/event_listener.js b/app/js/event_listener.js index de15e11..6ff3074 100644 --- a/app/js/event_listener.js +++ b/app/js/event_listener.js @@ -42,7 +42,7 @@ function removeEventListener(event, id) { throw "unknown event"; } - var listener = main.dispatchEvents[event][id -1]; + var listener = main.dispatchEvents[event][id - 1]; if(!listener) { throw "unknown listener"; } @@ -51,7 +51,7 @@ function removeEventListener(event, id) { console.log("Event listener for event \"" + event + "\" removed", listener); } - delete main.dispatchEvents[event][id -1]; + delete main.dispatchEvents[event][id - 1]; } /** diff --git a/app/js/events.js b/app/js/events.js index ee8cdd8..880e9e0 100644 --- a/app/js/events.js +++ b/app/js/events.js @@ -101,8 +101,7 @@ var events = { main.globals.isDown = false; if(helpers.clickedInCanvas(e.target)) { if(helpers.validateTouchMoveClickMargin(main.globals.clickStart, main.globals.dragPosition) && !main.globals.isScaling) { - var point = main.object.levels.getCurrent() - .points.hitAPoint(main.globals.dragPosition.x, main.globals.dragPosition.y); + var point = main.object.levels.getCurrent().points.hitAPoint(main.globals.dragPosition.x, main.globals.dragPosition.y); if(point !== null && !main.globals.isScaling) { main.object.popups.get(point.number).show(); } else { @@ -166,8 +165,7 @@ var events = { ); main.globals.dragPosition = { x: e.pageX, y: e.pageY }; - - main.object.context.fillRect(e.pageX - 5, e.pageY -5, 10, 10); + main.object.context.fillRect(e.pageX - 5, e.pageY - 5, 10, 10); currentLevel.draw(); } else if(helpers.clickedInCanvas(e.target)) { @@ -242,9 +240,9 @@ var events = { }; if(!( - (currentLevel.level == main.object.levels.getLowest().level && !pinching) || - (currentLevel.level == main.object.levels.getHighest().level && pinching) - )) { + (currentLevel.level == main.object.levels.getLowest().level && !pinching) || + (currentLevel.level == main.object.levels.getHighest().level && pinching) + )) { gPz = helpers.gesturePinchZoom(e) / 40; } if(gPz < 1 && gPz > -1) { @@ -380,7 +378,11 @@ var events = { } if(!fullscreen) { - main.globals.videoFullscreen = { value: false, date: new Date().getTime(), noEvents: main.globals.videoFullscreen.noEvents+1 }; + main.globals.videoFullscreen = { + value: false, + date: new Date().getTime(), + noEvents: main.globals.videoFullscreen.noEvents + 1 + }; } } }; \ No newline at end of file diff --git a/app/js/globals.js b/app/js/globals.js index 869f521..633eede 100644 --- a/app/js/globals.js +++ b/app/js/globals.js @@ -1,40 +1,40 @@ main.globals = { - // Keep track of the cursor; if it's down (clicked) - isDown: false, - // If the user is scaling - isScaling: false, - // The location of the initial click - clickStart: { x: 0, y: 0 }, - // The location of the last move event - dragPosition: { x: 0, y: 0 }, - // The offset of the map on screen - mapOffset: { x: 0, y: 0 }, - // If the user has double tapped or clicked - doubleTap: null, - // If a video prompted the fullscreen and when - videoFullscreen: { value: false, date: null, noEvents: 2 }, - // - scroll: { value: 0, timeout: null }, - // - startDistance: 0, - // - scaleFactor: 1.1, - // - lastPos: { x: 0, y: 0 }, - // - interact: { isInteracting: false, timer: null }, + // Keep track of the cursor; if it's down (clicked) + isDown: false, + // If the user is scaling + isScaling: false, + // The location of the initial click + clickStart: { x: 0, y: 0 }, + // The location of the last move event + dragPosition: { x: 0, y: 0 }, + // The offset of the map on screen + mapOffset: { x: 0, y: 0 }, + // If the user has double tapped or clicked + doubleTap: null, + // If a video prompted the fullscreen and when + videoFullscreen: { value: false, date: null, noEvents: 2 }, + // + scroll: { value: 0, timeout: null }, + // + startDistance: 0, + // + scaleFactor: 1.1, + // + lastPos: { x: 0, y: 0 }, + // + interact: { isInteracting: false, timer: null }, - // mapOffset helper functions - offset: { - changeBy: function (x, y) { - main.globals.mapOffset.x += x; - main.globals.mapOffset.y += y; - }, - changeTo: function (x, y) { - main.globals.mapOffset = { x: x, y: y }; - }, - get: function () { - return main.globals.mapOffset; - } - } + // mapOffset helper functions + offset: { + changeBy: function(x, y) { + main.globals.mapOffset.x += x; + main.globals.mapOffset.y += y; + }, + changeTo: function(x, y) { + main.globals.mapOffset = { x: x, y: y }; + }, + get: function() { + return main.globals.mapOffset; + } + } }; \ No newline at end of file diff --git a/app/js/helpers.js b/app/js/helpers.js index 09e97f6..06bb878 100644 --- a/app/js/helpers.js +++ b/app/js/helpers.js @@ -144,8 +144,8 @@ var helpers = { */ validateTouchMoveClickMargin: function(a, b) { return ( - (a.x > b.x -2 && a.x < b.x +2) && - (a.y > b.y -2 && a.y < b.y +2) + (a.x > b.x - 2 && a.x < b.x + 2) && + (a.y > b.y - 2 && a.y < b.y + 2) ); }, diff --git a/app/js/options.js b/app/js/options.js index b01f9dc..cdf2550 100644 --- a/app/js/options.js +++ b/app/js/options.js @@ -4,8 +4,12 @@ (function(options) { main.startTime = new Date().getTime(); - if(!options.path) throw 'M4nInteractive Parameter \'path\' is missing'; - if(!container) throw 'M4nInteractive: No container was given'; + if(!options.path) { + throw 'M4nInteractive Parameter \'path\' is missing'; + } + if(!container) { + throw 'M4nInteractive: No container was given'; + } main.interact = options.interact || "scroll"; main.environment = options.environment || "online"; diff --git a/app/js/setup.js b/app/js/setup.js index 9e13a43..1dd34a3 100644 --- a/app/js/setup.js +++ b/app/js/setup.js @@ -32,7 +32,7 @@ function initializeM4n(mapJson) { main.object = revive(mapJson); main.controlContainer = helpers.createElement('div', 'm4n-control-container'); - main.controlContainer.style.zIndex = main.object.canvas.style.zIndex +1; + main.controlContainer.style.zIndex = main.object.canvas.style.zIndex + 1; if(main.object.levels.count() > 1 && main.zoomControls) { main.api.controls.add([ @@ -84,7 +84,9 @@ function initializeM4n(mapJson) { main.object.popups.generateHTML(); main.api.reset(); - if(typeof callback === 'function') callback(returnObject); + if(typeof callback === 'function') { + callback(returnObject); + } main.endTime = new Date().getTime(); if(main.dev) { @@ -119,7 +121,7 @@ function enableEventListeners() { * @param {object} ctx - the context */ function trackTransforms(ctx) { - var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg'); + var svg = document.createElementNS("http://www.w3.org/2000/svg", 'svg'); var xform = svg.createSVGMatrix(); ctx.getTransform = function() { return xform; }; @@ -180,7 +182,8 @@ function trackTransforms(ctx) { var pt = svg.createSVGPoint(); ctx.transformedPoint = function(x, y) { - pt.x = x; pt.y = y; + pt.x = x; + pt.y = y; return pt.matrixTransform(xform.inverse()); }; } diff --git a/app/less/controls.less b/app/less/controls.less index 162a493..786245e 100644 --- a/app/less/controls.less +++ b/app/less/controls.less @@ -1,46 +1,46 @@ // Icon container position and styling .m4n-control-container { - position: absolute; - top: 20px; - right: 10px; - font-size: 15px; - font-weight: bold; - font-family: "Arial", serif; - color: #555555; - text-align: center; - pointer-events: none; + position: absolute; + top: 20px; + right: 10px; + font-size: 15px; + font-weight: bold; + font-family: "Arial", serif; + color: #555555; + text-align: center; + pointer-events: none; } .m4n-control-container > div:not(.m4n-control-separator) { - border-bottom: 0; + border-bottom: 0; } // Separator .m4n-control-container .m4n-control-separator { - height: 10px; - pointer-events: none; + height: 10px; + pointer-events: none; } .m4n-control-button { - width: 20px; - height: 20px; - line-height: 20px; - cursor: pointer; - border: 1px solid #CCCCCC; - background-color: #FFFFFF; - pointer-events: all; + width: 20px; + height: 20px; + line-height: 20px; + cursor: pointer; + border: 1px solid #CCCCCC; + background-color: #FFFFFF; + pointer-events: all; } .m4n-control-button:hover { - background: #EFEFEF; + background: #EFEFEF; } .m4n-control-button.disabled { - background: #DDDDDD; - color: #AAAAAA; - cursor: not-allowed; + background: #DDDDDD; + color: #AAAAAA; + cursor: not-allowed; } .m4n-custom-control-container div.m4n-control-button::before { - content: attr(data-content); + content: attr(data-content); } \ No newline at end of file diff --git a/app/less/main.less b/app/less/main.less index 62179b1..c8b8b45 100644 --- a/app/less/main.less +++ b/app/less/main.less @@ -1,53 +1,53 @@ .m4n-container *, .m4n-container *:after, .m4n-container *:before { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } .m4n-container { - position: relative; - display: inline-block; + position: relative; + display: inline-block; } .m4n-container::after { - clear: both; + clear: both; } .m4n-canvas { - float: left; - cursor: grab; - cursor: -moz-grab; - cursor: -webkit-grab; + float: left; + cursor: grab; + cursor: -moz-grab; + cursor: -webkit-grab; } .m4n-canvas.grabbing { - cursor: move; - cursor: grabbing; - cursor: -moz-grabbing; - cursor: -webkit-grabbing; + cursor: move; + cursor: grabbing; + cursor: -moz-grabbing; + cursor: -webkit-grabbing; } .m4n-canvas.pointing { - cursor: pointer; + cursor: pointer; } .m4n-video::-webkit-media-controls-current-time-display, .m4n-video::-webkit-media-controls-time-remaining-display, .m4n-video::-webkit-media-controls-toggle-closed-captions-button, .m4n-video::-webkit-media-controls-volume-slider { - display:none; + display: none; } .m4n-timeout-overlay { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - background-color: rgba(0, 0, 0, 0.3); - z-index: 2; - cursor: pointer; - display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(0, 0, 0, 0.3); + z-index: 2; + cursor: pointer; + display: block; } @import "popups/popover"; diff --git a/app/less/popups/overlay.less b/app/less/popups/overlay.less index 853ae32..ae697d3 100644 --- a/app/less/popups/overlay.less +++ b/app/less/popups/overlay.less @@ -1,71 +1,70 @@ .m4n-overlay { - position: absolute; - top: 0; - background: rgba(0, 0, 0, 0.8); - color: white; - text-align: center; - width: 100%; - height: 100%; - z-index: 10; - overflow-y: auto; - display: none; + position: absolute; + top: 0; + background: rgba(0, 0, 0, 0.8); + color: white; + text-align: center; + width: 100%; + height: 100%; + overflow-y: auto; + display: none; } .m4n-overlay > div { - display: table; - width: 100%; - height: 100%; + display: table; + width: 100%; + height: 100%; } .m4n-overlay > div > div { - display: table-cell; - vertical-align: middle; + display: table-cell; + vertical-align: middle; } .m4n-overlay > div > div > div { - margin-left: auto; - margin-right: auto; + margin-left: auto; + margin-right: auto; } .m4n-overlay .m4n-title, .m4n-overlay .m4n-media, .m4n-overlay .m4n-info { - max-width: 90%; - margin: 0 auto; + max-width: 90%; + margin: 0 auto; } .m4n-overlay .m4n-title { - font-size: 13px; - font-weight: bold; - line-height: 1.5; - padding-bottom: 8px; + font-size: 13px; + font-weight: bold; + line-height: 1.5; + padding-bottom: 8px; } .m4n-overlay .m4n-media img, .m4n-overlay .m4n-media iframe { - max-width: 100%; - max-height: 100%; + max-width: 100%; + max-height: 100%; } .m4n-overlay .m4n-info { - font-size: 12px; - font-weight: normal; - line-height: 1.5; + font-size: 12px; + font-weight: normal; + line-height: 1.5; } -.close_overlay::before { - content: '✕'; +.m4n-overlay .close-overlay::before { + content: '✕'; } -.close_overlay { - position: absolute; - top: 0; - right: 5px; - font-weight: bold; - font-size: 20px; - cursor: pointer; +.m4n-overlay .close-overlay { + position: absolute; + top: 0; + right: 5px; + font-weight: bold; + font-size: 20px; + cursor: pointer; } -.close_overlay:hover { - color: grey; +.m4n-overlay .close-overlay:hover { + color: grey; } \ No newline at end of file diff --git a/app/less/popups/popover.less b/app/less/popups/popover.less index f1602e7..cff2125 100644 --- a/app/less/popups/popover.less +++ b/app/less/popups/popover.less @@ -1,32 +1,31 @@ .m4n-popover { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - position: absolute; - max-width: 200px; - text-align: left; - color: black; - border: 0.5px solid #DDDDDD; - border-radius: 5px; - background-color: white; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.4); - z-index: 10; - display: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: absolute; + max-width: 200px; + text-align: left; + color: black; + border: 0.5px solid #DDDDDD; + border-radius: 5px; + background-color: white; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.4); + display: none; } .m4n-popover .m4n-popover-header { - font-size: 14px; - line-height: 1.5; - padding: 10px; - background: rgb(240, 240, 240); - border-top-left-radius: 5px; - border-top-right-radius: 5px; + font-size: 14px; + line-height: 1.5; + padding: 10px; + background: rgb(240, 240, 240); + border-top-left-radius: 5px; + border-top-right-radius: 5px; } .m4n-popover .m4n-media { - min-height: 1px; - width: 200px; + min-height: 1px; + width: 200px; } .m4n-popover .m4n-media img, @@ -34,71 +33,71 @@ .m4n-popover .m4n-media object, .m4n-popover .m4n-media video, .m4n-popover .m4n-media iframe { - max-width: 100%; + max-width: 100%; } .m4n-popover .m4n-info { - font-size: 12px; - line-height: 1.5; - padding: 5px 10px 10px 10px; - z-index: 1; + font-size: 12px; + line-height: 1.5; + padding: 5px 10px 10px 10px; + z-index: 1; } .m4n-popover-triangle, .m4n-popover-triangle { - content: ''; - position: absolute; - display: block; - width: 22px; - height: 22px; - margin-left: -12px; - -webkit-transform: rotate(45deg); - -moz-transform: rotate(45deg); - -ms-transform: rotate(45deg); + content: ''; + position: absolute; + display: block; + width: 22px; + height: 22px; + margin-left: -12px; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); } .m4n-popover-triangle.bottom { - bottom: -11px; - background: white; - box-shadow: 1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); - z-index: -1; + bottom: -11px; + background: white; + box-shadow: 1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); + z-index: -1; } .m4n-popover-triangle.top { - top: -11px; - background: rgb(240, 240, 240); - box-shadow: -1.5px -1.5px 3px 0 rgba(0, 0, 0, 0.2); - z-index: -1; + top: -11px; + background: rgb(240, 240, 240); + box-shadow: -1.5px -1.5px 3px 0 rgba(0, 0, 0, 0.2); + z-index: -1; } .m4n-popover-triangle.right { - right: -11px; - background: white; - box-shadow: 1.5px -1.5px 3px 0 rgba(0, 0, 0, 0.2); - z-index: -1; + right: -11px; + background: white; + box-shadow: 1.5px -1.5px 3px 0 rgba(0, 0, 0, 0.2); + z-index: -1; } .m4n-popover-triangle.left { - left: 1px; - background: white; - box-shadow: -1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); - z-index: -1; + left: 1px; + background: white; + box-shadow: -1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); + z-index: -1; } .m4n-popover-close { - float: right; - color: #888; - text-align: center; - font-family: "Arial", serif; - font-weight: bold; - cursor: pointer; - top: 0; + float: right; + color: #888888; + text-align: center; + font-family: "Arial", serif; + font-weight: bold; + cursor: pointer; + top: 0; } .m4n-popover-close:hover { - color: #555; + color: #555555; } .m4n-popover-close::before { - content: '✕'; + content: '✕'; } \ No newline at end of file diff --git a/app/less/popups/sidebar.less b/app/less/popups/sidebar.less index 862ec3a..91a1576 100644 --- a/app/less/popups/sidebar.less +++ b/app/less/popups/sidebar.less @@ -1,110 +1,109 @@ .m4n-sidebar-container { - display: inline-block; - position: absolute; - pointer-events: none; - width: 230px; - top: 20px; - bottom: 20px; - left: 20px; - font-size: 12px; - max-height: 100%; - z-index: 10; + display: inline-block; + position: absolute; + pointer-events: none; + width: 230px; + top: 20px; + bottom: 20px; + left: 20px; + font-size: 12px; + max-height: 100%; } .m4n-sidebar { - max-height: inherit; - position: relative; - background: white; - box-shadow: 0 0 4px 0 #aaa; - pointer-events: auto; + max-height: inherit; + position: relative; + background: white; + box-shadow: 0 0 4px 0 #AAAAAA; + pointer-events: auto; } .m4n-sidebar > div { - display: inline-block; + display: inline-block; } .m4n-sidebar-header { - top: 0; - font-size: 16px; - font-weight: bold; - width: 100%; - padding: 10px 10px; - background: inherit; + top: 0; + font-size: 16px; + font-weight: bold; + width: 100%; + padding: 10px 10px; + background: inherit; } .m4n-sidebar-footer { - height: 40px; - background: #ddd; - width: 100%; - padding: 0; + height: 40px; + background: #DDDDDD; + width: 100%; + padding: 0; } .m4n-sidebar-content { - overflow-y: auto; - overflow-x: hidden; - max-height: ~"calc(100% - 119px)"; - padding: 10px; - width: 100%; - background: inherit; - word-break: break-all; + overflow-y: auto; + overflow-x: hidden; + max-height: ~"calc(100% - 119px)"; + padding: 10px; + width: 100%; + background: inherit; + word-break: break-all; } .m4n-sidebar .m4n-title { - margin-top: 4px; + margin-top: 4px; } .m4n-sidebar .m4n-media { - margin-bottom: 10px; + margin-bottom: 10px; } .m4n-sidebar .m4n-media iframe, .m4n-sidebar .m4n-media img { - max-width: 100%; - margin-bottom: 5px; + max-width: 100%; + margin-bottom: 5px; } .m4n-sidebar-close { - float: right; - color: #ccc; - text-align: center; - font-family: "Arial", serif; - font-weight: bold; - font-size: 20px; - cursor: pointer; - top: 0; + float: right; + color: #CCCCCC; + text-align: center; + font-family: "Arial", serif; + font-weight: bold; + font-size: 20px; + cursor: pointer; + top: 0; } .m4n-sidebar-close:hover { - color: #aaa; + color: #AAAAAA; } .m4n-sidebar-close::before { - content: '✕'; + content: '✕'; } .m4n-pagination { - margin: 0; - padding: 0; - list-style: none; - color: #333; + margin: 0; + padding: 0; + list-style: none; + color: #333333; } .m4n-pagination li { - display: inline-block; - cursor: pointer; - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAAAoCAYAAADqiIZ/AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT9JREFUeNrs3Mtpw0AUBVBJFbgEl+ASrBK0DJgUFwJZTglJCS7BJbgES2YCIUTIiwRe5p0Dwsg7c+cyHyx1HQAAAAAAAAAA8P/0mX7sy+vbbv44ztfH8+npKn6ZRTUkC/h9vsryWe+RmRkzQMCHL1+f52s0c8rMjBkn4K7eFxUIq6xklmLmHJKW8tPe+A9rLZsU5RwSl3JZDk3Gf1hTzShlOfvEpVz2KmfjP3SOh5rjWgGb3XP2SolyKqZSopwJ95hFKdtTMxs39pxNnbAPYgfF/GtTXdb85L7Mrcsi2lvKNnXC7vAH+0vFVE6UMm0xlVMp7TGDqoGNG3tO/5WNq2QtZdPFfLCcF+M/rEvWUjZfzI1yNneS15hpJbMUj32leYPBtz2nZzFlppjBgj52Xi0iMwAAAAAAAAAAgF93E2AAKdG+bRyMOEsAAAAASUVORK5CYII=") no-repeat; - width: 50%; - height: 40px; + display: inline-block; + cursor: pointer; + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAAAoCAYAAADqiIZ/AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT9JREFUeNrs3Mtpw0AUBVBJFbgEl+ASrBK0DJgUFwJZTglJCS7BJbgES2YCIUTIiwRe5p0Dwsg7c+cyHyx1HQAAAAAAAAAA8P/0mX7sy+vbbv44ztfH8+npKn6ZRTUkC/h9vsryWe+RmRkzQMCHL1+f52s0c8rMjBkn4K7eFxUIq6xklmLmHJKW8tPe+A9rLZsU5RwSl3JZDk3Gf1hTzShlOfvEpVz2KmfjP3SOh5rjWgGb3XP2SolyKqZSopwJ95hFKdtTMxs39pxNnbAPYgfF/GtTXdb85L7Mrcsi2lvKNnXC7vAH+0vFVE6UMm0xlVMp7TGDqoGNG3tO/5WNq2QtZdPFfLCcF+M/rEvWUjZfzI1yNneS15hpJbMUj32leYPBtz2nZzFlppjBgj52Xi0iMwAAAAAAAAAAgF93E2AAKdG+bRyMOEsAAAAASUVORK5CYII=") no-repeat; + width: 50%; + height: 40px; } .m4n-pagination li:hover { - background-color: rgb(230,230,230); + background-color: rgb(230, 230, 230); } .m4n-pagination li:first-child { - background-position: 0 0; + background-position: 0 0; } .m4n-pagination li:last-child { - background-position: -115px 0; + background-position: -115px 0; } \ No newline at end of file From c81603aaf8094d8b5bd8ec6fdc650b709bf144a1 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Tue, 19 Jul 2016 15:11:12 +0200 Subject: [PATCH 19/34] Allow inline object in dev mode, regardless of environment #21 --- app/js/options.js | 4 ++-- docs.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/js/options.js b/app/js/options.js index cdf2550..fcb519c 100644 --- a/app/js/options.js +++ b/app/js/options.js @@ -15,17 +15,17 @@ main.environment = options.environment || "online"; main.zoomControls = typeof options.zoomControls !== 'undefined' ? options.zoomControls : true; main.homeButton = typeof options.homeButton !== 'undefined' ? options.homeButton : true; - main.inlineObject = main.environment === 'development' && typeof options.object !== 'undefined'; main.version = { map: '2.0', code: '2.0.5' }; main.dev = (function() { if(typeof options.debug !== 'undefined') { - return options.debug; + return !!options.debug; } return main.environment === 'development'; })(); + main.inlineObject = main.dev && typeof options.object !== 'undefined'; main.isMobile = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); main.isIframe = window.location !== window.parent.location; diff --git a/docs.md b/docs.md index a0fdc07..5e7e836 100644 --- a/docs.md +++ b/docs.md @@ -76,7 +76,7 @@ The M4nInteractive class accepts the following parameters: - __homeButton__. (optional; default true) Enable or disable the home button - __debug__. (not recommended) true or false, this allows the map object to be returned from the browser's console. - - __object__. (only with environment "development") Add your map object inline for debugging without a webserver. + - __object__. (only in development mode) Add your map object inline for debugging without a webserver. 2. The div container node (in this case the `div` with id `m4n-map`). 3. The callback (optional), this will be called after the map has finished initializing. Best used for subscribing to custom events. The callback function has 1 parameter, the map object, as described below. From fc754c7880feb56219897558a11553b7cc039b89 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Wed, 20 Jul 2016 11:56:18 +0200 Subject: [PATCH 20/34] Fix set style when not smart interact mode --- app/js/helpers.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/js/helpers.js b/app/js/helpers.js index 06bb878..9798fc6 100644 --- a/app/js/helpers.js +++ b/app/js/helpers.js @@ -124,16 +124,20 @@ var helpers = { * Show the timeout overlay */ showTimeoutOverlay: function() { - main.timeoutOverlay.style.display = "block"; - main.globals.interact.isInteracting = false; + if(main.environment === 'smart') { + main.timeoutOverlay.style.display = "block"; + main.globals.interact.isInteracting = false; + } }, /** * Hide the timeout overlay */ hideTimeoutOverlay: function() { - main.timeoutOverlay.style.display = "none"; - main.globals.interact.isInteracting = true; + if(main.environment === 'smart') { + main.timeoutOverlay.style.display = "none"; + main.globals.interact.isInteracting = true; + } }, /** From ae3aa24407e0eddfa069733d73dede3ed652015e Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Wed, 20 Jul 2016 12:01:31 +0200 Subject: [PATCH 21/34] Small popup css fixes --- app/less/popups/popover.less | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/less/popups/popover.less b/app/less/popups/popover.less index cff2125..a445bf8 100644 --- a/app/less/popups/popover.less +++ b/app/less/popups/popover.less @@ -25,7 +25,7 @@ .m4n-popover .m4n-media { min-height: 1px; - width: 200px; + max-width: 200px; } .m4n-popover .m4n-media img, @@ -40,6 +40,7 @@ font-size: 12px; line-height: 1.5; padding: 5px 10px 10px 10px; + background: white; z-index: 1; } @@ -51,6 +52,7 @@ width: 22px; height: 22px; margin-left: -12px; + background: white; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); @@ -58,7 +60,6 @@ .m4n-popover-triangle.bottom { bottom: -11px; - background: white; box-shadow: 1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); z-index: -1; } @@ -72,14 +73,12 @@ .m4n-popover-triangle.right { right: -11px; - background: white; box-shadow: 1.5px -1.5px 3px 0 rgba(0, 0, 0, 0.2); z-index: -1; } .m4n-popover-triangle.left { left: 1px; - background: white; box-shadow: -1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); z-index: -1; } From fa87e6323a1b353fb27dff84eb50bab7f243d913 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Wed, 20 Jul 2016 12:20:39 +0200 Subject: [PATCH 22/34] Rework popup placement logic --- app/js/classes/popup.js | 82 +++++++++++++---------------------------- 1 file changed, 25 insertions(+), 57 deletions(-) diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index 80b206d..44f35b7 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -57,43 +57,14 @@ Popup.prototype.show = function(center) { // Center the map if(center) { helpers.moveTo(point.position.left + (point.size.width / 2), point.position.top + (point.size.height / 2)); - } else { - var object = { x: 0, y: 0 }; - - var location = point.location(); - - if(location.location.x !== "center" || location.location.y !== "center") { - // Check if popup isn't wider than the canvas - if(!(location.left <= 5 && location.right <= 5)) { - if(location.left < 5) { - object.x = 5 - location.left; - } else if(location.right < 5) { - object.x = -(5 - location.right); - } - } - - // Check if the popup isn't higher than the canvas - if(!(location.top <= 5 && location.bottom <= 5)) { - if(location.top < 5) { - object.y = 5 - location.top; - } else if(location.bottom < 5) { - object.y = -(5 - location.bottom); - } - } - - if(object.x !== 0 || object.y !== 0) { - helpers.moveBy(object.x, object.y); - } - } } - var wasShown = (function() { - if(main.isMobile) { - return this.onShowMobile(point); - } else { - return this.onShowDesktop(point); - } - }.bind(this))(); + var wasShown; + if(main.isMobile) { + wasShown = this.onShowMobile(point); + } else { + wasShown = this.onShowDesktop(point); + } if(wasShown) { this.startVideo(); @@ -340,8 +311,8 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h var triangle = popup.getElementsByClassName("m4n-popover-triangle")[0]; // Position for triangle - var left = Math.max(0.15, Math.min(0.85, ((point.position.left + main.globals.offset.get().x) / main.object.canvas.clientWidth))); - var top = Math.max(0.05, Math.min(0.85, ((point.position.top + main.globals.offset.get().y) / main.object.canvas.clientHeight))); + var left = Math.max(0.10, Math.min(0.90, ((point.position.left + main.globals.offset.get().x) / main.object.canvas.clientWidth))); + var top = Math.max(0.10, Math.min(0.90, ((point.position.top + main.globals.offset.get().y) / main.object.canvas.clientHeight))); // Bounding Client Rect of the canvas var boundingRect = main.object.canvas.getBoundingClientRect(); @@ -355,19 +326,18 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h }; // Booleans for where the popup fits - var fits = { - onCanvas: { - above: formulas.above > popup.clientHeight, - beneath: formulas.beneath > popup.clientHeight, - left: formulas.left > popup.clientWidth, - right: formulas.right > popup.clientWidth - }, - onScreen: { - above: (formulas.above + boundingRect.top) > popup.clientHeight, - beneath: (formulas.beneath + (window.innerHeight - boundingRect.height - boundingRect.top)) > popup.clientHeight, - left: (formulas.left + boundingRect.left) > popup.clientWidth, - right: (formulas.right + (window.innerWidth - boundingRect.width - boundingRect.left)) > popup.clientWidth - } + var onCanvas = { + above: formulas.above > popup.clientHeight, + beneath: formulas.beneath > popup.clientHeight, + left: formulas.left > popup.clientWidth, + right: formulas.right > popup.clientWidth + }; + + var onScreen = { + above: (formulas.above + boundingRect.top) > popup.clientHeight && !(formulas.left < 5 || formulas.right < 5), + beneath: (formulas.beneath + (window.innerHeight - boundingRect.height - boundingRect.top)) > popup.clientHeight && !(formulas.left < 5 || formulas.right < 5), + left: (formulas.left + boundingRect.left) > popup.clientWidth, + right: (formulas.right + (window.innerWidth - boundingRect.width - boundingRect.left)) > popup.clientWidth }; var show = { @@ -397,15 +367,15 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h } }; - if(fits.onCanvas.above && fits.onScreen.above) { + if(onCanvas.above && onScreen.above) { show.above(); - } else if(fits.onCanvas.beneath && fits.onScreen.beneath) { + } else if(onCanvas.beneath && onScreen.beneath) { show.beneath(); } else { - if(fits.onCanvas.left && fits.onScreen.left) { + if(onCanvas.left && onScreen.left) { show.left(); - } else if(fits.onCanvas.right && fits.onScreen.right) { + } else if(onCanvas.right && onScreen.right) { show.right(); } else { show.above(); @@ -501,9 +471,7 @@ Popup.prototype.generateSidebar = function(popup, title_html, info_html, media_h } else { new_popup = main.api.popup(main.object.popups.getLast().number); } - if(!!new_popup) { - new_popup.show(true); - } + if(!!new_popup) { new_popup.show(true); } }.bind(this) }), // Next From d2293f92fdfb0741795a50ac2bfad30e7eb7197c Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Wed, 20 Jul 2016 13:58:36 +0200 Subject: [PATCH 23/34] images max-width 100% in popups --- app/less/main.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/less/main.less b/app/less/main.less index c8b8b45..0f2ecce 100644 --- a/app/less/main.less +++ b/app/less/main.less @@ -13,6 +13,10 @@ clear: both; } +.m4n-container img { + max-width: 100%; +} + .m4n-canvas { float: left; cursor: grab; From 52aae607659848bb42ab7cc6773d1e8b3dff023d Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Wed, 20 Jul 2016 14:27:16 +0200 Subject: [PATCH 24/34] Added contributing guidelines --- .github/CONTRIBUTING.md | 15 +++++++++++++++ .github/ISSUE_TEMPLATE.md | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..0c34739 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contribute to Maps4News Interactive + +#### Please use English for all communications. +Issues in any language other than Engish will be ignored. + +## Issues + +- Please keep the title as short as possible. +- Try to explain your issue in as much detail as possible. +- If possible try to add an image of your developer console. + +## Pull Requests + +- Pull requests should be made towards the develop branch. +- Please don't send pull requests just because you want feature x, a lot of customizability is possible via the api. [api documentation](../docs.md) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..49e4ad6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,18 @@ +### What happened? + + + +### What did you expect to happen? + + + +### Steps to reproduce +1. + + +### Your map code snippet +```html + + + +``` From cbea13eeacf49d7a61ed8375f7b7adc75ae8d4d2 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 21 Jul 2016 10:31:59 +0200 Subject: [PATCH 25/34] Remove popover centering on mobile --- app/js/classes/popup.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index 44f35b7..3f5ab02 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -295,14 +295,6 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h return true; }; - this.onShowMobile = function() { - popup.style.display = "block"; - popup.style.left = (main.object.canvas.clientWidth / 2) - (popup.clientWidth / 2) - main.object.canvas.getBoundingClientRect().left + "px"; - popup.style.top = (main.object.canvas.clientHeight / 2) - (popup.clientHeight / 2) - main.object.canvas.getBoundingClientRect().top + "px"; - - return true; - }; - this.onShowDesktop = function(point) { popup.style.display = "block"; From 6b3661860623264eedacb768dc4c2b562549aa46 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 21 Jul 2016 11:24:56 +0200 Subject: [PATCH 26/34] UTF-8 characters to unicode string --- app/less/popups/overlay.less | 2 +- app/less/popups/popover.less | 2 +- app/less/popups/sidebar.less | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/less/popups/overlay.less b/app/less/popups/overlay.less index ae697d3..2bff866 100644 --- a/app/less/popups/overlay.less +++ b/app/less/popups/overlay.less @@ -53,7 +53,7 @@ } .m4n-overlay .close-overlay::before { - content: '✕'; + content: "\u2715"; } .m4n-overlay .close-overlay { diff --git a/app/less/popups/popover.less b/app/less/popups/popover.less index a445bf8..1c59f02 100644 --- a/app/less/popups/popover.less +++ b/app/less/popups/popover.less @@ -98,5 +98,5 @@ } .m4n-popover-close::before { - content: '✕'; + content: "\u2715"; } \ No newline at end of file diff --git a/app/less/popups/sidebar.less b/app/less/popups/sidebar.less index 91a1576..8152d0b 100644 --- a/app/less/popups/sidebar.less +++ b/app/less/popups/sidebar.less @@ -78,7 +78,7 @@ } .m4n-sidebar-close::before { - content: '✕'; + content: "\u2715"; } .m4n-pagination { From 79be66fba75eb51f06a1be6f7cfac5dc22e1cea4 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Thu, 21 Jul 2016 11:31:40 +0200 Subject: [PATCH 27/34] Fix utf8 chars --- app/less/popups/overlay.less | 2 +- app/less/popups/popover.less | 4 ++-- app/less/popups/sidebar.less | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/less/popups/overlay.less b/app/less/popups/overlay.less index 2bff866..deed66e 100644 --- a/app/less/popups/overlay.less +++ b/app/less/popups/overlay.less @@ -53,7 +53,7 @@ } .m4n-overlay .close-overlay::before { - content: "\u2715"; + content: "\2715"; } .m4n-overlay .close-overlay { diff --git a/app/less/popups/popover.less b/app/less/popups/popover.less index 1c59f02..72ef82e 100644 --- a/app/less/popups/popover.less +++ b/app/less/popups/popover.less @@ -97,6 +97,6 @@ color: #555555; } -.m4n-popover-close::before { - content: "\u2715"; +.m4n-popover-close:before { + content: "\2715"; } \ No newline at end of file diff --git a/app/less/popups/sidebar.less b/app/less/popups/sidebar.less index 8152d0b..623fbb3 100644 --- a/app/less/popups/sidebar.less +++ b/app/less/popups/sidebar.less @@ -78,7 +78,7 @@ } .m4n-sidebar-close::before { - content: "\u2715"; + content: "\2715"; } .m4n-pagination { From 25b736f3b9ec31182957d69e0e86b4db0a82eaf9 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 22 Jul 2016 14:44:06 +0200 Subject: [PATCH 28/34] Grammar fix --- docs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs.md b/docs.md index 5e7e836..2c7cfa7 100644 --- a/docs.md +++ b/docs.md @@ -75,7 +75,7 @@ The M4nInteractive class accepts the following parameters: - __homeButton__. (optional; default true) Enable or disable the home button - - __debug__. (not recommended) true or false, this allows the map object to be returned from the browser's console. + - __debug__. (enables development mode) true or false, this allows the map object to be returned from the browser's console. - __object__. (only in development mode) Add your map object inline for debugging without a webserver. 2. The div container node (in this case the `div` with id `m4n-map`). @@ -318,7 +318,7 @@ The `add` method accepts a single object or an array of objects with the followi disabled: { event: 'level_changed', callback: function() { - // Disable the button is the level is 0 + // Disable the button if the level is 0 return mapi.api.levels().current == 0; } } From 2d6cbde6e445327eb52faa861657c8a26b9d45d4 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 22 Jul 2016 14:44:47 +0200 Subject: [PATCH 29/34] Change debug messages to console.debug --- app/js/event_listener.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/js/event_listener.js b/app/js/event_listener.js index 6ff3074..a00a810 100644 --- a/app/js/event_listener.js +++ b/app/js/event_listener.js @@ -18,7 +18,7 @@ function addEventListener(event, callback) { } if(main.dev) { - console.log("Event listener for event \"" + event + "\" added", callback); + console.debug("Event listener for event \"" + event + "\" added", callback); } return main.dispatchEvents[event].push(callback); @@ -48,7 +48,7 @@ function removeEventListener(event, id) { } if(main.dev) { - console.log("Event listener for event \"" + event + "\" removed", listener); + console.debug("Event listener for event \"" + event + "\" removed", listener); } delete main.dispatchEvents[event][id - 1]; From 0dcb24cbfeab34ef68c61b586cf59461a5258b11 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 22 Jul 2016 14:46:15 +0200 Subject: [PATCH 30/34] remove unused method --- app/js/classes/point.js | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/app/js/classes/point.js b/app/js/classes/point.js index 93879a8..68092d8 100644 --- a/app/js/classes/point.js +++ b/app/js/classes/point.js @@ -49,38 +49,4 @@ Point.prototype.isOn = function(x, y) { y > this.position.top + main.globals.offset.get().y && y < this.position.top + this.size.height + main.globals.offset.get().y ); -}; - -/** - * Get info about the current position of a point - * @returns {object} - */ -Point.prototype.location = function() { - var object = { - left: this.position.left + main.globals.offset.get().x, - top: this.position.top + main.globals.offset.get().y, - right: -(this.position.left + main.globals.offset.get().x - main.object.canvas.clientWidth + this.size.width), - bottom: -(this.position.top + main.globals.offset.get().y - main.object.canvas.clientHeight + this.size.height) - }; - - object.location = { - x: (function() { - if(object.left < 5) { - return "left"; - } else if(object.right < 5) { - return "right"; - } - return "center"; - })(), - y: (function() { - if(object.top < 5) { - return "above"; - } else if(object.bottom < 5) { - return "beneath"; - } - return "center"; - })() - }; - - return object; }; \ No newline at end of file From 2eff9dd2a2b56a6402179f09f824e5d4454879ef Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 22 Jul 2016 14:46:34 +0200 Subject: [PATCH 31/34] Optimize css --- app/less/main.less | 20 +++++++++++++++----- app/less/popups/popover.less | 19 +------------------ app/less/popups/sidebar.less | 1 - 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/app/less/main.less b/app/less/main.less index 0f2ecce..aa46cf7 100644 --- a/app/less/main.less +++ b/app/less/main.less @@ -1,4 +1,6 @@ -.m4n-container *, .m4n-container *:after, .m4n-container *:before { +.m4n-container *, +.m4n-container *:after, +.m4n-container *:before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; @@ -13,10 +15,6 @@ clear: both; } -.m4n-container img { - max-width: 100%; -} - .m4n-canvas { float: left; cursor: grab; @@ -54,6 +52,18 @@ display: block; } +// Default popup settings +.m4n-container img { + max-width: 100%; +} + +.m4n-container .m4n-media embed, +.m4n-container .m4n-media object, +.m4n-container .m4n-media video, +.m4n-container .m4n-media iframe { + max-width: 100%; +} + @import "popups/popover"; @import "popups/sidebar"; @import "popups/overlay"; diff --git a/app/less/popups/popover.less b/app/less/popups/popover.less index 72ef82e..5045d22 100644 --- a/app/less/popups/popover.less +++ b/app/less/popups/popover.less @@ -23,19 +23,6 @@ border-top-right-radius: 5px; } -.m4n-popover .m4n-media { - min-height: 1px; - max-width: 200px; -} - -.m4n-popover .m4n-media img, -.m4n-popover .m4n-media embed, -.m4n-popover .m4n-media object, -.m4n-popover .m4n-media video, -.m4n-popover .m4n-media iframe { - max-width: 100%; -} - .m4n-popover .m4n-info { font-size: 12px; line-height: 1.5; @@ -44,7 +31,6 @@ z-index: 1; } -.m4n-popover-triangle, .m4n-popover-triangle { content: ''; position: absolute; @@ -56,31 +42,28 @@ -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); + z-index: -1; } .m4n-popover-triangle.bottom { bottom: -11px; box-shadow: 1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); - z-index: -1; } .m4n-popover-triangle.top { top: -11px; background: rgb(240, 240, 240); box-shadow: -1.5px -1.5px 3px 0 rgba(0, 0, 0, 0.2); - z-index: -1; } .m4n-popover-triangle.right { right: -11px; box-shadow: 1.5px -1.5px 3px 0 rgba(0, 0, 0, 0.2); - z-index: -1; } .m4n-popover-triangle.left { left: 1px; box-shadow: -1.5px 1.5px 3px 0 rgba(0, 0, 0, 0.2); - z-index: -1; } .m4n-popover-close { diff --git a/app/less/popups/sidebar.less b/app/less/popups/sidebar.less index 623fbb3..f131203 100644 --- a/app/less/popups/sidebar.less +++ b/app/less/popups/sidebar.less @@ -58,7 +58,6 @@ .m4n-sidebar .m4n-media iframe, .m4n-sidebar .m4n-media img { - max-width: 100%; margin-bottom: 5px; } From 403d9c9370cc60f6f7f27e1b24e64b04da4cc0cd Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 22 Jul 2016 14:54:44 +0200 Subject: [PATCH 32/34] Refactor popup placement logic --- app/js/classes/popup.js | 71 +++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index 3f5ab02..0464395 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -299,18 +299,18 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h popup.style.display = "block"; // Triangle - var heightTriangle = 16.97056274847714; // 24 = width of a triangle plus the border var triangle = popup.getElementsByClassName("m4n-popover-triangle")[0]; - - // Position for triangle - var left = Math.max(0.10, Math.min(0.90, ((point.position.left + main.globals.offset.get().x) / main.object.canvas.clientWidth))); - var top = Math.max(0.10, Math.min(0.90, ((point.position.top + main.globals.offset.get().y) / main.object.canvas.clientHeight))); + var heightTriangle = Math.sqrt(triangle.clientHeight * triangle.clientHeight + triangle.clientWidth * triangle.clientWidth); // Bounding Client Rect of the canvas var boundingRect = main.object.canvas.getBoundingClientRect(); + // Position for triangle + var top = Math.max(0.05, Math.min(0.85, ((point.position.top + main.globals.offset.get().y) / main.object.canvas.clientHeight))); + var left = Math.max(0.15, Math.min(0.85, ((point.position.left + main.globals.offset.get().x) / main.object.canvas.clientWidth))); + // Formulas for where the popup fits - var formulas = { + var sides = { above: main.globals.offset.get().y + point.position.top - heightTriangle, beneath: boundingRect.height - (main.globals.offset.get().y + point.position.top + point.size.height) - heightTriangle, left: main.globals.offset.get().x + point.position.left - heightTriangle, @@ -318,58 +318,81 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h }; // Booleans for where the popup fits - var onCanvas = { - above: formulas.above > popup.clientHeight, - beneath: formulas.beneath > popup.clientHeight, - left: formulas.left > popup.clientWidth, - right: formulas.right > popup.clientWidth + var fitsOnCanvas = { + above: sides.above > popup.clientHeight, + beneath: sides.beneath > popup.clientHeight, + left: sides.left > popup.clientWidth, + right: sides.right > popup.clientWidth }; - var onScreen = { - above: (formulas.above + boundingRect.top) > popup.clientHeight && !(formulas.left < 5 || formulas.right < 5), - beneath: (formulas.beneath + (window.innerHeight - boundingRect.height - boundingRect.top)) > popup.clientHeight && !(formulas.left < 5 || formulas.right < 5), - left: (formulas.left + boundingRect.left) > popup.clientWidth, - right: (formulas.right + (window.innerWidth - boundingRect.width - boundingRect.left)) > popup.clientWidth + var fitsOnScreen = { + above: (sides.above + boundingRect.top) > popup.clientHeight, + beneath: (sides.beneath + (window.innerHeight - boundingRect.height - boundingRect.top)) > popup.clientHeight, + left: (sides.left + boundingRect.left) > popup.clientWidth, + right: (sides.right + (window.innerWidth - boundingRect.width - boundingRect.left)) > popup.clientWidth }; var show = { above: function() { triangle.classList.add("bottom"); - popup.style.top = main.globals.offset.get().y + point.position.top - popup.clientHeight - heightTriangle + 10 + 'px'; + popup.style.top = main.globals.offset.get().y + point.position.top - popup.clientHeight - (heightTriangle / 2) + 10 + 'px'; popup.style.left = main.globals.offset.get().x + point.position.left + (point.size.width / 2) - (popup.clientWidth * left) + 'px'; triangle.style.left = (left * 100) + "%"; }, beneath: function() { triangle.classList.add("top"); - popup.style.top = main.globals.offset.get().y + point.position.top + point.size.height + heightTriangle - 10 + 'px'; + popup.style.top = main.globals.offset.get().y + point.position.top + point.size.height + (heightTriangle / 2) - 10 + 'px'; popup.style.left = main.globals.offset.get().x + point.position.left + (point.size.width / 2) - (popup.clientWidth * left) + 'px'; triangle.style.left = (left * 100) + "%"; }, left: function() { triangle.classList.add("right"); popup.style.top = (main.globals.offset.get().y + point.position.top + (point.size.height / 2) - (popup.clientHeight * top) - 10) + 'px'; - popup.style.left = main.globals.offset.get().x + point.position.left - popup.clientWidth - heightTriangle + 10 + 'px'; + popup.style.left = main.globals.offset.get().x + point.position.left - popup.clientWidth - (heightTriangle / 2) + 10 + 'px'; triangle.style.top = (top * 100) + "%"; }, right: function() { triangle.classList.add("left"); popup.style.top = (main.globals.offset.get().y + point.position.top + (point.size.height / 2) - (popup.clientHeight * top) - 10) + 'px'; - popup.style.left = main.globals.offset.get().x + point.position.left + point.size.width + heightTriangle - 10 + 'px'; + popup.style.left = main.globals.offset.get().x + point.position.left + point.size.width + (heightTriangle / 2) - 10 + 'px'; triangle.style.top = (top * 100) + "%"; } }; - if(onCanvas.above && onScreen.above) { + var lowest = (function() { + var object = null; + for(var side in sides) { + if(sides.hasOwnProperty(side) && (object == null || object.value > sides[side])) { + object = { key: side, value: sides[side] } + } + } + + return object; + })(); + + // Placement logic + if(lowest.value < 0) { + if(lowest.key == "above") { + show.beneath(); + } else if(lowest.key == "beneath") { + show.above(); + } else if(lowest.key == "left") { + show.right(); + } else if(lowest.key == "right") { + show.left(); + } + } else if(fitsOnCanvas.above && fitsOnScreen.above) { show.above(); - } else if(onCanvas.beneath && onScreen.beneath) { + } else if(fitsOnCanvas.beneath && fitsOnScreen.beneath) { show.beneath(); } else { - if(onCanvas.left && onScreen.left) { + if(fitsOnCanvas.left && fitsOnScreen.left) { show.left(); - } else if(onCanvas.right && onScreen.right) { + } else if(fitsOnCanvas.right && fitsOnScreen.right) { show.right(); } else { + // TODO move map to fit popup show.above(); } From b158fc4c6a7b47041d4bafbcc0e2c89014f9ee4f Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 22 Jul 2016 15:01:57 +0200 Subject: [PATCH 33/34] Add variable hotspot margin --- app/js/classes/point.js | 8 ++++---- app/js/classes/popup.js | 8 ++++---- app/js/options.js | 1 + docs.md | 3 +-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/js/classes/point.js b/app/js/classes/point.js index 68092d8..da1186d 100644 --- a/app/js/classes/point.js +++ b/app/js/classes/point.js @@ -15,12 +15,12 @@ var Point = function(point) { } this.position = { - left: Math.min.apply(null, this.shape.map(function(item) { return item.x })) - 10, - top: Math.min.apply(null, this.shape.map(function(item) { return item.y })) - 10 + left: Math.min.apply(null, this.shape.map(function(item) { return item.x })) - main.hotspotMargin, + top: Math.min.apply(null, this.shape.map(function(item) { return item.y })) - main.hotspotMargin }; this.size = { - width: Math.max.apply(null, this.shape.map(function(item) { return item.x })) - this.position.left + 10, - height: Math.max.apply(null, this.shape.map(function(item) { return item.y })) - this.position.top + 10 + width: Math.max.apply(null, this.shape.map(function(item) { return item.x })) - this.position.left + main.hotspotMargin, + height: Math.max.apply(null, this.shape.map(function(item) { return item.y })) - this.position.top + main.hotspotMargin }; }; diff --git a/app/js/classes/popup.js b/app/js/classes/popup.js index 0464395..4fde229 100644 --- a/app/js/classes/popup.js +++ b/app/js/classes/popup.js @@ -335,26 +335,26 @@ Popup.prototype.generatePopover = function(popup, title_html, info_html, media_h var show = { above: function() { triangle.classList.add("bottom"); - popup.style.top = main.globals.offset.get().y + point.position.top - popup.clientHeight - (heightTriangle / 2) + 10 + 'px'; + popup.style.top = main.globals.offset.get().y + point.position.top - popup.clientHeight - (heightTriangle / 2) + main.hotspotMargin + 'px'; popup.style.left = main.globals.offset.get().x + point.position.left + (point.size.width / 2) - (popup.clientWidth * left) + 'px'; triangle.style.left = (left * 100) + "%"; }, beneath: function() { triangle.classList.add("top"); - popup.style.top = main.globals.offset.get().y + point.position.top + point.size.height + (heightTriangle / 2) - 10 + 'px'; + popup.style.top = main.globals.offset.get().y + point.position.top + point.size.height + (heightTriangle / 2) - main.hotspotMargin + 'px'; popup.style.left = main.globals.offset.get().x + point.position.left + (point.size.width / 2) - (popup.clientWidth * left) + 'px'; triangle.style.left = (left * 100) + "%"; }, left: function() { triangle.classList.add("right"); popup.style.top = (main.globals.offset.get().y + point.position.top + (point.size.height / 2) - (popup.clientHeight * top) - 10) + 'px'; - popup.style.left = main.globals.offset.get().x + point.position.left - popup.clientWidth - (heightTriangle / 2) + 10 + 'px'; + popup.style.left = main.globals.offset.get().x + point.position.left - popup.clientWidth - (heightTriangle / 2) + main.hotspotMargin + 'px'; triangle.style.top = (top * 100) + "%"; }, right: function() { triangle.classList.add("left"); popup.style.top = (main.globals.offset.get().y + point.position.top + (point.size.height / 2) - (popup.clientHeight * top) - 10) + 'px'; - popup.style.left = main.globals.offset.get().x + point.position.left + point.size.width + (heightTriangle / 2) - 10 + 'px'; + popup.style.left = main.globals.offset.get().x + point.position.left + point.size.width + (heightTriangle / 2) - main.hotspotMargin + 'px'; triangle.style.top = (top * 100) + "%"; } }; diff --git a/app/js/options.js b/app/js/options.js index fcb519c..dfa34ae 100644 --- a/app/js/options.js +++ b/app/js/options.js @@ -15,6 +15,7 @@ main.environment = options.environment || "online"; main.zoomControls = typeof options.zoomControls !== 'undefined' ? options.zoomControls : true; main.homeButton = typeof options.homeButton !== 'undefined' ? options.homeButton : true; + main.hotspotMargin = parseInt(options.hotspotMargin) || 10; main.version = { map: '2.0', code: '2.0.5' }; diff --git a/docs.md b/docs.md index 2c7cfa7..77bebb4 100644 --- a/docs.md +++ b/docs.md @@ -72,11 +72,10 @@ The M4nInteractive class accepts the following parameters: | smart | an overlay will be placed over the map when the user is not interacting with the map and disables the events to the map (the overaly will reappear when the user clicks outside the map) | - __zoomControls__. (optional; default true) Enable or disable the zoom controls for maps with more than 1 level. - - __homeButton__. (optional; default true) Enable or disable the home button - - __debug__. (enables development mode) true or false, this allows the map object to be returned from the browser's console. - __object__. (only in development mode) Add your map object inline for debugging without a webserver. + - __hotspotMargin__. (optional; default 10) The number of pixels of margin to add to the hotspots. 2. The div container node (in this case the `div` with id `m4n-map`). 3. The callback (optional), this will be called after the map has finished initializing. Best used for subscribing to custom events. The callback function has 1 parameter, the map object, as described below. From bb5a0c421c852bb2577d6f86ad23736d8eb8c593 Mon Sep 17 00:00:00 2001 From: Kevin Richter Date: Fri, 22 Jul 2016 15:19:47 +0200 Subject: [PATCH 34/34] version bump --- app/js/main.js | 2 +- app/js/options.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/js/main.js b/app/js/main.js index 92ca60a..993017e 100644 --- a/app/js/main.js +++ b/app/js/main.js @@ -2,7 +2,7 @@ * @file Maps4News Interactive Map * @copyright Maps4News 2016 * - * M4nInteractive 2.0.5 + * M4nInteractive 2.0.5-1 */ var M4nInteractive = (function(options, container, callback) { "use strict"; diff --git a/app/js/options.js b/app/js/options.js index dfa34ae..d43bb2b 100644 --- a/app/js/options.js +++ b/app/js/options.js @@ -17,7 +17,7 @@ main.homeButton = typeof options.homeButton !== 'undefined' ? options.homeButton : true; main.hotspotMargin = parseInt(options.hotspotMargin) || 10; - main.version = { map: '2.0', code: '2.0.5' }; + main.version = { map: '2.0', code: '2.0.5-1' }; main.dev = (function() { if(typeof options.debug !== 'undefined') {