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

Are you asking how to use that custom-element in an Ember template or are you asking how to recreate/redesign the same feature as its own Ember component/feature?

If you add the custom element code to an initializer then in templates you can use them like you would in vanilla HTML

If you mean to port it (rewrite it from scratch) in Ember then using a modifier is likely the way to go.