Make images in a text clickable in React - reactjs

I'm building a website where I get a blog post from an API call. The body of the post is just html code mixed with text, images and even objects like youtube videos (it is build with ckeditor in the back). Everything is working as expected but I would like to make images clickable. Clicking the image, would open a modal in lightbox style.
I was considering extracting all the images (if any) from the body and making a gallery at the bottom of the post. But I think that would be more elegant just making images clickable and opening the dialag without showing them twice along the post.
An example of the response:
body: "<p>this is a text with some images: <img src='path/to/image1' /> and <img src='path/to/image2' /> how to make them clickable in React?</p>"
That body is rendered this way:
<GridItem xs={12} sm={8} md={8}>
<div dangerouslySetInnerHTML={{ __html: text }} />
</GridItem>

You can use the onClick event in your image:
<img src='path/to/image2' onClick={() => {aFunction}} />
ps: if you want to, you can add a className to put a cursor:pointer too.

I think this might help you
first of all, you need to cover the content of blog post (returned HTML from API call) into one single wrapper div.
after that, you can need to get all the elements of blog post using javascript like the example below
const elements = document.getElementById("wrapper").elements
now you can iterate throw all elements in blog post including the images
elements.forEach(item => {
if (item.type == "img")
// do this
})
I will edit the second code example in a few minutes

Related

Dynamic Modal routing with NextJS like Instagram

I am looking for someone to help me with the following issue:
I am trying to implement a modal system where the modals are dependent on the route using NextJS.
So say I am on the following page:
website.com/help
and say I have the modals category1, category2, and category3, all of which I would prefer to be able to persist after closing them (they are loading iframes), however this is not a must.
Then I would want the routes for these modals to be:
website.com/help/category1
website.com/help/category2
website.com/help/category3
I have already found this in the official NextJS examples:
with-route-as-modal
But the problem I am having is that with queryString routing, when you reload/visit the modal route directly, the modal wont be used. So the content will become full screen (it is a page of its own).
With dynamic routing, this is not an issue, since if you visit the modal route directly the modal will be kept. But the problem I am having with this is that these modals aren't exactly modals, the original page "behind" the modal just becomes the body background. The other issue is that I wont be able to persist these.
Here is the demo on stackblitz:
https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-route-as-modal?file=README.md
I would appreciate anyone helping me with this so much because it has really driven me mad trying to solve this!
I have a solution that you may like. For the example you provided you only need to import <Grid/> in /article/[articleId].js like it's done in /index.js
so when you open the modal the articles/posts list is shown in the background
// article/[articleId].js
import Grid from '../../components/Grid';
<>
<Modal
isOpen={true}
onRequestClose={() => router.push('/', undefined, { scroll: false })}
contentLabel="Post modal"
>
<Article id={articleId} pathname={router.pathname} />
</Modal>
<Grid />
</>
don't forget to give scroll false in router.push() and <Link/> so when you go back to articles/posts list it doesn't jump to the top of the page
router.push('/', undefined, { scroll: false })
<Link
key={index}
href="/article/[articleId]"
as={`/article/${id}`}
scroll={false}
>
<a className={styles.postCard}>{id}</a>
</Link>
you can see an example here: https://stackblitz.com/edit/github-rkrovd

Gatsby Image inside Flickity carousel

I am creating a gatsby website that uses the flickity-react-component to display a slider with product images. I believe that I should use the gatsby image to make it load faster, but when I try it, the Image does not display (it is 0x0 pixels).
This is the code I am trying to run:
const ThirdPage = ({ data }) => {
...
function Carousel() {
return (
<Flickity
className={'carousel'} // default ''
elementType={'div'} // default 'div'
options={flickityOptions} // takes flickity options {}
disableImagesLoaded={false} // default false
reloadOnUpdate // default false
static // default false
>
<Img fluid={data.imgPrincipal.childImageSharp.fluid} alt="Mulher a lavar o cabelo com o chuveiro ecológico" />
<img src="https://placeimg.com/640/480/nature" />
<img src="https://placeimg.com/640/480/nature" />
<img src="https://placeimg.com/640/480/architecture" />
</Flickity>
);
}
The "Img" is the one using the gatsby image, the others are what I had before.
This is the result
I don't get an error when running this, I believe this might be because gatsby-image creates a div.
Can someone help me make this work? I am a beginner, so if it's something very advanced, I would appreciate an alternative ... Thank you.
Indeed, gatsby-image is not only a simple image. It creates a wrapper with a few nested div HTML structure inside to make the blur effect and the rest of the improvements.
Take a look at gatsby-image docs:
Note: gatsby-image is not a drop-in replacement for <img />. It’s
optimized for fixed width/height images and images that stretch the
full-width of a container. Some ways you can use <img /> won’t work
with gatsby-image.
It may not work with all sliders.
I've used it with other sliders that accept a nested structure inside, not only a single <img> tag such as Swiper or Slick.

Update dom without refresh the page in react 16

So, I've been looking for a way to render this img tag on my dom without refresh the screen. But I didn't find a definitive answer on how to do that! I mean, in a natural way, with react library and without change a lot of things.
So, when I click this div, it calls a method
<div ref={(ref) => this.refProjectImageCenter = ref} onClick={(e) => this.selectImage(e, this.refProjectImageCenter)} >
<img src="images/projects/new-account.png" alt="new account" />
</div>
And in this method, I update my state with a new img element (not sure if it's the best way to do it tho)
selectImage(e: any , el: HTMLDivElement)
{
e.preventDefault(); // This is not working
this.setState({ selected_img: <img src={el.children[0].getAttribute("src")} /> });
}
And the state will update this part of the DOM
<div className="image detail">
{this.state.selected_img}
</div>
It renders the img indeed, but the page flashes(refresh), and I want to do that asynchronously. It's possible to do that with react? If it's not, how everybody is doing it right now? Thanks a lot.
I found the problem Henry and Shubham. I was updating the css class of the main html tag:
this.refMasterDOM.classList.remove("active");
Inside the method componentWillUpdate(). I removed this line and it stopped refreshing the page with sestate command. Although I don't know why.

reactstrap carousel html tag on variable

good day to all. im new to react app, and i usses reactstrap for my carousel. i just copied the code from reactstrap documentation. and i want to add a html tag on the item variable. but just print the html tags on my website. how do i do it correctly?
my variable is:
const items = [
{
imageUrl: 'static/media/slide1.jpg',
idName: 'S1',
captionHeader: 'slide 1 <strong>text here</strong>',
captionText: 'slide 1 <strong>text here</strong>',
},
{
imageUrl: 'static/media/slide2.jpg',
idName: 'S2',
captionHeader: 'Slide 2',
captionText: 'Slide 2'
}
];
then i added it here:
<CarouselItem
onExiting={this.onExiting}
onExited={this.onExited}
key={item.src}
>
<div className="carouselIMG" id={item.idName} style={{ backgroundImage: `url(${item.imageUrl})` }}>
</div>
<CarouselCaption captionText={item.captionText} captionHeader={item.captionHeader} />
</CarouselItem>
this part:
<CarouselCaption captionText={item.captionText} captionHeader={item.captionHeader} />
p.s.
can you aso check my "imageUrl" is there a best way to grab the image location? atfirst i tried ../images/imagename.jpg, just like what i do when im importing js file. but it doesnt seem to located the address, so i just manually check if where the images are stored when build.
thanks in advance.
You can see that in react strap documentation the prop types are,
CarouselCaption.propTypes = {
captionHeader: PropTypes.string,
captionText: PropTypes.string.isRequired,
cssModule: PropTypes.object
};
So the captionHeader and captionText need to be strings. How ever you can give font-weight css style for this whole text.
And regarding the picking of images you may check out this SOF answer.
It sounds like you are getting the values rendered in the user view, but what you want is the values stored on a tag on the html.
Note that CarouselCaption is not html, it is a custom react component. ;)
You need to place the following code like attributes on native html tags to get them stored in html dom.
<div> captionText={item.captionText} captionHeader={item.captionHeader}> </div>
A good example is found in their github repo under demos.
https://github.com/gajus/react-carousel/blob/master/demo/src/index.js
Here you notice that they create an array of a bunch of these using map.
<div key={String(index)}>{index}</div>;
Then they render this as a child of the carousel. So you'd just put your attributes on the html. With html I can create a div like
<div thisIsACustomHTMLAnAttribute="valuesToBeStoredInTheDom"> </div>
However the equivalent in custom react component would try to either pass to the component for use or try to render it as values.
<div captionText={item.captionText}> </div>

Displaying gifv with react

I've been trying to view the imgur format gifv for a while but i just cant seem to get it working.
Been testing with img tags, video tags, iframes. So far only the iframe seems to work - but i cant resize the iframe due to browser limitations.
<img src="http://i.imgur.com/rCkPdZm.gifv" /> - nope
<video src="http://i.imgur.com/rCkPdZm.gifv"/> - nope
Any tips on how to display for example http://i.imgur.com/rCkPdZm.gifv
Thanks!
A gifv is not an image format, it's a made-up "extension" to make the landing page look like you have opened an image link directly, while being able to stream video instead of a much larger gif file. Use the "view source" option and go find out! :)
You can right-click on the gifv "image" and the browser should give you an option to "copy video url", which you can then use in a <video> element:
<video src="http://i.imgur.com/rCkPdZm.mp4" />
https://jsfiddle.net/xc4cqoh5/
In this context it doesn't matter if it's React or just plain HTML website, the solution is the same: you need to grab the URL of the actual video being played, not the gifv page that embeds it. It seems you can just replace the .gifv extension with .mp4. To make this answer relevant to the reactjs tag here's an example:
const Player = props => {
let videourl = props.videourl.replace('.gifv', '.mp4');
return <video src={ videourl } />;
};
ReactDOM.render( <Player videourl="http://i.imgur.com/rCkPdZm.gifv" />,
document.getElementById('container'));
http://jsfiddle.net/69z2wepo/47077/

Resources