Clear GeoJSON layer every time function is called - javascript

The function getCountryBorders() updates the map by drawing the desired country border every time the function is run. However, it just adds each country border to the current layer, rather than replacing the old border.
How can I clear the current layer each time the function is called?
const getCountryBorders = function() {
$.ajax({
url: "libs/php/getCountryBorders.php",
type: 'POST',
dataType: 'json',
success: function(result) {
const countries = result["data"]["features"];
function countryFilter(feature) {
if (feature.properties.iso_a2 === countryCode) return true
}
const borderStyle = {
"color": "red"
}
borderLayer = L.geoJson(countries, {
filter: countryFilter,
style: borderStyle
}).addTo(map);
},
error: function(jqXHR, textStatus, errorThrown) {
}
})
}

Since your borderLayer is in global scope, a very easy solution is to remove it from the map just before reassigning it:
if (borderLayer) {
borderLayer.remove();
}
borderLayer = L.geoJson(countries).addTo(map);

Related

Not able to set javascript variable back to null after defining it

I want to set the variable selectedColumnIndex back to null after using it each time.
I need to be able to check that a new selectedColumnIndex value has been set after each use. It could be used once or dozens of times in a row (it's for "cut and insert" functionality in a table-style UI component).
If I put a browser breakpoint at the variable var check, selectedColumnIndex will show as null. But then if $(document).on('click', '.columnUpdatesInsert', function () { } runs again without $(document).on('click', '.columnUpdates', function () { } ever running, selectedColumnIndex will be back to the previous value.
var selectedColumnIndex = null;
$(document).on('click', '.columnUpdates', function () {
selectedColumnIndex = $(this).attr("data-columnindex");
});
$(document).on('click', '.columnUpdatesInsert', function () {
if (selectedColumnIndex != null) {
// get variables from click element etc.
$(updateColumnPosition(tableId, selectedColumnIndex, newColumnIndex));
}
else {
alert("No column was selected to move.");
}
});
function updateColumnPosition(tableId, selectedColumnIndex, newColumnIndex) {
$.ajax({
type: "POST",
url: "/Task/UpdateColumnIndex",
data: { projectId: _projectId, tableId: tableId, selectedColumnIndex: selectedColumnIndex, newColumnIndex: newColumnIndex },
dataType: 'json',
success: function (data) {
if (data.success) {
// do other unrelated work
selectedColumnIndex = null; // this successfully sets it to null, but it is getting set back to the previous value before this code is explicitly setting it again.
var check = 0;
}
else {
// handle error
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status + " " + thrownError);
},
});
}
Probably because you are passing selectedColumnIndex as an arg to the function it becomes a local to that function.
Try not passing the value selectedColumnIndex as arg and use it as global all the time.
var selectedColumnIndex = null;
$(document).on('click', '.columnUpdates', function () {
selectedColumnIndex = $(this).attr("data-columnindex");
});
$(document).on('click', '.columnUpdatesInsert', function () {
if (selectedColumnIndex != null) {
// get variables from click element etc.
$(updateColumnPosition(tableId, newColumnIndex));
}
else {
alert("No column was selected to move.");
}
});
function updateColumnPosition(tableId, newColumnIndex) {
$.ajax({
type: "POST",
url: "/Task/UpdateColumnIndex",
data: { projectId: _projectId, tableId: tableId, selectedColumnIndex: selectedColumnIndex, newColumnIndex: newColumnIndex },
dataType: 'json',
success: function (data) {
if (data.success) {
// do other unrelated work
selectedColumnIndex = null; // this successfully sets it to null, but it is getting set back to the previous value before this code is explicitly setting it again.
var check = 0;
}
else {
// handle error
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status + " " + thrownError);
},
});
}

Updating only those properties are changed

I am plotting LineStrings in Mapbox.So now I am updating the color of the lines when the property is changed.
function update_the_map(){
$.ajax({
url:"http://dataurl",
contentType : "application/json; charset=utf-8",
type: "GET",
dataformat:"JSON",
async : false,
success: function(data){
for (i = 0; i <lines.features.length; i++) {
lines['features'][i]['properties']['points']=data[i].points;
var style_update =getColor( lines['features'][i]['properties']['points']);
geojson.setFeatureStyle(lines['features'][i]['properties']['id'], style_update);
}
setTimeout( update_the_map, 10000);
console.log("updated");
},
error:function(){}
});
}
But this changes all the color of the lines and not those points are greater than 5.Because my get color function is like
function getColor(d) {
if(d==10 || d==9 || d==8 || d==7 || d==6){
return '#ff0000';
}
else {
return '#00a1ff';
}
}
So it returns red if points>5 else it returns blue.But this returns blue for everything and the whole lines color is changed.ANy help is appreciated.This is how i create the layer.
geojson = L.vectorGrid.slicer(lines, {
vectorTileLayerStyles: {
sliced: style},
maxZoom: 24, // max zoom to preserve detail on
interactive: true,
getFeatureId: function(f) {
return f.properties.id;
}
}).on('mouseover', mouseover_function).addTo(map);
My lines is a variable as below :
var lines= {
"type":"FeatureCollection","features": [{"type": "Feature","geometry":{"type":"LineString",
"coordinates":[[ 101.942139,4.252606],[101.766357,3.134346]]},
"properties": {"id":"01","points":10}},....
]};
Can you show that what is inside the line.features array OR check the value of d in console, passed to getColor function.
The following did make the update work like a charm. So insteading of passing only the color I passed the weight and opacity and color It worked fine.
function update_the_map(){
$.ajax({
url:"http://dataurl",
contentType : "application/json; charset=utf-8",
type: "GET",
dataformat:"JSON",
async : false,
success: function(data){
var style_update; //changed declaration here
for (i = 0; i <lines.features.length; i++) {
lines['features'][i]['properties']['points']=data[i].points;
style_update = {
weight: 2,
opacity: 1,
color: getColor(links['features'][i]['properties']['score']),
fillOpacity: 0.7
};//added this whole for variable style update
geojson.setFeatureStyle(links['features'][i]['properties']['id'],style_update);
}
setTimeout( update_the_map, 10000);
console.log("updated");
},
error:function(){}
});
}

how to transform function to setTimeout

I'm using setInterval for now, but wish to use setTimeout.
$.when(
data['layout'] = "getMessages",
data['limit'] = limit,
fetchMsg(data,'[data-messages]',{"background-color":"#fff"})
).then(
setInterval(function(){
data['lastupdate'] = localStorage.lastupdate;
data['layout'] = "getNewMessages",
fetchMsg(data, '[data-body-new]',{"background-color":"#b4eeb4"});
}, 1000)
);
//the function
function fetchMsg(info, container, messageStyle){
$.ajax({
method: "POST",
url: window.root+"/index.php",
"data": info,
error: function() {
alert('error');
},
success: function(result) {
..........
}
});
I tried below but it doesn't work:
setTimeout(function(){
data['lastupdate'] = localStorage.lastupdate;
data['layout'] = "getNewMessages",
fetchMsg(data, '[data-body-new]',{"background-color":"#b4eeb4"});
}, 1000)
//the function
function fetchMsg(info, container, messageStyle){
$.ajax({
method: "POST",
url: window.root+"/index.php",
"data": info,
error: function() {
alert('error');
},
success: function(result) {
..........
},
complete:fetchMsg
});
I won't fix your code for you but here is a basic idea of going from an interval to a setTimeout.
Firstly, make your 'interval' equal to a variable.
var init = setInterval(doFunc,1000);
Later when you want to make the change:
clearInterval(init);
and then to set Timeout just do:
setTimeout(doFunc);
And thats basically it.

How to combine multiple call to Ajax Data base from different JS files

I have some code on a file that makes Ajax calls. This file is being called as a function by multiple other files that creates a new instance each time.
This is the JS code that is being called:
define(["underscore", "homeop", "domReady!"],
function (_, homeop, domready) {
var timeout = 500;
return function (opUrl, opList, onCallback) {
// IRRELEVANT CODE
var getFetch = function (optionName) {
$.ajax({
url: optionsUrl,
data: { optionNames: [optionName] },
type: "POST",
dataType: "json",
async: false,
traditional: true,
success: function (data) {
_.each(data, function (optionData, optionName) {
if (homeop.globalCache[optionName] === null) {
homeop.globalCache[optionName] = optionData;
}
});
},
error: function (message) {
console.error(message.responseText);
}
});
};
self.getInfo = function (optionName) {
if (homeop.globalCache[optionName] === undefined) {
if (!_.contains(homeop.getOption(), optionName)) {
getFetch(optionName);
}
// MORE IRRELEVANT CODE GOES HERE
In other JS files, I call the get function; for example
var these = new getOptions(optionsUrl, optionsList, onLoadCallback);
var getOpt = these.get(OptionsUrl);
The problem is I am making multiple calls to the get information from the database causing multiple call to my JS file. Each new instance of the JS file will create a ajax call.
Is there a way to wait for all the calls to be done and then get data from the database? In other words how can I somehow combine all the call to my 'getOption.js'?
Thanks
Try this.. You can also implement queue in place of stack
var optionStack = [];
var isAvailable = true;
var getFetch = function (optionName) {
if(isAvailable){
isAvilable = false; // function not available now
}
else {
optionStack.push(optionName)
return;
}
$.ajax({
url: optionsUrl,
data: { optionNames: [optionName] },
type: "POST",
dataType: "json",
async: false,
traditional: true,
success: function (data) {
_.each(data, function (optionData, optionName) {
if (homeop.globalCache[optionName] === null) {
homeop.globalCache[optionName] = optionData;
}
});
},
error: function (message) {
console.error(message.responseText);
},
done: function (){
isAvailable = true;
if(optionStack.length > 0){
getFetch(optionStack.pop());
}
}
});
};

React State Change Not Causing component to Re-Render

I'm still new to ReactJS, and I've run into a bit of a snag. I'm trying to implement pagination in a React component; however, even though my pagination function is being called successfully the state change is not causing the component to Render again.
I'm using one function to get the initial data (getMainFeed) and then a second one (getMoreItems) for the pagination. The second function is called by my 'handleScroll' function. Interestingly enough, when I replace the 'getMoreItems' function with the 'getMainFeed' function, the state change causes the component to render the additional data perfectly. Unfortunately I need to hit these two separate APIs and I don't think it would be in good form to combine the two calls into one function. So is there a way that I can get 'getMoreItems' to render the new items to the screen?
var data = [];
var GridView = React.createClass({
getInitialState: function() {
window.addEventListener("scroll", this.handleScroll);
return {
data: [],
page: 0, //for pagination
loadingFlag: false,
};
},
getMainFeed: function() {
var nextPage = 1; //increase the page count
ajax_url = "http://127.0.0.1:8200/api/content/main/";
ajax_type = "GET";
ajax_data = {
'BatchCount': "20"
};
$.ajax({
url: ajax_url,
type: ajax_type,
contentType: 'application/x-www-form-urlencoded',
data: ajax_data,
dataType: 'json',
success: function(data) {
this.setState({
data: data,
loadingFlag:false,
page: 2
});
//loading("off");
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
}, //end function
getMoreItems: function() {
var nextPage = this.state.page+1; //increase the page count
ajax_url = "http://127.0.0.1:8200/api/content/page/1/";
ajax_type = "GET";
ajax_data = {
'BatchCount': "20"
};
$.ajax({
url: ajax_url,
type: ajax_type,
contentType: 'application/x-www-form-urlencoded',
data: ajax_data,
dataType: 'json',
success: function(data) {
this.setState({
data: data,
loadingFlag:false,
page: nextPage
});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
}, //end function
componentDidMount: function() {
//loading("on");
this.getMainFeed();
},
handleScroll:function(e){
//this function will be triggered if user scrolls
var windowHeight = $(window).height();
var inHeight = window.innerHeight;
var scrollT = $(window).scrollTop();
var totalScrolled = scrollT+inHeight;
if(totalScrolled+1200>windowHeight){ //user reached at bottom
if(!this.state.loadingFlag){ //to avoid multiple request
this.setState({
loadingFlag:true,
});
//loading("on");
this.getMoreItems();
}
}
},
componentDidUpdate: function() {
$('#grid-container').imagesLoaded( function() {
MasonryInit();
});
},
render: function() {
return (
<div id="feed-container-inner">
<GridMain data={this.state.data} />
</div>
);
}
});
When the state change it will re-render. Also you saw that it was working with your getmainfeed function.
So I think that your getmoreitems function just do not success. Have you verified that this call succeed ?
The problems turns out to be that I wasn't concatenating the data to the end of the existing data like so data: this.state.data.concat(data),.
This surprises me, because I would have expected the getMoreItems function to simply replace the existing data.

Categories