new Blazy in js not executing

Created on 8 June 2023, over 1 year ago
Updated 10 June 2023, over 1 year ago

Problem/Motivation

When upgrading from v2.5 to v2.16 our instances of new Blazy no longer fire.

For example, in the following, success or error, never fire.

    const bLazy = new Blazy({
      success: function (element) {
        // Image has loaded
	console.log("success");
      },
      error: function (element, msg) {
        console.error("error");
      }
    });

Steps to reproduce

On v2.16 instantiate new Blazy in js.

Im aware of the notice on the project page about issues with 2.6-2.9+ so not sure if this is part of that issue. Im a bit confused if 2.9+ means 2.9.x or includes 2.10, 2.11, etc...

Anyhow I went ahead and tried to upgrade directly to 2.16 where Im experiencing this. In the mean time Ill try to upgrading to previous versions in case I can find anymore details.

💬 Support request
Status

Fixed

Version

2.16

Component

JavaScript

Created by

🇺🇸United States justclint

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @justclint
  • Status changed to Postponed: needs info over 1 year ago
  • 🇮🇩Indonesia gausarts

    You are partly correct.

    The old bLazy was made as a fallback for old browsers only since 2.6, see project home requirements, including the why there. The main engine now is native browsers: Intersection Observer (IO) +/- native lazy loading optional via Blazy UI.

    Yours will only work at old browsers since then.

    Since IO was introduced, you can actually access both instances via Drupal.blazy.init object, better than reinitializing it separately.

    Let me know?

  • 🇺🇸United States justclint

    Thanks @gausarts!

    I see we have Drupal.blazy.init.load(), Drupal.blazy.init.revalidate(), etc.. and options.success and options.error.

    Im able to execute on options.success and options.error but I get unexpected results where params are always undefined. Im guessing my syntax might be off here:

        Drupal.blazy.init.options.success(function (element, msg) {
          console.log("success");
          console.log(element);
          console.log(msg);
        });
    
        Drupal.blazy.init.options.error(function (element, msg) {
          console.log("error");
          console.log(element);
          console.log(msg);
        });
    

    What would be the correct way to replicate this https://dinbror.dk/blog/blazy/#Callback in new IO? I need to execute on each image after successful lazyload and log any errors if they come up.

  • 🇮🇩Indonesia gausarts

    You are right. Limitation, or simplification.

    IO only provides messages -1| false for error, and 1|true for success:
    https://git.drupalcode.org/project/blazy/-/blob/8.x-2.x/js/base/io/bio.m...

    Some old invalid and missing are errors which should be taken care of server-side. Both will result in the same b-error CSS class.

    However should you want to have those original messages, I would accept patches, maybe around these:
    https://git.drupalcode.org/project/blazy/-/blob/8.x-2.x/js/base/io/bio.m...

        // Preload `img` to have correct event handlers.
        $.decode(img)
          .then(function () {
            load(el, true);
          })
          .catch(function () {
            load(el, isResimage);
    
            // Allows to re-observe.
            if (!isResimage) {
              el.bhit = false;
            }
          });

    > options.success and options.error but I get unexpected results where params are always undefined
    Correct. Drupal.blazy.init is an already initialized object which overrides those error and success functions removing such messages:
    https://git.drupalcode.org/project/blazy/-/blob/8.x-2.x/js/base/blazy.dr...

    success: me.clearing.bind(me),
    error: me.clearing.bind(me),
    

    Notice both functions are handled with the exact same function, no more messages after param el:
    https://git.drupalcode.org/project/blazy/-/blob/8.x-2.x/js/base/blazy.dr...
    clearing: function (el) {
    That is why "params are always undefined". Only relied on b-error and b-loaded CSS classes to react accordingly.

    > What would be the correct way to replicate this https://dinbror.dk/blog/blazy/#Callback in new IO?
    If b-error and b-loaded is not enough, consider overriding Drupal.blazy.globals instead via $.extend().
    https://git.drupalcode.org/project/blazy/-/blob/8.x-2.x/js/base/blazy.dr...

    Or selectively via: Drupal.blazy.options
    https://git.drupalcode.org/project/blazy/-/blob/8.x-2.x/js/base/blazy.dr...

    See Ajaxin and IO which extends Blazy IO for different behaviors/ purposes such as replacing loading animation, and lazy loading blocks using AJAX respectively.

    > The usecase in our example is disabling a skeleton loader overlay after image has loaded.
    This was done exactly by Ajaxin .

    Perhaps listening to blazy.done will be simpler:
    $.on(el, 'blazy.done', doneCallback, false);

    Where dollar sign $ is for dBlazy, not jQuery.
    doneCallback is your function which reacts on the el which has b-error and b-loaded:
    https://git.drupalcode.org/project/blazy/-/blob/8.x-2.x/js/base/blazy.dr...

    If you would like to improve the current implementation, consider patches. So much room for improvements.
    Thanks.

  • 🇺🇸United States justclint

    Thanks for the detailed explanation. This is very helpful.

    I tried listening to blazy.done and it works but I must be missing or misunderstanding something in regards to timing.

    When I use it like this I guess I was expecting that after blazy was done, we'd see the data-src value moved to src but this doesnt seem to be the case in my test:

    (function ($, Drupal, once, dBlazy) {
      Drupal.behaviors.cardGrid = {
        attach: function (context, settings) {
          once('cardGrid', '.card-grid', context).forEach(function (element) {
            $(".card").each(function () {
              const cardImage = $(".b-lazy", this);
    
              const showImage = function () {
                console.log(image.data('src')); // STILL POPULATED
                console.log(image.attr('src')); // STILL EMPTY
                // Hide skeleton overlay...
              }
              dBlazy.on(cardImage, 'blazy.done', showImage, false);
            });
          });
        }
      };
    })(jQuery, Drupal, once, dBlazy);
    

    For sake of this issue, I think we can close. What you provided above puts me in the right direction and if I can come up with meaningful patches I will.

    Thanks again!

  • Status changed to Fixed over 1 year ago
  • 🇮🇩Indonesia gausarts

    > the data-src value moved to src but this doesnt seem to be the case in my test
    Correct. Because that is beyond blazy.done event, might be executed too early before the event is triggered. Even if you depends your scripts on blazy/load. If not be sure to add dependencies on blazy/load to avoid misses for other use cases. Unless you want to modify things before Blazy, of course. Basically just script orders.

    You can access the el properties via its callback instead:

    var doneCallback = function (e) {
            var el = e.target;
            console.log($.attr(el, 'data-src') + ' : ' + el.src);
          };
    
          $.on(el, 'blazy.done', doneCallback, false);
    

    By then only el.src has its value.

    Although it is working as it is now, your last comment is useful to make me think to put the event trigger after the rest of other minor functions in there. Thanks.

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024