Leaflet map with embedded Bootstrap Switch toggle - javascript

I am trying to add a bootstrap switch inside my leaflet.js map.
So far I have a working button (see snippet) but I want to use a switch instead.
See attached image:
So far it is a complete failure.
Among the things I have tried is the code below (which obviously does not work):
var customControl_2 = L.Control.extend({
options: {
position: 'topright'
},
onAdd: function (map) {
var container = L.DomUtil.create('input', 'mySwitch');
container = $("[class='mySwitch']").bootstrapSwitch({})
//container.onclick = function(){
// console.log('buttonClicked');
//}
return container;
}
});
map.addControl(new customControl_2());
Does anyone know how this should work please? As always, any help is greatly appreciated. If the same toggle switch can be achieved in some other way (ie without bootstrap) that is also going to be fine.
Many thanks!
<!DOCTYPE html>
<html>
<head>
<title>Leaflet</title>
<meta charset="utf-8" />
<!--jquery -->
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<!-- bootstrap switch -->
<link rel="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/css/bootstrap3/bootstrap-switch.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/js/bootstrap-switch.js"></script>
<!--d3 -->
<script src='https://d3js.org/d3.v4.min.js'></script>
<!-- leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet.js"></script>
<style>
html,
body {
height: 100%;
margin: 0;
}
#map {
width: 600px;
height: 400px;
}
</style>
</head>
<body>
<div id='map'></div>
<script type="text/javascript">
var map = L.map('map', {
minZoom: 0,
}).setView([37, -103], 3);
var positron = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
attribution: "CartoDB"
}).addTo(map);
// Toggle button to turn layers on and off
var customControl = L.Control.extend({
options: {
position: 'topright'
},
onAdd: function(map) {
var container = L.DomUtil.create('input');
container.type = "button";
container.title = "Some title";
container.value = "Off";
container.style.backgroundColor = 'white';
container.style.backgroundSize = "80px 30px";
container.style.width = '80px';
container.style.height = '30px';
function toggle(button) {
if (button.value == "Off") {
button.value = "On"
button.innerHTML = "On"
removeLayers();
} else if (button.value == "On") {
button.value = "Off"
button.innerHTML = "Off"
addLayers();
}
}
container.onclick = function() {
toggle(this);
console.log('buttonClicked');
}
return container;
}
});
map.addControl(new customControl());
</script>
</body>
</html>

The $("[class='mySwitch']") finds Elements based on the string selector. You have to adjust the Bootstrap Switch example to your usage. In your case, you do not need a selector but you can directly pass the HTML Element you created, so that it is wrapped by jQuery and can be transformed by Bootstrap Switch: $(container).bootstrapSwitch({})
Do not try to transform your Control container directly, but embed a child checkbox input into that container:
var container = L.DomUtil.create('div');
// Use a child input.
var input = L.DomUtil.create('input');
input.type = "checkbox";
// Insert the input as child of container.
container.appendChild(input);
// Transform the input, not the container.
$(input).bootstrapSwitch({});
You have a typo in:
<link rel="https:....css">
…should be:
<link rel="stylesheet" href="https:....css">
Live result:
var map = L.map('map', {
minZoom: 0,
}).setView([37, -103], 3);
var positron = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
attribution: "CartoDB"
}).addTo(map);
// Toggle button to turn layers on and off
var customControl = L.Control.extend({
options: {
position: 'topright'
},
onAdd: function(map) {
var container = L.DomUtil.create('div');
// Use a child input.
var input = L.DomUtil.create('input');
input.type = "checkbox";
input.title = "Some title";
input.value = "Off";
// Insert the input as child of container.
container.appendChild(input);
jQuery(input).bootstrapSwitch({
// http://bootstrapswitch.site/options.html
onSwitchChange: function(event) {
console.log('buttonClicked', event.target.checked);
}
});
return container;
}
});
map.addControl(new customControl());
html,
body,
#map {
height: 100%;
margin: 0;
}
<!--jquery -->
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!--script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script-->
<!-- bootstrap switch -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/css/bootstrap3/bootstrap-switch.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/js/bootstrap-switch.js"></script>
<!-- leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet.js"></script>
<div id='map'></div>

Related

Extending leaflet SVG renderer fails to show vector layers

I am working on modifying the Leaflet SVG renderer for some cosmetic changes, but I have not been able to get even the most basic extension to work (even without any custom code aside from changing things like create() to L.DomUtil.create()).
here is my most simple example setup:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>
<style>
body{
padding: 0;
margin: 0;
}
#mapid{
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div id="mapid" style=""></div>
<script>
L.SVG.test = L.SVG.extend({
_initPath: function(layer){
const path = layer._path = L.DomUtil.create('path');
// #namespace Path
// #option className: String = null
// Custom class name set on an element. Only for SVG renderer.
if(layer.options.className){
path.classList.add(...L.Util.splitWords(layer.options.className));
}
if(layer.options.interactive){
path.classList.add('leaflet-interactive');
}
this._updateStyle(layer);
this._layers[L.Util.stamp(layer)] = layer;
},
_updateStyle: function(layer){
const path = layer._path,
options = layer.options;
if(!path){
return;
}
if(options.stroke){
path.setAttribute('stroke', options.color);
path.setAttribute('stroke-opacity', options.opacity);
path.setAttribute('stroke-width', options.weight);
path.setAttribute('stroke-linecap', options.lineCap);
path.setAttribute('stroke-linejoin', options.lineJoin);
if(options.dashArray){
path.setAttribute('stroke-dasharray', options.dashArray);
} else {
path.removeAttribute('stroke-dasharray');
}
if(options.dashOffset){
path.setAttribute('stroke-dashoffset', options.dashOffset);
} else {
path.removeAttribute('stroke-dashoffset');
}
} else {
path.setAttribute('stroke', 'none');
}
if(options.fill){
path.setAttribute('fill', options.fillColor || options.color);
path.setAttribute('fill-opacity', options.fillOpacity);
path.setAttribute('fill-rule', options.fillRule || 'evenodd');
} else {
path.setAttribute('fill', 'none');
}
}
});
var testRenderer = new L.SVG.test();
var map = L.map('mapid', {preferCanvas: false, renderer: testRenderer}).setView([51.505, -0.09], 13);
var tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
L.marker([51.5, -0.09]).addTo(map)
.bindPopup("<b>Hello world!</b><br />I am a popup.");
L.polygon([
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047]
], {fillOpacity: 0.5}).addTo(map).bindPopup("I am a polygon.");
L.circle([51.508, -0.11], 500, {fillOpacity: 0.5}).addTo(map).bindPopup("I am a circle.");
</script>
</body>
</html>
It does not throw any errors in the console and I really don't know where to go from here.
Inspecting the dom shows that the layers exist in the svg tag and that they have coordinates, but the g element does not seem to have any height.
what am I doing wrong?

How to detect overlap in Phaser.js?

I am new to Phaserjs, and I am trying to make a shooting game. I want the damage function to fire when a bullet touches plane2, that is the green plane. Can somone please tell me what am I doing wrong here?
Here is my code:
var config = {
type: Phaser.AUTO,
width: 800,
height: 800,
parent:"game",
physics: {
default: 'arcade',
arcade: {
debugging:true,
gravity: {y: 0}
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var plane1
var plane2
var hp;
var botHp;
function preload (){
this.load.setBaseURL('https://shoot.abaanshanid.repl.co/assets');
this.load.image("bg", "bg.jpg");
this.load.image("plane1", "plane1.png");
this.load.image("plane2", "plane2.png");
this.load.image("bullet", "bullet.png");
}
function create (){
this.background = this.add.image(400, 400, "bg");
plane1 = this.physics.add.sprite(400,700,"plane1");
plane2 = this.physics.add.sprite(400,100,"plane2");
plane1.enableBody = true;
}
function update(){
keys = this.input.keyboard.createCursorKeys();
if (keys.left.isDown) {
plane1.x = plane1.x - 7.5;
}else if(keys.right.isDown){
plane1.x = plane1.x + 7.5;
}else if(keys.space.isDown){
var bullet = this.physics.add.sprite(plane1.x,600,"bullet");
bullet.enableBody = true;
setInterval(function(){
bullet.y = bullet.y - 25;
},50);
this.physics.overlap(bullet,plane2,this.damage);
}
}
function damage(){
console.log("less HP")
}
var game = new Phaser.Game(config);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.54.0/phaser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.54.0/phaser-arcade-physics.min.js"></script>
</head>
<body>
<div id="game"></div>
<script defer src="script.js"></script>
</body>
</html>
Here is the link to the game if needed https://shoot.abaanshanid.repl.co/
This works:
this.physics.add.overlap(bullet,plane2,damage);
but its kinda laggy. Id try to destroy bullet on impact and i also found:
this.physics.add.collider(bullet,plane2,damage);

Here maps api: Behavior not reacting in Microsoft Web Browser ActiveX

I tried example in Here maps about draggable Marker:
Draggable Marker | Here
On first try map didn't show in AX2009 Microsoft Web Browser ActiveX. I switched from vector to raster and added engineType: H.map.render.RenderEngine.EngineType.P2The marker in default web browser like IE11, Chrome, edge is working fine, I can drag marker. But in ActiveX on AX2009 the marker isnt dragging, but i can see map istelf like in default web browser. Any ideas what should i add to code? Any help appreciated.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<script src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-core-legacy.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-service-legacy.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
<link
rel="stylesheet"
type="text/css"
href="https://js.api.here.com/v3/3.1/mapsjs-ui.css"
/>
<title>Simple Map</title>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var point = {lat:56.983849, lng:24.237360};
var apikey = "xxx",
platform = new H.service.Platform({
apikey: apikey,
}),
pixelRatio = window.devicePixelRatio || 1,
ppi,
defaultLayers,
mapElement = document.getElementById("map"),
tileSize,
map,
behavior,
ui;
if (pixelRatio > 1) {
ppi = 250;
}
defaultLayers = platform.createDefaultLayers({
ppi: ppi,
});
map = new H.Map(mapElement, defaultLayers.raster.normal.map, {
zoom: 14,
center: point,
renderBaseBackground: { lower: 2, higher: 2 },
pixelRatio: pixelRatio,
engineType: H.map.render.RenderEngine.EngineType.P2D,
});
window.addEventListener("resize", function () {
map.getViewPort().resize();
});
function addDraggableMarker(map, behavior){
var marker = new H.map.Marker(point, {
// mark the object as volatile for the smooth dragging
volatility: true
});
// Ensure that the marker can receive drag events
marker.draggable = true;
map.addObject(marker);
// disable the default draggability of the underlying map
// and calculate the offset between mouse and target's position
// when starting to drag a marker object:
map.addEventListener('dragstart', function(ev) {
var target = ev.target,
pointer = ev.currentPointer;
if (target instanceof H.map.Marker) {
var targetPosition = map.geoToScreen(target.getGeometry());
target['offset'] = new H.math.Point(pointer.viewportX - targetPosition.x, pointer.viewportY - targetPosition.y);
behavior.disable();
}
}, false);
// re-enable the default draggability of the underlying map
// when dragging has completed
map.addEventListener('dragend', function(ev) {
var target = ev.target;
if (target instanceof H.map.Marker) {
behavior.enable();
}
}, false);
// Listen to the drag event and move the position of the marker
// as necessary
map.addEventListener('drag', function(ev) {
var target = ev.target,
pointer = ev.currentPointer;
if (target instanceof H.map.Marker) {
target.setGeometry(map.screenToGeo(pointer.viewportX - target['offset'].x, pointer.viewportY - target['offset'].y));
}
}, false);
}
behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
ui = H.ui.UI.createDefault(map, defaultLayers);
addDraggableMarker(map, behavior);
</script>
</body>
</html>

Bootstrap + C3; Grid layout doesn't work on load

C3 version: 0.6.7
D3 version: 5
Browser: Firefox ESR
OS: Debian 9
I want to make a web page that has four rows of three donut charts each. I'm using Bootstrap with C3.js.
My code looks like this.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>U.S. presidential vote, 1972-2016, by race</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="css/c3.min.css" rel="stylesheet">
<style type="text/css">
.c3-chart-arcs-title {
font-size: 1.5rem;
}
</style>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="js/c3.min.js"></script>
<script type="text/javascript">
var dataDir = "vote-by-race";
d3.csv(dataDir + "/white.csv").then(function(data) {
var row;
data.forEach(function(d, i) {
if (i % 3 === 0) {
row = document.createElement("div");
row.className = "row";
}
var col = document.createElement("div");
col.className = "col-sm";
var chartDiv = document.createElement("div");
chartDiv.id = "chart" + i;
col.appendChild(chartDiv);
row.appendChild(col);
document.getElementById("charts").appendChild(row);
var chartDataObj = Object.assign({}, d);
delete chartDataObj["Year"];
var chart = c3.generate({
data: {
json: chartDataObj,
type: "donut",
colors: {
Democrat: "#2166ac",
Republican: "#b2182b",
Other: "#bbb"
}
},
tooltip: {
show: false
},
legend: {
show: false
},
donut: {
title: d["Year"],
label: {
format: function(value, ratio, id) {
return d3.format('.0%')(value / 100);
}
}
},
bindto: '#' + chartDiv.id
});
});
});
</script>
</head>
<body>
<div id="charts" class="container"></div>
</body>
</html>
My CSV...
Year,Democrat,Republican,Other
1972,32,66,2
1976,47,52,1
1980,35,56,9
1984,35,64,1
1988,40,59,1
1992,39,40,21
1996,43,46,11
2000,42,54,4
2004,41,58,1
2008,43,55,2
2012,39,59,2
2016,37,58,5
When I load the page in my browser, I see 12 donut charts in a single vertical column. But when I resize the browser window to its thinnest, then expand it again, I see four rows of three donut charts each.
How do I make the browser show four rows of three charts each when the charts are first loaded?

Adding a background image under a background color function

I have the three functions running on my interactive pet (change background, dimmer lights, mouse follow). I'm trying to add an image to the background of the body, but every time I try it gets pushed to the top and the dirty/clean tank function doesn't work. Could someone tell me how to change the color sections of the first function below to switch between images instead of color codes? I think that would solve the immediate problem. :/
CSS Code:
//change background color: dirty/clean tank
setTimeout(function dirty() { //sets background color to murky green
document.body.style.backgroundColor = ****"#CCCC99";** //would like this to be an image**
var btn = document.body.appendChild(document.createElement('button'));
btn.appendChild(document.createTextNode("Clean the tank!"));
document.body.style.marginTop = "-1000px";
btn.onclick = function clean() {
btn.parentNode.removeChild(btn);
document.body.style.backgroundColor = **"#CCFFFF";//would like this to be an image**
setTimeout(dirty,27000); //how long it takes to make the tank dirty
};
},500); //first loading of clear blue timeout
//dim the lights
var dimmed = 0;
function toggleLights()
{
var dimmer = document.getElementById("dimmer");
if(dimmed == 0) dimmed = 1;
else dimmed = 0;
if(dimmed == 1)
{
dimmer.style.opacity = 0.8;
dimmer.style.visibility = "visible";
}
if(dimmed == 0)
{
dimmer.style.opacity = 0.0;
dimmer.style.visibility = "hidden";
}
}
//fish moves on mouse hover
$(document).ready(function() {
$("#swim").mousemove(function (event) {
var fish = $("#fish1");
var position = fish.position();
var mousey = event.pageX;
if (position.left > mousey) {
$("#fish1").html("<img src='images/happy.png' />");
} else {
$("#fish1").html("<img src='images/happyback.png'/>");
}
$("#fish1").stop().animate({
left: event.pageX,
top: event.pageY
}, 300);
});
});
HTML Code:
<HTML>
<HEAD>
<TITLE>Untitled</TITLE>
<link href="style.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"
</script>
<script type="text/javascript" src="pet.js"></script>
<script type="text/javascript" src="core.js"></script>
</HEAD>
<div id="table">
<div id="dimmer" onClick="toggleLights()"></div>
<a href="javascript:toggleLights();"><img src="images/table-lamp.png" height="380px"
alt="table lamp"></a>
</div>
<div id="swim">
<div id="fish1"><img src="images/happy.png"/></div>
</div>
</BODY>
</HTML>
Add a starting <body> tag in your HTML, and change element classes with javascript, instead of style properties. That way you have more control over the styling through your CSS file.
So you would do something like:
document.body.className = 'state1';
And in your CSS
.state1{
background-image: url(the/image.jpg);
}
and so on...

Categories