I am working on an application with Django. There in this application, I am first using Django to create a database with points and extract a JSON file (It is called "markers.json"). Then, using this JSON file, I am creating markers on a map with Leaflet. When I finished entering all the points to the database they will be around 5000 thousand. So, I decided that it is a good idea to be able to search this markers with an input tag and a search button. I enter the "site_name" as input and when I click the "search" button the related marker should popup. However, always the same marker pops up and I don't know where I am doing wrong.
Could you please help me on that?
HTML PART
<input type="text" id="mast_find" name="mastName" placeholder="Search or masts...">
<button type="submit" id="mast_button">Search</button>
JAVASCRIPT PART
var streets = L.tileLayer( 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap',
subdomains: ['a', 'b', 'c']
}),
esri = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
}),
topo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
maxZoom: 17,
attribution: 'Map data: © OpenStreetMap, SRTM | Map style: © OpenTopoMap (CC-BY-SA)'
});
var map = L.map( 'map', {
center: [20.0, 5.0],
minZoom: 2,
zoom: 2,
layers: [streets, esri, topo]
})
var baseMaps = {
"Streets": streets,
"Esri": esri,
"Topo": topo
};
$('.leaflet-control-attribution').hide()
L.control.scale().addTo(map);
L.control.layers(baseMaps).addTo(map);
var myURL = jQuery( 'script[src$="leaf.js"]' ).attr( 'src' ).replace( 'leaf.js', '' )
var myIcon = L.icon({
iconUrl: myURL + '/images/pin24.png',
iconRetinaUrl: myURL + '/images/pin48.png',
iconSize: [29, 24],
iconAnchor: [9, 21],
popupAnchor: [0, -14]
})
for ( var i=0; i < markers.length; ++i )
{
var deneme = [];
var meleme = L.marker( [markers[i].fields.latitude, markers[i].fields.longitude], {icon: myIcon} )
.bindPopup( "<b>" + "Mast name: " + "</b>" + markers[i].fields.site_name + "<b>" + "<br>" + "A: " + "</b>" + markers[i].fields.a_measured_height_lt + "<br>" + "<b>" + "k: " + "</b>" + markers[i].fields.k_measured_height_lt )
.addTo( map );
deneme.push(meleme);
document.getElementById("mast_button").onclick = mastFunct;
function mastFunct(){
var data = document.getElementById("mast_find");
for (var i=0; i < markers.length; ++i ){
var markerID = markers[i].fields.site_name;
if (markerID = data.value){
deneme[i].openPopup()
}
}
};
if (markerID = data.value){
should be
if (markerID == data.value){
the only issue that i see is this with the if (markerID = data.value){.
But you can try this alternative:
instead your for-loop:
map.eachLayer(function(marker){
if(marker.options){
var markerID = marker.options.site_name;
if (markerID == data.value){
marker.openPopup();
}
}
});
and add this to your marker creation:
L.marker([51.493782, -0.089951],{icon: myIcon, site_name: 'test'}).addTo(map)
Related
(I am a new developer)I have a list that I put in a viewBag to make a dropwdown in my view and I would like to add 3 elements to this list so that we can see them at the end of my dropdown. I make a timesheet for the employees and I have a dropdown of the projects that the person worked during the week and I would like to add at the end of the dropdown the 3 options "Vacancy", "Unplanned Absence", "Planned Absence" if the person has been on leave instead of working.
This is my request for the projects :
var projectAssignment = (from pa in db.ProjectAssignment
join p in db.Projects on pa.ProjectId equals p.ID
where pa.EmployeeId == EmployeeId && pa.StartDate !=null && (pa.EndDate == null || pa.EndDate >= DateTime.Now)
select new ProjectTimesheetList
{
ProjectName = p.ProjectName,
ProjectId = pa.ProjectId
});
ViewBag.ProjectTimeSHeet = projectAssignment;
This is a the modal to add my timehseet and i want to put the 3 daysoff type at the end of dropdown, so in this case after "NatureBooker"
And this is my code of my dropdown:
<select name="' + row + '_' + col + '" class="custom-select" id="tsCell_' + row + '_' + col + '" data-row="' + row + '" data-col="' + col + '">' +
'<option value="">----Select----</option>#Html.Raw(projsStr)</select>';
SOLUTION:
var projectAssignment = (from pa in db.ProjectAssignment
join p in db.Projects on pa.ProjectId equals p.ID
where pa.EmployeeId == EmployeeId && pa.StartDate !=null && (pa.EndDate == null || pa.EndDate >= DateTime.Now)
select new ProjectTimesheetList
{
ProjectName = p.ProjectName,
ProjectId = pa.ProjectId
});
List<ProjectTimesheetList> projectAssignments = projectAssignment.ToList();
projectAssignments.Add(new ProjectTimesheetList
{
ProjectName = "Vacancy",
ProjectId = -1,
});
projectAssignments.Add(new ProjectTimesheetList
{
ProjectName = "Unplanned Absence",
ProjectId = -2,
});
projectAssignments.Add(new ProjectTimesheetList
{
ProjectName = "Planned Absence",
ProjectId = -3,
});
ViewBag.ProjectTimeSHeet = projectAssignments;
And the result:
Still not clear what exactly you want, but if my guess is right you probably want to add "fake" projects to the enumerable you're binding to (not a list, by the way).
As long as you understand that this is absolutely wrong and grounds for being fired on the spot, here you go:
ViewBag.ProjectTimeSHeet = projectAssignment
.Concat(new[]
{
new ProjectTimesheetList
{
ProjectName = "Vacancy",
ProjectId = -1,
},
new ProjectTimesheetList
{
ProjectName = "Unplanned Absence",
ProjectId = -2,
},
new ProjectTimesheetList
{
ProjectName = "Planned Absence",
ProjectId = -3,
},
});
var myOptions = {
val1 : 'Vacancy',
val2 : 'Unplanned Absence',
val3 : 'Planned Absence',
};
var mySelect = $('#dropdownID');
$.each(myOptions, function(val, text) {
mySelect.append(
$('<option></option>').val(val).html(text)
);
});
through Javascript
var ddl = document.getElementById("dropdownID");
for ( let key in myOptions )
{
var option = document.createElement("OPTION");
option.innerHTML = key
option.value = myOptions[key]
ddl.options.add(option);
}
Is there a way to invoke a Django view and pass it a parameter(s) from a D3.js onclick event handler associated with a heatmap? For my heatmap, I'm using the code found at the following:
https://www.d3-graph-gallery.com/graph/heatmap_style.html
Any help would be greatly appreciated. Thanks.
This is javascript code, which makes HTTP request when click on rectangle. Use jquery library (I am using here, in this example $.ajax({}) is jQuery's function). You can use Javascript's XMLHttpRequest class also, to make AJAX call. You should just pass correct URL of Django's view. Also, use GET request for testing purposes to avoid CSRF Features of Django.
<script>
// set the dimensions and margins of the graph
var margin = {top: 80, right: 25, bottom: 30, left: 40},
width = 450 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/heatmap_data.csv", function(data) {
// Labels of row and columns -> unique identifier of the column called 'group' and 'variable'
var myGroups = d3.map(data, function(d){return d.group;}).keys()
var myVars = d3.map(data, function(d){return d.variable;}).keys()
// Build X scales and axis:
var x = d3.scaleBand()
.range([ 0, width ])
.domain(myGroups)
.padding(0.05);
svg.append("g")
.style("font-size", 15)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSize(0))
.select(".domain").remove()
// Build Y scales and axis:
var y = d3.scaleBand()
.range([ height, 0 ])
.domain(myVars)
.padding(0.05);
svg.append("g")
.style("font-size", 15)
.call(d3.axisLeft(y).tickSize(0))
.select(".domain").remove()
// Build color scale
var myColor = d3.scaleSequential()
.interpolator(d3.interpolateInferno)
.domain([1,100])
// create a tooltip
var tooltip = d3.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
// Three function that change the tooltip when user hover / move / leave a cell
var mouseover = function(d) {
tooltip
.style("opacity", 1)
d3.select(this)
.style("stroke", "black")
.style("opacity", 1)
}
var mousemove = function(d) {
tooltip
.html("The exact value of<br>this cell is: " + d.value)
.style("left", (d3.mouse(this)[0]+70) + "px")
.style("top", (d3.mouse(this)[1]) + "px")
}
var mouseleave = function(d) {
tooltip
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 0.8)
}
// add the squares
svg.selectAll()
.data(data, function(d) {return d.group+':'+d.variable;})
.enter()
.append("rect")
.attr("x", function(d) { return x(d.group) })
.attr("y", function(d) { return y(d.variable) })
.attr("rx", 4)
.attr("ry", 4)
.attr("width", x.bandwidth() )
.attr("height", y.bandwidth() )
.style("fill", function(d) { return myColor(d.value)} )
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
.on("click", function(arg1, arg2, arg3) {
console.log('clicked !!!');
// make AJAX call now !
$.ajax({
type: 'GET',
url: '<DJANGO_VIEW_URL_HERE>',
data: {'key1': 'val1', 'key2': 'val2'},
success: function(data) {
console.log('server returned status code 200');
},
error: function() {
console.log('problem on server during processing');
}
});
})
})
// Add title to graph
svg.append("text")
.attr("x", 0)
.attr("y", -50)
.attr("text-anchor", "left")
.style("font-size", "22px")
.text("A d3.js heatmap");
// Add subtitle to graph
svg.append("text")
.attr("x", 0)
.attr("y", -20)
.attr("text-anchor", "left")
.style("font-size", "14px")
.style("fill", "grey")
.style("max-width", 400)
.text("A short description of the take-away message of this chart.");
</script>
Good luck.
I'm working on a project using Angular 5 and Chart.js.
I needed to create custom legends into my charts so I follow this git issue to help me a bit: Github Issue Chart.js.
It was very helpful and It worked as expected only with pure javascript, but trying to reply the example into Angular 5 App just doesn't work, it throws me this.updateDataset() is not a function.
Here is a snippet of what I'm currently doing into the options object of Chart.js library:
legendCallback: (chart) => {
const legendHtml = [];
legendHtml.push('<table>');
legendHtml.push('<tr>');
for (let i=0; i<chart.data.datasets.length; i++) {
const color = chart.data.datasets[i].borderColor;
const legendId = 'linear-d'+i;
legendHtml.push(
'<td onclick="this.updateDataset(event,' + '\'' + chart.legend.legendItems[i].datasetIndex + '\'' + ', ' + '\'' + legendId + '\'' + ')">' +
'<div id="'+legendId+'-square" style="background-color:' + color +'; border: 2px solid ' + color +'; width: 15px; height: 15px;"></div>' +
'</td>'
);
if (chart.data.datasets[i].label) {
legendHtml.push('<td id="'+legendId+'-text" style="cursor: default; font-size: 12px;" onclick="this.updateDataset(event,' + '\'' + chart.legend.legendItems[i].datasetIndex + '\'' + ', ' + '\'' + legendId + '\'' + ')">' + chart.data.datasets[i].label + '</td>');
}
}
legendHtml.push('</tr>');
legendHtml.push('</table>');
return legendHtml.join("");
},
So the important part is this one '<td onclick="this.updateDataset(event,' + '\'' + chart.legend.legendItems[i].datasetIndex + '\'' + ', ' + '\'' + legendId + '\'' + ')">' where the onclick is trying to call this.updateDataset().
How should I call the function updateDataset() into the onclick event of the element or how should I declare the function so I could access to it from the onclick event.
It's not a neat solution but it's the only one I found so far.
Instead of using the onclick event I added an eventListener after adding the new legend. Then you need to do minor changes to the updateDataset() function.
The legendCallback should look something like this:
legendCallback: (chart) => {
var legendHtml = [];
legendHtml.push('<table>');
legendHtml.push('<tr>');
for (var i=0; i<chart.data.datasets.length; i++) {
legendHtml.push('<td><div class="chart-legend" style="background-color:' + chart.data.datasets[i].backgroundColor + '"></div></td>');
if (chart.data.datasets[i].label) {
legendHtml.push('<td class="chart-legend-label-text" id="' + chart.id + '_' + chart.legend.legendItems[i].datasetIndex + '">' + chart.data.datasets[i].label + '</td>');
}
}
legendHtml.push('</tr>');
legendHtml.push('</table>');
return legendHtml.join("");
},
And then add the listener and the updateDataset() function after the declaration of the Chart:
document.getElementById("customLegend" + this.chartId).innerHTML = myChart.generateLegend();
var legenTags = document.getElementsByClassName("chart-legend-label-text");
var updateDataset = function(e) {
var id = e.currentTarget.id;
var index = id.split('_')[1];
var chartId= id.split('_')[0];
if (myChart.id == chartId) {
var meta = myChart.getDatasetMeta(index);
// See controller.isDatasetVisible comment
meta.hidden = meta.hidden === null? !myChart.data.datasets[index].hidden : null;
// We hid a dataset ... rerender the chart
myChart.update();
}
}
for (var i = 0; i < legenTags.length; i++) {
legenTags[i].addEventListener('click', updateDataset, false);
}
I hope it helps.
If anyone has a better solution please share.
I've have an index.html file that includes a gogglemap.js file to display a map of users location. Currently I am attempting to add the proper code to the index.html to pass the lat, lng info to the js file.
Here is filler content for the index file to show what I am attempting to do:
<h3><display user city></h3> <---- this needs to display users city and has filler text to show what I am trying to accomplish.
<div id="map"></div>
<script>var lat=12.356;var lng=-19.31;var country="User Country";var city="User City";</script> <----- seems like it is getting the lat/lng somehow before the index page loads and inserting this script into the index file?
Here is the js file code:
var styles = [{yourcustomstyle}]
var myLatlng = { lat: lat, lng: lng };
function initialize() {
var mapOptions = {
zoom: 12,
center: myLatlng,
styles: styles,
panControl: false,
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false
};
var map = new google.maps.Map( document.getElementById('map'), mapOptions );
for (var a = 0; a < 6; a++) {
c = Math.random();
c = c * (0 == 1E6 * c % 2 ? 1 : -1);
d = Math.random()
d = d * (0 == 1E6 * d % 2 ? 1 : -1);
c = new google.maps.LatLng( lat + 0.08 * c + 0.052, lng + 0.2 * d + 0.08),
marker = new google.maps.Marker({
map: map,
position: c,
icon: 'marker.png'
});
}
}
function loadScript() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&callback=initialize';
document.body.appendChild( script );
}
window.onload = loadScript;
I'm trying to build a countdown with Famous Timer.
As a first step, I want to make a scrolling digit, so I made 3 digits which are doing the needed animation and now I need to show only the middle one.
I saw the clipSize option, but couldn't understand how to use it.
If there are some other way to do it, that's great too.
My app is here: http://slexy.org/view/s2R8VNhgEO
Thanks, Alex A.
Rather than fix your code, I wrote an example of how you can create the effect you are looking for with the Lightbox render controller and clipping the view to only show the current count down index. Of course, this can be improved as needed.
Example of the working code in jsBin: Just click to start the counter.
Main Context
var mainContext = Engine.createContext();
var cview = new CountdownView({
start: 10,
size: [50, 50]
});
var counter = 0;
var started = false;
var funcRef;
cview.on('click', function () {
if (started) {
Timer.clear(funcRef);
started = false;
} else {
started = true;
funcRef = Timer.setInterval(function(){
console.log('setNext ' + cview.nextIndex);
cview.setNext();
},1000);
}
});
var container = new ContainerSurface({
size: [100, 100],
properties: {
overflow: 'hidden'
}
});
container.add(cview);
mainContext.add(container);
CountdownView
function CountdownView(options) {
View.apply(this, arguments);
this.options.start = options.start || 10;
this.surfaces = [];
for (var i = 0; i <= this.options.start; i++) {
var surface = new Surface({
size: this.options.size,
content: i.toString(),
properties: {
backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
lineHeight: this.options.size[1]+"px",
textAlign: "center",
fontSize: "30px",
cursor:'pointer'
}
});
this.surfaces.push(surface);
surface.pipe(this._eventOutput);
}
this.renderer = new Lightbox({
inOpacity: 0,
outOpacity: 0,
inOrigin: [1, 1],
inAlign: [1, 1],
showOrigin: [0, 0],
inTransform: Transform.translate(0,0,0.0002),
outTransform: Transform.translate(0,this.options.size[1],0.0001),
outOrigin: [1,1],
outAlign: [1,1],
inTransition: { duration: 600, curve: Easing.inCirc },
outTransition: { duration: 1000, curve: Easing.outCirc },
overlap: true
});
this.add(this.renderer);
this.renderer.show(this.surfaces[this.options.start]);
this.nextIndex = this.options.start - 1;
}
CountdownView.prototype = Object.create(View.prototype);
CountdownView.prototype.constructor = CountdownView;
CountdownView.prototype.setNext = function setNext() {
this.renderer.show(this.surfaces[this.nextIndex]);
this.nextIndex = (this.nextIndex -1 < 0) ? this.options.start : this.nextIndex - 1;
};
CountdownView.prototype.setIndex = function setIndex(newIndex) {
if (newIndex < 0 || newIndex > this.countStart) return;
this.renderer.show(this.surfaces[newIndex]);
};
CountdownView.prototype.getLength = function getLength() {
return this.surfaces.length;
};