Translating vanilla JS into an Ember Component

Hello! Currently, I’m trying to translate some code from an existing source to an ember project. I’m fairly new, so I’m a bit lost and confused. My goal is to implement a zoom feature for images and then hover/navigate around that enlarged image. I’ve had seen an example of using eventListiner, but I don’t know how to translate that over to Ember. This is the original code that I’m trying to implement in an ember component:

class ZoomHover extends HTMLElement {
  constructor() {
    super();
    this.root = this.attachShadow({ mode: "open" });
    this.root.innerHTML = `
        <template id='zoom-template'>
            <style>
                .zoom-img {
                          background-repeat: no-repeat;
                         
                         }
                .zoom-img:hover img {
                        opacity: 0;
                        cursor: zoom-in;
                    }
                .tumb {
                        align-items: center;
                        justify-content: center;
                        padding:1px;
                }
                .tumb img {
                        max-width: 100%;
                        max-height: 100%;
                    }
             </style>
                
             <figure class="tumb zoom-img">
               <img src='' alt="not found" />
            </figure>
    </template>`;

    this.backgroundImage = "";
    this.backgroundPosition = "0% 0%";
    this.height = "400px";
  }

  connectedCallback() {
    const content = this.root
      .querySelector("#zoom-template")
      .content.cloneNode(true);
    const image = content.querySelector("img");
    const figure = content.querySelector("figure");
    this.hasAttribute("height")
      ? (figure.style.height = `${this.getAttribute("height")}px`)
      : (figure.style.height = this.height);
    if (this.hasAttribute("image")) {
      const imgAttr = this.getAttribute("image");
      this.backgroundImage = `url(${imgAttr})`;
      image.src = imgAttr;
      this.root.appendChild(content);
    }

    figure.addEventListener("mousemove", e => {
      const { left, top, width, height } = e.target.getBoundingClientRect();
      const x = ((e.pageX - left) / width) * 100;
      const y = ((e.pageY - top) / height) * 100;
      this.backgroundPosition = `${x}% ${y}%`;
      figure.style.backgroundImage = this.backgroundImage;
      figure.style.backgroundPosition = this.backgroundPosition;
    });

    figure.addEventListener("mouseout", e => {
      figure.style.backgroundImage = "";
      figure.style.backgroundPosition = "0% 0%";
    });
  }
}

customElements.define("zoom-hover", ZoomHover);

module.exports = ZoomHover;

If anyone can point me in the right direction, I would appreciate it.

Hi @Luis_Miranda, welcome!

With the caveat that I haven’t used a web component or the shadow DOM in Ember I think there are a couple ways you could go here.

The most straightforward translation would be writing an “element modifier”, and attaching the modifier to a regular img tag (or whatever you choose in terms of the tag, could be a div or something too. A modifier is a bit of javascript that you attach to a DOM element much in the way that this web component is working. A theoretical invocation of this modifier might look something like:

<img src="..." {{zoom-hover height="600"}} />

or if it should be attached to a div maybe more like:

<div {{zoom-hover image="image-url-here" height="600"}}></div>

The other way you could go is write a regular component which does the same thing, but that is less of a tweak and reuse and more of a full rewrite situation to adapt the web component code to idiomatic Ember component code.

At first glance I’d think the modifier makes a lot of sense and would be a fairly easy translation. But like I said I’ve never actually tried shadow dom or other web-component-y stuff and I haven’t looked SUPER deeply at the code so i’m not 100% how much tweaking you’d have to do at the end of the day.

3 Likes