Customize and create multiple line of tooltips in bar chart - jquery-mobile

I have try the code from the answer of potatopeelings in the Customize different tooltips of bar chart, but chart.js seems doesn't work under jquery mobile.
Following is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script src="Chart.js"></script>
<script>
function Plot(){
function Label(short, long) {
this.short = short;
this.long = long
}
Label.prototype.toString = function() {
return this.short;
}
var ctx = $("#myChart").get(0).getContext("2d");
var data = {
labels: [
new Label("J", "S JAN\b JAN JAN JAN JAN JAN JAN E"),
new Label("F", "S FEB\b E"),
new Label("M", "S MAR\b E"),
new Label("A", "S APR\b APR APR APR APR APR APR E"),
new Label("M", "S MAY\b E"),
new Label("J", "S JUN\b E"),
new Label("J", "S JUL\b JUL JUL JUL JUL JUL JUL JUL JUL JUL JUL JUL JUL JUL E")
],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}]
};
var myLineChart = new Chart(ctx).Bar(data, {
tooltipTemplate: "<%if (label){%><%=label.long%>: <%}%><%= value %>",
customTooltips: function (tooltip) {
var tooltipEl = $('#chartjs-tooltip');
if(!tooltip) {
tooltipEl.css({
opacity: 0
});
return;
}
// split out the label and value and make your own tooltip here
var parts = tooltip.text.split(":");
var re = new RegExp('\b', 'g');
var innerHtml = '<span>' + parts[0].trim().replace(re, '<br/>') + '</span> : <span><b>' + parts[1].trim() + '</b></span>';
tooltipEl.html(innerHtml);
tooltipEl.css({
opacity: 1,
// the minimum amount is half the maximum width of the tooltip that we set in CSS ...
// ... + the x scale padding so that it's not right at the edge
left: Math.max(75 + 10, tooltip.chart.canvas.offsetLeft + tooltip.x) + 'px',
top: tooltip.chart.canvas.offsetTop + tooltip.y + 'px',
fontFamily: tooltip.fontFamily,
fontSize: tooltip.fontSize,
fontStyle: tooltip.fontStyle,
});
}
});
}
</script>
<style>
#chartjs-tooltip {
opacity: 0;
position: absolute;
background: rgba(0, 0, 0, .7);
color: white;
padding: 3px;
border-radius: 3px;
-webkit-transition: all .1s ease;
transition: all .1s ease;
pointer-events: none;
-webkit-transform: translate(-50%, -120%);
transform: translate(-50%, -120%);
max-width: 30px;
}
</style>
</head>
<body>
<div id="container" data-role="page">
<div id="header" data-role="header" data-position="fixed" data-tap-toggle="false" data-theme="c">
<h1>TEST</h1>
</div>
<div data-role="content" class="ui-content">
<canvas id="myChart" width="400" height="200"></canvas>
<div id="chartjs-tooltip"></div>
<input type="button" value="Review" onclick="Plot()">
</div>
</div>
</body>
</html>
Is there any idea?
Thanks a lot.

Related

Programmatically sort jquery-ui sortable?

I have a bunch of divs inside a display:flex parent div. The parent div is sortable with jquery-ui's sortable function.
As well as allowing the user to sort, I would like to add some buttons that do an animated sort.
For example, with this HTML:
<div class="sortable">
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<div id="div4"></div>
<div id="div5"></div>
</div>
I would like a button that when pressed would animate moving div1 to be between div4 and div5, moving smoothly (in fact, a little erratically as if it were being moved by hand would be even better) and shifting all the divs it passes, so it looks as if it were being moved by hand.
Is this possible using jquery-ui's sortable(), or am I better off building a custom solution?
Consider the following example.
$(function() {
function arrange(obj, pre) {
obj = $(obj);
var t = $("[id^='div']:eq(" + pre + ")");
obj.animate({
top: t.position().top + "px"
}, {
duration: 1000,
step: function(i) {
$(this).position({
my: "left top",
at: "left bottom",
of: t,
});
},
complete: function() {
obj.detach().css("top", "").insertAfter(t);
}
});
}
$(".sortable").sortable().disableSelection();
$("#arrange").click(function() {
arrange($("#div1"), 3);
});
});
.sortable {
list-style-type: none;
margin: 0;
padding: 0;
position: relative;
}
.sortable div {
margin: 0 3px 3px 3px;
padding: 0.4em;
height: 18px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="sortable">
<div id="div1" class="ui-state-default">Item 1</div>
<div id="div2" class="ui-state-default">Item 2</div>
<div id="div3" class="ui-state-default">Item 3</div>
<div id="div4" class="ui-state-default">Item 4</div>
<div id="div5" class="ui-state-default">Item 5</div>
</div>
<button class="btn" id="arrange">Arrange</button>
Built from https://css-tricks.com/jquery-ui-position-function/
Update
$(function() {
function swap(a, b, ms) {
console.log("Swap:", a.attr("id"), "with", b.attr("id"));
a.animate({
top: b.position().top + "px"
}, {
duration: ms,
step: function(i) {
$(this).position({
my: "left top",
at: "left bottom",
of: b,
});
},
complete: function() {
a.detach().css("top", "").insertAfter(b);
}
});
}
function arrangeAfter(a, b) {
var n = a.next();
for (var c = parseInt(n.attr("id").slice(-1)); n.index() <= b.index(); c++) {
swap(a, n, 400);
n = $("#div" + (c + 1));
}
}
$(".sortable").sortable().disableSelection();
$("#arrange").click(function() {
arrangeAfter($("#div1"), $("#div4"));
});
});
.sortable {
list-style-type: none;
margin: 0;
padding: 0;
position: relative;
}
.sortable div {
margin: 0 3px 3px 3px;
padding: 0.4em;
height: 18px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="sortable">
<div id="div1" class="ui-state-default">Item 1</div>
<div id="div2" class="ui-state-default">Item 2</div>
<div id="div3" class="ui-state-default">Item 3</div>
<div id="div4" class="ui-state-default">Item 4</div>
<div id="div5" class="ui-state-default">Item 5</div>
</div>
<button class="btn" id="arrange">Arrange</button> <button class="btn" id="reset">Reset</button>

How to set zindex in konva.js?

I have a problem with the Zindex in konva.js. After I added everything to the layer
I am trying to assign a property to a node for each element separately. But it does not work. For example
for(let i = 0; i<=this.layer['children']; i++){
this.layer['children'][i].setZIndex(someInt);
}
How can i set zindex for all elements in layer?
zIndex in Konva is just index of the element in an array of children of the parent element. So you can't set any number to it and it can not be bigger than children.length - 1.
Working snippet illustrating the getZIndex(), setZIndex(), moveUp() and moveDown() methods of the Kovajs.Shape object. See also example at Konvajs site.
Buttons allow use to move green circle up and down the z-index list by increments of 1, then also to try to move up +10 and down -100. Resulting z-index is shown in text below circles.
// Create the stage
var stage = new Konva.Stage({
container: 'container',
width: $('#container').width(),
height: $('#container').height()
});
// create the layer
var layer = new Konva.Layer();
var data = [ {x: 60, color: 'red'}, {x: 90, color: 'limegreen'}, {x: 120, color: 'gold'}]
var circles = [];
for (var i = 0; i < data.length; i = i + 1){
// create some circles
var circle = new Konva.Circle({
x: data[i].x,
y: 60,
radius: 50,
fill: data[i].color,
stroke: 'black',
strokeWidth: 2
});
layer.add(circle);
circles.push(circle);
}
stage.add(layer);
var green = circles[1];
function sayIndex(){
$('#info').html("Green zIndex=" + circles[1].getZIndex());
}
$('#greenup').on('click', function(){
green.moveUp();
sayIndex();
layer.draw();
})
$('#greendn').on('click', function(){
green.moveDown();
sayIndex();
layer.draw();
})
$('#greenup10').on('click', function(){
var ind = circles[1].getZIndex();
green.setZIndex(ind + 10);
sayIndex();
layer.draw();
})
$('#greendn100').on('click', function(){
var ind = circles[1].getZIndex();
green.setZIndex(ind - 100);
sayIndex();
layer.draw();
})
#container
{
width: 200px;
height: 150px;
border: 1px solid #666;
float: left;
}
#buttons
{
width: 200px;
height: 150px;
border: 1px solid #666;
float: left;
}
#info
{
position: absolute;
left: 20px;
top: 135px;
}
p
{
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.rawgit.com/konvajs/konva/1.6.5/konva.min.js"></script>
<div id="container"></div>
<div id="buttons">
<p><button id='greenup'>Move Green + 1</button></p>
<p><button id='greendn'>Move Green -1</button></p>
<p><button id='greenup10'>Move Green +10</button></p>
<p><button id='greendn100'>Move Green -100</button></p>
<span id='info'></span>
</div>
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#2.4.2/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Shape Layering Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
#buttons {
position: absolute;
left: 10px;
top: 0px;
}
button {
margin-top: 10px;
display: block;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="buttons">
<button id="toTop">
yellow z-index -2
</button>
<button id="toBottom">
yellow -9
</button>
<button id="up">
yellow z-index 1
</button>
<button id="down">
yellow z-index -5
</button>
<button id="zIndex">
Set yellow box zIndex to 3
</button>
</div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
var offsetX = 0;
var offsetY = 0;
var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
var yellowBox = null;
for(var n = 0; n < 6; n++) {
// anonymous function to induce scope
(function() {
var i = n;
var box = new Konva.Rect({
x: i * 30 + 210,
y: i * 18 + 40,
width: 100,
height: 50,
fill: colors[i],
stroke: 'black',
strokeWidth: 4,
draggable: true,
name: colors[i]
});
box.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
box.on('mouseout', function() {
document.body.style.cursor = 'default';
});
if(colors[i] === 'yellow') {
yellowBox = box;
}
layer.add(box);
})();
}
stage.add(layer);
// add button event bindings
document.getElementById('toTop').addEventListener('click', function() {
yellowBox.setZIndex(-2);
layer.draw();
}, false);
document.getElementById('toBottom').addEventListener('click', function() {
yellowBox.setZIndex(-9);
layer.draw();
}, false);
document.getElementById('up').addEventListener('click', function() {
yellowBox.setZIndex(1);
layer.draw();
}, false);
document.getElementById('down').addEventListener('click', function() {
yellowBox.setZIndex(-5);
layer.draw();
}, false);
document.getElementById('zIndex').addEventListener('click', function() {
yellowBox.setZIndex(3);
layer.draw();
}, false);
</script>
</body>
</html>
Last
Fun messing with ZIndex code,
the setZIndex is all you need; It will vain the z-index inside Konva.JS
If you would prefer to be able to set the render order of nodes using arbitrary numbers (like CSS, or how it works in most game engines, etc), you can use this fork of Konva. Alternatively, you could also grab & apply just the rejected pull request for this feature if you already have a customized Konva version.
The new feature works by adding a zOrder property to all Nodes, and a special kind of group AbsoluteRenderOrderGroup that reads and understands this property for all children.

Strange default size in leaflet map

I have taken a working Leaflet map, but when I added a JQuery Mobile header and back button the formatting went crazy.
Initially loading the page all the contents is loaded in the upper-left-hand corner, but when the page is resized the smallest bit on a desktop, or rotated on a mobile, everything is fine.
This is what it looks like when opened:
and what it looks like after rotating (and what it should be):
Here is the code for the page
<!DOCTYPE html>
<html>
<head>
<title>Toronto CAD Activity Map</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../css/leaflet.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../css/tfscad.mobile.css" />
<link rel="stylesheet" href="../css/jquery.mobile-1.4.5.min.css">
<link rel="stylesheet" href="../css/font-awesome.min.css">
<script src="../js/jquery-1.11.1.min.js"></script>
<script src="../js/jquery.mobile-1.4.5.min.js"></script>
<script src="../js/iframeResizer.contentWindow.js"></script>
<!--[if lte IE 8]><link rel="stylesheet" href="../dist/leaflet.ie.css" /><![endif]-->
<style>
#mapPage {
height: calc(100% - 42px);
}
#map {
height: 100%;
}
#map-content{
height: 100%;
padding: 0px;
margin:0px;
z-index: -1;
}
#curLoc{
position: absolute;
bottom: 0;
left: 10px;
}
</style>
</head>
<body>
<body>
<div data-role="page" id="mapPage" data-theme="a">
<div data-role="header" data-position="fixed" data-theme="a">
<a id="backButton" href="#" data-rel="back"
data-transition="slide" data-direction="reverse">Back</a>
<h1>Toronto CAD Map</h1>
</div>
<div id="map-content" data-role="content">
<div id="map"></div>
</div>
<a id="curLoc" data-role="button" data-icon="location" data-iconpos="notext"></a>
</div>
<script src="../js/jquery-1.11.1.min.js"></script>
<script src="../js/leaflet.js"></script>
<script type="text/javascript">
window.onload = function() {
getGeoJson();
getTPSJson();
};
var map = L.map('map').setView([43.7178,-79.3762], 11);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © 2011 OpenStreetMap contributors, Imagery © 2012 CloudMade',
}).addTo(map);
function getGeoJson(){
// load GeoJSON from an external file
$.getJSON("../appdata/geo.json",function(data){
L.geoJson(data ,{
pointToLayer: function(feature,latlng){
var TFS = new L.icon({
iconUrl: '../images/tfs_logo.png',
iconSize: [22, 22],
popupAnchor: [0, -22]
});
var TPS = new L.icon({
iconUrl: '../images/tps_logo.png',
iconSize: [22, 22],
popupAnchor: [0, -22]
});
var ESC = new L.icon({
iconUrl: '../images/tps_logo.png',
iconSize: [22, 22],
popupAnchor: [0, -22]
});
if(feature.properties.icon == 'TFS'){
var marker = L.marker(latlng,{icon: TFS});
marker.bindPopup('<strong>' + feature.properties.event_type + '</strong><br/>' + feature.properties.OPEN_DT);
return marker;
}else if(feature.properties.icon == 'TPS'){
var marker = L.marker(latlng,{icon: TPS});
marker.bindPopup('<strong>' + feature.properties.event_type + '</strong><br/>' + feature.properties.OPEN_DT);
return marker;
}else if(feature.properties.icon == 'ESC'){
var marker = L.marker(latlng,{icon: ESC});
marker.bindPopup('<strong>' + feature.properties.event_type + '</strong><br/>' + feature.properties.OPEN_DT);
return marker;
}
}
} ).addTo(map);
});
}
function getTPSJson(){
var myStyle = {
"color": "#ff7800",
"weight": 5,
"opacity": 0,
"offset": 1.5
};
// load GeoJSON from an external file
$.getJSON("../appdata/TPSDiv.json",function(myLines){
L.geoJson(myLines, {
style: myStyle
}).addTo(map);
})
}
setInterval(function()
{
getGeoJson();
}, 10000);//time in milliseconds
function onClick(e) {
//console.log(this.options.win_url);
window.open(this.options.win_url);
}
</script>
</body>
jQuery Mobile has its own way to create pages from div's, so you may better stick to JQM events.
Here is a great post of Omar which explain how to solve this (typical) issue when loading Google Maps. You should wait for pagecontainershow or use a placeholder to pre-load the maps in advance.
In my example below, you will find a variation of this approach for Leaflet which uses the same canvasHeight() function (see also the answers here: set content height 100% jquery mobile).
I noticed you are about to implement a footer button for the geo-location feature, so for your convenience i show you also a possible way to do that (credits: Getting current user location automatically every “x” seconds to put on Leaflet map?).
Please note: i had to reposition the default map attribution so it won't overlap with the footer button.
var map, actualPosition, actualAccuracy, autoUpdate;
function canvasHeight(canvas) {
var mapPage = $("#page-map"),
screen = $.mobile.getScreenHeight(),
header = $(".ui-header", mapPage).hasClass("ui-header-fixed") ? $(".ui-header", mapPage).outerHeight() - 1 : $(".ui-header", mapPage).outerHeight(),
footer = $(".ui-footer", mapPage).hasClass("ui-footer-fixed") ? $(".ui-footer", mapPage).outerHeight() - 1 : $(".ui-footer", mapPage).outerHeight(),
newHeight = screen - header - footer;
$(canvas).height(newHeight);
}
$(window).on("throttledresize orientationchange", function() {
canvasHeight("#map");
})
function onLocationFound(e) {
var radius = e.accuracy / 2;
actualPosition = L.marker(e.latlng).addTo(map);
actualAccuracy = L.circle(e.latlng, radius).addTo(map);
}
function onLocationError(e) {
alert(e.message);
}
function showLocation() {
if (actualPosition) {
map.removeLayer(actualPosition);
map.removeLayer(actualAccuracy);
}
map.locate({setView: true,maxZoom: 16});
}
function loadMap(canvas) {
map = L.map(canvas).setView([43.7178, -79.3762], 11);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(map);
map.on('locationfound', onLocationFound);
map.on('locationerror', onLocationError);
// Your custom initialization
//getGeoJson();
//getTPSJson();
}
function toggleAutoUpdate() {
if (autoUpdate) {
$("#autoUpdate").removeClass("ui-btn-active");
clearInterval(autoUpdate);
autoUpdate = null;
if (actualPosition) {
map.removeLayer(actualPosition);
map.removeLayer(actualAccuracy);
}
} else {
$("#autoUpdate").addClass("ui-btn-active");
showLocation();
autoUpdate = setInterval(function() {
showLocation();
// Your custom Update
//getGeoJson();
}, 10 * 1000);
}
}
$(document).on("pagecontainershow", function(e, ui) {
if (ui.toPage.prop("id") == "page-map") {
canvasHeight("#map");
if (!map) {
loadMap("map");
}
}
});
#map {
margin: 0;
padding: 0;
}
#page-map .footer {
position: fixed;
z-index: 1000;
bottom: .1em;
width: 100%;
}
#footer-button {
width: 100%;
text-align: center;
background: transparent;
}
#map-attribution {
text-align: center;
background: rgba(255, 255, 255, 0.7);
}
.leaflet-control-attribution.leaflet-control {
display: none;
}
/* Don't show scrollbars on SO code snippet */
.ui-mobile .ui-page {
min-height: 100px !important;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<link rel="stylesheet" href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.1.0/leaflet.css">
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.1.0/leaflet.js"></script>
</head>
<body>
<div data-role="page" id="page-map">
<div data-role="header" data-position="fixed" data-theme="a">
Back
<h1>Toronto CAD Map</h1>
</div>
<div id="map" data-role="content">
<div class="footer">
<div id="footer-button">
<button id="autoUpdate" onclick="toggleAutoUpdate();" class="ui-btn ui-btn-inline ui-corner-all ui-icon-location ui-btn-icon-notext"></button>
</div>
<div id="map-attribution">
Leaflet Map data © 2011 OpenStreetMap contributors, Imagery © 2012 CloudMade
</div>
</div>
</div>
</div>
</body>
</html>
jQuery Mobile manages the pages of your multi-pages document and resizes them appropriately when DOM is loaded.
The issue is that you have already instantiated your map with Leaflet before that event happens, so the map container (i.e. <div id="map"></div>) is not displayed yet by jQuery Mobile, and therefore its size is not computed yet by the browser.
This is a variant of map container size not being valid yet at map instantiation. See Data-toggle tab does not download Leaflet map
Since you already have a listener on window.onload, which executes after jQuery Mobile does its stuff, you could very simply call map.invalidateSize() at that moment:
window.onload = function() {
// Request Leaflet to re-evaluate the map container size
// AFTER jQuery Mobile displays the page.
map.invalidateSize();
getGeoJson();
getTPSJson();
};
Demo: https://plnkr.co/edit/TigW44s5MlqMifimWkSw?p=preview

dynamic legend for fusion table map

I have a modified sample of fusion table map and its code is given below.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<title>Fusion Tables Layer Example: Dynamic styles and templates</title>
<style>
body { font-family: Arial, sans-serif; font-size: 12px; }
#map-canvas { height: 660px; width: 100%; }
#map-canvas img { max-width: none; }
#visualization { height: 100%; width: 100%; }
#legend1 { width: 200px; background: #FFF;padding: 10px; margin: 5px;font-size: 12px;font-family: Arial, sans-serif;border: 1px solid black;}
.color {border: 1px solid;height: 12px;width: 15px; margin-right: 3px;float: left;}
.red {background: #C00;}
.blue {background: #06C;}
</style>
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
function initialize() {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: new google.maps.LatLng(37.4, -122.1),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var layer = new google.maps.FusionTablesLayer({
query: {
select: 'Address',
from: '15UY2pgiz8sRkq37p2TaJd64U7M_2HDVqHT3Quw'
},
map: map,
styleId: 1,
templateId: 1
});
var legend1 = document.createElement('div');
legend1.id = 'legend1';
var content1 = [];
content1.push('<p><div class="color red"></div>Red markers</p>');
legend1.innerHTML = content1.join('');
legend1.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(legend1);
var legend2 = document.createElement('div');
legend2.id = 'legend1';
var content2 = [];
content2.push('<p><div class="color blue"></div>Blue markers</p>');
legend2.innerHTML = content2.join('');
legend2.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(legend2);
google.maps.event.addDomListener(document.getElementById('style'),
'change', function() {
var selectedStyle = this.value;
layer.set('styleId', selectedStyle);
var selectedTemplate = this.value;
layer.set('templateId', selectedTemplate);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
<div>
<label>Select style:</label>
<select id="style">
<option value="1">Red</option>
<option value="2">Blue</option>
</select>
</div>
</body>
</html>
How can I add dynamic legend to this map so that when selecting blue markers, the legend should show only a blue marker with its name and when selecting red markers it will show the red marker icon in legend.
You must clear the controls(remove all legends) and then add the desired legend again.
right before
google.maps.event.addDomListener(document.getElementById('style')[...]
add this code:
//we need a copy of all legends(nodes),
//otherwise they wouldn't be accessible when they have been removed
var clonedArray = map.controls[google.maps.ControlPosition.RIGHT_BOTTOM]
.getArray().slice();
//observe changes of the styleId
google.maps.event.addListener(layer,'styleid_changed',function(){
//clear the controls
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].clear();
//add the desired control
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM]
.push(clonedArray[this.get('styleId')-1])
});
//trigger the event to initially have only the legend
//based on the selected style
google.maps.event.trigger(layer,'styleid_changed');
Demo: http://jsfiddle.net/doktormolle/t3nY6/

Using jQuery slider to change Google chart viewWindow

I have prepared a simple test case with screenshot, demonstrating my problem and am probably missing a tiny bit, just few lines of code.
I have a diagram representing wins and losses in a web game over the weeks.
I.e. the vertical axis represents the game score and the horizontal axis represents numbers of weeks.
My ajax script returns the data for 52 weeks, but I'd like to add a slider and allow users change the viewed number of weeks to any number between 12 and 52.
Can anybody please advise me, how to modify the change function?
$("#money_slider").slider({
min: 12,
max: 52,
change: function(event, ui) {
// XXX what to do here with
// hAxis.viewWindow.min and .max?
}
});
Below is my complete test case, just save it to an .html file and you will be able to try it in a browser:
<!DOCTYPE HTML>
<html>
<style type="text/css">
h3,p,div {
text-align: center;
}
#slider {
width: 700px;
margin-left: auto;
margin-right: auto;
}
</style>
<style type="text/css" title="currentStyle">
#import "https://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css";
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['corechart'],'language':'ru'}]}"></script>
<script type="text/javascript">
google.setOnLoadCallback(drawChart);
$(function() {
$('#slider').slider({
disabled: true,
range: 'min',
min: 12,
max: 52,
change: function(event, ui) {
// XXX what to do here with
// hAxis.viewWindow.min and .max?
$("#header").text("debug=" + ui.value);
}
});
});
function drawChart() {
var jsonData = '{"cols":[{"label":"Week number","type":"string"},{"label":"Week leader","type":"number"},{"label":"Your win","type":"number"},{"label":"Your loss","type":"number"}],"rows":[{"c":[{"v":"2011-33"},{"v":10671},{"v":0},{"v":-3113}]},{"c":[{"v":"2011-34"},{"v":7975},{"v":0},{"v":-2113}]},{"c":[{"v":"2011-35"},{"v":11009},{"v":0},{"v":-2244}]},{"c":[{"v":"2011-36"},{"v":10679},{"v":0},{"v":-689}]},{"c":[{"v":"2011-37"},{"v":11197},{"v":305},{"v":0}]},{"c":[{"v":"2011-38"},{"v":6762},{"v":419},{"v":0}]},{"c":[{"v":"2011-39"},{"v":7823},{"v":0},{"v":-1563}]},{"c":[{"v":"2011-40"},{"v":10171},{"v":1152},{"v":0}]},{"c":[{"v":"2011-41"},{"v":9903},{"v":0},{"v":-1008}]},{"c":[{"v":"2011-42"},{"v":5940},{"v":0},{"v":-1332}]},{"c":[{"v":"2011-43"},{"v":7979},{"v":0},{"v":-593}]},{"c":[{"v":"2011-44"},{"v":7833},{"v":0},{"v":-653}]},{"c":[{"v":"2011-45"},{"v":9691},{"v":0},{"v":-562}]},{"c":[{"v":"2011-46"},{"v":8836},{"v":0},{"v":-1686}]},{"c":[{"v":"2011-47"},{"v":10358},{"v":0},{"v":-2120}]},{"c":[{"v":"2011-48"},{"v":9956},{"v":0},{"v":-1353}]},{"c":[{"v":"2011-49"},{"v":8787},{"v":160},{"v":0}]},{"c":[{"v":"2011-50"},{"v":9590},{"v":0},{"v":0}]},{"c":[{"v":"2011-51"},{"v":8931},{"v":887},{"v":0}]},{"c":[{"v":"2011-52"},{"v":8529},{"v":0},{"v":-1434}]},{"c":[{"v":"2012-01"},{"v":8680},{"v":0},{"v":-1416}]},{"c":[{"v":"2012-02"},{"v":9932},{"v":0},{"v":-169}]},{"c":[{"v":"2012-03"},{"v":8334},{"v":0},{"v":-3149}]},{"c":[{"v":"2012-04"},{"v":8077},{"v":217},{"v":0}]},{"c":[{"v":"2012-05"},{"v":7788},{"v":0},{"v":-3683}]},{"c":[{"v":"2012-06"},{"v":10070},{"v":113},{"v":0}]},{"c":[{"v":"2012-07"},{"v":8318},{"v":1704},{"v":0}]},{"c":[{"v":"2012-08"},{"v":8208},{"v":0},{"v":-104}]},{"c":[{"v":"2012-09"},{"v":11561},{"v":272},{"v":0}]},{"c":[{"v":"2012-10"},{"v":7797},{"v":0},{"v":0}]},{"c":[{"v":"2012-11"},{"v":9893},{"v":0},{"v":-90}]},{"c":[{"v":"2012-12"},{"v":9197},{"v":0},{"v":-191}]},{"c":[{"v":"2012-13"},{"v":7287},{"v":651},{"v":0}]},{"c":[{"v":"2012-14"},{"v":7072},{"v":646},{"v":0}]},{"c":[{"v":"2012-15"},{"v":7183},{"v":0},{"v":-907}]},{"c":[{"v":"2012-16"},{"v":6021},{"v":0},{"v":-993}]}]}';
var data = new google.visualization.DataTable(jsonData);
var options = {
width: 700,
height: 500,
legend: {position: 'top'},
areaOpacity: 1.0,
vAxis: {format: '$#'},
hAxis: {title: 'Week number', titleTextStyle: {color: 'blue'}, slantedText: true},
colors: ['CCFFCC', '66CC66', 'FF9999'],
animation: {duration: 1000, easing: 'out'}
};
var chart = new google.visualization.SteppedAreaChart(document.getElementById('money'));
google.visualization.events.addListener(chart, 'ready', function() {
$('#slider').slider('enable');
});
chart.draw(data, options);
}
</script>
</head>
<body>
<h3 id="header">Money</h3>
<div id="money"></div>
<div id="slider"></div>
</body>
</html>
I've read the Google example (on the bottom), but don't grok it yet.
My own solution (has rendering problems with Opera 11.62 though - I've filed a bug #882 for that):
<!DOCTYPE HTML>
<html>
<style type="text/css">
h3,p,div {
text-align: center;
}
#slider {
width: 700px;
margin-left: auto;
margin-right: auto;
}
</style>
<style type="text/css" title="currentStyle">
#import "https://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css";
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['corechart'],'language':'ru'}]}"></script>
<script type="text/javascript">
google.setOnLoadCallback(initChart);
var jsonData = '{"cols":[{"label":"Week number","type":"string"},{"label":"Week leader","type":"number"},{"label":"Your win","type":"number"},{"label":"Your loss","type":"number"}],"rows":[{"c":[{"v":"2011-33"},{"v":10671},{"v":0},{"v":-3113}]},{"c":[{"v":"2011-34"},{"v":7975},{"v":0},{"v":-2113}]},{"c":[{"v":"2011-35"},{"v":11009},{"v":0},{"v":-2244}]},{"c":[{"v":"2011-36"},{"v":10679},{"v":0},{"v":-689}]},{"c":[{"v":"2011-37"},{"v":11197},{"v":305},{"v":0}]},{"c":[{"v":"2011-38"},{"v":6762},{"v":419},{"v":0}]},{"c":[{"v":"2011-39"},{"v":7823},{"v":0},{"v":-1563}]},{"c":[{"v":"2011-40"},{"v":10171},{"v":1152},{"v":0}]},{"c":[{"v":"2011-41"},{"v":9903},{"v":0},{"v":-1008}]},{"c":[{"v":"2011-42"},{"v":5940},{"v":0},{"v":-1332}]},{"c":[{"v":"2011-43"},{"v":7979},{"v":0},{"v":-593}]},{"c":[{"v":"2011-44"},{"v":7833},{"v":0},{"v":-653}]},{"c":[{"v":"2011-45"},{"v":9691},{"v":0},{"v":-562}]},{"c":[{"v":"2011-46"},{"v":8836},{"v":0},{"v":-1686}]},{"c":[{"v":"2011-47"},{"v":10358},{"v":0},{"v":-2120}]},{"c":[{"v":"2011-48"},{"v":9956},{"v":0},{"v":-1353}]},{"c":[{"v":"2011-49"},{"v":8787},{"v":160},{"v":0}]},{"c":[{"v":"2011-50"},{"v":9590},{"v":0},{"v":0}]},{"c":[{"v":"2011-51"},{"v":8931},{"v":887},{"v":0}]},{"c":[{"v":"2011-52"},{"v":8529},{"v":0},{"v":-1434}]},{"c":[{"v":"2012-01"},{"v":8680},{"v":0},{"v":-1416}]},{"c":[{"v":"2012-02"},{"v":9932},{"v":0},{"v":-169}]},{"c":[{"v":"2012-03"},{"v":8334},{"v":0},{"v":-3149}]},{"c":[{"v":"2012-04"},{"v":8077},{"v":217},{"v":0}]},{"c":[{"v":"2012-05"},{"v":7788},{"v":0},{"v":-3683}]},{"c":[{"v":"2012-06"},{"v":10070},{"v":113},{"v":0}]},{"c":[{"v":"2012-07"},{"v":8318},{"v":1704},{"v":0}]},{"c":[{"v":"2012-08"},{"v":8208},{"v":0},{"v":-104}]},{"c":[{"v":"2012-09"},{"v":11561},{"v":272},{"v":0}]},{"c":[{"v":"2012-10"},{"v":7797},{"v":0},{"v":0}]},{"c":[{"v":"2012-11"},{"v":9893},{"v":0},{"v":-90}]},{"c":[{"v":"2012-12"},{"v":9197},{"v":0},{"v":-191}]},{"c":[{"v":"2012-13"},{"v":7287},{"v":651},{"v":0}]},{"c":[{"v":"2012-14"},{"v":7072},{"v":646},{"v":0}]},{"c":[{"v":"2012-15"},{"v":7183},{"v":0},{"v":-907}]},{"c":[{"v":"2012-16"},{"v":6021},{"v":0},{"v":-993}]}]}';
var data = new google.visualization.DataTable(jsonData);
var chart;
var options = {
width: 700,
height: 500,
legend: {position: 'top'},
areaOpacity: 1.0,
vAxis: {format: '$#'},
hAxis: {title: 'Week number', titleTextStyle: {color: 'blue'}, slantedText: true, viewWindow: {min: 20, max: 35}},
colors: ['CCFFCC', '66CC66', 'FF9999'],
animation: {duration: 1000, easing: 'out'}
};
$(function() {
$('#slider').slider({
disabled: true,
range: 'min',
value: 20,
min: 0,
max: 20,
change: function(event, ui) {
$('#header').text('debug=' + ui.value);
options.hAxis.viewWindow.min = ui.value;
drawChart();
}
});
});
function initChart() {
chart = new google.visualization.SteppedAreaChart(document.getElementById('money'));
google.visualization.events.addListener(chart, 'ready', function() {
$('#slider').slider('enable');
});
drawChart();
}
function drawChart() {
chart.draw(data, options);
}
</script>
</head>
<body>
<h3 id="header">Money</h3>
<div id="money"></div>
<div id="slider"></div>
</body>
</html>

Resources