How can I make a SVG element clickable on React? - javascript

I am using React Native with Expo and I have 4 SVG elements that I need them to be clickable. This is the code for each of these:
<Svg.G
id="Passangers-Going-B"
onPress={() => console.log(`${cardinalPoint} Avatar Was Clicked`)}
>
...
With that code I am able to click on the SVG element but the weird thing is that when I try to click on another element the click is still firing the event of the last element I clicked on.
I recorded a video with the behavior
So, is there a better way to do this? All I need is to click on those SVG elements in order to change to a new route.
Any ideas?
I am using SVG from expo. import { Svg } from 'expo'; -> https://docs.expo.io/versions/latest/sdk/svg/
I also created a Snack but I don't see it is working at all -> https://snack.expo.io/#maketroli/expo.svg-example?session_id=snack-session-_9YKofW2Y
What I see is that if I click on one of the elements the click gets stuck there because if I click a new element it throws the function of the last clicked element. I have to click around 3 times the new element in order to focus the click on that element.
I saw something about PanResponder but I don't know this has something to do with it.

You should wrap your SVG into a Component that aims only to handle the Press event.
import { TouchableOpacity } from "react-native"
<TouchableOpacity onPress={() => console.log(`${cardinalPoint} Avatar Was Clicked`)}>
<Svg.G
id="Passangers-Going-B"
/>
</TouchableOpacity>
You will need to style it appropriatly.

Related

How to use d3 component in react without breaking its animation

I was trying out d3 sunburst component from here. I wanted to use it in react. To use it in react, we have to use another library called react-kapsule:
import SunburstChart from "sunburst-chart";
import fromKapsule from "react-kapsule";
const ReactSunburst = fromKapsule(SunburstChart, {
methodNames: ["onClick"]
});
<ReactSunburst
width={200}
height={200}
label="name"
size="size"
data={flare}
onClick={(entry) => {
console.log("Hello from inside onClick handler!!");
}}
/>
It renders as follows:
The problem is with specifying custom onClick handler. When I specify methodNames: ["onClick"], clicking on slice of sunburst chart zooms in that slice, but it does not log the message to the console. codesandbox link
If I remove onClick from methodNames, it logs the message to method names, but it does not zooms in the slice. codesandbox link
How I add working onClick handler while at the same time ensuring that the component's default behavior wont break?

append material ui snackbar to body

I have a component that is only visible when a user hovers over it. In that component I have a button which allows the user to add something to the local storage. If the button is clicked the component is removed from the DOM. This works fine, but I want to show the user a toast when the action is completed. The issue is that the toast is also removed when the button is clicked because it's part of that component:
return (
<React.Fragment>
<Overlay backdrop_path={movie.backdrop_path}>
<div>
<AddMovie onClick={() => addMovie(movie)}>Add movie to your watchlist</AddMovie>
</div>
</Overlay>
<Snackbar
open={open}
onClose={handleClose}
TransitionComponent={Slide}
message="Movie has been added"
/>
</React.Fragment>
)
I rather not put the Snackbar toast in a different component because this component is responsible for adding a movie to the local storage, and I don't want to do a lot of props lifting etc to get the result.
So I thought, maybe it's possible to append the Snackbar element to the body instead of the components element. This way if the components element is removed the Snackbar should still be visible. Not sure if this logic will actually work though.
Is it possible to append a element/component to another part of the DOM structure, if so: how?
Seems appending rendered elements into other DOM elements isn't difficult:
return ReactDOM.createPortal(
<Snackbar
open={true}
onClose={handleClose}
TransitionComponent={Slide}
message="Movie has been added"
/>,
document.body
);
But this element also gets removed the instant the component that renders it is removed. Which makes sense. So it looks I need to render the Snackbar in a different element. Shame.
// edit. By using Redux it might be possible to create a global state for using the Snackbar elements > https://browntreelabs.com/snackbars-in-react-redux-and-material-ui/
// edit#2. https://github.com/iamhosseindhv/notistack this package makes it a lot easier and is supported by the Material UI team.

toggle divs so only one is open at a time, but be able to close them all as well javascript

I have these divs that I can toggle onclick to scale larger one at a time. It works perfectly except that once one is enlarged, one is always enlarged. I am using toggleOpen for this. I am looking to be able to make it so that it can do what it already does, but then onclick of the enlarged div have it go back to its original size without having to toggle with another div. In other words, I need a way to make the page go back to a state where all the divs are in original size. I have tried else statements to no avail as well as adding another function to remove class. I only want a js solution - no jquery or anything else please. Here is the JS portion of it.
const event = document.querySelectorAll('.eventsBorder')
function toggleOpen() {
let opened = document.getElementsByClassName('large')[0];
if(opened!=undefined)
opened.classList.toggle('large');
this.classList.toggle('large');
}
event.forEach(eventsBorder => eventsBorder.addEventListener('click', toggleOpen));
Here is my codepen
Thanks in advance for any help!
The opened variable gives you back a list of all the HTML elements which have the large class, and when you click again on an already enlarged div that automatically satisfied this criteria. So, what happens is that if you click on the same item twice, your toggleOpen function first removes the large class from that item and then adds it again because of the following line in your code-
this.classList.toggle('large');
The best way to achieve what you want would be to make sure that in addition to opened not being undefined, you should also make sure opened is not the same item as the one you clicked on. You can accomplish that using-
if(opened != undefined && opened != this)
Here is a link to the updated codepen to see it in action.
So it looks like you are using querySelectorAll to select all elements with the class "large", then you're toggling the class. If you toggle the class, it will no longer be a part of that query selection, as it no longer has that class applied, so it will not be able to remove it.
const event = document.querySelectorAll('.eventsBorder')
event.forEach(eventsBorder =>
eventsBorder.onclick = () =>
eventsBorder.classList.toggle('large'));
This seems to accomplish what you'd like.

How to inspect element of Zebkit UI

As part of automation testing, we want to inspect the element in a website which is made of using the Zebkit UI framework.
We are unable to find the element using zebra.ui
examples can be found here
Can someone help us on inspecting the element
Zebkit UI components are rendered on HTML5 Canvas. So they are not part of browser DOM tree what can be a problem for a test tool that expects DOM as an input. But it doesn't mean you cannot go over zebkit UI stuff to perform test cases.
First of all keep in mind zebkit components are a hierarchy/tree like DOM is. Every rendered on a canvas zebkit UI component has a related JS instance of appropriate class. There are number of API methods you can use to travel over UI components tree. These methods expect path (XPath-like) since path (from my point of view) is less "encrypted" way than CSS selector.
The API methods you probably need:
byPath(path [,callback]) - traversing UI components tree by the given path
var zcanvas = new zebkit.ui.zCanvas();
...
// travel over all UI components in tree
zcanvas.byPath("//*", function(comp) {
// perform test cases here
...
});
properties([path,] properties) applies the specified properties set to component or number of components requested by the given path
var zcanvas = new zebkit.ui.zCanvas();
...
// set color property to black value for all labels
zcanvas.properties("//zebkit.ui.Label", { color: "black" });
on([eventName], [path], handler) add listener method(s) for the given event (or all events) of the given component or components identified with the path:
var zcanvas = new zebkit.ui.zCanvas();
...
// register event listener for all found buttons
zcanvas.on("//zebkit.ui.Button", function (src) {
// handle button press event here
...
});
fire([eventName,] [path,] [argument]) fire the given event to the given component or to components identified with the path:
var zcanvas = new zebkit.ui.zCanvas();
...
// fire button pressed event to button with id equals "testButton"
zcanvas.fire("//[#id='testButton']");
...
// or the same with a shortcut
zcanvas.fire("#testButton");
I'm not sure I understand correctly your issue, but assume you cannot click right button on canvas to open context menu and select "Inspect element" option.
You can
press F12 in browser
switch to "Elements"/"HTML" tab
in search field (CTRL + F) print "canvas"/"<canvas" and press Enter
Continue pressing Enter until required canvas found (current element should be highlighted)
These controls are implemented using an HTML5 CANVAS tag. Selenium cannot see "inside" this tag because it doesn't contain HTML. It's like an app inside the page. From the page you linked, it looks like you should be able to use JS to access elements inside the control. When I've done things with CANVAS tags in the past, I generally find JS that does or returns what I want and then wrap that code in a function that I can call. It will work but you will likely have to do some research on Zebkit to find out what JS you will need to validate, etc. all the different things you will want to validate... and it may end up that you won't be able to validate some things.

tree element in firefox sidebar with dynamic elements and click functionality

I have created an extension to show a sidebar in firefox.
Now i need to display a tree like structure where the third level will be dynamic and loads a particular link on clicking.
I know how to create the three level hierarchy but with static data.. heres the code
<treechildren>
<treeitem container="true" open="true">
<treerow>
<treecell label="Guys"/>
</treerow>
<treechildren>
<treeitem>
<treerow>
<treecell id="cell-of-treeitem1" label="Bob" onclick="alert('bob')"/>
</treerow>
</treeitem>
<treeitem>
<treerow>
<treecell label="Jerry"/>
</treerow>
</treeitem>
</treechildren>
</treeitem>
</treechildren>
The onclick does not showup anything
1)How can i implement the link functionality.. as in a link to be opened on clicking a treecell element? The "onclick" attribute doesnot work. Also and can i run javascript functions on clicking of the individual items.
2) How can i have a dynamic list displayed. suppose i have a JS function that reurns a list, how can i show it here as tree elements (basically then the js should run everytime i expand the tree parent to see the children)
First, place the onclick event handler on the tree itself, not on the elements. When the user clicks on a cell, because of the event bubbling, the tree will catch it, no matter which cell receives the click:
function clickedOnSomething(event) {
if(event.originalTarget.localName == "treechildren") {
//do something here based on who is event.originalTarget
}
}
Second, to create the content dynamically, you create an empty tree in XUL:
<tree id="myTree" onclick="clickedOnSomething(event)" flex="1" seltype="single">
<treecols>
<treecol id="myCol" label="Stuff" primary="true" flex="1" />
</treecols>
<treechildren/>
</tree>
Then in JavaScript, you create an object that implements the nsITreeView interface (see link below), and assign it as the view of the tree you created in XUL.
This object will serve as a interface for the Tree widget to the data will allow the tree to update itself automatically if the data changes.
You can find more information about custom tree views here: https://developer.mozilla.org/en/XUL_Tutorial/Custom_Tree_Views

Categories