0

I tried this but it doesn't work. Each text element should change the corresponding image. In the browser console city_name appears as html collections

let city_name = document.getElementsByClassName("city_name");
let city_img = document.getElementsByClassName("city_img");


for (let i = 0; i < city_name.length; i++) {
    city_name[i].addEventListener("mouseover", blur(i))   
}
    
function blur(i) {
    city_img[i].style.filter = "blur(4px)"  
}
<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css">
    <script src="API.js"></script>
    <title>WeatherLike</title>

</head>

<body>
    <div class="top_city">

        <div class="city">
            <img src="milano.jpg" class="city_img">
            <h1 class="city_name">Milano</h1>
        </div>
        <div class="city">
            <img src="torino.jpg" class="city_img">
            <h1 class="city_name">Torino</h1>
        </div>
        <div class="city">
            <img src="bologna.jpg" class="city_img">
            <h1 class="city_name">Bologna</h1>
        </div>
        <div class="city">
            <img src="firenze.jpg" class="city_img">
            <h1 class="city_name">Firenze</h1>
        </div>
        <div class="city">
            <img src="roma.jpg" class="city_img">
            <h1 class="city_name">Roma</h1>
        </div>
        <div class="city">
            <img src="napoli.jpg" class="city_img">
            <h1 class="city_name">Napoli</h1>
        </div>
        <div class="city">
            <img src="palermo.jpg" class="city_img">
            <h1 class="city_name">Palermo</h1>
        </div>
   
        
    </div>  
</body>

</html>

Thanks.

@ChrisG @Adyson yes, ChrisG is right. But "hover the name and the image gets blurry" doesn't work in my HTML page. Maybe for the CSS?

@import url('https://fonts.googleapis.com/css2?family=Bitter:wght@700&display=swap');

*{
    margin: 0;
    padding: 0;
}

body{
    height: 100vh;
}

.top_city{
    display: flex;
    flex-direction: row;
    height: 20vh;
    
}

.city_img{
    background-size: cover;
    border: 1px solid lightgrey;
    height: 20vh;   
}

.city_name{
    color: white;
    text-align: center;
    position: absolute;
    width: 14.2%;
    margin-top: 55px;
    font-family: 'Bitter', serif ;
    border: 1px solid rgb(255, 255, 255);
    text-shadow: 1px 1px 1px black;
    background-color: rgb(0,0,0); /* Fallback color */
    background-color: rgba(0,0,0, 0.2); /* Black w/opacity/see-through */
}

.city{
    overflow: hidden;
    display: flex;
    width: 16.66%;
}
Frank
  • 23
  • 3
  • 1
    You need `.addEventListener("mouseover", function () { blur(i); })` – Chris G May 13 '20 at 18:04
  • [How to pass arguments to addEventListener listener function?](https://stackoverflow.com/questions/256754/how-to-pass-arguments-to-addeventlistener-listener-function) + [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Andreas May 13 '20 at 18:11
  • @ChrisG it doesn't work... – Frank May 13 '20 at 18:40
  • Yes it does: https://jsfiddle.net/khrismuc/pdb0vg21/ (hover the name and the image gets blurry) – Chris G May 13 '20 at 19:11
  • @Frank ChrisG is right. If it's not working for you, you'll have to explain in more detail – ADyson May 13 '20 at 19:47
  • @Adyson yes, ChrisG is right. But "hover the name and the image gets blurry" doesn't work in my HTML page. Maybe for the CSS? – Frank May 13 '20 at 21:12
  • @Frank Well we can test that. I applied your CSS to Chris's example. Demo: https://jsfiddle.net/2cvpustk/ . Although the text now appears over the top of the pictures (I don't know if that's your intention), you can still just about see that the pictures do get blurred. And using your browser's element inspector to check the CSS rules being applied to those images (once you've moved your mouse over the text) will confirm it for you. So if that's not happening in your own page, then there must still be something else about the situation which you haven't discovered / told us about yet. – ADyson May 13 '20 at 21:44

5 Answers5

2

You have several problems in your code :

  1. getElementsByClass return a collection and not an array as you expected. You should use document.querySelectorAll to get an array of your elements.
  2. As it has already said , you need a callback for your function blur
  3. instead of passing i in parameters, you're better to use the event.target to be sure to blur the right element. use previousElementSibling to spot the picture.
    let city_name = document.querySelectorAll(".city_name");
    let city_img = document.querySelectorAll(".city_img");

    for (let i = 0; i < city_name.length; i++) {
        city_name[i].addEventListener("mouseover", (e)=>{blur(e)})   
    }

    function blur(e) {
        e.target.previousElementSibling.style.filter = "blur(4px)"  
    }
Gazowski
  • 46
  • 3
1

You need to create a function callback, because now it assume the blur function return a function callback.

Replace the blur(i) with function(){ blur(i); }

let city_name = document.getElementsByClassName("city_name");
let city_img = document.getElementsByClassName("city_img");


for (let i = 0; i < city_name.length; i++) {
    city_name[i].addEventListener("mouseover", function(){ blur(i); });   
}
    
function blur(i) {
    city_img[i].style.filter = "blur(4px)";
}
<!DOCTYPE html>
<html lang="en">
<head>
    
    <title>WeatherLike</title>

</head>

<body>
    <div class="top_city">

        <div class="city">
            <img style="height:45px;" src="https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-12/256/united-states.png" class="city_img">
            <h1 class="city_name">Milano</h1>
        </div>
        <div class="city">
            <img style="height:45px;" src="https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-12/256/uruguay.png" class="city_img">
            <h1 class="city_name">Torino</h1>
        </div>
        <div class="city">
            <img src="bologna.jpg" class="city_img">
            <h1 class="city_name">Bologna</h1>
        </div>
        <div class="city">
            <img src="firenze.jpg" class="city_img">
            <h1 class="city_name">Firenze</h1>
        </div>
        <div class="city">
            <img src="roma.jpg" class="city_img">
            <h1 class="city_name">Roma</h1>
        </div>
        <div class="city">
            <img src="napoli.jpg" class="city_img">
            <h1 class="city_name">Napoli</h1>
        </div>
        <div class="city">
            <img src="palermo.jpg" class="city_img">
            <h1 class="city_name">Palermo</h1>
        </div>
   
        
    </div>  
</body>

</html>
Benoit
  • 949
  • 9
  • 26
0

If you place the name (<h1> tags) before the image (<img>), you can reach your event listener only with css and you don't need any javascript code :

h1:hover + img{
  filter:blur(4px);
}
Gazowski
  • 46
  • 3
0

I assume your js script is in the API.js file, that you have imported in the <head> section of your HTML file. The problem is that the script is imported and executed during the loading of the page, so it can't see the HTML elements (called by document.getElementsByClassName function) yet.

You can fix it in many ways:

  1. Import your API.js script after the HTML elements you need to call:

    <div class="top_city">
    
        <div class="city">
            <img src="milano.jpg" class="city_img">
            <h1 class="city_name">Milano</h1>
        </div>
        ...
    
    </div>
    
    <script src="API.js"></script>
    
    <!-- other code here -->
    
    </body>
    
  2. Add the async tag:

    <script src="API.js" async></script>
    
  3. Execute your code during the loading of the page. I think this the best practice:

    window.onload = function(){
        let city_name = document.querySelectorAll(".city_name");
        let city_img = document.querySelectorAll(".city_img");
    
        for (let i = 0; i < city_name.length; i++) {
            city_name[i].addEventListener("mouseover", (e)=>{blur(e)})   
        }
    
        function blur(e) {
            e.target.previousElementSibling.style.filter = "blur(4px)"  
        }
     }
    

    See this answer for more details.

Luca8991
  • 16
  • 1
  • 4
-2

you likely need an 'id' tag on each image and then reference it in your blur() function.

by the way have you considered using a more structured framework like angular? this entire page could be written like this:

<div class="city" *ngFor="let city of cityList">
  <img id="{{city.id}}" src="{{city.img}}" class="city_img">
  <h1 class="city_name" (blur)="blurCity(city)">{{city.name}}</h1>
</div>
Rick
  • 1,142
  • 2
  • 11