How to style features depending on comparison operators in Leaflet - switch-statement

All the examples I find online that talk about how to style a feature depending on one of its properties use a switch statement that evaluates whether that property corresponds to a specific value.
For example this is taken form one of Leaflet's official tutorials:
L.geoJSON(states, {
style: function(feature) {
switch (feature.properties.party) {
case 'Republican': return {color: "#ff0000"};
case 'Democrat': return {color: "#0000ff"};
}
}
}).addTo(map);
What if I wanted to determine the feature's color depending on a numeric treshold? Say all features that have propertyX (which is a number) bigger than a certain value get colored red, otherwise blue.
I found this post where one user explains that switch statements are not made for comparisons; how can I do one then?
If use an external function (see code below) the latter seems to not be able to access the feature's properties.
L.geoJSON(states, {
style: styling
}).addTo(map);
function styling () {
if (feature.properties.numericProp > 100) {
return {color: "red"}
} else {
return {color: "blue"}
}
}

The feature gets passed a parameter of your function, you forgot to add it:
function styling (feature) {
// feature is now available
}

Related

Rendering one of multiple pages with lit-element

The lit-element documentation describes conditional rendering via (condition ? a : b). I was wondering how to use that to render one of multiple pages, f.e. in combination with mwc-tab-bar from Googles material web components.
My current solution is something like this:
render() {
... other stuff ...
${this.selectedPage === 0 ? html`
<div>
...
</div>
` : html``}
${this.selectedPage === 1 ? html`
<div>
...
</div>
` : html``}
... further pages ...
}
I don't like the :html`` part but is that how it's meant to be?
Use more simple code like this.
constructor(){
super();
// don't forget add `prop` and `selectedPage` to `static get properties()`
this.prop = 1;
}
render() {
return this.getPage(this.selectedPage);
}
getPage(num){
switch(num){
default:
case 1:
return html`<div>P${this.prop}<div>`;
case 2:
return html`<div>P2<div>`;
}
}
There are multiple ways of achieving this, your solution is one, but as you mention, it's not the prettiest
One way you could modularize this somewhat is using an object/array and render functions, basically the idea is this:
First, define render functions for each page (this can be on the same file or on different files):
const page0Renderer = (context) => {
return html`<section>${context.someData}</section>`;
};
Then, you could define an object that has a match between the page identifiers and their respective functions, you are using numbers so the sample below uses numbers:
const pageRenderers = {
'0': page0Renderer,
'1': page1Renderer,
'2': page2Renderer,
// etc
};
And in your main render function you could use all these like this:
render() {
return html`
${pageRenderers[`${this.selectedPage}`](this)}
`;
}
This would basically call the render function that matches the selected page and send it a reference to the main web component so that you can access its properties.
Then again, this approach also has its flaws and I wouldn't really recommend it much if you need your child templates to be complex.
In that case, instead of rendering functions you probably would be better off creating other components for each view and that way you could also do some lazy loading and so on.
For that kind of approach, you might want to check out routers like vaadin router which help you both with routing and changing which component gets displayed accordingly

Azure maps - change the color of a pin based on data driven styling

I am trying to create a data driven layer style that uses a boolean expression, but I am not sure how to make it work.
I have a Feature shape defined. Notice the property bag has an assigned property.
new atlas.data.Feature(new atlas.data.Point([-122.3802, 47.54384]), {
leaseNo: '928928A',
assigned: true
}),
Then for the SymbolLayer the Feature is assigned to uses a style definition as...
iconOptions: {
image: [
'match',
['get', 'assigned'],
['==', 'true'], 'marker-red',
'marker-darkblue'
]
}
It retrieves the value of the assigned property and returns a marker based on whether the value is true or false.
However, it's not working, so my syntax isn't correct. Can someone help me with the syntax to make this work?
I found a solution using case.
iconOptions: {
image: [
'case',
['get', 'assigned'], 'marker-red',
'marker-darkblue'
]
}

Changing anyMatch default for Filter.JS in ExtJS for MultiSelect search

I have a multiselect bound to a store in which I implemented use of anyMatch: true to allow for True to allow any match - no regex start/end line anchors will be added (as per the comment in Filter.js). My problem is that I need to implement this as per the answer to multiselect-search-whole-string, in particular the solution provided in this fiddle https://fiddle.sencha.com/#fiddle/jf5
What I want to do is just set anyMatch: true, regardless, so I set it in Filter.js, but this has no effect on use of it. I searched the entire codebase for other instances of anyMatch: false and the only other one is in ext-all-debug.js. Why isn't setting these values having any effect? I don't see where else this default value could be set?
EDIT 1
I tried a different override, and while it is not exhibiting the right behavior, it is actually doing something this time. I figured that since the chunk of code that does work when embedded in the search attribute within the MultiSelector control was pretty much what was found in the MultiSelectorSearch's search method, that this was what I needed to focus on for the override. Any suggestions on tweaking this would be most welcome:
Ext.define('Ext.overrides.view.MultiSelectorSearch', {
override: 'Ext.view.MultiSelectorSearch',
search: function (text, me) {
var filter = me.searchFilter,
filters = me.getSearchStore().getFilters();
if (text) {
filters.beginUpdate();
if (filter) {
filter.setValue(text);
} else {
me.searchFilter = filter = new Ext.util.Filter({
id: 'search',
property: me.field,
value: text,
anyMatch: true
});
}
filters.add(filter);
filters.endUpdate();
} else if (filter) {
filters.remove(filter);
}
}
});
EDIT 2
Got it! The key was that originally, since this code was embedded in a singleton, I could reference the method by passing me from the calling form.panel. This did not work globally as an override, and required me to define the method as
search: function (text) {
var me = this,
I hope this helps someone out there!
Changing in ext-all-debug.js is not safe, when you do a production build this file will not get included.
Best way is to override the Filter class, here is how you can do it.
Ext.define('Ext.overrides.util.Filter', {
override: 'Ext.util.Filter',
anyMatch: true
});
And import this class in Application.js
Ext.require([
'Ext.overrides.util.Filter'
]);

How to attach a property to string?

Can I do something like this in haxe:
trace ("Blue".description);
trace ("Green".description);
trace ("Red".description);
then, somewhere add a switch based on string value to return different description for each case?
I saw people using this for localization, like "Car".i18()
Any one can help?
Check out static extensions.
Basically it allows you to pretend static methods are member methods, but the first argument is the object you're operating on.
In your example
class ColorDescriptions {
static public function description( color:String ) {
return switch (color) {
case "red": "passionate";
case "blue": "calm";
case "green": "environmentally friendly";
default: "unknown colour";
};
}
}
And then:
using ColorDescriptions; // Use static methods from `ColourDescriptions` as mixins
...
trace( "red".description() ); // "passionate"
This only works with methods/functions, not properties. So "red".description() is possible, but "red".description is not.

using object.defineproperty with knockout observables

can i (and if yes how) create a ko.observable out of a object.defineproperty something like this
Strength: ko.observable(
Object.defineProperty(this, "strength", {
get: function () {
return this.level * 2;
},
enumerable: true
});
)
and
<span> str: <span data-bind="text: Strength"></span> / 100 </span>
what im trying to do is update the display of strength when its called after every level-up
i.e.
level up
(fight) request the current strength
update strength (+=2)
update strength display
using Object.defineProperty
i would probably just use ko.computable, but im wondering if there is a way to do it.
a bit unclear what you want to achive but I'd go with ko.computed. If you want the subscribers (namely your span) of your Strength property to be notified (when the level changes after the initial binding), you should also make level observable.
if you still want to use defineProperty, I hope this little example suits you (edit: added a button to level up)
function ViewModel() {
var self = this;
self.level=ko.observable(5);
self.really_use_computed = ko.computed(function() {
return self.level() * 2;
});
}
var MyViewModel=new ViewModel();
Object.defineProperty(MyViewModel, "Strength", {
get: function () {
return this.level() * 2;
},
enumerable: true
});
ko.applyBindings(MyViewModel);
please note that Internet Explorer 8 standards mode supports DOM objects but not user-defined objects for the first argument of Object.defineProperty() and that earlier versions of IE don't support Object.defineProperty() at all.
The Knockout ES5 plugin will do what you need. Although I had to also include the Weakmap shim to make it work.

Resources