10

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>
Shomz
  • 37,421
  • 4
  • 57
  • 85
TurgidWizard
  • 619
  • 1
  • 7
  • 22
  • [It does work.](http://jsfiddle.net/uav0b0e0/) – Pointy Jan 27 '15 at 15:19
  • 1
    Uncaught TypeError: Failed to execute 'animate' on 'Element': Valid arities are: [1], but 0 arguments provided. – mplungjan Jan 27 '15 at 15:19
  • 2
    Doesn't work in Chrome, works in IE. ~~[See this](http://stackoverflow.com/questions/1791515/onclick-does-not-work-properly-on-p-tag).~~ Its not related to onclick on the p tag, but the animate function. – charles Jan 27 '15 at 15:20
  • 4
    Rename animate to anim. Seems animate is a reserved word (in Chrome) – mplungjan Jan 27 '15 at 15:21
  • @charles Works for me in Chrome. – AStopher Jan 27 '15 at 15:21
  • Try a different name the method animate() already exists and you're naming is confusing the Internets – Dave Goten Jan 27 '15 at 15:21
  • 1
    second @mplungjan ... animate is reserved – Ji_in_coding Jan 27 '15 at 15:22
  • Yes, animate is reserved in most browsers. – El Guapo Jan 27 '15 at 15:23
  • Ahh, interesting that it doesn't work in Chrome. I changed the name to function's name to anim and whole things works perfectly. This is the kind of thing that crushes my spirit, when I can't understand why it doesn't work - it should work, but then it turns out to be something like this. Also, who down-voted me and why? – TurgidWizard Jan 27 '15 at 15:25
  • 2
    There are many people here who downvote first, and use their brains later... Just ignore them. Your question is a good one, I just changed the title a bit so it reflects the issue better and will help future users who stumble upon this issue. Welcome to SO! – Shomz Jan 27 '15 at 15:35
  • To @mplungjan and the two others that said this: **`animate` is not a reserved word**. It doesn’t work because, in short, the `onclick` attribute assumes an implicit `with`-scope that includes parts of the element’s prototype chain which contains the function property `animate` from `Element.prototype.animate`, overshadowing the `animate` function defined above. Which, by the way, is one of [_many_ reasons to avoid `onclick`](https://stackoverflow.com/a/43459991/4642212). – Sebastian Simon Aug 14 '19 at 18:46
  • @SebastianSimon as elaborated in the answer https://stackoverflow.com/a/28174022/295783 – mplungjan Aug 14 '19 at 18:48

3 Answers3

14

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>
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Btw. Why use `var div = document.getElementById('demo');` shouldnt `var div = this;` be enought? Without a fix id it would be even usable for multiple elements... – wawa May 18 '15 at 22:27
  • @wawa OK, true, I just used OP's code. I will leave it as is to keep it simple (instead of using `call` to pass the `this` to the function when using event handler content attributes). – Oriol May 18 '15 at 22:34
  • Wouldn’t it be better to turn the order of solutions upside-down, so they’re from most recommended to least recommended? – Sebastian Simon Sep 23 '21 at 15:54
5

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);
Shomz
  • 37,421
  • 4
  • 57
  • 85
  • 1
    Well found. I could not find it fast enough since it is not an ecmascript thing – mplungjan Jan 27 '15 at 15:28
  • 2
    Thank you, @mplungjan. I assumed it was not ecma, so went straight in and looked for Chrome(ium) implementations. – Shomz Jan 27 '15 at 15:29
-1

I have just had the same problem. Now I know that 'animate' is a reserved word or something. I changed the name of my function from 'animate' to 'anim' and the program worked fine. What a prank!

Peristilo peris
  • 105
  • 1
  • 7