I've encountered a strange issue while trying to run scripts within my .cshtml file. I am trying to run a script that sets an icon depending on how the user clicks on it, and other which uses the Leaflet Javascript library to display a map.
My issue is that only the last script to be listed in the section works (aka if I put star.js after mapdisplay.js, star.js would work and mapdisplay.js would not, and vice-versa).
I am running this on .NET 5.0
Index.cshtml - #section scripts
#section scripts {
<script type="text/javascript" src="~/scripts/star.js"></script>
<script>
var lat = '#Model.Latitude';
var long = '#Model.Longitude';
</script>
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin="">
</script>
<script type="text/javascript" src="~/scripts/mapdisplay.js"></script>
}
And just in case, here's both scripts.
star.js
window.onload = function () {
//Adds click event handler to make an AJAX request to star when the star is clicked
$(".clickable").click(function () {
let star = $(this);
//Might be undefined if user deletes the attribute
if (star.attr("reportId") != undefined) {
let id = parseInt(star.attr("reportId"));
//NaN might happen if user changes reportId attribute to something which isn't a number
if (!isNaN(id)) {
let dataToSend = {
reportId: id
}
//Sends ajax request
$.ajax({
type: 'POST',
url: '/Home/Star',
data: dataToSend,
dataType: "json",
success: function (response) {
if (response) {
//If StarReport finished successfully, update the UI
if (star.hasClass("starred")) {
star.removeClass("starred").addClass("unstarred");
} else {
star.removeClass("unstarred").addClass("starred");
}
}
}
});
} else {
alert("Don't mess with the code!");
}
} else {
alert("Don't mess with the code!");
}
});
}
mapdisplay.js
window.onload = function () {
//Creates map bounds
let topLeftCorner = L.latLng(35.11111111115, 14.111111111);
let bottomRightCorner = L.latLng(35.1123231312, 14.67243783646247);
let bounds = L.latLngBounds(topLeftCorner, bottomRightCorner);
let map = L.map("map", {
center: L.latLng(lat, long),
zoom: 14,
zoomControl: false,
dragging: false,
keyboard: false,
maxBoundsViscosity: 1.0
});
map.setMinZoom(18);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
).addTo(map);
marker = L.marker([lat, long], { draggable: false }).addTo(map);
}
Any help would be appreciated, as this is driving me nuts.
For closure's sake I'll respond to my own question. As user:charlietfl pointed out in comments, window.onload can only be assigned to one function.
I personally simply solved this by using window.addEventListener('load', function () { in the .js files instead of window.onload, which works in my context.
Related
I'm trying to assign a unique ID to each feature that gets drawn on this Google Map, and then use the rightclick event to remove the feature that gets clicked on. Currently all features get removed, which is a problem.
Once the feature is added to the collection, I try to assign the unique ID:
var uniqueID = function() {
return ++currentID;
}
dataLayer.addListener('addfeature', savePolygon, function(event) {
event.feature.setProperty('featureID', uniqueID);
});
Then on rightclick event, I want to remove the feature that gets clicked on. I assumed you would need to have unique IDs for this step, hence the prior step.
dataLayer.addListener('rightclick', function() {
dataLayer.forEach(function(feature) {
dataLayer.remove(feature);
localStorage.removeItem('geoData');
});
});
Full code below.
JS:
var map;
var currentID = 0;
var uniqueID = function() {
return ++currentID;
}
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 4,
// only show roadmap type of map, and disable ability to switch to other type
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false
});
map.data.setControls(['Polygon']);
map.data.setStyle({
editable: true,
draggable: true
});
bindDataLayerListeners(map.data);
//load saved data
loadPolygons(map);
}
// Apply listeners to refresh the GeoJson display on a given data layer.
function bindDataLayerListeners(dataLayer) {
dataLayer.addListener('addfeature', savePolygon, function(event) {
event.feature.setProperty('featureID', uniqueID);
});
dataLayer.addListener('rightclick', function() {
dataLayer.forEach(function(feature) {
dataLayer.remove(feature);
localStorage.removeItem('geoData');
});
});
dataLayer.addListener('setgeometry', savePolygon);
}
function loadPolygons(map) {
var data = JSON.parse(localStorage.getItem('geoData'));
map.data.forEach(function(f) {
map.data.remove(f);
});
map.data.addGeoJson(data)
}
function savePolygon() {
map.data.toGeoJson(function(json) {
localStorage.setItem('geoData', JSON.stringify(json));
});
}
initMap();
Original source: I built this example from a JSFiddle found in this thread.
your addfeature listener was wrong, as addListener takes only a single callback function, so you need to call e.feature.setProperty then savePolygon inside a single anonymous callback function
Note, you had event.feature.setProperty('featureID', uniqueID); - it needs to be event.feature.setProperty('featureID', uniqueID());
dataLayer.addListener('addfeature', function(event) {
event.feature.setProperty('featureID', uniqueID());
savePolygon(event);
});
Then, in the rightclick lsitener, you can simply get the geoData - filter out the clicked item, save the geoData and then dataLayer.remove(e.feature);
dataLayer.addListener('rightclick', function(e) {
var data = JSON.parse(localStorage.getItem('geoData'));
data.features = data.features.filter(function(feature) {
return feature.properties.featureID !== e.feature.getProperty('featureID');
});
localStorage.setItem('geoData', JSON.stringify(data));
dataLayer.remove(e.feature);
});
working fiddle
I am trying to update the contents of my popups in leaflet. First, I create markers and bind popups to them:
$.ajax({
type: "GET",
url: "/?p=map&json=1"+filter,
dataType: 'json',
success: function (response) {
geojson = L.geoJson(response, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng);
},
onEachFeature: onEachFeature
});
markers.addLayer(geojson);
map.addLayer(markers);
});
}
});
var layers = [];
function onEachFeature(feature, layer) {
feature.layer = layer;
layer.origID = feature.properties.id;
if (feature.properties && feature.properties.project_name) {
var divNode = document.createElement('DIV');
divNode.innerHTML = 'initial popup content from database <button onclick="makeAjaxCall('+feature.properties.id+')">more</button>';
layer.bindPopup(divNode);
}
layers.push(layer);
}
Initially, there's a button inside the popup, thats triggers an ajax call for updated popup content.
That ajax call returns and calls setPopupContent():
function setPopupContent(id,data){
for(var i=0;i<layers.length;i++){
if(layers[i].origID == id){
console.log(layers[i]);
var p = layers[i].getPopup();
p.setContent(data);
p.update();
}
}
}
Everything works as expected but the popup's size is not updating to its new content. It remains at 301px. Shouldn't p.update() also update the popup size?
Or is there a better way to handle popup content updates that are triggered from within that popup?
Here's an example: http://plnkr.co/edit/LUyOWqkSVazhiadEix2q?p=preview (thx iH8!)
Thanks for help!
Your popup width is being constrained by the maxWidth option of L.Popup which defaults to 300px:
http://leafletjs.com/reference.html#popup-maxwidth
This can easily be set when binding/initializing the popup like this:
L.Marker([0, 0]).bindPopup('Lorem', {maxWidth: 600}).addTo(map);
A fork of your fork on Plunker: http://plnkr.co/edit/nfxhuUV40dfRV21YKFpu?p=preview
I use the jQuery Mobile in order to get the weather data from openweathermap.org and to display it. It works properly on IE10 but it doesn't work on IE11 . What can be the reason ? (It works in Chrome.) You can see the codes on http://jsfiddle.net/Gajotres/frSsS/
$(document).on('pageinit', '#index', function(){
$(document).on('click', '#city-search-btn', function(){
var cityName = $('#city-search').val();
if(cityName.length > 0) {
var url = 'http://api.openweathermap.org/data/2.5/weather?q='+cityName+'&units=metric';
$.ajax({
url: url,
dataType: "jsonp",
async: true,
beforeSend: function() {
// This callback function will trigger before data is sent
$.mobile.loading('show', {theme:"a", text:"Please wait...", textonly:false, textVisible: true}); // This will show ajax spinner
},
complete: function() {
// This callback function will trigger on data sent/received complete
$.mobile.loading('hide'); // This will hide ajax spinner
},
success: function (result) {
ajax.parseJSONP(result);
},
error: function (request,error) {
alert('Network error has occurred please try again!');
}
});
} else {
alert('Please enter city name!');
}
});
});
$(document).on('pagehide', '#map', function(){
$(this).remove();
});
$(document).on('pageshow', '#map',function(e,data){
var minZoomLevel = 12;
var myLatLng = new google.maps.LatLng(weatherData.response.coord.lat, weatherData.response.coord.lon);
var map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: minZoomLevel,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var image = {
url: 'http://openweathermap.org/img/w/'+weatherData.response.weather[0].icon+'.png'
};
infoWindow = new google.maps.InfoWindow();
infoWindow.setOptions({
content: "<div class='info-window'><div class='icon-holder'><img src='http://openweathermap.org/img/w/"+weatherData.response.weather[0].icon+".png'/></div><div class='info-holder'><span class='info-text'>City:</span><br/>"+weatherData.response.name+"<br/><span class='info-text'>Min. Temp:</span><br/>"+weatherData.response.main.temp_min+" °C<br/><span class='info-text'>Temp:</span><br/>"+weatherData.response.main.temp+" °C<br/><span class='info-text'>Max. Temp:</span><br/>"+weatherData.response.main.temp_max+" °C</div></div>",
position: myLatLng,
});
infoWindow.open(map);
});
var ajax = {
parseJSONP:function(result){
weatherData.response = result;
//alert(JSON.stringify(weatherData.response.weather[0].icon));
var mapPage = $('<div>').attr({'id':'map','data-role':'page'}).appendTo('body');
var mapHeader = $('<div>').attr({'data-role':'header', 'data-theme' : 'b','id':'map-header'}).appendTo(mapPage);
$('<h3>').html(weatherData.response.name + ' weather').appendTo(mapHeader);
$('<a>').attr({'href':'#index', 'class' : 'ui-btn-righ'}).html('Back').appendTo(mapHeader);
var mapContent = $('<div>').attr({'data-role':'content'}).appendTo(mapPage);
$('<div>').attr({'id':'map_canvas', 'style':'height:100%'}).appendTo(mapContent);
$.mobile.changePage( "#map", { transition: "slide"});
}
}
var weatherData = {
response : null
}
I don't know how much help this is, perhaps someone else will provide better explanation.
First of all looks like pageinit has been depreciated since jQuery.mobile 1.4.0: https://api.jquerymobile.com/pageinit/ They recommend replacing it with pagecreate
But the problem is obvious: neither pageinit nor pagecreate are firing in IE11. Therefore the button onlcick never gets bound. Not sure if it's IE bug or jsFiddle's...
Simply replacing pageinit with $(document).ready fixed the issue for me.
See fiddle: http://jsfiddle.net/frSsS/54/
Using the NetChart of zoomcharts (1.5.1), it seems that addData() only works for navigation = showall. In case I try using navigation = manual, it requires initialNodes.
Is there a way initialNodes automatically gets populated with existing data (that was added incrementally)? The reason I want that is because, I want to intially load a specific set of nodes/links using navigation = showall and then change it to navigation = manual so that user can click to see all neighbors
Basically, the following example shows this case... node 'f-1' is getting overwritten by initialNodes of 'm-1'.
<script>
var t = new NetChart({
container: document.getElementById("demo"),
area: { height: 350 }
});
t.addData({nodes: [{loaded: true,id: "f-1",name: "Anna"},{id: "m-1",name: "Joe"}],links: [{to: "f-1",from: "m-1",id: "l01",type: "friend"}]});
t.updateSettings({
data:
{
preloadNodeLinks:true,
dataFunction: function(nodeList, success, error){
//return just the first node, net chart will ask for more
jQuery.ajax({
url:"/dvsl/data/net-chart/friend-net/"+nodeList[0]+".json",
success: success,
error: error});
}
},
navigation:{
initialNodes:["m-1"],
mode:"manual"
}
});
</script>
Found a workaround by use of doubleclick:
<script>
var t = new NetChart({
container: document.getElementById("demo"),
area: {
height: 350
},
events:{
onDoubleClick: dclickEvent
}
});
t.addData({nodes: [{loaded: true,id: "f-1",name: "Anna"},{id: "m-1",name: "Joe"}],links: [{to: "f-1",from: "m-1",id: "l01",type: "friend"}]});
function dclickEvent(event){
if (!$("#click")[0].checked) return;
console.log('event.clickNode', event.clickNode);
if (event.clickNode) {
jQuery.ajax({
url: "/dvsl/data/net-chart/friend-net/" + event.clickNode.id + ".json",
success: function(data) {
console.log('test-foo-data', data);
t.addData(data);
}
})
}
}
</script>
In my form I have the tab type Togglable tabs front-end Bootstrap. With each click of the tab, I need to display the maps, which unfortunately are displayed in gray part. The code used:
#Using Ajax.BeginForm("Index", New AjaxOptions() With { _
.UpdateTargetId = "AnswerSN",
.HttpMethod = "POST"
})
#<Script>
init("tab1");
function ChangeDiv(whoDiv) {
if (whoDiv.href.indexOf("#tab1") != -1) {
$(".mezzouno").attr("id", "old-map")
$(".flottauno").attr("id", "basic-map")
clearTimeout(TimeR)
init("tab1");
} else if (whoDiv.href.indexOf('#mezzo1') != -1) {
$(".flottauno").attr("id", "old-map")
$(".mezzouno").attr("id", "basic-map")
clearTimeout(TimeR)
init("mezzo1");
}
}
var TimeR;
function Fleet() {
var updateUrl = '#Url.Action("FleetVb", "Home")';
$.ajax({
url: updateUrl,
success: function (result) {
FleetJs(result);
},
cache: false
});
clearTimeout(TimeR)
TimeR= window.setTimeout("Fleet()", 60000);
}
function Vehicle() {
var updateUrl = '#Url.Action("PointVb", "Home")';
$.ajax({
url: updateUrl,
success: function (result) {
initialize(result);
},
cache: false
});
clearTimeout(TimeR)
TimeR= window.setTimeout("Vehicle()", 60000);
}
function init(whoDiv) {
var myOptions = {
zoom: 8,
center: new google.maps.LatLng(41.895122, 12.481627),
mapTypeId: google.maps.MapTypeId.ROADMAP,
panControl: true,
panControlOptions: {
position: google.maps.ControlPosition.RIGHT_TOP
},
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
streetViewControl: false,
scaleControl: true
};
map = new google.maps.Map(document.getElementById("basic-map"), myOptions);
google.maps.event.trigger(map, 'resize');
if (whoDiv== 'tab1') {
window.setTimeout("ProvaFlotta()", 1000);
} else if (whoDiv== 'mezzo1') {
window.setTimeout("Prova()", 1000);
}
}
</script>
#<div id="AnswerSN" style="position:absolute; top:100px"></div>
End Using
Where do I handle the click of the tab and under it and check the id of the map?
Unfortunately, I get this:
You can bring up the full map and not gray?
enlarging the browser window, the map becomes visible, click on the tab I see the other map with the gray back and widening the window visible.
How do I make it always visible? There seems to be something that goes in conflict ....
Help
Then,
the resize I plugged in the two functions "Fleet()" and "Vehicle()" using another variable of type Boolean, so that the resize is done only once. The calls to these two functions are performed by "init()" with a timer of 200 milliseconds so that the map may not be displayed in gray.
Thank you again.