How to set leaflet map layer selected as default - django

In my Django app I have a leaflet map with two layers "active_event_layer" and "inactive_event_layer". I can select which layer I want to see in the top right menu. But when the page is loaded no layer is selected by default, so in order to see a layer I must selected it first. What I want to do is to set a layer by default, so, when the page is loaded the "Active events" layer is selected by default.
Here is my code:
var active_event_collection = {{ active_events|geojsonfeature:"name"|safe }};
var inactive_event_collection = {{ inactive_events|geojsonfeature:"name"|safe }};
function onEachFeature(feature, layer) {
layer.bindPopup(feature.properties.name);
}
function map_init(map, options) {
var active_event_layer= L.geoJson(active_event_collection, {onEachFeature: onEachFeature})
var inactive_event_layer = L.geoJson(inactive_event_collection, {onEachFeature: onEachFeature})
var basemaps = {
"Gray scale": L.tileLayer('http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '© OpenStreetMap'
}),
Streets: L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
})
};
var overlayMaps = {
"Active events": active_event_layer,
"Inactive events": inactive_event_layer,
};
var features = L.control.layers(basemaps, overlayMaps).addTo(map);
map.fitBounds(active_event_layer.getBounds());
}

Related

Is there a way to filter data in Chart.js?

I'm working with Chart.js and I'm wondering if there's a way when you click on part of a pie chart, it filters the bar chart.
Since this is a Chart.js question :-), this is how you do it Chart.js (and it's not too complex either)
Setting up the Pie Chart
// pie
var data = [
{
value: 300,
color: "#F7464A",
highlight: "#FF5A5E",
label: "Red",
subData: [28, 48, 40, 19, 86, 27, 190]
}, {
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green",
subData: [90, 28, 48, 40, 19, 86, 127]
}, {
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow",
subData: [28, 48, 40, 19, 86, 27, 190]
}
]
var canvas = document.getElementById("chart");
var ctx = canvas.getContext("2d");
var myPieChart = new Chart(ctx).Pie(data);
Setting up the Bar Chart using Pie Data
// bar using pie's sub data
var bardata = {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
datasets: [
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: data[0].subData.map(function (point, i) {
var pointTotal = 0;
data.forEach(function (point) {
pointTotal += point.subData[i]
})
return pointTotal;
})
}
]
};
var subcanvas = document.getElementById("subchart")
var subctx = subcanvas.getContext("2d");
var myBarChart = new Chart(subctx).Bar(bardata);
Updating Bar data when Clicking Pie
// connect them both
canvas.onclick = function (evt) {
var activeSector = myPieChart.getSegmentsAtEvent(evt);
myBarChart.datasets[0].bars.forEach(function (bar, i) {
var pointTotal = 0;
data.forEach(function (point, j) {
if (activeSector.length === 0 || point.label === activeSector[0].label)
pointTotal += data[j].subData[i]
})
bar.value = pointTotal;
});
myBarChart.update();
};
Clicking outside the pie (but in the pie chart's canvas) resets the bar chart.
Fiddle - http://jsfiddle.net/0zwkjv8a/
Other answers posted already cover what I would generally advise here which is to use dc-js if you want crossfilter enabled charts out of the gate. I would have commented on this answer, but I don't have enough reputation so I'm posting this as option 'c.)' where 'a.)' is using dc-js and 'b.)' is making some modifications to an existing Chart.js chart.
Option 'c.)' is to extend the Chart.js chart type and make the child chart work like a dc-js chart. Chart.js chart types follow an inheritance hierarchy, so if you like a chart that already exists you can wrap its prototype methods with some of your own. Additionally important to this option, in the selected answer to the stack overflow question with heading 'dc.js - Listening for chart group render', it is described how the current implementation of dc-js's chartRegistry object is fairly decoupled from d3 or dc internals, so any chart implementing chartRegistry's interface can be part of a chartGroup.
I was in the position of wanting very much to use Polar Area Charts in a dataset where I was already using a chart group full of dc-js charts to crossfilter the data. I wrote an extension for Polar Area charts that could serve as an example of one way (I'm going to go ahead and say probably not the best way) to extend a chart type with dc-js like behaviors. The repo for this is at https://github.com/nsubordin81/Chart.dc.js, Licensed under an MIT License, and in case that ever goes anywhere, all of the code is copied into the example fiddle: http://jsfiddle.net/nsubordin81/3w725o3c/1/
Chart.dc.js v. 0.1.0
MIT Licensed: opensource.org/licenses/MIT
Copyright (c) 2015 Taylor Bird
(function () {
"use strict";
var root = this,
Chart = root.Chart,
dc = root.dc,
helpers = Chart.helpers,
//class for data structure that manages filters as they relate to chart segments. This should probably be generalized to chart elements of all kinds.
FilterManager = function (segmentList) {
//private member variable
var filterMap = [];
//constructor
//accepts a list of SegmentArcs that have had the extra properties added to them
for (var i = 0; i < segmentList.length; i++) {
add(segmentList[i].segmentID);
}
//private methods
function testOnAll(test) {
var testResult = true;
for (var i = 0; i < filterMap.length; i++) {
//one failure of test means testOnAll fails
if (!test(filterMap[i])) {
testResult = false;
}
}
return testResult;
}
//add a filter, pretty much just a wrapper for push
function add(segmentID) {
filterMap.push({
"segmentID": segmentID,
"active": false
});
}
//remove a filter by id, returns removed filter
function remove(segmentID) {
var removed = filterMap.find(segmentID);
filterMap = filterMap.filter(function (elem) {
return elem.segmentID !== segmentID;
});
return removed;
}
//return this segment if it is filtered
function find(segmentID) {
for (var i = 0; i < filterMap.length; i++) {
if (filterMap[i].segmentID === segmentID) {
return filterMap[i];
}
}
return -1;
}
//public methods
return {
//tell me if the filter for this segment is active
isActive: function (segmentID) {
var filter = find(segmentID);
if (filter === -1) {
console.error("something went wrong, the filter for this segment does not exist");
}
return filter.active;
},
//for the given segment, activate or deactivate its filter. return whether the filter is on or off.
flip: function (segmentID) {
var filter = find(segmentID);
if (filter === -1) {
console.error("something went wrong, the filter for this segment does not exist");
}
filter.active ? filter.active = false : filter.active = true;
return filter.active;
},
//if all filters are on, we want to be able to quickly deactivate them all
turnAllOff: function () {
for (var i = 0; i < filterMap.length; i++) {
filterMap[i].active = false;
}
},
//tell me if all of the filters are off
allOff: function () {
return testOnAll(function (elem) {
return !elem.active;
});
},
//tell me if all the filters are on
allOn: function () {
return testOnAll(function (elem) {
return elem.active;
});
}
}
};
//utility function, Takes an array that has some property as its key
//and forms a javascript object with the keys as properties so we can get O(1) access
function createKeyMap(arr, propName) {
var keyMap = {}
for (var i = 0; i < arr.length; i++) {
keyMap[arr[i][propName]] = arr[i];
}
return keyMap;
}
Chart.types.PolarArea.extend({
name: "PolarAreaXF",
//this will have to be a member
dimension: undefined,
colorTypes: {
"NORMAL": 0,
"HIGHLIGHT": 1,
"FILTER": 2,
"FILTER_HIGHLIGHT": 3
},
chartGroup: undefined,
filters: undefined,
originalDataKeys: undefined,
initialize: function (data) {
//--PRE--
var that = this;
//Polar Area initialize method is expecting (data, options) in arguments,
//but we pass in an array of components to merge. Let's clean this up.
var argsArray = Array.prototype.slice.call(arguments);
//remove the first element of arguments which is our array, then we do a bunch of Chartjs converison on it . . .
argsArray.splice(0, 1);
//TODO - check if data is an array, if not, put a message in a console explaining how you are supposed to send data in an array
this.dimension = data.dimension;
data.chartGroup ? this.chartGroup = data.chartGroup : this.chartGroup = 0;
//short but magical line. Now we are linked with all dc charts in this group!
dc.registerChart(this, this.chartGroup);
var data = this.setupChartData(data.colors, data.highlights, data.labels);
//... and push the result in its place.
argsArray.unshift(data);
//originalDataArray -- this is used as a reference to the original state of the chart, since segments can come and go,
//we use this to track what a segment's original colors were when adding it back in. This would mess up adding a truly new segment, but who
//is gonna do that? Assumption here is dimensions start with so many groups and that is it.
this.originalDataKeys = createKeyMap(data, "key");
//parent's initialize
Chart.types.PolarArea.prototype.initialize.apply(this, argsArray);
//--modify SegmentArcs--
//assign colors and ids to all existing segment arcs
var mySegments = this.segments;
for (var i = 0; i < mySegments.length; i++) {
mySegments[i].colorList = [undefined, undefined, "#777", "#aaa"];
mySegments[i].colorList[this.colorTypes.NORMAL] = mySegments[i].fillColor;
mySegments[i].colorList[this.colorTypes.HIGHLIGHT] = mySegments[i].highlight;
mySegments[i].segmentID = i;
mySegments[i].key = data[i].key;
}
//add methods to SegmentArc objects that will color them one way or the other depending on their filter
this.SegmentArc.prototype.setIncluded = function (include) {
if (include) {
this.fillColor = this.colorList[that.colorTypes.NORMAL];
this.highlight = this.colorList[that.colorTypes.HIGHLIGHT];
} else {
this.fillColor = this.colorList[that.colorTypes.FILTER];
this.highlight = this.colorList[that.colorTypes.FILTER_HIGHLIGHT];
}
}
//--initialize filters--
this.filters = new FilterManager(this.segments);
//handle clicks on segments as filter events, do the styling and crossfilter changes at the Chart level in the filter method.
helpers.bindEvents(this, ["mousedown"], function (evt) {
var activeSegment = Chart.types.PolarArea.prototype.getSegmentsAtEvent.apply(this, [evt])[0];
this.handleFilter(activeSegment);
});
},
//convert crossfilter dimension into chart.js Polar Area data object array
setupChartData: function (colors, highlights, labels) {
var chartJSible = [];
//probably need checks here to make sure client actually passed in a crossfilter dimension
var grouped = this.dimension.group().reduceCount().top(Infinity);
//probably need checks here to either fail if the arrays aren't all long enough or have some way to add random colors/highlights if they are shorter.
for (var i = 0; i < grouped.length; i++) {
var dataObject = {
value: grouped[i].value,
key: grouped[i].key,
color: colors[i],
highlight: highlights[i],
label: labels ? (labels[i] ? labels[i] : grouped[i].key) : grouped[i].key
};
chartJSible.push(dataObject);
}
return chartJSible;
},
//figure out what changed between Chart.js' internally maintained data object array and crossfilter's dimension data. use the saved information
//about what colors and highlight a key has to rebuild the segmentArc list 'segments'. can't trash the old, it might mess up the animations.
redraw: function () {
var grouped = this.dimension.group().reduceCount().top(Infinity);
var currentSegmentKeys = createKeyMap(this.segments, "key");
var crossfilterGroupKeys = createKeyMap(grouped, "key");
//loop through the segment list, if the segment for a group is already there, update the value, if it is not there, add it back using the
//original data as a guide for what it's color and highlight color should be. if there are segments in the existing list
var length = Math.max(this.segments.length, grouped.length);
//going through both lists, whichever is longer
for (var i = 0; i < length; i++) {
var sList = this.segments;
var gList = grouped;
//only do this part if we still have items in the new filtered list
if (gList[i]) {
//we already have a segment for this crossfilter group, just get that segment and update its value
if (currentSegmentKeys[gList[i].key]) {
currentSegmentKeys[gList[i].key].value = gList[i].value;
} else {
//the chart doesn't have the crossfilter group item, add a new segment with the right colors and values from original data
var theSegment = this.originalDataKeys[gList[i].key];
this.addData(theSegment, 0, true);
}
}
//only do this part if we still have items in the current chart segment list
if (sList[i]) {
//we don't have this segment in the new crossfilter group, remove it from the chart
if (!crossfilterGroupKeys[sList[i].key]) {
this.removeData(i);
}
}
}
this.update();
},
filterAll: function () {
this.dimension.filterAll();
this.filters.turnAllOff();
this.colorMeIn();
this.redraw();
},
handleFilter: function (clicked) {
//after we have all of the filters figured out, change the colors to reflect what they should be and update the chart
this.filters.flip(clicked.segmentID);
this.colorMeIn();
if (this.filters.allOn()) {
this.dimension = this.dimension.filterAll();
dc.redrawAll(this.chartGroup);
this.filters.turnAllOff();
}
dc.redrawAll(this.chartGroup);
},
colorMeIn() {
var activeFilters = [];
var segments = this.segments;
for (var i = 0; i < segments.length; i++) {
var segment = segments[i];
if (this.filters.isActive(segment.segmentID) || this.filters.allOff()) {
segment.setIncluded(true);
activeFilters.push(segment.key);
} else {
segment.setIncluded(false);
}
}
this.dimension = this.dimension.filterFunction(function (d) {
for (var i = 0; i < activeFilters.length; i++) {
if (d === activeFilters[i]) {
return true;
}
}
return false;
});
}
})
}).call(this);
Use dc.js: https://dc-js.github.io/dc.js/
It has exactly the functionality asked for.

How can i add additional Data(Type) to chart.js

i had already done adding a click handler to each Segment of my doughnut chart with adding the following Code :
$("#myChart").click(
function(evt){
var activePoints = myNewChart.getSegmentsAtEvent(evt);
var chartelementid = activePoints[0].label;
alert(chartelementid);
//$('.details div').css("display", "none");
//$('#' + chartelementid).show();
}
);
This works fine, when finished it should display an additional Div with Details for this segment.
Unfortunality my labels are more then just Single Words, so i'm struggeling to create div ID's with the same name...
My Idea is to add to every Segment an additional Data like value,label, etc. so it could be an ID. but if i just add the ID information to the Segment it will not exist as variable.
Add DataType:
var dataImprove = [
{
value: 30,
color:"#001155",
highlight: "#1c2f7c",
label: "KnowHow Erhalt / Transfer & Aufbau",
id:"test"
}
]
where can i add in chart.js an additional dataType like shown above my ID to be accessible in the DOM?
kind regards Marco
As an alternative pass a JSON string as your label, then intercept to render. For example:
var canvas = document.getElementById(id);
var d = canvas.getContext("2d");
var chart = new Chart(d).Pie(json, {
segmentStrokeWidth: 1,
tooltipTemplate: "<%=label%>", //default the label
customTooltips: function (tooltip) {
// Hide if no tooltip
if (!tooltip) {
return;
}
var tooltipObj = JSON.parse(tooltip.text);
// etc
already found : between line 999 and 1023 in chart.js before drawing - i've added the line
id: ChartElements[0].id,
so the Data with the name ID is in the DOM avaiable.

Dojo: set store for template filteringselect

in order to get familiar with dojo I'm working on a test project which consists of the following components:
data grid (created declaratively), filled with JSON data; clicking on a line will open a dialog containing a form (works)
form (created from template), with several input fields, filled with data from the grid store (works)
FilteringSelect (part of form) (doesn't work, no content)
The FilteringSelect contains dynamic data. In order to keep data traffic low, I thought it wise to get this data when the whole page is loaded and to pass it into the template initialization function.
In fact, I don't really know how to assign the store to the FilteringSelect.
Any help would be greatly appreciated.
Here's my code. I shorten it to the what I consider relevant parts so that it's easier to understand.
Grid Part:
var data_list = fetchPaymentProposalList.fetch();
/*create a new grid*/
var grid = new DataGrid({
id: 'grid',
store: store,
structure: layout
});
// store for FilteringSelect
var beneficiaryList = FetchBeneficiaryList.fetch();
var beneficiaryListStore = new Memory({
identifier : "id",
data : beneficiaryList
});
return {
// function to create dialog with form
instantiate:
function(idAppendTo) {
/*append the new grid to the div*/
grid.placeAt(idAppendTo);
/*Call startup() to render the grid*/
grid.startup();
grid.resize();
dojo.connect(grid, "onRowClick", grid, function(evt) {
var rowItem = this.getItem(evt.rowIndex);
var itemID = rowItem.id[0];
var store = this.store;
var paymentProposalForm = new TmpPaymentProposalForm();
paymentProposalForm._init(store.getValue(rowItem, "..."), ..., beneficiaryListStore);
});
}
};
The beneficiarylist comes as something like this:
return { 12: { id : 1, name : "ABC" }};
The FilteringSelect in the template looks like this:
<input data-dojo-type="dijit/form/FilteringSelect" name="recipient" id="recipient" value="" data-dojo-props="" data-dojo-attach-point="recipientNode" />
Template Init Code looks like this:
_init: function(..., beneficiaryListStore) {
this.recipientNode.set("labelAttr", "name");
this.recipientNode.set("searchAttr", "name");
// here should come the store assignment, I guess???
var dia = new Dialog({
content: this,
title: "ER" + incoming_invoice,
style: "width: 600px; height: 400px;"
});
dia.connect(dia, "hide", function(e){
dijit.byId(dia.attr("id")).destroyRecursive();
});
dia.show();
}
For anyone who's interested, here's my solution:
var beneficiaryList = FetchBeneficiaryList.fetch();
var beneficiaryData = {
identifier : "id",
items : []
};
for(var key in beneficiaryList)
{
if(beneficiaryList.hasOwnProperty(key))
{
beneficiaryData.items.push(lang.mixin({ id: key }, beneficiaryList[key]));
}
}
var beneficiaryListStore = new Memory({
identifier : "id",
data : beneficiaryData
});
That did the trick

Refresh a Grid using dojo

I want to refresh a dojo grid in my web page. I tried .refresh which is given in dojotoolkit.org without success. is there any other convenient way to do refreshing? Thanks in advance.
Maybe this helps. This is the way i refresh my Grid:
if(!registry.byId("GraphGrid")){
var grid = new EnhancedGrid({
id: 'GraphGrid',
store: GraphicStore,
query: { ident: "*" },
structure: layout,
rowSelector: '20px',
plugins: {
indirectSelection: {
headerSelector:true,
width:"40px",
styles:"text-align: center;"
}}
},"GridGraphicInMap");
/*Call startup() to render the grid*/
grid.startup();
dojo.connect(grid, "onRowClick", grid, function(evt){
var idx = evt.rowIndex,
item = this.getItem(idx);
// get a value out of the item
var value = this.store.getValue(item, "geom");
highlightGeometry(value,true);
// do something with the value.
});
}
else {
registry.byId("GraphGrid").setStore(GraphicStore);
}
When i first call my function the grid is generated. Evrytime i call the function later only the store is refreshed.
Regards, Miriam

problem with my tableView GROUPED

Here I have a problem with my tableView I want to insert text into each row of the table
can you help me please
here is the code
// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('white');
// create tab group
var tabGroup = Titanium.UI.createTabGroup({
});
// create base UI tab and root window
var win1= Titanium.UI.createWindow({
title:'',
tabBarHidden: true,
barColor:'black',
backgroundColor:'white'
});
var tab= Ti.UI.createTab({
title:'Connexion ',
window:win1
});
//
// This is a test that is meant to verify that a row object can have a header
// and the table view has no table view header - the header should be displayed
var win = Titanium.UI.currentWindow;
var inputData = [
{title:'Pseudo/email :', header:'Connexion ......'},
{title:'Password :'},
{title:'Créer votre compte',hasChild:true, header:'not yet registered ?'},
];
var tableView = Titanium.UI.createTableView({
data:inputData,
style:Titanium.UI.iPhone.TableViewStyle.GROUPED
});
win1.add(tableView);
tabGroup.addTab(tab);
// open tab group-----------------------------------------
tabGroup.open();
win1.open();
that's what I did right now but I have a problem with the title of my table and then I add another table.
there are also some ouci with the cursor which moves in the mid-line titles
here is the code
var win1= Titanium.UI.createWindow({
title:'',
tabBarHidden: true,
barColor:'black',
backgroundColor:'white'
});
var view = Titanium.UI.createView({
backgroundColor: "#FFFEEE"
});
var row1 = Ti.UI.createTableViewRow({
height:'auto',
selectionStyle:Ti.UI.iPhone.TableViewCellSelectionStyle.NONE
});
var label1 = Titanium.UI.createLabel({
text:'Pseudo/e-mail :',
left: 10
});
var usernametf = Ti.UI.createTextField({
left: 100,
right:10,
//hintText: 'Pseudo/email :',
//textAlign:"right",
borderStyle: Ti.UI.INPUT_BORDERSTYLE_NONE
});
var row2 = Ti.UI.createTableViewRow({
height:'auto',
selectionStyle:Ti.UI.iPhone.TableViewCellSelectionStyle.NONE
});
var label2 = Titanium.UI.createLabel({
text:'Mot de passe :',
left: 10
});
var passwordtf = Ti.UI.createTextField({
left: 100,
//textAlign:"right",
//hintText: 'password',
right:30,
passwordMask:true,
borderStyle: Ti.UI.INPUT_BORDERSTYLE_NONE
});
row1.add(label1);
row1.add(usernametf);
row2.add(label2);
row2.add(passwordtf);
var data = [row1,row2];
var table = Ti.UI.createTableView
({
data:data,
style: Ti.UI.iPhone.TableViewStyle.GROUPED
});
view.add(table);
win1.add(view);
win1.open();
I let you know that I really began with Appcelerator
Is there any reason why you wouldn't just use textfields? You could then just grab the values on button press and insert.
Kitchen Sink example link
https://github.com/appcelerator/titanium_mobile/blob/master/demos/KitchenSink/Resources/examples/textfield_events.js
Another example of a screen like this would be the Tweetanium App https://github.com/appcelerator/tweetanium
Whether you use textfields or tableviews there are several ways to work with the Ti Database object.
Two common ways would be:
1) You can loop through your inputData object and insert. Below are a few examples.
https://github.com/appcelerator/titanium_mobile/blob/master/demos/KitchenSink/Resources/examples/database_2.js
https://github.com/appcelerator/titanium_mobile/blob/master/demos/KitchenSink/Resources/examples/database_3.js
2) You can use the tableview object itself or a wrapper similar to this example https://github.com/kwhinnery/Persistence
I would recommend using textfields if possible.