Raphael JS Dynamic path update not working in IE 11 - raphael

When I try to have a path follow the mouse pointer in IE 11 it wont work, but it works fine in Chrome.
Please see the code here http://jsfiddle.net/3xy3oba2/1/
<body>
<div id="container" onmousemove="move(event)"></div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script>
var paper = Raphael("container", 500, 500);
console.log("Path redraw test");
var arrow = paper.path("M 250, 250, L 0, 0");
arrow.attr('stroke-width', 2);
arrow.attr('stroke', "#0000FF");
arrow.attr('arrow-end', "classic-wide-long");
function move(event)
{
var x = event.layerX;
var y = event.layerY;
var path = "M 250, 250, L " + x + ", " + y;
arrow.attr('path', path);
}
</script>
</body>
Anyone got a idea about what goes wrong?

The work around mentioned above is this. Remove the arrow head, change the path, add the arrow head back.
Update code here: http://jsfiddle.net/7fz5qb7e/2/
Also found the same solution here, https://groups.google.com/forum/#!topic/raphaeljs/m-H63bb7Nsw
Full JS code here:
<body>
<div id="container" onmousemove="move(event)"></div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script>
var paper = Raphael("container", 500, 500);
console.log("Path redraw test");
var arrow = paper.path("M 250, 250, L 0, 0");
arrow.attr('stroke-width', 2);
arrow.attr('stroke', "#0000FF");
arrow.attr('arrow-end', "classic-wide-long");
function move(event)
{
var x = event.offsetX;
var y = event.offsetY;
var path = "M 250, 250, L " + x + ", " + y;
arrow.attr('arrow-end', "");
arrow.attr("path", path);
arrow.attr('arrow-end', "classic-wide-long");
}
</script>
</body>

Related

Search Marker Leaflet Map

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)

Call Django View from D3.js onclick event on Heatmap

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.

Django Localhost is giving an error for my csv file when using it with d3.js

In my Django application I'm creating a csv file. When I try to use that file with a D3.js boilerplate it can't find the csv file?
I've tried moving where the csv file is to the root and into it's own folder but it doesn't do anything different
{% extends "lm_test/base.html" %}
{% block content %}
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
}
.y.axis path {
display: none;
}
.y.axis line {
stroke: #fff;
stroke-opacity: .2;
shape-rendering: crispEdges;
}
.y.axis .zero line {
stroke: #000;
stroke-opacity: 1;
}
.title {
font: 300 78px Helvetica Neue;
fill: #666;
}
.birthyear,
.age {
text-anchor: middle;
}
.birthyear {
fill: #fff;
}
rect {
fill-opacity: .6;
fill: #e377c2;
}
rect:first-child {
fill: #1f77b4;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 40, bottom: 30, left: 20},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
barWidth = Math.floor(width / 19) - 1;
var x = d3.scale.linear()
.range([barWidth / 2, width - barWidth / 2]);
var y = d3.scale.linear()
.range([height, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("right")
.tickSize(-width)
.tickFormat(function(d) { return Math.round(d / 1e6) + "M"; });
// An SVG element with a bottom-right origin.
var svg = d3.select("body").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 + ")");
// A sliding container to hold the bars by birthyear.
var birthyears = svg.append("g")
.attr("class", "birthyears");
// A label for the current year.
var title = svg.append("text")
.attr("class", "title")
.attr("dy", ".71em")
.text(2000);
d3.csv("../temp.csv", function(error, data) {
// Convert strings to numbers.
data.forEach(function(d) {
d.people = +d.people;
d.year = +d.year;
d.age = +d.age;
});
// Compute the extent of the data set in age and years.
var age1 = d3.max(data, function(d) { return d.age; }),
year0 = d3.min(data, function(d) { return d.year; }),
year1 = d3.max(data, function(d) { return d.year; }),
year = year1;
// Update the scale domains.
x.domain([year1 - age1, year1]);
y.domain([0, d3.max(data, function(d) { return d.people; })]);
// Produce a map from year and birthyear to [male, female].
data = d3.nest()
.key(function(d) { return d.year; })
.key(function(d) { return d.year - d.age; })
.rollup(function(v) { return v.map(function(d) { return d.people; }); })
.map(data);
// Add an axis to show the population values.
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ",0)")
.call(yAxis)
.selectAll("g")
.filter(function(value) { return !value; })
.classed("zero", true);
// Add labeled rects for each birthyear (so that no enter or exit is required).
var birthyear = birthyears.selectAll(".birthyear")
.data(d3.range(year0 - age1, year1 + 1, 5))
.enter().append("g")
.attr("class", "birthyear")
.attr("transform", function(birthyear) { return "translate(" + x(birthyear) + ",0)"; });
birthyear.selectAll("rect")
.data(function(birthyear) { return data[year][birthyear] || [0, 0]; })
.enter().append("rect")
.attr("x", -barWidth / 2)
.attr("width", barWidth)
.attr("y", y)
.attr("height", function(value) { return height - y(value); });
// Add labels to show birthyear.
birthyear.append("text")
.attr("y", height - 4)
.text(function(birthyear) { return birthyear; });
// Add labels to show age (separate; not animated).
svg.selectAll(".age")
.data(d3.range(0, age1 + 1, 5))
.enter().append("text")
.attr("class", "age")
.attr("x", function(age) { return x(year - age); })
.attr("y", height + 4)
.attr("dy", ".71em")
.text(function(age) { return age; });
// Allow the arrow keys to change the displayed year.
window.focus();
d3.select(window).on("keydown", function() {
switch (d3.event.keyCode) {
case 37: year = Math.max(year0, year - 10); break;
case 39: year = Math.min(year1, year + 10); break;
}
update();
});
function update() {
if (!(year in data)) return;
title.text(year);
birthyears.transition()
.duration(750)
.attr("transform", "translate(" + (x(year1) - x(year)) + ",0)");
birthyear.selectAll("rect")
.data(function(birthyear) { return data[year][birthyear] || [0, 0]; })
.transition()
.duration(750)
.attr("y", y)
.attr("height", function(value) { return height - y(value); });
}
});
</script>
{% endblock content %}
The view is:
def results(request):
disease = request.GET.get('disease_name')
year_from = int(request.GET.get('year_from'))
year_to = int(request.GET.get('year_to'))
if year_from < year_to:
years = range(year_from, year_to, +1)
else:
years = range(year_from, year_to, -1)
Entrez.email = "chrisgbeldam#gmail.com" #Required by NCBI
results_file = open('temp.csv', 'w') #Open csv file
result_writer = csv.writer(results_file, delimiter=',')
result_writer.writerow(['Year', 'Number Of Results'])
for year in years: #Checks the number of results for each year and then loops
handle = Entrez.esearch(
db="pubmed",
sort="relevance",
term=disease,
mindate=year,
maxdate=year,
retmode="xml",
)
results = Entrez.read(handle)
results_count = results['Count'] # Total number of results for the search
results_yearly = print(f"Number of papers in {year} is {results_count}")
handle.close() #Close E Search
result_writer.writerow([year,results_count]) # Writes out the results to csv file
results_file.close()
context = {
'disease': disease,
'year': year,
'results': results,
'results_count': results_count,
'results_file': results_file,
}
return render(request, 'lm_test/results.html', context)
I expect the outcome to be that D3 can see my temp.csv file but it refuses to and gives me a 'Failed to load resource: the server responded with a status of 404 (Not Found)' error and also a Uncaught TypeError: Cannot read property 'forEach' of undefined
at Object. (?csrfmiddlewaretoken=4I4wgoSynXQX6FyeSsDJWgNnjH6CgQyoZ0U7pvJV0D8vEBRynwYSalwrCZPjtw7v&disease_name=Cancer&year_from=2016&year_to=2000&submit=:117)
at Object.t (d3.v3.min.js:1)
at XMLHttpRequest.i (d3.v3.min.js:1)' error
Seem to work properly after closing and rerunning the virtual environment! Odd

Passing the lat, lng information to the google map script

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;

graphael bar chart with text x-axis

I was wondering how I can make a simple bar chart that perhaps has day as the x-axis, with values 'today' and 'yesterday', and the y-axis as perhaps 'time' with corresponding values '1' and '2'. I guess I'm confused as to how to set text as the values for the x-axis, how to show the y axis, and what exactly r.g.axis does...
(I found an example using axis = r.g.axis(0,300,400,0,500,8,2) and I only know it's the xpos, ypos,width, ??, ?? num ticks, ??). Any insight would be great! Or a page with more fully featured bar chart examples (labels, etc). Thanks.
For the sake of all those googling this:
r.g.axis(x_start, y_start, x_width, from, to, steps, orientation, labels, type, dashsize)
x_start and y_start: distance of the axis text from the bottom left corner
x_width: position of the end of the text along the x axis
from and to: used to specify and range to use instead of using the labels argument
steps: is the number of ticks - 1
orientation: seems to specify x-axis vs. y-axis
type: is the type of tick mark used.
This was all deduced from the source code. I think I'll be switching to a charting library with documentation now...
The current code (Raphaeljs 2.0) has changed and has to be slightly adapted to use Raphael.g.axis instead of r.g.axis:
Raphael.g.axis(85,230,310,null,null,4,2,["Today", "Yesterday",
"Tomorrow", "Future"], "|", 0, r)
You're on the right track. You use g.axis and the positional arguments for setting the text is found in the 'text' arg (positional) and for toggling the y using the 'orientation' args. I added an example here,
Barchart with text x-axis
Reading this Q&A and a dozen like it, I still could not get gRaphaël to show proper labels for a bar chart. The recipes all seemed to refer to older versions of the library, or to github pages that are no longer there. gRaphaël produces some great looking output--but its docs leave much to be desired.
I was, however, able to use a combination of Firebug and Inspect This Element to follow the code and see what it produced. Diving into the barchart object, the required geometry is right there. To save others the frustration, here's how I solved the problem:
<script>
function labelBarChart(r, bc, labels, attrs) {
// Label a bar chart bc that is part of a Raphael object r
// Labels is an array of strings. Attrs is a dictionary
// that provides attributes such as fill (text color)
// and font (text font, font-size, font-weight, etc) for the
// label text.
for (var i = 0; i<bc.bars.length; i++) {
var bar = bc.bars[i];
var gutter_y = bar.w * 0.4;
var label_x = bar.x
var label_y = bar.y + bar.h + gutter_y;
var label_text = labels[i];
var label_attr = { fill: "#2f69bf", font: "16px sans-serif" };
r.text(label_x, label_y, label_text).attr(label_attr);
}
}
// what follows is just setting up a bar chart and calling for labels
// to be applied
window.onload = function () {
var r = Raphael("holder"),
data3 = [25, 20, 13, 32, 15, 5, 6, 10],
txtattr = { font: "24px 'Allerta Stencil', sans-serif", fill: "rgb(105, 136, 39)"};
r.text(250, 10, "A Gratuitous Chart").attr(txtattr);
var bc = r.barchart(10, 10, 500, 400, data3, {
stacked: false,
type: "soft"});
bc.attr({fill: "#2f69bf"});
var x = 1;
labelBarChart(r, bc,
['abc','b','card','d','elph','fun','gurr','ha'],
{ fill: "#2f69bf", font: "16px sans-serif" }
);
};
</script>
<div id="holder"></div>
There are a bunch of little cleanups you could do to labelBarChart(), but this basically gets the job done.
Here's a function I wrote for adding the labels. It's not particularly elegant but it will add the labels:
Raphael.fn.labelBarChart = function(x_start, y_start, width, labels, textAttr) {
var paper = this;
// offset width and x_start for bar chart gutters
x_start += 10;
width -= 20;
var labelWidth = width / labels.length;
// offset x_start to center under each column
x_start += labelWidth / 2;
for ( var i = 0, len = labels.length; i < len; i++ ) {
paper.text( x_start + ( i * labelWidth ), y_start, labels[i] ).attr( textAttr );
}
};
Usage is as follows:
var paper = Raphael(0, 0, 600, 400);
var chart = paper.barchart(0, 0, 600, 380, [[63, 86, 26, 15, 36, 62, 18, 78]]);
var labels = ['Col 1', 'Col 2', 'Col 3', 'Col 4', 'Col 5', 'Col 6', 'Col 7', 'Col 8'];
paper.labelBarChart(0, 390, 600, labels, {'font-size': 14});
I would like to propose a solution of an issue of the labelBarChart function proposed by Jonathan Eunice.
considering stacked bar-graphes (or other bar-graphes with more than one array of values), I added a test on bc.bars[0] in case the bc.bars.length means the number of arrays of values stacked.
This lead to the code :
<script>
function labelBarChart(r, bc, labels, attrs) {
// Label a bar chart bc that is part of a Raphael object r
// Labels is an array of strings. Attrs is a dictionary
// that provides attributes such as fill (text color)
// and font (text font, font-size, font-weight, etc) for the
// label text.
//Added test : replace bc.bars by generic variable barsRef
var barsRef = (typeof bc.bars[0].length === 'undefined') ? bc.bars : bc.bars[0];
var bar, gutter_y, label_x, label_y, label_text;
//Added consideration of set attrs (if set)
var label_attr = (typeof attrs === 'undefined') ? {} : attrs;
label_attr['fill'] = (typeof label_attr['fill'] === 'undefined') ? "#2f69bf" : label_attr['fill'];
label_attr['font'] = (typeof label_attr['font'] === 'undefined') ? "16px sans-serif" : label_attr['font'];
for (var i = 0; i<barsRef.length; i++) {
bar = barsRef[i];
gutter_y = bar.w * 0.4;
label_x = bar.x
label_y = bar.y + bar.h + gutter_y;
label_text = labels[i];
r.text(label_x, label_y, label_text).attr(label_attr);
}
}
// what follows is just setting up a bar chart and calling for labels
// to be applied
// I added an array of data to illustrate : data4
window.onload = function () {
var r = Raphael("holder"),
data3 = [25, 20, 13, 32, 15, 5, 6, 10],
data4 = [0, 2, 1, 40, 1, 65, 46, 11],
txtattr = { font: "24px 'Allerta Stencil', sans-serif", fill: "rgb(105, 136, 39)"};
r.text(250, 10, "A Gratuitous Chart").attr(txtattr);
var bc = r.barchart(10, 10, 500, 400, [data3, data4] {
stacked: true,
type: "soft"});
bc.attr({fill: "#2f69bf"});
labelBarChart(r, bc,
['abc','b','card','d','elph','fun','gurr','ha'],
{ fill: "#2f69bf", font: "16px sans-serif" }
);
};
</script>
<div id="holder"></div>
I just tested it with 2 arrays of values stacked.