Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS function named `animate` doesn't work in Chrome, but works in IE

This won't work, nothing happens. How do I make it work, what am I doing wrong?

function animate() {
  var div = document.getElementById('demo');
  div.style.left = "200px";
  div.style.color = "red";
}
#demo {
  position: absolute;
}
<p id='demo' onclick="animate()">lolol</p>
like image 830
TurgidWizard Avatar asked Jan 27 '15 15:01

TurgidWizard


2 Answers

The problem is that, since you use an event handler content attribute, your global function...

window.animate

...is shadowed by...

Element.prototype.animate

...which was introduced recently in Web Animations:

5.21 Extensions to the Element interface

Since DOM Elements may be the target of an animation, the Element interface [DOM4] is extended as follows:

Element implements Animatable;

This allows the following kind of usage.

elem.animate({ color: 'red' }, 2000);

This behavior is explained in step 10 of getting the current value of the event handler:

Lexical Environment Scope

  1. If H is an element's event handler, then let Scope be the result of NewObjectEnvironment(document, the global environment).

    Otherwise, H is a Window object's event handler: let Scope be the global environment.

  2. If form owner is not null, let Scope be the result of NewObjectEnvironment(form owner, Scope).

  3. If element is not null, let Scope be the result of NewObjectEnvironment(element, Scope).

Note: NewObjectEnvironment() is defined in ECMAScript edition 5 section 10.2.2.3 NewObjectEnvironment (O, E)

That means that the scope of the target element shadows the global scope.

Therefore, you can

  • Rename your function

    function animate__() {
      var div = document.getElementById('demo');
      div.style.left = "200px";
      div.style.color = "red";
    }
    #demo {
      position: absolute;
    }
    <p id='demo' onclick="animate__()">Click me</p>
  • Use window.animate (assuming window has not been shadowed):

    <p id='demo' onclick="window.animate()">Click me</p>
    

    function animate() {
      var div = document.getElementById('demo');
      div.style.left = "200px";
      div.style.color = "red";
    }
    #demo {
      position: absolute;
    }
    <p id='demo' onclick="window.animate()">Click me</p>
  • Use an event handler IDL attribute instead of a content attribute one:

    document.getElementById('demo').onclick = animate;
    

    function animate() {
      var div = document.getElementById('demo');
      div.style.left = "200px";
      div.style.color = "red";
    }
    document.getElementById('demo').onclick = animate;
    #demo {
      position: absolute;
    }
    <p id='demo'>Click me</p>
  • Use an event listener instead of an event handler:

    document.getElementById('demo').addEventListener('click', animate);
    

    function animate() {
      var div = document.getElementById('demo');
      div.style.left = "200px";
      div.style.color = "red";
    }
    document.getElementById('demo').addEventListener('click', animate);
    #demo {
      position: absolute;
    }
    <p id='demo'>Click me</p>
like image 88
Oriol Avatar answered Oct 20 '22 16:10

Oriol


As mentioned in the comment, the fix is to rename the function because it seems Chrome has reserved the original name.

element.animate()

The forthcoming Web Animations JavaScript API lets you animate web content from script. The element.animate() function included in today’s Beta is the first part of the API to ship in Chrome: it makes it possible to create simple CSS Animations using JavaScript. This means that animations can be dynamically generated without paying a CSS style recalculation cost. Animations created in this way are also cancelable and provide guaranteed end events (in contrast, CSS Transitions only generate events if they cause a style change).

http://blog.chromium.org/2014/05/chrome-36-beta-elementanimate-html.html

This is the usage example of the original animate function:

elem.animate([
    {transform: 'translateX(0px)'},
    {transform: 'translateX(100px)'}
], 3000);
like image 33
Shomz Avatar answered Oct 20 '22 17:10

Shomz