I need to refresh an openlayers map after updating the size of pie charts in a mapfile displayed on the map (on button click). I cannot refresh the whole page or I lose the data. It works when I change the zoom level. I have tried map.updateSize() (no effect), map.render() (TypeError "a" is not defined), layer.redraw(). I am not sure if I am missing something openlayers-related, or if it is an issue with my javascript. I have looked through a number of posts, but can't seem to get any of the answers working in my case.
$(document).ready(function() {
map = new OpenLayers.Map( 'map' ,
{ maxExtent: new OpenLayers.Bounds({{bounds.0}}, {{bounds.1}}, {{bounds.2}}, {{bounds.3}}),
controls:[new OpenLayers.Control.Navigation(),
new OpenLayers.Control.LayerSwitcher(),
new OpenLayers.Control.PanZoomBar()],
numZoomLevels:20
}
);
var mpLayer = new OpenLayers.Layer.MapServer('Zones Layer', '{{ mapserverpath }}', {
map:'{{mapFile}}',
layers:'all',
isBaseLayer: 'true'
},{
singleTile: 'true'
// ratio: 2.0
}
);
map.addLayers([mpLayer]);
//map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
map.zoomToMaxExtent();
map.events.register("click", map, qryDB );
$(document).on('click', '#bttnMinus', function(){
pieFact*=0.5;
updatePieFact();
mpLayer.redraw();
});
$(document).on('click', '#bttnPlus', function(){
pieFact*=1.5;
updatePieFact();
mpLayer.redraw();
});
$(document).on('click', '#bttnReset', function(){
pieFact=1.0;
updatePieFact();
mpLayer.redraw();
});
});
You can try to call "clearGrid()" function before redrawing.
"clearGrid()" is a function of Layer.Grid (Layer.MapServer inherits from Layer.Grid). It will destroy each tile of the layers.
Just remark that "clearGrid ()" is not a APIMethod, so it is not supposed to be called in this way.
There are also a similar question/answer here.
try this. It worked for me.
$(window).trigger('resize');
This code sets the screen again.
Related
I have recently downloaded Googles armsglobe chromeexperiment and used it for showing country datas on the globe. but i wanted to refresh the data every 5mins. here is how i tried to update the data:
// ensure the map images are loaded first!!
mapIndexedImage = new Image();
mapIndexedImage.src = 'images/map_indexed.png';
mapIndexedImage.onload = function() {
mapOutlineImage = new Image();
mapOutlineImage.src = 'images/map_outline.png';
mapOutlineImage.onload = function(){
loadCountryCodes(
function(){
loadWorldPins(
function(){
loadContentData(
function(){
initScene();
animate();
}
);
}
);
}
);
};
};
//setInterval(mapIndexedImage.onload, 300000);
The ^ last commented line was my only code. it works and gets the data; loadContentData() gets the data from server(db) and the two functions inside draws and animate() the globe according to the data provided. but whenever a new data is received the globe crashes and doesn't move. is there any better way to implement this without crashing the globe?
Thanks for your help!!! Really appreciated.
I'm attempting to create a custom popup while using the angular-leaflet-directive. I'm opening the popup from the leaflet.draw on:create event. Here:
map.on('draw:created', function(e) {
layer = e.layer;
drawnItems.addLayer(layer);
var newComment = "Enter Comment";
var newID = "ID";
var newGeoJsonFeat = layer.toGeoJSON();
newGeoJsonFeat.properties = {"comment":newComment, "id":newID};
console.log(newGeoJsonFeat);
onEachFeature(newGeoJsonFeat,layer);
layer.openPopup();
});
Then I'm using #blackjid's logic as seen here: https://github.com/tombatossals/angular-leaflet-directive/issues/238 to bind the custom popup
function onEachFeature(feature, layer) {
// Create get the view template
var popupContent = '<div ng-include="\'partials/popup_newfeat.html\'"></div>';
console.log("assigning popup");
// Bind the popup
// HACK: I have added the stream in the popup options
layer.bindPopup(popupContent,{
closeButton: false,
maxHeight: 300,
feature: feature
});
};
$scope.$on('leafletDirectiveMap.popupopen', function(event, leafletEvent){
// Create the popup view when is opened
var feature = leafletEvent.leafletEvent.popup.options.feature;
var newScope = $scope.$new();
newScope.stream = feature;
$compile(leafletEvent.leafletEvent.popup._contentNode)(newScope);
});
Long story short, Everything works fine except the popup container isn't resizing properly to fit the new content. The height seems right, but the width is off.
I tried using:
.leaflet-popup-content {
width:auto !important;
}
Which will probably suffice, but this causes the popup anchor to shift to the bottom left of the popup for some reason. AutoPan is also broken when clicking near the top of the map.
Does anyone know where and how I can get popup.update() to fire? I believe thats what needs to happen, but I don't know where to implement it. I've tried calling it after layer.openPopup() like so:
onEachFeature(newGeoJsonFeat,layer);
layer.openPopup();
layer.getPopup().update();
});
But that doesn't seem to do anything. Any help is greatly appreciated!
You need to use the 'leafletEvent'. Try this:
myApp.controller('YourController', ['$scope', 'leafletEvent', function($scope) {
// after all your crazy custom popup stuff ...
leafletData.getMap().then(function(map) {
layer.getPopup().update();
});
}]);
I ended up storing the image width in the properties of the GeoJson, and then setting the minWidth to that value in the bindPopup function.
layer.bindPopup(popupContent,{
closeButton: true,
closeOnClick: false,
minWidth: feature.properties.width,
autoPanPadding: L.point(20,20),
keepInView: false,
feature: feature
});
My javascript code loops through some user data and adds each one as a marker to a container. It then adds that container to a nokia map and uses the Display zoomTo to zoom to the bounding box of the container holding all the markers.
However, right after that happens, the map just zooms itself all the way back out. The zoomTo call is the very last of my code that executes so it seems like something weird is going on.
this.finishMapping = function () {
map.objects.add(multiMapContainer);
var markerHopefully = multiMapContainer.objects.get(0);
$.ajax({
dataType: "jsonp",
url: "https://route.api.here.com/routing/7.2/calculateroute.json?app_id=WgevZ2m4AF8WHx1TY6GS&app_code=G11AO2dbvCRTdCjfTf-mUw&waypoint0=geo!" + markerHopefully.coordinate.latitude + "," + markerHopefully.coordinate.longitude + "&waypoint1=geo!" + markerHopefully.coordinate.latitude + "," + markerHopefully.coordinate.longitude + "&mode=fastest;car;",
success: function (data) {
onRouteCalculated(data)
},
jsonp: "jsoncallback"
});
function onRouteCalculated(data) {
if (data.response) {
var position = data.response.route[0].waypoint[0].mappedPosition;
var coordinate = new nokia.maps.map.StandardMarker([position.latitude, position.longitude]);
var tempContainer = new nokia.maps.map.Container();
tempContainer.objects.add(coordinate);
map.zoomTo(multiMapContainer.getBoundingBox().merge(tempContainer.getBoundingBox()), false);
}
}
}
I debugged through it in Chrome and I can see that zoomTo does actually zoom to the proper bounding box, but then right after I hit the 'continue' button it jumps back to the highest zoom level.
I recently came across a similar issue. The basic issue was that the containing <DIV> for the map was itself being initialized during the map initialization. My problem was compounded because map.zoomTo() doesn't work during map initialization anyway (since 2.5.3 map loading is always asynchronous)
The crux of the issue was that I was trying to use zoomTo() on a 0x0 pixel map since the <DIV> wasn't displayed yet - hence I ended up with a zoomLevel zero map.
The solution is to add listeners to the map as shown:
map.addListener("displayready", function () {
if(bbox){map.zoomTo(bbox, false);}
});
map.addListener("resize", function () {
if(bbox){map.zoomTo(bbox, false);}
});
And set up the bbox parameter as each coordinate is received as shown:
function onCoordinateReceived(coordinate){
if(bbox){
bbox = nokia.maps.geo.BoundingBox.coverAll([
bbox.topLeft, bbox.bottomRight, coordinate]);
} else {
bbox = nokia.maps.geo.BoundingBox.coverAll([coordinate]);
}
map.zoomTo(bbox, false);
}
So that:
If the map is already intialized and displayed the zoomTo() in the onCoordinateReceived() will fire
If the map completes intialization after onCoordinateReceived(), the zoomTo() in the displayready listener will fire.
If the <DIV> update occurs last, the zoomTo() in the resize listener will fire, which will alter from a zoomed Out map to the "right" zoom level.
I'm trying to use ZeroClipboard for a "Click to copy" feature on an element and the same time show a bootstrap tooltip.
Unfortunately the tooltip doesn't work if I use ZeroClipboard on an element. Any help would be greatly appreciated...
// BOOTSTRAP TOOLTIP
$('.myDiv').tooltip({
title: 'Click to copy',
placement: 'right',
trigger: 'hover',
animation: true
});
// ZEROCLIPBOARD
var clip = new ZeroClipboard.Client();
clip.setHandCursor(true);
$('.myDiv').live('mouseover', function () {
clip.setText($(this).text());
if (clip.div) {
clip.receiveEvent('mouseout', null);
clip.reposition(this);
} else clip.glue(this);
clip.receiveEvent('mouseover', null);
});
Managed to get it working in a very simple way
var zero = new ZeroClipboard($el);
$(zero.htmlBridge).tooltip({title: "copy to clipboard", placement: 'bottom'});
Sometimes it is hard to get all the snippets together and to work ... this is a complete solution using ZeroClipboard 1.3.2 and Bootstrap 3.1.0:
HTML:
<a id="copycommand" href="#" data-clipboard-text="text to copy">Copy ...</a>
ZeroClipboard create a container with the ID global-zeroclipboard-html-bridge, this is the access point for the Bootstrap Tooltip.
jQuery:
// initialize Tooltip
$('#global-zeroclipboard-html-bridge').tooltip();
// ZeroClipboad
ZeroClipboard.config({ moviePath: 'ZeroClipboard.swf' });
var clip = new ZeroClipboard(document.getElementById('copycommand'));
clip.on('complete', function(client, args){
alert("Copied text to clipboard: " + args.text);
});
// settings for the Tooltip
clip.on('load', function(client) {
$('#global-zeroclipboard-html-bridge').attr({
'data-toggle':'tooltip',
'data-title': 'Tooltip text goes here ...',
'data-placement': 'bottom',
'data-html': true
});
// show the tooltip
$('#global-zeroclipboard-html-bridge').tooltip('show');
});
If you run Tooltip after ZeroClipboard it should work without problems!
Found a workaround by putting the tooltip to be shown on click for Bootstrap, but then using hooks in ZeroClipboard to show and hide it upon hover.
Here is how I did it:
$('div.color-inspiration span').tooltip({
title: 'Click to copy',
placement: 'right',
trigger: 'click',
animation: false
});
var element = null;
var clip = new ZeroClipboard.Client();
clip.setHandCursor(true);
$('div.color-inspiration span').live('mouseover', function () {
element = $(this);
clip.setText($(this).text());
if (clip.div) {
clip.receiveEvent('mouseout', null);
clip.reposition(this);
} else clip.glue(this);
clip.receiveEvent('mouseover', null);
});
clip.addEventListener( 'onMouseOver', my_mouse_over_handler );
function my_mouse_over_handler( client ) {
$(element).tooltip('show');
}
clip.addEventListener( 'onMouseOut', my_mouse_out_handler );
function my_mouse_out_handler( client ) {
$(element).tooltip('hide');
}
clip.addEventListener( 'onMouseUp', my_mouse_up_handler );
function my_mouse_up_handler( client ) {
$(element).tooltip('hide');
}
Old question but I recently encountered this problem and was able to find a solution, it's rather simple but a bit blanket. Because the flash element positions itself with a zindex of 10000 on top of whatever element you have on the page you'll have to append the flash element with a selector and title. This can be done with the ZeroClipboard callbacks.
clip.on( 'load', function(client) {
$('#global-zeroclipboard-html-bridge').attr('rel', 'tooltip').attr('title', 'Click Here To Copy URL');
} );
With Zero Clipboard 2.2 and Bootstrap 3 I got it to work like this
var $copyButton = $('.clipboard');
var clip = new ZeroClipboard($copyButton);
clip
.on('ready', function() {
$('#global-zeroclipboard-html-bridge').attr({
'data-toggle': 'tooltip',
'data-title': 'Copy to clipboard...',
'data-placement': 'right'
});
$('#global-zeroclipboard-html-bridge').tooltip({
container: 'body',
trigger: 'hover'
});
})
.on('aftercopy', function() {
$('#global-zeroclipboard-html-bridge').tooltip('hide');
});
Change the selector on line one.
the #global-zeroclipboard-html-bridge selector targets a div that is inserted by the Zero Clipboard component and that overlays the copy button.
bug is a known issue and mentioned here: Zeroclipboard bug causing issue: see # https://github.com/zeroclipboard/zeroclipboard/issues/369
Adding to #gnorsilva's answer. Here is how I set new text on the tooltip once it was copied successfully:
$(clip.htmlBridge).tooltip({
title: 'copy to clipboard',
placement: 'bottom'
});
clip.on('load', function(client) {
client.on('complete', function() {
$('.tooltip .tooltip-inner').text('copied!');
});
});
This achieves the same effect as GitHub when you click one of their ZeroClipboard elements such as copy SHA or when you click the clone URL button
How do I redraw/rescale a google linechart on window resize?
To redraw only when the window resize is completed and avoid multiple triggers, I think is better create an event:
//create trigger to resizeEnd event
$(window).resize(function() {
if(this.resizeTO) clearTimeout(this.resizeTO);
this.resizeTO = setTimeout(function() {
$(this).trigger('resizeEnd');
}, 500);
});
//redraw graph when window resize is completed
$(window).on('resizeEnd', function() {
drawChart(data);
});
The original code by Google simply does this at the end:
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
Changing it with a little javascript you can scale it when the window resizes:
function resize () {
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
window.onload = resize;
window.onresize = resize;
Since the window.resize event fires multiple times on each resize event, I believe that the best solution is to use smartresize.js and use smartdraw(). This limits the number of chart redraw’s per window.resize.
By using the provided js you can do it as simply as this:
// Instantiate and draw our user charts, passing in some options (as you probably were doing it)
var chart = new google.visualization.LineChart(document.getElementById('div_chart'));
chart.draw(data, options);
// And then:
$(window).smartresize(function () {
chart.draw(data, options);
});
This is the simplest way I can work out of doing this without causing too much stress to the browser:
var chart1 = "done";
$(window).resize(function() {
if(chart1=="done"){
chart1 = "waiting";
setTimeout(function(){drawChart();chart1 = "done"},1000);
}
});
All it does is wait 1 second before the chart reloads and doesn't let the function call again in this waiting period. as window resize functions are called multiple times any time you change the window size this helps make the function only actually work once each time you change the window size, the rest of the calls get stopped by the if statement.
I hope this helps
There is no option in Google Visualization API to make Google Charts responsive.
But we can make Google Charts responsive as Window Resizes. To make Google Chart responsive there is jQuery library available at GitHub - jquery-smartresize licensed under MIT License, which has the ability to resize graphs on window resize event.
This project on GitHub has two script files :-
jquery.debouncedresize.js: adds a special event that fires once after the window
has been resized.
&
jquery.throttledresize.js: adds a special event that fires at a reduced rate (no
more double events from Chrome and Safari).
Here are two examples of responsive charts...
Responsive Google Pie Chart
Responsive Google Bar Chart
We can change the bottom padding of visualization_wrap to match the desired aspect ratio of chart.
Calculate as Height / Width x 100
For a 16x9 display it would be 9/16 = 0.5625 x 100 = 56.25%
For a square it'd be 100%
We can customize chartarea option of Google Chart to ensure that labels don't get cut off on resizing.
Redraw/rescale a Google linechart on window resize:
$(document).ready(function () {
$(window).resize(function(){
drawChart();
});
});
I personally prefer the following approach, if You can live with using addEventListener, and don't mind lack of support for IE < 9.
var windowResizeTimer;
window.addEventListener('resize', function(e){
clearTimeout(windowResizeTimer);
windowResizeTimer = setTimeout(function(){
chart.draw(data, options);
}, 750);
});
Note the use of the setTimeout() and clearTimeout() functions and the added delay of 750 milliseconds, which makes this slightly less intensive when multiple resize events fire in quick succession (which is often the case for browsers on desktop when resizing using a mouse).
I've been stuck on the same thing for days and I found out that adding an event works best.
window.addEventListener("resize", drawChart);
Just add this line after declaring your function and it will work fine.
Replace drawChart with the name of your function.
Try with these approaches
window.dispatchEvent(new Event('resize'))
Chartkick.charts["<id of chart element like chart-1>"].redraw()
Using Tiago Castro's answer, I have implemented a line chart to show the demonstration.
google.load('visualization', '1', {
packages: ['corechart', 'line']
});
google.setOnLoadCallback(drawBackgroundColor);
function drawBackgroundColor() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'X');
data.addColumn('number', 'Compute Time');
data.addColumn('number', 'Compute Times');
console.log("--");
data.addRows([
[0, 0, 0],
[10, 10, 15],
[20, 20, 65]
]);
console.log(data);
var options = {
height: 350,
legend: {
position: 'bottom'
},
hAxis: {
title: 'Nb Curves'
},
vAxis: {
title: 'Time (ms)'
},
backgroundColor: '#f1f8e9'
};
function resize() {
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
window.onload = resize();
window.onresize = resize;
}
<script src='https://www.google.com/jsapi'></script>
<div id="chart_div">