My issue is react-leaflet tooltips overlapping. When hovering over either a marker or the corresponding list on the right-hand side, the tooltip above it increases in size. However, I want the tooltip to appear layered above other tooltips.
I tried changing the style z-index in styling, but that doesn't work. I found a suggestion to change the Tooltip pane instead, but that didn't work either. It seems like changing the pane doesn't update.
Default pane reference: https://leafletjs.com/reference-1.5.0.html#map-pane
render() {
var job = this.props.job;
var icon_to_use = pointerIcon;
var css_class = 'tooltip-normal';
var paneToUse = 'tooltipPane';
if (this.props.selectedJob === this.props.id) {
css_class = 'tooltip-bold';
paneToUse = 'popupPane';
}
return (
<div>
<Marker position={[job.lat, job.lng]} pane={'markerPane'} icon={icon_to_use}>
<Tooltip permanent={true} pane={paneToUse} direction {'top'} offset={L.point(-10, -15)}>
<div className={css_class}>
{job.location}
</div>
</Tooltip>
</Marker>
</div>
)
}
The way I'm deciding which Tooltip should currently be active is by checking if this.props.selectedJob equals the current id. This works perfectly fine for assigning the css class in this line: css_class = 'tooltip-bold';, but not for the next line where I'm assigning the popupPane.
Even though I'm assigning the pane in the Tooltip component, they don't change in the actual application. Is there any way to dynamically make one tooltip overlay another based on hovering?
I found a solution, and I figure I'll post it here in case someone else comes across this. I simply had to set the tooltip className to a class with a certain index. Here's the basic idea (leaving out some unnecessary stuff):
if(condition){
tooltipCssClass = 'front-tooltip-class';
}
return (
<Tooltip permanent={true} className={tooltipCssClass} direction={'top'} offset={L.point(-10, -15)}>
...
</Tooltip>
)
CSS:
.back-tooltip-class {
z-index: -100;
}
.front-tooltip-class {
z-index: 100;
}
Related
I am trying to show tooltip on mouse enter and hide on mouse leave.first i make a simple demo which is working fine.
https://codesandbox.io/s/exciting-shannon-4zuij?file=/src/list.js
above code working fine on hover it show's the tooltip and hide on leave.
see same concept i apply on a application.(this code is not working)
https://codesandbox.io/s/cool-liskov-8rvjw?file=/src/App.js
when I hover a item is show the tooltip.but it is not hiding the tooltip when you leaving the item.something went wrong.
const Student = ({students,clickHandler}) => {
console.log(students,"---ee")
const [selectedStudent,setSelectedStudent] = useState(null)
const onMouseHandler = (student,e)=>{
student.visibility = true
setSelectedStudent(student)
}
const onMouseLeaveHandler = (student)=>{
console.log('======',student)
student.visibility = false
setSelectedStudent(student)
}
return (
<ul className="student-container">
{
students && students.length > 0 ? students.map((student,index)=>{
return (
<li key={index} onClick={()=>{
clickHandler(student)
}}
onMouseLeave={()=>{
onMouseLeaveHandler(student)
}}
onMouseEnter={(e)=>{
onMouseHandler(student,e)
}} style={{position:'relative'}}>
<a><span>{student.name}</span></a>
{student.visibility? <ToolTip showToolTip={student.visibility} selectedStudent={selectedStudent}/>:null}
</li>
)
}):null
}
</ul>
);
};
export default Student;
Step too reproduce
Hover on first item Raj
and then try to hover sameer.both tooltip will display.I want only one tooltip will be display which is hovered.
I want my handlers should be in my functional component . I don't want to move these handler to parent component and pass handler as a props
In your demo it's also not work well, - one hide only when open another.
when you set student.visibility you not set state, so nothing has rerendered.
Then when you call setSelectedStudent you pass there just the same referance as was before, since it's the same object, so the state not changed, and again - nothing got rerendered.
What you have to do is pass the updated student in a new variable. like so:
setSelectedStudent({...student})
Then all should work
This question already has answers here:
Getting the ID of the element that fired an event
(24 answers)
Closed 10 months ago.
<tooltip message="Click" content="preview"></tooltip>
<tooltip message="Tooltip 1" class="repeat-tooltip" content="Click tooltip 1 preview"></tooltip>
<tooltip trigger="hover" class="repeat-tooltip" message="Hover Tooltip" content="Hover tooltip preview"></tooltip>
New and trying to create a custom tooltip tag and only one tooltip will be active at a time.
<tooltip>
<p class="tooltip-content" control="tooltip">{ message } ref="target"</p>
<div class="tooltip-wrapper" show={show_message} ref="content">
//inner html
</div>
</tooltip>
Trying to use show toggling show_message value to display and hide the tooltips. But show_message is within the context of that particular elements click event. Onclick of a particular tooltip, how can I access other custom tag's context to hide the value of that particular element if that tooltip already open?
this.root.addEventListener('click', (e) => that.toggle_message(e));
this.toggle_message = function(e) {
//here close all other tooltips before opening this one. How can I access the refs of all the open tooltip?
this.show_message = !this.show_message;
this.update();
};
From the specs of Riot.js I could not find anything that will allow you to keep track of all tags of same type so solution that I can think of for this particular scenario is to store collection of tooltips under windows and show/hide them on click of each individual tooltip.
As I do not have all component that you posted, I created bare minimum working example over here.
My demo component look like:
<tooltip>
<p>{ content }</p>
<span riot-style="display: { show_message ? 'inline-block' : 'none' }; background: black; color: white; padding:3px;"> { message } </span>
const self = this;
this.content = opts.content || '';
this.message = opts.message || '';
this.root.addEventListener('click', (e) => self.showTooltip(e));
this.toggle_message = function(show) {
self.show_message = show;
self.update();
};
this.showTooltip = function(e){
const bShow = !self.show_message;
for(var i=0; i<window.tooltips.length; i++){
window.tooltips[i].toggle_message(false);
}
self.toggle_message(bShow);
};
<script>
this.on('mount', function(){
if(!window.tooltips)
window.tooltips = [];
window.tooltips.push(this);
});
</script>
</tooltip>
On mount event it adds it's self to window.tooltips array collection and later when one of the components is clicked, event handler iterates through all registered components and hides them before showing current component.
Update - I found a better solution here using riot events. Add the events to windows and listen to that event on document body click and other trigger elements click, so that you will get the context of all tooltips and close it.
I have been trying to implement a hover effect on a div-element like in this codesandbox:
https://codesandbox.io/s/XopkqJ5oV
The component in which I want to do this, is a reusable component that is used multiple times on the same page. I suppose that is the reason why I can't get it to work. What am I missing?
Even using the above code won't work in my application.
EDIT: Thank you for your responses. I found the issue:
I was not letting ShouldComponentUpdate know, it should take state.isHovering into account.
shouldComponentUpdate(nextProps, nextState) {
return (
nextProps.post.id !== this.props.post.id ||
nextProps.screenshotClickUrl !== this.props.screenshotClickUrl ||
nextProps.onImageClick !== this.props.onImageClick ||
nextProps.handleMouseHover !== this.props.handleMouseHover ||
nextState.isHovering !== this.state.isHovering
)
}
You're missing a this in:
toggleHoverState(state) {
return {
isHovering: !state.isHovering // Need a "this" to access state.
};
}
If you stack the elements too closely it will interfere with the mouse enter/leave events, e.g., if you space them apart:
const Foo = () => {
return (
<div>
<HoverExample />
<div style={{height: '2em', border: '1px solid blue'}} />
<HoverExample />
</div>
)
}
it work like (I think) you'd expect.
https://codesandbox.io/s/93l25m453o
I put borders around it to help visualize the issue.
If that doesn't make sense, see what happens when you have the hover indicator in an adjacent span rather than stacked:
https://codesandbox.io/s/5k5jj3rpok
I have some files that load into my react components, which have HTML code.
As it is now, the pure HTML code renders just fine, however there is some 'hidden' code that appears whenever you click certain buttons in other parts of the application or on the text above (think of it like panels that expand when you click on it).
The HTML is hidden just using the good old <div id="someId" style="display:none">.
Anyway I am trying to get the correct panel to expand upon clicking their respective buttons.
So in theory, what I need to do is find the element by id, and switch it's display to block whenever needed, and then switch it back when the parent is clicked again.
Unfortunately I have no idea how to do this and so far have gotten nowhere. As it is now, I have access to the component's ids. What I want to know is how in the world can I access that and get to change whatever is rendering?
Create your function:
function element_do(my_element, what_to_do) {
document.getElementById(my_element).style.display = what_to_do;
}
and latter in code you can append wherever you want through javascript onclick or not depends what do you need:
element_do("someId", "none"); // to hide
element_do("someId", "block"); // to show
or create yourself toggle:
function toggle_element(element_id) {
var element = document.getElementById(element_id);
element.style.display = (element.style.display != 'none' ? 'none' : 'block' );
}
// and you can just call it
<button onClick="toggle_element('some_id')">toggle some element</button>
The react way to do it would be with states. Assuming that you know how to use states I'd do something like this:
class ShowHide extends React.Component {
constructor() {
super();
this.state = {myState: true};
this.onClick = this.onClick.bind(this)
}
onClick() {
this.setState({myState: !this.state.myState}) //set the opposite of true/false
}
render() {
const style = {myState ? "display: none" : "display:block"} //if myState is true/false it will set the style
return (<div>
<button onClick={this.onClick}>Click me to hide/show me </button>
<div id="myDiv" style={style}> Here you will hide/show div on click </div>
</div>)
}
}
I have a progress bar that I am building in React.js and Zurb Foundation that I would like to reflect the current state. I understand that in the beginning I can set the width with something like this:
render: function() {
var spanPercent = (this.props.a - this.props.b)/this.props.a + '%';
var spanStyle = {
width: spanPercent
};
return (
<div className="progress">
<span className="meter" style={spanStyle}></span>
</div>
);
}
however, when the value of props changes due to a state change, the inline style doesn't update even though the props value changes. Is there a best practice for doing this, such as using a callback, or placing the code somewhere else? I would appreciate any help!
One solution is to put a key of the percentage on the element you want to update. That way when react checks to see what in the DOM has changed it sees that the key has changed and thus will rebuild the DOM for the element.
See example below:
render: function() {
var spanPercent = (this.props.a - this.props.b)/this.props.a + '%';
var spanStyle = {
width: spanPercent
};
return (
<div className="progress">
<span key={spanPercent} className="meter" style={spanStyle}></span>
</div>
);
}