AlexBerd
AlexBerd

Reputation: 1504

DomContentLoaded event on image preview pages

For example I have some image src.

enter image description here

I open this page in the new chrome tab. On the page I have script that runs on DOMContentLoaded event:

 document.addEventListener('DOMContentLoaded', function() {
     console.log('done');/*call to init function*/
 }, false);

However in this case the event is never fire. On the regular page with full CSS and hierarchical DOM tree all works fine. Only in the case with open image alone in the new tab something goes wrong or I miss some details in using this event . Will be glad of any help or explanation

JSFIDDLE

UPDATE

According to this answer , the DOMContentLoaded event fires only on document.readyState=interactive, but the image view page never gave this status... So my question is there is any workaround of this issue?

Upvotes: 1

Views: 673

Answers (3)

Imran Rafiq Rather
Imran Rafiq Rather

Reputation: 8118

To answer the question, let's decode the question first from the start to set the context right and try to reach a reasonable solution.

Part 1: INITIAL QUESTION:

On the regular page with full CSS and hierarchical DOM tree, all works fine. Only in the case with open image alone in the new tab, something goes wrong or I miss some details in using this event.

My response to Part-1 (for what I understood):

The issue is related to the DOMContentLoaded event not firing when an image is opened alone in a new tab. When an image is directly opened, it does not create an HTML document context where DOMContentLoaded would be applicable. Instead, the browser treats it as a standalone image.

Handling Both Scenarios

Scenario 1: Image in an HTML Document

If you are dealing with an HTML document that includes an image, the DOMContentLoaded event should work as expected.

Scenario 2: Standalone Image

If you open the image directly in a browser tab (not embedded in an HTML document), DOMContentLoaded will not fire because there is no HTML document to load.

Handling Both Scenarios

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>Image Load Test</title>
  </head>
  <body>
    <img
      src="https://images.pexels.com/photos/1000366/pexels-photo-1000366.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
      alt="random image"
    />

    <script>
      console.log('JS loading ...')

      document.addEventListener(
        'DOMContentLoaded',
        function () {
          console.log('DOMContentLoaded event fired')
        },
        false
      )

      window.addEventListener('load', function () {
        if (document.contentType && document.contentType.startsWith('image/')) {
          console.log('Image loaded in a standalone context')
        } else {
          console.log('Window load event fired')
        }
      })
    </script>
  </body>
</html>

Explanation:

  1. DOMContentLoaded Event:

    This event is added to handle regular HTML documents. It fires when the HTML document has been completely loaded and parsed.

  2. window.addEventListener('load'):

This event is added to handle scenarios where an image is opened directly in a new tab.

It checks if the document's content type starts with 'image/'. If so, it logs a message indicating that an image was loaded in a standalone context.

If the content is not an image, it logs a different message.

PART-2: UPDATE QUESTION

UPDATE: According to this answer, the DOMContentLoaded event fires only on document.readyState=interactive, but the image view page never gave this status... So my question is there is any workaround for this issue?

Response:

The issue arises because the DOMContentLoaded event fires only when document.readyState is 'interactive', which doesn't occur in standalone image contexts. As a result, the event fails to trigger.

A workaround is to use the load event for images, as it ensures proper initialization after the image has fully loaded. Here's how you can implement it:

Workaround

Use the load event for images, ensuring the initialisation logic runs correctly regardless of the content type:

<script>
  console.log('JS loading ...')

  document.addEventListener(
    'DOMContentLoaded',
    function () {
      console.log('DOMContentLoaded event fired')
      init()
    },
    false
  )

  window.addEventListener('load', function () {
    if (document.contentType && document.contentType.startsWith('image/')) {
      console.log('Image loaded in a standalone context')
    } else {
      console.log('Window load event fired')
    }
    init()
  })

  function init() {
    console.log('Initialization function called')
    // Your initialization logic here
  }
</script>

By utilizing the load event, you ensure that your initialization logic runs regardless of the context in which the image is loaded. This addresses the issue effectively.

Upvotes: -2

David Bradshaw
David Bradshaw

Reputation: 13097

The problem is in modern browsers images are loaded asynchronously, so the DOMContentLoaded event fires before the images are fully read in. Looking at your fiddle you don’t have a <html> or <body> elements, so I expect this is why you don’t get it at all, or it could be that their is so little content that it fires before you JS has time to run.

There are two possible work arounds to this issue.

ResizeObserver If you don’t predefined the size of the image, the element will resize as the images loads and you can detect this by adding a resizeObserver to the image element, or maybe even the body tag of the document if and only if the image is in the main document flow.

Load event of the image The image element has it’s own events for load and error and you could listen for these instead.

element.addEventListener('load', imageLoaded, false)
element.addEventListener('error', imageError, false)

This is going to be the more robust approach.

Upvotes: 0

Andrew Evt
Andrew Evt

Reputation: 3689

all works fine, http://jsfiddle.net/k1L6mwzs/2/

in jsfiddle you had onLoad event setted in list at the left side of screen, and your js code is called after it.

But DOMContentLoaded event fires BEFORE onload, thats why you don't see your alert.

(if your problem is not in jsfiddle, please show us full code of page (html) and script. You are also use jQuery -> for what?)

Upvotes: -2

Related Questions