vis.js timeline set custom background color on items without overwriting borders - vis.js

I'm using vis.js timeline and I'm trying to find a way to mark workhours (give them a different background). Using the backgrundareas with groups example I have managed to get my workhours colored for specific dates.
I do not want to use the standard blue color for background, so in order to avoid this I add a class workhours. Then I can set my custom color, but then the borders of the cells are hidden unless I also set a opacity less than 1.
I have a color scheme which I'm using, so setting opacity changes the color and my workhours does not look the same in the whole application.
I'm using this code
.vis-item.vis-background.workhours {
background: ##AFD9FE;
opacity: 0.75;
}
and where filterFromdate is my start date, durationDay is numbers of days in my timeline and startHour and endHour defines my working hours
for (i=0; i<durationDays; i++) {
items.add([
{
id: "W"+i,
start: moment(filterFromdate).add(i, 'days').hour(startHour).valueOf(),
end: moment(filterFromdate).add(i, 'days').hour(dayEndHour).valueOf(),
className : 'workhours',
type: "background"
}
]);
}
this give me
Can anyone tell me how to either get my class workhours to behave like a standard vis background class (like vis-today)?
or if there is another approach to handle background on specific hours (or days)?

Thanks to Issue 3773 I reliased that I could set the z-index, which did the trick.
So my css ended up being
.vis-item.vis-background.workhours {
background: #AFD9FE;
z-index: -1;
}

Related

CSS Calc setting a new z-index value based on current z-index value

I have a Leaflet map with hundreds of map markers.
Some of these map markers are underneath others, as the map is crowded.
The user would like certain types or criteria of markers to appear on the top of the marker "stack" on the map.
This is easily done with adjusting the Z-index of each marker element.
The marker elements currently have this below CSS, which is loop-generated by Leaflet.js in the construction/population phase:
/* Constructed by Leaflet 1.7 */
element {
margin-left: -10px;
margin-top: -20px;
width: 25px;
height: 30px;
transform: translate3d(551px, 252px, 0px);
z-index: 58;
outline: currentcolor none medium;
}
The value of z-index is a counter of markers, so this marker is number 58, and the next marker, (regardless of its position on the map) has z-index: 59;, etc.
Here is an example difference, with manually edited z-index;
Above; some red pins are hidden behind blue pins. These would need to be promoted to be more visible.
Above; red pins are promoted above other pins via z-index editing, but also retain their stacking with each other (Ascending).
However, because the number of markers is variable the value of z-index is also variable. I can of course update all of these with javascript, and I'm almost certain that will have to be done, but I was curious if:
Is there a way with CSS (only) to relatively update the z-index value, based on its current value?
For example; to 'promote' this marker could be z-index: calc(<current_value> + 200);
However, I can not find a CSS-only way of catching the current value of Z-index; most "calc" current values use 100% but Z-index does not use percentage.
Why can't we just set it to some high number?
Using some arbitary high catch-all value will not give an ideal result because, for example, setting the z-index to 9999 means all the selected marker elements will have the same z-index. The markers are output from database data and ordered in a certain way (in this case, by date), so the group of markers that are "promoted" should still be relative to each other, while being promoted with an added value to their z-index above those who are not in the group.
One idea could be the use of translateZ() to promote all the elements the same way but I see that you already have transform applied. You can probably apply it to another wrapper.
Here is an illustration of the idea:
$('.box i').each(function() {
var z = $(this).index();
$(this).css('z-index',z);
});
.box{
padding:20px;
counter-reset:num;
transform-style:preserve-3d; /* here */
}
.box i {
display:inline-block;
position:relative;
margin:0 -5px;
border-radius:50%;
height:30px;
width:30px;
background:blue;
border:2px solid green;
color:#fff;
font-size:25px;
}
.box i::before {
content:counter(num);
counter-increment:num;
}
.box i.red {
background:red;
transform:translateZ(1px); /* and here */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box">
<i></i><i></i><i></i><i></i><i></i><i class="red"></i><i></i><i></i><i class="red"></i><i></i><i class="red"></i><i></i><i></i><i class="red"></i><i></i><i></i><i class="red"></i><i class="red"></i><i class="red"></i><i></i><i></i><i></i>
</div>
You're wrong in this part of your analysis:
The value of z-index is a counter of markers, so this marker is number 58, and the next marker, (regardless of its position on the map) has z-index: 59;, etc.
Leaflet manages the zIndex of the marker icons so that markers further north (up) have a greater zIndex than those south (down), with this bit of code, setting a value that is later applied to the CSS property of the icon's ImageHTMLElement:
this._zIndex = pos.y + this.options.zIndexOffset;
But Leaflet markers have a zIndexOffset option to control the kind of issue you're facing. There's also a setZIndexOffset method available in L.Markers to change this value, e.g.:
marker1.setZIndexOffset(100);
marker2.setZIndexOffset(0);
Assuming that you have markers in a L.LayerGroup (or a L.FeatureGroup or L.GeoJSON), you can leverage its invoke method to call setZIndexOffset on all of its markers at the same time, e.g.
groupWithRedMarkers.invoke("setZIndexOffset", 100);
groupWithBlueMarkers.invoke("setZIndexOffset", 0);
The value of zIndexOffset should be at least the height of the marker icons (measured in CSS pixels), since Leaflet uses screen pixel coordinates to calculate the final zIndex values. Remember to reset the zIndexOffsets to zero when needed.
Another approach would be to leverage map panes, assuming that the criteria to display markers on top/bottom doesn't change through time.
The tl;dr version would be:
map.createPane('topmarkers');
map.getPane('topmarkers').style.zIndex = 650;
marker = L.Marker(latlng, {pane: 'topmarkers'});
Is there a way with CSS (only) to relatively update the z-index value, based on its current value?
No, since Leaflet changes the z-index of markers dynamically as the user pans and zooms the map.

Changing the style of a leaflet cluster when pressing it

I have created a map with clusters created like so:
//create clustering markers
var markers = L.markerClusterGroup({
spiderfyOnMaxZoom: false,
showCoverageOnHover: false,
zoomToBoundsOnClick: false,
singleMarkerMode: true, //makes sure that single incidents looks the same as clusters (but are still treated as single markers)
iconCreateFunction: defineClusterIcon
});
var layer_group = L.geoJSON(geoJson);
markers.addLayer(layer_group);
map.addLayer(markers);
map.fitBounds(markers.getBounds());
In the defineClusterIcon function, I create a SVG which then is converted to HTML and defines the icon:
return L.divIcon({
iconSize: new L.Point(40, 45),
html: html,
classname: 'leaflet-div-icon'
});
I now want to be able to change the style of the cluster (or marker, which also is styled as a cluster), when pressing it - and I want it to return to the original styling when pressed again.
Instead of changing the style of the actual svg elements, I am thinking that it might be easier to just change the style of the class:
.leaflet-div-icon {
background: rgba(0,0,0,0);
border: none;
}
Where I then want to have a border when the cluster/marker has been pressed. I do not know, whether it is possible to change the class within the on clusterclick or click functions, or if it can be done in another way.
My code, as it is now can be found here - where the wanted effect also can be seen on the controls on the right side: http://bl.ocks.org/skov94/f006cd45d2daa2bc67e4f514774fdd0d
Instead of switching the outline property of the leaflet-interactive div, i would toggle a class as you did with the controls on the right side (say a outlined class).
This class toggling has to be done in a "onclick" event handler. Leaflet clustering provide its own cluster click events (clusterclick).
The possible targets of the clusterclick event seem to be either the text, circle, or svg nodes of the cluster. We want to get the enclosing div with class leaflet-interactive to add or remove the outlined class on it. This will be made easily possible with Element.closest:
Javascript file
markers
[...]
.on('clusterclick',function(c) {
console.log("pressed");
map.closePopup();
c.originalEvent.target.closest(".leaflet-interactive")
.classList.toggle("outlined");
});
Then, simply change the style of its circle descendants with css:
CSS file
.leaflet-interactive.outlined circle {
stroke-width: 2px;
stroke: blue;
}
Edit: If you're not familiar with css, the selector means: circle nodes that are descendants of nodes with classes leaflet-interactive AND outlined.

JavaFX2.0 fx-pref-width not working

I use JavaFX2.0 to my java application, then I use .fxml file to build my UI, then I use css to decorate button or label.
Just like:
/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
.lebel{
-fx-alignment: center ;
-fx-pref-width:20% ;
-fx-pref-height: 180 ;
-fx-background-color: transparent ;
-fx-text-fill: white ;
-fx-background-size: stretch;
-fx-padding: 0 0;
-fx-font-size: 20sp;
}
Five labels are placed horizontally, but the property -fx-pref-width:20% doesn't work on the UI. I am trying to use -fx-pref-width:% to design UI for different sizes of stage.
-fx-pref-width is defined by Region. See this.
This is the abstract from it:
Property: -fx-min-width, -fx-pref-width, -fx-max-width
Values: < number >
Default: -1
Comments: Percentage values are not useful since the actual value would be computed from the width and/or height of the Region's parent before the parent is laid out.
So, percentages are not supported. You would need to do it using code via binding perhaps.

How to set color, width and draw dashed line simultaneously for javafx line?

I have to draw multiple lines using javafx line chart. Since one line can overlap other lines. I want to use dashed line or line with different thickness to represent each line.
Below is my code snippet:-
for (XYChart.Series<Number, Number> s : chart.getData()) {
// Used for Line color
if (("Current Threshold").equals(s.getName())) {
s.getNode().setStyle(" -fx-stroke-width: 10; ");
s.getNode().setStyle("-fx-stroke: #00FF00; ");
s.getNode().setStyle("-fx-stroke-dash-array: 2 12 12 2; ");
}
else if(some condition)
{
// Some other condition to draw other lines
}
}
where chart is instance of LineChart.
Node.setStyle() methods override each other. I am unable to set multiple style together. Last style persists and others are overridden. ie for above sequence, dashed line is drawn. I am using css styles in java code.
Is there any way to apply multiple style, without overriding others.
Thanks
Node.setStyle() is, as the name should suggest, a setter method for the style attribute of a JavaFX Node.
By calling this method three times in a row, only the last invocation has an effect as the previous ones get overwritten.
So if you want to apply all three styles you should write:
node.setStyle("-fx-stroke-width: 10; -fx-stroke: #00FF00; -fx-stroke-dash-array: 2 12 12 2;");
Or even better, use a CSS File, see this answer for further reference: JavaFX Text styling for dynamic objects

FullCalendar event text colour change

I added className fc-selected to [any selected day] which took care of my background colour changes for that selected cell. Thinking that I was home free and only needed to change color for the text next, I forcefully removed a few locks of hair when, only way later, did I realize that the date events are not even in the date cell but absolutely positioned above and outside of it.
How can I target the DOM of the events for a selected date in the calendar?
PS: Basically the background color for a date cell goes dark red on selection and I need the title text to temporarily change to white.
You can set an event's
textColor: white or #FFF
http://arshaw.com/fullcalendar/docs/event_data/Event_Object/
You can also set eventTextColor while redering event
http://arshaw.com/fullcalendar/docs/event_rendering/eventTextColor/
Actually, I tried many times and any variations of textColor or eventTextColor didn't worked at all. So, I tried changing color attributes manually;
.portlet.calendar .fc-event .fc-time {
color: white;
}
.portlet.calendar .fc-event .fc-title {
color: white;
}
By using simple javascript like this you can also set font-color of fullcalendar;
var colorStyle = document.getElementsByClassName('fc-title');
for (var i=0; i<colorStyle.length; i++) {
colorStyle[i].style.color = 'white';
}

Resources