setCenter within "center" event callback - here-api

I want to keep the map center coordinates into some limits. For this I call the setCenter method inside my "center" related callback function:
map.addObserver("center", function (obj, key, newValue, oldValue) {
var limits = {minLat: 47.4136, minLon: 5.9845, maxLat: 54.8073, maxLon: 14.3671};
if (newValue.latitude < limits.minLat || newValue.longitude < limits.minLon ||
newValue.latitude > limits.maxLat || newValue.longitude > limits.maxLon) {
var newLatLon = {latitude: Math.max(Math.min(newValue.latitude, limits.maxLat), limits.minLat),
longitude: Math.max(Math.min(newValue.longitude, limits.maxLon), limits.minLon)};
map.setCenter(nokia.maps.geo.Coordinate.fromObject(newLatLon));
console.log(newValue);
console.log(map.center);
}
});
If I drag the map outside the limits, I see in the console the map.center being correctly adjusted, but the newValue coordinates keep being outisde the limits.
Did I misunderstand the API ?
I am using http://api.maps.nokia.com/2.2.3/jsl.js?with=all

Adding an observer to a property and then altering that property within the observer function is not guaranteed to work for all properties. My understanding is that re-setting the center is not supported in order to avoid infinite loops. You would be better off using the event framework rather than observers in this case.
The code below restricts the centre of the map to remain within a rectangle centred on Germany. If you drag the map it will stop dead, if you flick the map it will bounce back. You will need to obtain your own free app id and token to get it to work.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=7; IE=EmulateIE9" />
<title>Nokia Maps API Example: Restricted Area</title>
<!-- KML support is required here. -->
<script type="text/javascript" charset="UTF-8" src="http://api.maps.nokia.com/2.2.3/jsl.js"></script>
</head>
<style type="text/css">
html {
overflow:hidden;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
width: 100%;
height: 100%;
position: absolute;
}
#mapContainer {
width: 80%;
height: 80%;
}
</style>
</head>
<body>
<div id="mapContainer"></div>
<script type="text/javascript">
/////////////////////////////////////////////////////////////////////////////////////
// Don't forget to set your API credentials
//
// Replace with your appId and token which you can obtain when you
// register on http://api.developer.nokia.com/
//
nokia.Settings.set( "appId", "APP ID");
nokia.Settings.set( "authenticationToken", "TOKEN");
//
/////////////////////////////////////////////////////////////////////////////////////
</script>
<div id="uiContainer"></div>
<script>
var mapContainer = document.getElementById("mapContainer");
var map = new nokia.maps.map.Display(mapContainer, {
center: [51, 7],
zoomLevel: 6
});
map.addComponent(new nokia.maps.map.component.Behavior());
var dragger = map.getComponentById("panning.Drag");
// Set of initial geo coordinates to create the purple polyline
var points = [
new nokia.maps.geo.Coordinate(47.4136, 5.9845),
new nokia.maps.geo.Coordinate(47.4136, 14.3671),
new nokia.maps.geo.Coordinate(54.8073, 14.3671),
new nokia.maps.geo.Coordinate(54.8073, 5.9845),
new nokia.maps.geo.Coordinate(47.4136, 5.9845)
];
// Transparent purple polyline
map.objects.add(new nokia.maps.map.Polyline(
points,
{
pen: {
strokeColor: "#22CA",
lineWidth: 5
}
}
));
var restrict = function(evt) {
var limits = {minLat: 47.4136, minLon: 5.9845, maxLat: 54.8073, maxLon: 14.3671};
if (map.center.latitude < limits.minLat || map.center.longitude < limits.minLon ||
map.center.latitude > limits.maxLat || map.center.longitude > limits.maxLon) {
var latitude = Math.max(Math.min(map.center.latitude, limits.maxLat), limits.minLat);
var longitude = Math.max(Math.min(map.center.longitude, limits.maxLon), limits.minLon);
map.setCenter(new nokia.maps.geo.Coordinate(latitude,longitude));
evt.cancel();
}
}
map.addListener("dragend", restrict);
map.addListener("drag", restrict);
map.addListener("mapviewchange", restrict);
map.addListener("mapviewchangeend", restrict);
map.addListener("mapviewchangestart", restrict);
</script>
</body>
</html>
I have added event listeners to five events here, dragend, drag, mapviewchange, mapviewchangeend and mapviewchangestart - depending upon the effect you require, you may not need them all. The line evt.cancel(); stops the event from being processed.

Related

Here Maps Marker plot with address

I have full address (Ex: 31, High Street, New York - 10001, United States of America), I need to plot this address as a marked on Here Maps. Can address be used to plot marker?
Please refer to the below steps to add a marker on your given address at here maps:
Step 1. Please refer to the below example makes a geocoding request and retrieve the latitude, longitude, and complete address details of 31, High Street, New York - 10001, United States of America based on free-form text input. A clickable marker is placed on the location found.
HTML Snippet:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Search for a Location based on an Address</title>
<link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
<link rel="stylesheet" type="text/css" href="demo.css" />
<link rel="stylesheet" type="text/css" href="styles.css" />
<link rel="stylesheet" type="text/css" href="../template.css" />
<script type="text/javascript" src='../test-credentials.js'></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
</head>
<body id="geocode">
<div class="page-header">
<h1>Search for a Location based on an Address</h1>
<p>Request a location using a free-form text input and display it on the map.</p>
</div>
<p>This example makes a geocoding request and retrieves the latitude, longitude and
complete address details of <b>31, High Street, New York - 10001, United States of America</b> based on a free-form
text input. A clickable marker is placed on the location found.</p>
<div id="map"></div>
<div id="panel"></div>
<h3>Code</h3>
<p>Access to the geocoding service is obtained from the <code>H.service.Platform</code>
by calling <code>getSearchService()</code>. The <code>geocode()</code> method is used
to find a location by passing in the relevant <code>q</code> parameter as defined in
Geocoding and Search API v7.
The styling and display of the response are under the developer's control.</p>
<script type="text/javascript" src='demo.js'></script>
</body>
</html>
Javascript Snippet:
/**
* Calculates and displays the address details of 31, High Street, New York - 10001, United States of America
* based on a free-form text
* A full list of available request parameters can be found in the Geocoder API documentation.
* see: http://developer.here.com/rest-apis/documentation/geocoder/topics/resource-geocode.html
* #param {H.service.Platform} platform A stub class to access HERE services
*/
function geocode(platform) {
var geocoder = platform.getSearchService(),
geocodingParameters = {
q: '31, High Street, New York - 10001, United States of America'
};
geocoder.geocode(
geocodingParameters,
onSuccess,
onError
);
}
/**
* This function will be called once the Geocoder REST API provides a response
* #param {Object} result A JSONP object representing the location(s) found.
*
* see: http://developer.here.com/rest-apis/documentation/geocoder/topics/resource-type-response-geocode.html
*/
function onSuccess(result) {
var locations = result.items;
/*
* The styling of the geocoding response on the map is entirely under the developer's control.
* A representative styling can be found in the full JS + HTML code of this example
* in the functions below:
*/
addLocationsToMap(locations);
addLocationsToPanel(locations);
// ... etc.
}
/**
* This function will be called if a communication error occurs during the JSON-P request
* #param {Object} error The error message received.
*/
function onError(error) {
alert('Can\'t reach the remote server');
}
/**
* Boilerplate map initialization code starts below:
*/
//Step 1: initialize communication with the platform
// In your own code, replace variable window.apikey with your own apikey
var platform = new H.service.Platform({
apikey: window.apikey
});
var defaultLayers = platform.createDefaultLayers();
//Step 2: initialize a map - this map is centered over New York
var map = new H.Map(document.getElementById('map'),
defaultLayers.vector.normal.map,{
center: {lat:41.033, lng:-73.7471},
zoom: 15,
pixelRatio: window.devicePixelRatio || 1
});
// add a resize listener to make sure that the map occupies the whole container
window.addEventListener('resize', () => map.getViewPort().resize());
var locationsContainer = document.getElementById('panel');
//Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Create the default UI components
var ui = H.ui.UI.createDefault(map, defaultLayers);
// Hold a reference to any infobubble opened
var bubble;
/**
* Opens/Closes a infobubble
* #param {H.geo.Point} position The location on the map.
* #param {String} text The contents of the infobubble.
*/
function openBubble(position, text){
if(!bubble){
bubble = new H.ui.InfoBubble(
position,
{content: text});
ui.addBubble(bubble);
} else {
bubble.setPosition(position);
bubble.setContent(text);
bubble.open();
}
}
/**
* Creates a series of list items for each location found, and adds it to the panel.
* #param {Object[]} locations An array of locations as received from the
* H.service.GeocodingService
*/
function addLocationsToPanel(locations){
var nodeOL = document.createElement('ul'),
i;
nodeOL.style.fontSize = 'small';
nodeOL.style.marginLeft ='5%';
nodeOL.style.marginRight ='5%';
for (i = 0; i < locations.length; i += 1) {
let location = locations[i];
var li = document.createElement('li'),
divLabel = document.createElement('div'),
address = location.address,
content = '<strong style="font-size: large;">' + address.label + '</strong></br>';
position = location.position;
content += '<strong>houseNumber:</strong> ' + address.houseNumber + '<br/>';
content += '<strong>street:</strong> ' + address.street + '<br/>';
content += '<strong>district:</strong> ' + address.district + '<br/>';
content += '<strong>city:</strong> ' + address.city + '<br/>';
content += '<strong>postalCode:</strong> ' + address.postalCode + '<br/>';
content += '<strong>county:</strong> ' + address.county + '<br/>';
content += '<strong>country:</strong> ' + address.countryName + '<br/>';
content += '<strong>position:</strong> ' +
Math.abs(position.lat.toFixed(4)) + ((position.lat > 0) ? 'N' : 'S') +
' ' + Math.abs(position.lng.toFixed(4)) + ((position.lng > 0) ? 'E' : 'W') + '<br/>';
divLabel.innerHTML = content;
li.appendChild(divLabel);
nodeOL.appendChild(li);
}
locationsContainer.appendChild(nodeOL);
}
/**
* Creates a series of H.map.Markers for each location found, and adds it to the map.
* #param {Object[]} locations An array of locations as received from the
* H.service.GeocodingService
*/
function addLocationsToMap(locations){
var group = new H.map.Group(),
position,
i;
// Add a marker for each location found
for (i = 0; i < locations.length; i += 1) {
let location = locations[i];
marker = new H.map.Marker(location.position);
marker.label = location.address.label;
group.addObject(marker);
}
group.addEventListener('tap', function (evt) {
map.setCenter(evt.target.getGeometry());
openBubble(
evt.target.getGeometry(), evt.target.label);
}, false);
// Add the locations group to the map
map.addObject(group);
map.setCenter(group.getBoundingBox().getCenter());
}
// Now use the map as required...
geocode(platform);
CSS Snippet:
#geocode #map {
display: block;
width: 95%;
margin-bottom: 3px;
height: 450px;
background: grey;
}
#geocode #panel {
display: block;
width: 95%;
min-height: 450px;
max-height: 450px;
border: 1px solid #e3e3e3;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
}
**Refer to the documentation for more details: https://developer.here.com/documentation/examples/maps-js/services/geocode-a-location-from-address
Code: https://jsfiddle.net/gh/get/jquery/2.1.0/heremaps/maps-api-for-javascript-examples/tree/master/map-with-dom-marker**
Step 2: This example displays a movable map of New York with a single marker highlighting the location of High Street (41.8625°N, 87.6166°W), your home. Marker displays the letter C in the correct club colors. The marker is capable of receiving DOM (Document Object Model) events such as mouseenter, mouseleave etc. The marker will fade if the mouse pointer is placed over it.
HTML Snippet:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>DOM Marker</title>
<link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
<link rel="stylesheet" type="text/css" href="demo.css" />
<link rel="stylesheet" type="text/css" href="styles.css" />
<link rel="stylesheet" type="text/css" href="../template.css" />
<script type="text/javascript" src='../test-credentials.js'></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
</head>
<body id="markers-on-the-map">
<div class="page-header">
<h1>DOM Marker</h1>
<p>Display a marker that is capable of receiving DOM events</p>
</div>
<p>This example displays a movable map of <b>New York</b> with a single marker
highlighting the location of High Street <i>(41.033°N, 73.7471°W)</i>,
your home. Marker displays the letter C in the correct club colors.</p>
<p>The marker is capable of receiving DOM (Document Object Model) events such as <code>mouseenter</code>,
<code>mouseleave</code> etc. The marker will fade if the mouse pointer is placed over it.</p>
<div id="map"></div>
<h3>Code</h3>
<p>DOM markers are created by using the <code>H.map.DomMarker</code> class by providing a <code>H.map.DomIcon</code>.</p>
<script type="text/javascript" src='demo.js'></script>
</body>
</html>
Java Script Snippet:
/**
* Create a marker that is capable of receiving DOM events and add it
* to the map.
* #param {H.Map} map A HERE Map instance within the application
*/
function addDomMarker(map) {
var outerElement = document.createElement('div'),
innerElement = document.createElement('div');
outerElement.style.userSelect = 'none';
outerElement.style.webkitUserSelect = 'none';
outerElement.style.msUserSelect = 'none';
outerElement.style.mozUserSelect = 'none';
outerElement.style.cursor = 'default';
innerElement.style.color = 'red';
innerElement.style.backgroundColor = 'blue';
innerElement.style.border = '2px solid black';
innerElement.style.font = 'normal 12px arial';
innerElement.style.lineHeight = '12px'
innerElement.style.paddingTop = '2px';
innerElement.style.paddingLeft = '4px';
innerElement.style.width = '20px';
innerElement.style.height = '20px';
// add negative margin to inner element
// to move the anchor to center of the div
innerElement.style.marginTop = '-10px';
innerElement.style.marginLeft = '-10px';
outerElement.appendChild(innerElement);
// Add text to the DOM element
innerElement.innerHTML = 'C';
function changeOpacity(evt) {
evt.target.style.opacity = 0.6;
};
function changeOpacityToOne(evt) {
evt.target.style.opacity = 1;
};
//create dom icon and add/remove opacity listeners
var domIcon = new H.map.DomIcon(outerElement, {
// the function is called every time marker enters the viewport
onAttach: function(clonedElement, domIcon, domMarker) {
clonedElement.addEventListener('mouseover', changeOpacity);
clonedElement.addEventListener('mouseout', changeOpacityToOne);
},
// the function is called every time marker leaves the viewport
onDetach: function(clonedElement, domIcon, domMarker) {
clonedElement.removeEventListener('mouseover', changeOpacity);
clonedElement.removeEventListener('mouseout', changeOpacityToOne);
}
});
// Marker for Chicago Bears home
var bearsMarker = new H.map.DomMarker({lat: 41.033, lng: -73.7471}, {
icon: domIcon
});
map.addObject(bearsMarker);
}
/**
* Boilerplate map initialization code starts below:
*/
//Step 1: initialize communication with the platform
// In your own code, replace variable window.apikey with your own apikey
var platform = new H.service.Platform({
apikey: window.apikey
});
var defaultLayers = platform.createDefaultLayers();
//Step 2: initialize a map - this map is centered over Chicago.
var map = new H.Map(document.getElementById('map'),
defaultLayers.vector.normal.map,{
center: {lat:41.881944, lng:-87.627778},
zoom: 11,
pixelRatio: window.devicePixelRatio || 1
});
// add a resize listener to make sure that the map occupies the whole container
window.addEventListener('resize', () => map.getViewPort().resize());
//Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Now use the map as required...
addDomMarker(map);
CSS Snippet:
#map {
width: 95%;
height: 450px;
background: grey;
}
#panel {
width: 100%;
height: 400px;
}
**Refer DOM Marker document for more details: https://developer.here.com/documentation/examples/maps-js/markers/map-with-dom-marker
Code: https://jsfiddle.net/gh/get/jquery/2.1.0/heremaps/maps-api-for-javascript-examples/tree/master/map-with-dom-marker**
TC

take a screenshot of a web map

I am just starting out with javascript and I am trying to create an interactive web map....
I want to be able to position the map then press a button that will take a screenshot and save it to the computer.
Here is the code for my map.....
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Display a map on a webpage</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = '[TOKEN]';
const map = new mapboxgl.Map({
container: 'map', // container ID
style: 'mapbox://styles/charlie-enright/cl5b8bjil002y14o5u8xrssah', // style URL
center: [-4.369240916438415, 51.925803756014965], // starting position [lng, lat]
zoom: 8, // starting zoom
projection: 'globe' // display the map as a 3D globe
});
map.on('style.load', () => {
map.setFog({}); // Set the default atmosphere style
});
</script>
</body>
</html>
I have tried using html2canvas (https://codepen.io/samsammurphy/pen/VXdOPv) but the button seems to end up in a layer behind my map and I can not take a screenshot of the displayed map.
Any ideas how I could create a button that allows for a screenshot to be taken which saves to the computer will be greatly appreciated.
Thanks,
Here's an example of using map.getCanvas().toDataURL() and then injecting an img tag into the DOM. (This is not my example, I found it on this codepen by Sam Murphy https://codepen.io/samsammurphy/pen/VXdOPv)
$('button').click(function() {
var img = map.getCanvas().toDataURL();
var width = $('#screenshotPlaceholder').width()
var height = $('#screenshotPlaceholder').height()
var imgHTML = `<img src="${img}", width=${width}, height = ${height}/>`
$('#screenshotPlaceholder').empty();
$('#screenshotPlaceholder').append(imgHTML);
});
});
The codepen I found this on was not working due to an expired access token, so here's a fork that works if you want to try it out.
https://codepen.io/chriswhong/pen/YzapomG
Here's the code I use to take map screenshots using html2canvas
html2canvas(document.getElementById("map"), {useCORS:true}).then(canvas => {
var pseudolink = document.createElement('a');
pseudolink.download = 'myMapScreenshot.png';
pseudolink.href = canvas.toDataURL()
pseudolink.click();
})

media queries not working on dc.js chart

I want to set different width of dc.chart svg on different resolution,but media queries are not working.Is dc.chart supporting media queries or not?
please suggest me solution for it as soon as possible.
<!DOCTYPE html>
<html lang="en" style="overflow:hidden">
<head>
<title>DVH Graph</title>
<meta charset="UTF-8">
<!-- Stop this page from being cached -->
<meta http-Equiv="Cache-Control" Content="no-cache">
<meta http-Equiv="Pragma" Content="no-cache">
<meta http-Equiv="Expires" Content="0">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="css/dc.css"/>
<script type="text/javascript" src="js/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/hash2Color.js"></script>
<script type="text/javascript" src="js/loadDVH.js"></script>
<script type="text/javascript" src="js/d3.js"></script>
<script type="text/javascript" src="js/crossfilter.js"></script>
<script type="text/javascript" src="js/dc.js"></script>
<style type="text/css">
#media(max-width:1280px) {
.dc-chart .axis path, .axis line { stroke:#000; }
.dc-chart .axis text { fill: #000; }
.dc-chart svg{width:350px;height:340px;margin-left:10px}
.dc-chart{margin-left:-7px;margin-top:-9px}
}
#media(max-width:1920px) {
.dc-chart .axis path, .axis line { stroke: #000; }
.dc-chart .axis text { fill: #000; }
.dc-chart svg{width:590px;height:340px;margin-left:10px}
.dc-chart{margin-left:-7px;margin-top:-9px}
}
</style>
</head>
<body style="background:#000000" border="0">
<div id="chartCumulativeDVH" style="background: #ffffff;"></div>
<script type="text/javascript">
var chart = dc.seriesChart("#chartCumulativeDVH");
var ndx, doseDimension, doseGroup;
function drawDVH(data) {
//
// The data returned from the DSS Data API isn't quite in the best format for dc graphs
// So, we need to reformat it slightly
//
var dvhColours = [];
var formatted = [];
for (var objCount = 0; objCount < data.length; objCount++) {
var contourID = objCount + 1;
for (var i = 0; i < data[objCount].NumberOfPoints; i++) {
data[objCount].Points[i].Contour = contourID;
formatted.push(data[objCount].Points[i]);
}
// Match the colour of the curve to the label.
var rgb = hash2Color(data[objCount].Contour);
dvhColours.push('rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')');
}
// Clear the existing chart
if(ndx) {
ndx.remove();
ndx.add(formatted);
dc.redrawAll();
}
ndx = crossfilter(formatted);
doseDimension = ndx.dimension(function(d) {
return [+d.Contour, +d.X];
});
doseDimension.filterFunction(function(d) {
return d;
});
doseGroup = doseDimension.group().reduceSum(function(d) {
return +d.Y;
});
chart
/* .width(347)
.height(280) */
.chart(function(c) { return dc.lineChart(c).interpolate('basis'); })
.x(d3.scale.linear().domain([0, 7500]))
.y(d3.scale.linear().domain([0, 100]))
.brushOn(false)
.yAxisLabel("% Volume")
.xAxisLabel("Dose mGy")
.clipPadding(10)
.dimension(doseDimension)
.group(doseGroup)
.mouseZoomable(true)
.seriesAccessor(function(d) { return "Contour: " + d.key[0]; })
.keyAccessor(function(d) { return +d.key[1]; })
.valueAccessor(function(d) { return +d.value; })
.ordinalColors(dvhColours);
chart.yAxis().tickFormat(function(d) {return d3.format(',d')(d + 0);});
chart.margins().left = 40;
dc.renderAll();
};
$(document).on("data-available", function (__e, __data) {
drawDVH(__data);
});
// Draw the default graph (e.g. no data)
drawDVH({});
</script>
</body>
</html>
The svg element is directly sized by dc.js, and since element-level styles override stylesheet-level styles, your media queries will have no effect.
What you want to do is set the size of the containing div (#chartCumulativeDVH or .dc-chart).
Then you have two at least three choices how to apply the size to the svg element that will be created:
Leave off the width and height as you show in your example. dc.js will automatically use the size of the container div if width and height are not specified. However, this will not work if anything else is in the div (or might show up there, like the filter and reset controls) because they will no longer be the same size, and the svg size can get out of control in these cases.
Set the size of the chart to match the div size, e.g. (using jQuery) something like
chart
.width($('#chartCumulativeDVH').innerWidth())
.height($('#chartCumulativeDVH').innerHeight())
Or, to base the width and height off the window size without using jQuery and without the media query, as we do in the resizing bar chart example:
chart
.width(window.innerWidth-20)
.height(window.innerHeight-20)

dojo datagrid OnStyleRow not correct after sorting via header

I am styling grid row based on a value in the column.
On initial load it looks ok, however, when I click on the header to sort, the styling follows the original style and does not reflect the value in the sorted list.
In the onStyleRow event that does the styling override, I can get the row object of the grid, But... how do I get the column data from the row so that I can style it properly.
I have gone through the two questions below and a few others in StackOverflow, Googled, checked Dojo API docs and reference, etc. So far no outcome...
dojox DataGrid onStyleRow works first time, then not again
dojo datagrid custom sorting server side
I attach working code below, you can cut and paste to a html file to run and see the problem I am facing (The //// comment in the code below is a key place to note).
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojo/resources/dojo.css">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dijit/themes/tundra/tundra.css">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojox/grid/resources/tundraGrid.css">
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.8.3/dojo/dojo.js" data-dojo-config="async:true,isDebug:true,parseOnLoad:true"></script>
<script>
var grid_report;
require([ 'dojo/parser', 'dojox/grid/DataGrid', 'dojox/data/CsvStore', 'dojo/domReady!' ], function(){
dojo.ready(function(){
var csvData = "id,val\n";
csvData += "1,10\n" + "2,20\n" + "3,30\n" + "4,40\n" + "5,50\n" + "6,60\n";
var csv_store = new dojox.data.CsvStore({identifier: "id", data: csvData});
grid_report = new dojox.grid.DataGrid({
style:'height:400px',
store: csv_store,
structure: [ { field: 'id', width: '80px', name: 'ID' }, { field: 'val', width: '80px', name: 'Value' }, ],
}, document.createElement('div'));
dojo.byId("gridDiv").appendChild(grid_report.domNode);
dojo.connect(grid_report, 'onStyleRow', function (row) {
var idx = row.index;
//// Below is not correct as index is the row index on the grid, but the data store is in a different order after sorting order change via clicking cell header
var _item = grid_report.getItem(idx);
if (!_item) return;
var val = parseInt( _item._csvStore._dataArray[ idx ][1] );
if (val <= 20) row.customStyles += 'background-color:#88f;';
else if (val > 40) row.customStyles += 'background-color:#f88;';
else row.customStyles += 'background-color:#ff8;';
dojox.grid.DataGrid.prototype.onStyleRow.apply(this, arguments);
});
grid_report.startup();
}); // end ready
}); // end require
</script>
</head>
<body class="tundra">
<div style="height:25px; width:100px; display:table-cell; text-align: center; vertical-align:middle; background-color:#88f;">Value 0-20</div>
<div style="height:25px; width:100px; display:table-cell; text-align: center; vertical-align:middle; background-color:#ff8;">Value 21-40 </div>
<div style="height:25px; width:100px; display:table-cell; text-align: center; vertical-align:middle; background-color:#f88;">Value 41 or more</div>
<div id="gridDiv" style="width:'800px';height:'600px';"></div>
</body>
</html>
I found a work around. It is not ideal as it may not work for all situations.
Change line with:
var idx = row.index;
to:
var idx = -1;
After the newly edit line above, add the following:
var _item = null;
grid_report.store.fetch({onComplete: function(items) {
dojo.forEach(items, function(item, index) {
// KLUDGE FOR finding item after sort
// use merged csv data AND row.node.textContent
var merged_csv_text = item._csvStore._dataArray[index].join('');
if (merged_csv_text == row.node.textContent) {
idx = index; // I finally get the correct index here!!!
return;
}
});
} });
if (idx == -1) return;
This works only if each data formed by merged_csv_text is unique.

Google maps KML polygons

I have successfully imported a kml file to a Google map so that it displays real estate boundaries.
I have also used the tutorial at https://google-developers.appspot.com/maps/documentation/javascript/examples/polygon-arrays to draw simple polygons and have them click-able.
However, I don't know how to make the polygons created by the kml file click-able. The polygons on the kml are quite complex shapes and consist of many coordinates to form the polygons. The example below is just for 1 real estate boundary:
-83.6530304633209,34.8237504877659,0 -83.65536046332301,34.8248804877671,0 -83.65672046332431,34.8262904877683,0 -83.6567504633242,34.8271904877693,0 -83.655330463323,34.8308304877725,0 -83.6565104633242,34.8333304877749,0 -83.65765046332511,34.8349204877764,0 -83.6571104633247,34.8383604877794,0 -83.6591604633265,34.8443604877853,0 -83.6588104633263,34.8468904877875,0 -83.6591604633265,34.8507504877912,0 -83.6583904633258,34.8543804877945,0 -83.6569404633244,34.8566604877968,0 -83.65475046332242,34.8599504877998,0 -83.6545604633223,34.8610404878007,0 -83.6543204633219,34.8635704878032,0 -83.65568046332331,34.8684104878075,0 -83.6553904633231,34.8695004878086,0 -83.6546604633224,34.8706904878097,0 -83.654380463322,34.872050487811,0 -83.6552304633228,34.8745504878134,0 -83.65494046332262,34.8759104878145,0 -83.65377046332161,34.8768304878154,0 -83.6504704633185,34.8796104878179,0 -83.64877046331689,34.8814504878196,0 -83.6469204633151,34.8849204878229,0 -83.6450204633134,34.8870304878249,0 -83.64227046331081,34.8897904878275,0 -83.6389204633076,34.8911304878288,0 -83.6344604633034,34.8921304878297,0 -83.6330604633022,34.8926104878301,0 -83.6295204632988,34.8948504878322,0 -83.6278404632974,34.8969604878341,0 -83.6273304632969,34.89832048783551,0 -83.62726046329681,34.8994904878366,0 -83.6286904632982,34.9030704878399,0 -83.6287304632981,34.9045104878412,0 -83.62844046329791,34.9056004878421,0 -83.6268704632964,34.9077104878443,0 -83.6256904632953,34.9086304878451,0 -83.6240704632939,34.9091204878455,0 -83.6226304632926,34.9088804878452,0 -83.6204304632904,34.9083904878448,0 -83.6179704632882,34.9100604878463,0 -83.61680046328711,34.9109904878471,0 -83.6157204632862,34.9116404878477,0 -83.61126046328189,34.9123704878484,0 -83.610200463281,34.91347048784951,0
These coordinates do not work when i manually convert them into latlng pairs and insert them into the Google tutorial above like so:
new google.maps.LatLng(-83.6530304633209,34.8237504877659),
new google.maps.LatLng(83.65536046332301,34.8248804877671),
new google.maps.LatLng(-83.65672046332431,34.8262904877683),
new google.maps.LatLng(-83.6567504633242,34.8271904877693)
Anyone have any ideas on how I can either make the kml layer polygons click-able or use the kml data to redraw the polygons and make them click-able?
Thanks
edit: This is the code i'm using to load the kml:
<!-- Declare the application as HTML5 using the <!DOCTYPE html> declaration -->
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map_canvas { height: 100% }
</style>
<!-- include the Maps API JavaScript using a script tag -->
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=AIzaSyAaWOu7N4OX8BlYUwZhvWP2V0P6YQryN9Y&sensor=true"></script>
<script type="text/javascript">
function initialize()
{
<!-- create a JavaScript object literal to hold a number of map properties -->
var myOptions =
{
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP,
fillColor: '#0000ff'
};
<!-- a JavaScript function to create a "map" object -->
var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
var myLayer = new google.maps.KmlLayer('http://www.domain.com/gmaps/1.kml',{suppressInfoWindows: true,map: map});
google.maps.event.addListener
(
myLayer,"mouseover",function()
{
this.setOptions({fillColor: "#000000"});
}
);
google.maps.event.addListener
(
myLayer, 'click', function(kmlEvent)
{
var text = kmlEvent.featureData.description;
showInContentWindow(text);
}
);
google.maps.event.addListener
(
myLayer,"mouseover",function()
{
this.setOptions
(
{
fillColor: "#000000"
}
);
}
);
function showInContentWindow(text)
{
var sidediv = document.getElementById('content_window');
sidediv.innerHTML = text;
}
}
</script>
</head>
<!-- initialize the map object from the body tag's onload event -->
<body onLoad="initialize()">
<!-- create a div element named "map_canvas" to hold the Map -->
<div id="map_canvas" style="width:79%; height:100%; float:left"></div>
<div id="content_window" style="width:19%; height:100%; float:left"></div>
</body>
</html>
Unfortunately, you don't get a mouseover event with the KmlLayerapi-doc; check at the api-doc, scroll down a bit to see the Events, and all you get for events are: click, defaultviewport_changed, and status_changed. I have also explored the options that are available because the KmlLayer is an MVCObjectapi-doc, but that doesn't offer additional events. I don't think this is possible.
There may be another way to achieve what you want, but I haven't found it; let's see what others may be able to add.
Using KmlLayer, you can't change the properties of the Polygons. If you use a third party KML parser like geoxml3 or geoxml-v3 to render the polygons as native Google Maps API v3 objects you can change their properties (but whether the performance is acceptable will depend on how complex your KML is). You can also dynamically change Polygons in tiles rendered using FusionTablesLayer (import your KML into a Fusion Tabel).
Example changing the color of Polygons from KML rendered using geoxml3 on mouseover

Resources