0

Style objectPosition Property gives this example of setting objectPosition:

document.getElementById("myImg").style.objectPosition = "0 10%";

However, when I try to set objectPosition it causes my JavaScript to crash.

In the following code I use CSS to set objectPosition like this:

#img1 {
  object-position: 0 0;
  width:  635px ;
  height: 580px ;
}

Near the bottom of function getImg, my debug code (the “insert” statement) shows it set to “0px 0px”. However, if I proceed this with

imgStyle.objectPosition = "0 0";

The “insert” statement and all following statements are not executed. Here’s my full code with the offending statement commented out:

"use strict";
const numberOfFigures = document.getElementsByTagName('figure').length;
const scale = 3; // scaling up factor

// The function "insert" is used purely for debug purposes
function insert(figNum) {
  document.getElementById("para").innerHTML = "OK so far" + figNum;
}

// Create all thumbnails & big images.
for (let i = 0; i < numberOfFigures; i++) {
  getImg(i + 1);
}


function getImg(figNum) {

  // Create the thumbnails and big images

  let startPosn = "0px"; // x-coordinate of object-position for thumbnail

  var btnDiv = document.createElement('div');
  btnDiv.setAttribute("id", "bigImg" + figNum);
  btnDiv.style.backgroundColor = "white";

  // Get the figure caption
  const figcap = document.getElementById("fig" + figNum).firstElementChild;

  btnDiv.innerHTML =
    '<button type="button"' +
    'class="displayBtn"' +
    'onclick="hideBigImg (' +
    figNum +
    ')">Hide large image</button>';
  const btnPtr = figcap.appendChild(btnDiv);
  /* Append the button to the
                                                     figcaption */

  var imgDiv = document.createElement('div');
  imgDiv.setAttribute("id", "imgDiv" + figNum);

  if (figNum === 1) {
    /* First image needs height: 100vh or only the top slice is
     displayed. Other images may be messed up if this is applied to
     them. */
    imgDiv.innerHTML = '<' + 'img id="img' + figNum + '" ' +
      'class = "sprite-img" ' +
      'src="bates-sprite.jpeg" ' +
      'style="height: 100vh; ' +
      'transform-origin: top left; ' +
      'transform: scale(' +
      scale + ');">';
  } else {
    imgDiv.innerHTML = '<' + 'img id="img' + figNum + '" ' +
      'class = "sprite-img" ' +
      'src="bates-sprite.jpeg" ' +
      'style="transform-origin: top left; ' +
      'transform: scale(' +
      scale + ');">';
  }
  const imgPtr = btnPtr.appendChild(imgDiv);
  /* Append the img to the
                                                    button */

  /* Make imgDiv high enough to hold the scaled up image & make the
     accompanying text visible.
     IMPORTANT to do this AFTER creating & appending the. */

  // Get the height and width of the image
  let img = document.getElementById("img" + figNum);
  const imgStyle = getComputedStyle(img);

  // Set imgDiv to exactly hold image
  imgDiv.style.width = parseInt(imgStyle.width) * scale + "px";
  imgDiv.style.height = parseInt(imgStyle.height) * scale + "px";
  imgDiv.style.overflow = "hidden"; // Clip off rest of sprite

  /*********************** Create thumbnail here *************/

  let thumbHTML = '<' + 'div id="thumbDiv' + figNum + '" ' +
    'onclick = "showBigImg(' +
    figNum + ')" ' +
    'style="float: left; ' +
    'height: imgStyle.height; ' +
    'width: imgStyle.width; ' +
    'margin-right: 1.5em; ' +
    'background-color: white; ' +
    'border: thick solid black;"> ' +

    '<' + 'img id="img' + figNum + '" ' +
    'class = "sprite-img" ' +
    'src="bates-sprite.jpeg" ' +
    'style="transform-origin: top left; ' +
    'transform: scale(0.5);" ' +
    'onclick = "showBigImg(' +
    figNum + ')";>' +

    '</div>';

  figcap.insertAdjacentHTML("afterend", thumbHTML);
  /* Append the
                                                           thumbnail to the
                                                           figcaption       */


  /* Shrink the div to match the size of the thumbnail, and free up all the
     blank space which the full size image would have occupied if it hadn't
     been reduced with transform: scale */

  let thumbnail = document.getElementById("thumbDiv" + figNum);
  thumbnail.style.width = parseInt(imgStyle.width) / 2 + "px";
  thumbnail.style.height = parseInt(imgStyle.height) / 2 + "px";

  // Set object-position for image in sprite
  //imgStyle.objectPosition = "0 0";
  insert(imgStyle.objectPosition);

  hideBigImg(figNum);
}

function showBigImg(figNum) {
  document.getElementById('bigImg' + figNum).style.display = 'block';
  document.getElementById('thumbDiv' + figNum).style.display = 'none';
}

function hideBigImg(figNum) {
  document.getElementById('bigImg' + figNum).style.display = 'none';
  document.getElementById('thumbDiv' + figNum).style.display = 'block';
}
/* Global constants */

 :root {
  --shrink: 0.30;
  /* Size compressed to 30% */
}

figure {
  display: block;
  width: 96%;
  float: left;
  border-width: thin;
}

figcaption {
  background-color: yellow;
}

.sprite-img {
  background-repeat: no-repeat;
  object-fit: none;
}

#img1 {
  object-position: 0 0;
  width: 635px;
  height: 580px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="general.css">

</head>

<body>

  <figure id="fig1">
    <figcaption>Camberley Mail</figcaption>
    <p id="para">Text to go with picture.</p>
  </figure>

</body>

</html>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hobbyist
  • 29
  • 6
  • 3
    "Crash" how? Is there an error on the browser's development console? – David Sep 20 '22 at 20:19
  • MDN states that "The object from getComputedStyle is read-only, and should be used to inspect the element's style [...] "The element.style object should be used to set styles on that element, or inspect styles directly added to it from JavaScript manipulation or the global style attribute." ~ https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle#description – Kostas Minaidis Sep 20 '22 at 20:29
  • 2
    I would expect you to get the error "Uncaught NoModificationAllowedError: Failed to set the 'object-position' property on 'CSSStyleDeclaration': These styles are computed, and therefore the 'object-position' property is read-only." – James Sep 20 '22 at 20:29
  • 1
    You should use `img.style` to get the style object that you can update. – Barmar Sep 20 '22 at 20:29
  • 1
    Probably duplication of https://stackoverflow.com/questions/60510438/failed-to-execute-setproperty-on-cssstyledeclaration-these-styles-are-compu – Vadym Lenda Sep 20 '22 at 20:37
  • That was incredibly helpful. I just needed to change imgStyle.objectPosition to img.style.objectPosition – Hobbyist Sep 20 '22 at 20:56

1 Answers1

1

The reason why the program 'crashes' or more specifically throws an Exception is because you are trying to modify the properties of a read-only object.

In detail:

const img = document.querySelector("img");
const imgStyle = getComputedStyle(img); // imgStyle is a read-only object
imgStyle.objectPosition = "0 0";

The above code will throw:

Uncaught DOMException: Failed to set the 'object-position' property on 'CSSStyleDeclaration': These styles are computed, and therefore the 'object-position' property is read-only.

As stated in the MDN documentation:

"The object from getComputedStyle is read-only, and should be used to inspect the element's style — including those set by a element or an external stylesheet.

The element.style object should be used to set styles on that element, or inspect styles directly added to it from JavaScript manipulation or the global style attribute."

So, based on the docs, you should use the element.style object for setting the properties:

img.style.objectPosition = "0 0";
Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25