How to escape "&" character in dryml? - ruby-on-rails

I've got this in my application.dryml file:
<def tag="googlemap">
<html>
<head>
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map_canvas { height: 100% }
</style>
<script type="text/javascript">
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAIbK8zw8fqY&sensor=false">
</script>
<script type="text/javascript">
function initialize() {
var mapOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var georssLayer = new google.maps.KmlLayer('http://waterwatch.org.au/waterwatch_php/all_sites.php');
georssLayer.setMap(map);
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"><div param="map" /></div>
</body>
</html>
</def>
I'm getting an error "Illegal character '&' in raw string" (the param separator in the maps.googleapis.com link.
How do I escape the & character in dryml?

Related

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

OSM building and jQuery mobile

I have a problem with input "range" and OSM Buildings for leaflet maps. I used basic example from official example which works fine but if I add jquery mobile to <head> section it breaks the range input. It's strange... I was using jquery mobile input to change the leaflet map opacity and it's working. Here is my basic example:
var map = new L.Map('map');
map.setView([52.52111, 13.40988], 16, false);
new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'osm.org',
maxZoom: 18,
maxNativeZoom: 20
}).addTo(map);
var osmb = new OSMBuildings(map).load();
//************************************************************
var now,
date, time,
timeRange, dateRange,
timeRangeLabel, dateRangeLabel;
function changeDate() {
var Y = now.getFullYear(),
M = now.getMonth(),
D = now.getDate(),
h = now.getHours(),
m = 0;
timeRangeLabel.innerText = pad(h) + ':' + pad(m);
dateRangeLabel.innerText = Y + '-' + pad(M+1) + '-' + pad(D);
osmb.date(new Date(Y, M, D, h, m));
}
function onTimeChange() {
now.setHours(this.value);
now.setMinutes(0);
changeDate();
}
function onDateChange() {
now.setMonth(0);
now.setDate(this.value);
changeDate();
}
function pad(v) {
return (v < 10 ? '0' : '') + v;
}
timeRange = document.getElementById('time');
dateRange = document.getElementById('date');
timeRangeLabel = document.querySelector('*[for=time]');
dateRangeLabel = document.querySelector('*[for=date]');
now = new Date;
changeDate();
// init with day of year
var Jan1 = new Date(now.getFullYear(), 0, 1);
dateRange.value = Math.ceil((now-Jan1)/86400000);
timeRange.value = now.getHours();
timeRange.addEventListener('change', onTimeChange);
dateRange.addEventListener('change', onDateChange );
timeRange.addEventListener('input', onTimeChange);
dateRange.addEventListener('input', onDateChange);
body {
font-family: sans-serif;
padding: 5px;
margin: 0;
}
#map {
width: 300px;
height: 300px;
float: left;
margin: 0 15px 0 0;
}
label {
height: 20px;
}
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Shadows</title>
<script src='http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js'></script>
<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.3.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script src='http://cdn.osmbuildings.org/OSMBuildings-Leaflet.js'></script>
<link rel='stylesheet prefetch' href='http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css'>
</head>
<body>
<div id="map"></div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<input id="date" type="range" min="1" max="365" step="1"><label for="date"></label><br>
<input id="time" type="range" min="0" max="23" step="1"><label for="time"></label>
</body>
</html>
For jQuery Mobile rangesliders you may use:
$(document).on("pagecreate", "#page-1", function() {
$("#date").on("change", onDateChange);
$("#time").on("change", onTimeChange);
});
Codepen: http://codepen.io/anon/pen/gLJRXb

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/

include a json file in a rails view path?

I am new to rails.
I am trying to add this code:
$.ajax({
url: "states.geojson",
dataType: 'json',
success: function load(d) {
var states = L.geoJson(d).addTo(map);
L.marker([38, -102], {
icon: L.mapbox.marker.icon({
'marker-color': '#f22'
}),
draggable: true
}).addTo(map)
.on('dragend', function(e) {
var layer = leafletPip.pointInLayer(this.getLatLng(), states, true);
document.getElementById('state').innerHTML = layer.length ?
layer[0].feature.properties.name : '';
});
}
});
which I got from here: http://www.mapbox.com/mapbox.js/example/v1.0.0/point-in-polygon/
this is my index.html.erb :
<!DOCTYPE html>
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' />
<script src='//api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.js'></script>
<link href='//api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.css' rel='stylesheet' />
<!--[if lte IE 8]>
<link href='//api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.ie.css' rel='stylesheet' >
<![endif]-->
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
#state {
position:absolute;
top:10px;
right:10px;
background:#fff;
font-size:30px;
padding:10px;
z-index:999;
}
</style>
<!-- <script src="leaflet-pip.min.js"></script> -->
<div id='map'></div>
<div id='state'></div>
<script type='text/javascript'>
var map = L.mapbox.map('map', 'lizozomro.map-6yvs8g1g')
.setView([38, -102.0], 5);
$.ajax({
url: "states.geojson",
dataType: 'json',
success: function load(d) {
var states = L.geoJson(d).addTo(map);
L.marker([38, -102], {
icon: L.mapbox.marker.icon({
'marker-color': '#f22'
}),
draggable: true
}).addTo(map)
.on('dragend', function(e) {
var layer = leafletPip.pointInLayer(this.getLatLng(), states, true);
document.getElementById('state').innerHTML = layer.length ?
layer[0].feature.properties.name : '';
});
}
});
</script>
</body>
</html>
I am getting a resource not found error (404) on states.geojson
I am not sure where exactly I should place it or how to reference using the correct paths.
Right now I have a copy of the file in my root app folder, one in my view folder(called maps), right next to the index.html.erb
How can I reference the resource correctly?
put it in the my_project/public/ folder. You also want to rename the file to states.geojson.json

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