Is there a way to use my magnifier on multiple images within a single page?

// magnify hover
function magnify(imgID, zoom) {
  var img, glass, w, h, bw;
  img = document.getElementById(imgID);
  /*create magnifier glass:*/
  glass = document.createElement("DIV");
  glass.setAttribute("class", "img-magnifier-glass");
  /*insert magnifier glass:*/
  img.parentElement.insertBefore(glass, img);
  /*set background properties for the magnifier glass:*/
  glass.style.backgroundImage = "url('" + img.src + "')";
  glass.style.backgroundRepeat = "no-repeat";
  glass.style.backgroundSize = (img.width * zoom) + "px " + (img.height * zoom) + "px";
  bw = 3;
  w = glass.offsetWidth / 2;
  h = glass.offsetHeight / 2;
  /*execute a function when someone moves the magnifier glass over the image:*/
  glass.addEventListener("mousemove", moveMagnifier);
  img.addEventListener("mousemove", moveMagnifier);
  /*and also for touch screens:*/
  glass.addEventListener("touchmove", moveMagnifier);
  img.addEventListener("touchmove", moveMagnifier);
  function moveMagnifier(e) {
    var pos, x, y;
    /*prevent any other actions that may occur when moving over the image*/
    e.preventDefault();
    /*get the cursor's x and y positions:*/
    pos = getCursorPos(e);
    x = pos.x;
    y = pos.y;
    /*prevent the magnifier glass from being positioned outside the image:*/
    if (x > img.width - (w / zoom)) {x = img.width - (w / zoom);}
    if (x < w / zoom) {x = w / zoom;}
    if (y > img.height - (h / zoom)) {y = img.height - (h / zoom);}
    if (y < h / zoom) {y = h / zoom;}
    /*set the position of the magnifier glass:*/
    glass.style.left = (x - w) + "px";
    glass.style.top = (y - h) + "px";
    /*display what the magnifier glass "sees":*/
    glass.style.backgroundPosition = "-" + ((x * zoom) - w + bw) + "px -" + ((y * zoom) - h + bw) + "px";
  }
  function getCursorPos(e) {
    var a, x = 0, y = 0;
    e = e || window.event;
    /*get the x and y positions of the image:*/
    a = img.getBoundingClientRect();
    /*calculate the cursor's x and y coordinates, relative to the image:*/
    x = e.pageX - a.left;
    y = e.pageY - a.top;
    /*consider any page scrolling:*/
    x = x - window.pageXOffset;
    y = y - window.pageYOffset;
    return {x : x, y : y};
  }
}
/* Initiate Magnify Function
with the id of the image, and the strength of the magnifier glass:*/
magnify("mag", 5);
* {box-sizing: border-box;}

.img-magnifier-container {
  position:relative;
}

.img-magnifier-glass {
  position: absolute;
  z-index: 3;
  border: 1px solid #000;
  border-radius: 20%;
  cursor: none;
  /*Set the size of the magnifier glass:*/
  width: 120px;
  height: 130px;
  opacity:0;
  pointer-events:none;
}
a:hover .img-magnifier-glass{
  opacity:1;
  pointer-events:initial;
}
<table class="img-magnifier-container" width="115" border="0" cellpadding="0" cellspacing="0" style="display: inline-block"><tr><td width="115" style="text-align: center"><center><a href="https://www.imdb.com/title/tt0478970/" title="Ant-Man (2015)" target="_blank"><img class="cover" width="115" height="133" border="0" id="mag" class="pstrart" id="pstr" src="https://images2.static-bluray.com/movies/covers/238380_front.jpg" style=""></a></center><center><input type="checkbox" name="movieboxes" value="Ant-Man" style="width: 15px; height: 15px; margin: 0px;">
<img title="United Kingdom" border="2" class="flag" id="flgborder" src="https://cdn.discordapp.com/attachments/530906893443399683/665554365897244693/union-jack-26119_960_720.png" style="width: 25px; height: 17px;">
</center></td></tr></table>&nbsp;
&nbsp;
<table class="img-magnifier-container" width="115" border="0" cellpadding="0" cellspacing="0" style="display: inline-block"><tr><td width="115" style="text-align: center"><center><a href="https://www.imdb.com/title/tt6644200/" title="A Quiet Place (2018)" target="_blank"><img class="cover" width="115" height="133" border="0" id="mag" class="pstrart" id="pstr" src="https://images2.static-bluray.com/movies/covers/202637_front.jpg" style=""></a></center><center><input type="checkbox" name="movieboxes" value="A Quiet Place" style="width: 15px; height: 15px; margin: 0px;">
<img title="United Kingdom" border="2" class="flag" id="flgborder" src="https://cdn.discordapp.com/attachments/530906893443399683/665554365897244693/union-jack-26119_960_720.png" style="width: 25px; height: 17px;">
</center></td></tr></table>&nbsp;
&nbsp;

Hello,

I just implemented a magnifier on hover with the help of the users on this platform. However, I am struggling to extend this functionality to all images instead of just one. I have included two images in the code snippet attached to demonstrate my issue.

Thank you in advance for any guidance!

Answer №1

Expanding on my previous comment, the primary issue at hand is:

  1. The presence of duplicate IDs and duplicate attributes across various elements on your webpage. It's crucial to ensure each ID is unique within a document. Additionally, consolidating multiple classes into one per element is preferred over having several class attributes.
  2. You've only initialized the magnification feature on a single element, lacking the iterative logic needed to cycle through all desired images for magnification.

Here are my recommendations:

  1. Rectify the DOM errors mentioned above. Assign a common class to the image elements that require magnification for easy selection. For instance, use class="magnify-image", but feel free to choose any relevant class names.
  2. Modify the magnify() method to accept an image element instead of an ID. This adjustment will allow our iterative logic to directly pass in the specified image element for magnification. Update it as follows:

    function magnify(img, zoom) { ... }
    and eliminate the var img = ... assignment.

  3. Assign a class to each image intended for magnification, then gather all these images into an HTMLCollection. Iterate through this collection and provide the image element during each iteration as the first argument.

Example showcasing iterative logic:

// Cycle through all images requiring magnification
const images = document.querySelectorAll('.magnify-image');
Array.from(images).forEach((image) => {
    // Directly pass the image element into the function
    magnify(image, 5);
});

If ES5 compatibility is mandatory, you can implement the following approach:

var images = document.getElementsByClassName('magnify-image');
Array.prototype.forEach.call(images, function(image) {
    // Directly pass the image element into the function
    magnify(image, 5);
});

View the proof-of-concept below:

// JS Function for Image Magnification
function magnify(img, zoom) {
  var glass, w, h, bw;
  /*create magnifier glass:*/
  glass = document.createElement("DIV");
  glass.setAttribute("class", "img-magnifier-glass");
  /*insert magnifier glass:*/
  img.parentElement.insertBefore(glass, img);
  /*set background properties for the magnifier glass:*/
  glass.style.backgroundImage = "url('" + img.src + "')";
  glass.style.backgroundRepeat = "no-repeat";
  glass.style.backgroundSize = (img.width * zoom) + "px " + (img.height * zoom) + "px";
  bw = 3;
  w = glass.offsetWidth / 2;
  h = glass.offsetHeight / 2;
  /*execute a function while moving the magnifier glass over the image:*/
  glass.addEventListener("mousemove", moveMagnifier);
  img.addEventListener("mousemove", moveMagnifier);
  /*for touch screens:*/
  glass.addEventListener("touchmove", moveMagnifier);
  img.addEventListener("touchmove", moveMagnifier);

  function moveMagnifier(e) {
    var pos, x, y;
    e.preventDefault();
    pos = getCursorPos(e);
    x = pos.x;
    y = pos.y;
    if (x > img.width - (w / zoom)) {
      x = img.width - (w / zoom);
    }
    if (x < w / zoom) {
      x = w / zoom;
    }
    if (y > img.height - (h / zoom)) {
      y = img.height - (h / zoom);
    }
    if (y < h / zoom) {
      y = h / zoom;
    }
    glass.style.left = (x - w) + "px";
    glass.style.top = (y - h) + "px";
    glass.style.backgroundPosition = "-" + ((x * zoom) - w + bw) + "px -" + ((y * zoom) - h + bw) + "px";  
  }

  function getCursorPos(e) {
    var a, x = 0, y = 0;
    e = e || window.event;
    a = img.getBoundingClientRect();
    x = e.pageX - a.left;
    y = e.pageY - a.top;
    x = x - window.pageXOffset;
    y = y - window.pageYOffset;
    return { x : x, y : y };
  }
}

// Cycle through all images requiring magnification
const images = document.querySelectorAll('.magnify-image');
Array.from(images).forEach((image) => {
  magnify(image, 5);
});
* {
  box-sizing: border-box; 
}

.img-magnifier-container {
  position: relative; 
}

.img-magnifier-glass {
  position: absolute;
  z-index: 3;
  border: 1px solid #000; 
  border-radius: 20%; 
  cursor: none; 
  width: 120px; 
  height: 130px;
  opacity: 0; 
  pointer-events: none; 
}

a:hover .img-magnifier-glass {
  opacity: 1;
  pointer-events: initial;
}
<table class="img-magnifier-container" width="115" border="0" cellpadding="0" cellspacing="0" style="display: inline-block">
  <tr>
    <td width="115" style="text-align: center">
      <center>
        <a href="https://www.imdb.com/title/tt0478970/" title="Ant-Man (2015)" target="_blank"><img width="115" height="133" border="0" class="cover pstrart magnify-image" src="https://images2.static-bluray.com/movies/covers/238380_front.jpg" style=""></a>
      </center>
      <center><input type="checkbox" name="movieboxes" value="Ant-Man" style="width: 15px; height: 15px; margin: 0px;">
        <img title="United Kingdom" border="2" class="flag" src="https://cdn.discordapp.com/attachments/530906893443399683/665554365897244693/union-jack-26119_960_720.png" style="width: 25px; height: 17px;">
      </center>
    </td>
  </tr>
</table>&nbsp; &nbsp;
<table class="img-magnifier-container" width="115" border="0" cellpadding="0" cellspacing="0" style="display: inline-block">
  <tr>
    <td width="115" style="text-align: center">
      <center>
        <a href="https://www.imdb.com/title/tt6644200/" title="A Quiet Place (2018)" target="_blank"><img width="115" height="133" border="0" class="cover pstrart magnify-image" src="https://images2.static-bluray.com/movies/covers/202637_front.jpg" style=""></a>
      </center>
      <center><input type="checkbox" name="movieboxes" value="A Quiet Place" style="width: 15px; height: 15px; margin: 0px;">
        <img title="United Kingdom" border="2" class="flag" src="https://cdn.discordapp.com/attachments/530906893443399683/665554365897244693/union-jack-26119_960_720.png" style="width: 25px; height: 17px;">
      </center>
    </td>
  </tr>
</table>&nbsp; &nbsp;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on accessing the left value of a absolutely positioned object that transitions on click using getComputedStyle or a similar method

Question: How can I ensure that when the target is clicked, the correct and updated value of the left property is returned? For example, I want it to return 120px if --moved is applied, and 100px if it is not applied. Background: Utilizing getComputedStyl ...

Update the unique identifier when saving a new object

Seeking assistance on updating the objectId of a foreign key in my schema post-saving router.post('/add/:id', (req,res)=>{ const newMenu = new Menu() newMenu.menu_name = req.body.menu_name const restaurantId = req.params.id ...

JavaScript-enabled tests encountering issues (Bootstrap 3, Rails 4, Travis CI)

I'm encountering a strange error that only shows up in my CI environment. This error doesn't occur in development, production, or local test environments. ActionController::RoutingError: No route matches [GET] "/fonts/bootstrap/glyphicons-halfli ...

Adding a CSS shadow to an element positioned beneath another

I'm attempting to recreate a shadow effect in HTML similar to one I created in Photoshop: https://i.sstatic.net/fBcBl.png I believe a basic HTML structure like the one below should suffice, but I'm unsure: <div id="anotherMask"> <di ...

Axios displays a status code of 0 instead of the expected 403

Trying to monitor the responses of requests using axios response interceptors has been quite a challenge for me. In one specific request that necessitates authorization, everything goes smoothly when the token is valid, and data is returned without any is ...

Unable to retrieve file paths for assets using Node.js Server and Three.js

I am facing challenges when it comes to loading 3D models from a folder on my computer using a localhost node.js test server with the three.js library. Below is my app.js file that I execute via command line in the project directory using the 'node a ...

Issues with Yii: Loading of Javascript and CSS not happening post-Ajax requests

I have set up a view with tabs, each containing a form with an ajax submit and gridview. I am using renderpartial in the tabs widget to display the form and gridview. Everything looks good within the tab until I click the submit button. Upon clicking submi ...

Similar to the app.get() method in Express, CasperJS provides a way

I have created a basic web scraping tool that extracts data from a website and displays it when I navigate to the URL - localhost:3434/page. This functionality was achieved using the express app.get() method. Now, I have a few inquiries: 1) I am curious ...

Expanding a container component with React TypeScript

I'm in the process of developing a foundational class, encapsulating it within a container, and extending it in my various components. Here's a basic example: let state = new State(); class Base extends React.Component<{}, {}> { } const ...

Obtaining the NodeValue from an input of type <td>

I have a HTML code snippet that I am trying to parse in order to extract the nodeValue of all elements within the table columns. <table id="custinfo"> <tr> <td><label>First Name</label></td> <td& ...

Successfully executing a JQuery ajax GET request results in receiving truncated data

Recently, I encountered an issue while retrieving a large amount of data from my server using a JQuery ajax GET request. The data returned was truncated unexpectedly (as shown in the image below). However, when I tried accessing the same URL directly throu ...

Understanding the problem of scope within a JavaScript object literal

Just diving into the world of programming and joining this community for the first time. I'm currently grappling with a scope issue involving object literals in my code. Any assistance would be greatly appreciated! var obj = { value: 3, print:() ...

pino-tea's logging feature suddenly halts after processing a few hundred lines

I've encountered an issue while streaming pino logging into pino-tee, where it stops working after around 200 to 400 lines out of the expected 1000. The code snippet below in index.js (ESM) illustrates this problem: import childProcess from "chil ...

Refreshing the page using location.reload triggers a reload of various elements

I am currently working on a website that supports multiple languages and utilizes a cookie named nav_lang to determine the user's preferred language for navigation. Whenever a user selects a new language, the cookie is updated accordingly and the page ...

detect and handle errors when deploying the Node.js function

I'm currently attempting to use code I found on Github to insert data into a Firestore database, but unfortunately, I keep encountering an error. Here's the specific error message: 21:1 error Expected catch() or return promise/catch-or-re ...

Issue with the reload animation jumping too quickly in Framer Motion on NextJS

While creating an animation for my landing page using NextJS with framer motion, I encountered a strange behavior after deploying the site. The animations started to happen too quickly and it felt a bit off. During development on localhost using Chrome, ev ...

What is the purpose of having mocha included in devDependencies?

At first glance, the idea of mocha being in devDependencies as suggested by tutorials seems reasonable, considering it is a development dependency. However, in reality, you install it globally with -g so that you can run mocha as a command. From what I ca ...

Transforming the JSON structure in JavaScript

Is there a way to transform the JSON format below into the desired output? [ { "type": "System Usability Score", "score": 74, "date": "2020-03-19T18:30:00.000+0000" }, { "type&quo ...

On certain websites, the footer may appear distorted or incorrectly displayed when viewed in the IE 9 web browser

Currently experiencing an issue with the display of the footer in IE9. On some pages, the footer is not properly fixed and overlaps the middle of the content. However, this problem does not occur when using other web browsers. Here is the code that I am c ...

How to pass Vue.js component value to pure JavaScript

I'm curious if it's possible to access the data of a component, specifically the count property, in regular JavaScript and log it. Can I use console.log(btn.data.count) for this purpose? <div id="app" v-cloak> <h1>{{ ...