Change record status: 
Project: 
Introduced in branch: 
8.0.x
Introduced in version: 
8.0.0-beta8
Description: 

jQuery Once now targets version 2.x. This update comes with some new features:

  • Performance improvements through using jQuery's .data() rather than manipulating the DOM
  • Moves towards jQuery chaining rather than function callbacks
  • A new .findOnce() method to select elements that have already been once'd.

Drupal 7

/**
 * Attach my behavior to the .mybehavior elements.
 */
Drupal.behaviors.mybehavior = {
  attach: function(context) {
    // Set the initial state of the toolbar.
    $('.mybehavior', context).once('mybehavior', function() {
      // Do something to the elements.
      $(this).css('background-color', 'red');
    });
  }
};

Drupal 8

/**
 * Attach my behavior to the .mybehavior elements.
 */
Drupal.behaviors.mybehavior = {
  attach: function(context) {
    // Set the initial state of the toolbar.
    $(context).find('[data-mybehavior]').once('mybehavior').each(function() {
      // Do something to the elements.
      $(this).css('background-color', 'red');
    });
  }
};

See more examples and information in the jQuery Once API.

Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

Anonymous’s picture

To me, it was not obvious right away what the change was so:

before

$('.something').once('init', function() {
  $(this).addClass('banana');
});

after

$('.something').once('init').each(function() {
  $(this).addClass('banana');
});

Also, previousely the value used for the once() method was used as class name and '-processed' was appended to is, so the example above would result in:

<a class="something init-processed banana">Banana</a>

now it is just:

<a class="something banana">Banana</a>

So in order to visually(browsing the source code) see if the script has run you need to attach the class(or any other indicator) manually. You can also try

$('.something').data()

and look for jQueryOnceInit: true but if you'd use the old code style

$('.something').once('init', function() {
  $(this).addClass('banana');
});

it would indicate the once() method has run but in fact the logic within the empty function() would not get executed.

If you have been using this code style:

$('.something').once('init').addClass('banana');

then this change does not concern you(except the '-processed' class removal).

taggartj’s picture

var $applyBtn =  $('#view-application');
// you can chain once() ...eg 
      $applyBtn.once().on('click', function(event) {
        event.preventDefault();
        return alert('only one time');
      });
alexpott’s picture

Another thing to make sure is that your library has a dependency on core/jquery.once

Alex Pott