2008-09-01  Dean Jackson  <dino@apple.com>

        Reviewed by Sam Weinig.

        https://bugs.webkit.org/show_bug.cgi?id=20571
        Make sure Window object can assign Animation/Transition event
        listeners via attributes.

        Also added a bunch of transition event tests, although
        only transition-end-event-window is directly relevant to this patch.

        (WebCore::JSDOMWindowBase::put):

        Tests: transitions/transition-end-event-all-properties.html
               transitions/transition-end-event-attributes.html
               transitions/transition-end-event-container.html
               transitions/transition-end-event-left.html
               transitions/transition-end-event-multiple-01.html
               transitions/transition-end-event-multiple-02.html
               transitions/transition-end-event-multiple-03.html
               transitions/transition-end-event-multiple-04.html
               transitions/transition-end-event-nested.html
               transitions/transition-end-event-transform.html
               transitions/transition-end-event-window.html


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@36021 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 7e21bfa..a8a6450 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,37 @@
+2008-08-29  Dean Jackson  <dino@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=20571
+        Add a bunch of tests for WebKitTransitionEndEvents.
+
+        * transitions/end-event-helpers.js: Added.
+        * transitions/interrupted-all-transition-expected.txt:
+        * transitions/interrupted-all-transition.html:
+        * transitions/opacity-transition-zindex-expected.txt:
+        * transitions/transition-end-event-all-properties-expected.txt: Added.
+        * transitions/transition-end-event-all-properties.html: Added.
+        * transitions/transition-end-event-attributes-expected.txt: Added.
+        * transitions/transition-end-event-attributes.html: Added.
+        * transitions/transition-end-event-container-expected.txt: Added.
+        * transitions/transition-end-event-container.html: Added.
+        * transitions/transition-end-event-left-expected.txt: Added.
+        * transitions/transition-end-event-left.html: Added.
+        * transitions/transition-end-event-multiple-01-expected.txt: Added.
+        * transitions/transition-end-event-multiple-01.html: Added.
+        * transitions/transition-end-event-multiple-02-expected.txt: Added.
+        * transitions/transition-end-event-multiple-02.html: Added.
+        * transitions/transition-end-event-multiple-03-expected.txt: Added.
+        * transitions/transition-end-event-multiple-03.html: Added.
+        * transitions/transition-end-event-multiple-04-expected.txt: Added.
+        * transitions/transition-end-event-multiple-04.html: Added.
+        * transitions/transition-end-event-nested-expected.txt: Added.
+        * transitions/transition-end-event-nested.html: Added.
+        * transitions/transition-end-event-transform-expected.txt: Added.
+        * transitions/transition-end-event-transform.html: Added.
+        * transitions/transition-end-event-window-expected.txt: Added.
+        * transitions/transition-end-event-window.html: Added.
+
 2008-09-01  Geoffrey Garen  <ggaren@apple.com>
 
         Reviewed by Darin Adler.
diff --git a/LayoutTests/transitions/end-event-helpers.js b/LayoutTests/transitions/end-event-helpers.js
new file mode 100644
index 0000000..b9986b0
--- /dev/null
+++ b/LayoutTests/transitions/end-event-helpers.js
@@ -0,0 +1,80 @@
+var results = new Array();
+
+function compareEventInfo(e1, e2) {
+  // sort by property name then event target id
+  // index 0 is the propertyName
+  if (e1[0]<e2[0]) return -1;
+  if (e1[0]>e2[0]) return +1;
+  // index 1 is the target id
+  if (e1[1]<e2[1]) return -1;
+  if (e1[1]>e2[1]) return +1;
+  return 0;
+}
+
+function recordEvent(event) {
+  results.push([
+    event.propertyName,
+    event.target.id,
+    event.type,
+    Math.round(event.elapsedTime * 1000) / 1000 // round off any float errors
+    ]);
+}
+
+function examineResults(expected) {
+  // sort results so events always display in the same order
+  results.sort(compareEventInfo);
+  var result = '<p>';
+  for (var i=0; i < results.length && i < expected.length; ++i) {
+    result += "Expected Property: " + expected[i][0] + " ";
+    result += "Target: " + expected[i][1] + " ";
+    result += "Type: " + expected[i][2] + " ";
+    result += "Elapsed Time: " + expected[i][3] + " -- ";
+    
+    if (expected[i][0] == results[i][0] &&
+        expected[i][1] == results[i][1] &&
+        expected[i][2] == results[i][2] &&
+        expected[i][3] == results[i][3])
+      result += "PASS";
+    else {
+      result += "FAIL -- Received";
+      result += "Property: " + results[i][0] + " ";
+      result += "Target: " + results[i][1] + " ";
+      result += "Type: " + results[i][2] + " ";
+      result += "Elapsed Time: " + results[i][3];
+      
+    }
+    result += "<br>";
+  }
+  result += "</p>";
+  
+  if (expected.length > results.length) {
+    result += "<p>Missing events -- FAIL<br>";
+    for (i=results.length; i < expected.length; ++i) {
+      result += "Missing Property: " + expected[i][0] + " ";
+      result += "Target: " + expected[i][1] + " ";
+      result += "Type: " + expected[i][2] + " ";
+      result += "Elapsed Time: " + expected[i][3] + "<br>";
+    }
+    result += "</p>";
+  } else if (expected.length < results.length) {
+    result += "<p>Unexpected events -- FAIL<br>";
+    for (i=expected.length; i < results.length; ++i) {
+      result += "Unexpected Property: " + results[i][0] + " ";
+      result += "Target: " + results[i][1] + " ";
+      result += "Type: " + results[i][2] + " ";
+      result += "Elapsed Time: " + results[i][3] + "<br>";
+    }
+    result += "</p>";
+  }
+  
+  return result;
+}
+
+function cleanup()
+{
+  document.body.removeChild(document.getElementById('container'));
+  document.getElementById('result').innerHTML = examineResults(expected);
+
+  if (window.layoutTestController)
+      layoutTestController.notifyDone();
+}
diff --git a/LayoutTests/transitions/transition-end-event-all-properties-expected.txt b/LayoutTests/transitions/transition-end-event-all-properties-expected.txt
new file mode 100644
index 0000000..76a2762
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-all-properties-expected.txt
@@ -0,0 +1,10 @@
+Initiating transitions on various properties of all boxes.
+
+Expected Property: Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: Target: box2 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: Target: box2 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.7 -- PASS
+Expected Property: Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.7 -- PASS
+Expected Property: Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.7 -- PASS
+Expected Property: Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.7 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-all-properties.html b/LayoutTests/transitions/transition-end-event-all-properties.html
new file mode 100644
index 0000000..40da04a
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-all-properties.html
@@ -0,0 +1,77 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-duration: 0.5s;
+    }
+    
+    .box1 {
+      left: 50px;
+    }
+    
+    .box2 {
+      background-color: red;
+      left: 50px;
+    }
+    
+    .box3 {
+      width: 150px;
+      background-color: green;
+      left: 50px;
+      height: 120px;
+      -webkit-transition-duration: 0.7s;
+    }
+    
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+
+    var expected = [
+      ["", "box1", "webkitTransitionEnd", 0.5],
+      ["", "box2", "webkitTransitionEnd", 0.5],
+      ["", "box2", "webkitTransitionEnd", 0.5],
+      ["", "box3", "webkitTransitionEnd", 0.7],
+      ["", "box3", "webkitTransitionEnd", 0.7],
+      ["", "box3", "webkitTransitionEnd", 0.7],
+      ["", "box3", "webkitTransitionEnd", 0.7]
+    ];
+    
+    function startTransition()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].addEventListener("webkitTransitionEnd", recordEvent, false);
+        boxes[i].className = "box box" + (i+1);
+      }
+      
+      window.setTimeout(cleanup, 1000);
+    }
+    
+    window.addEventListener('load', startTransition, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating transitions on various properties of all boxes.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+  <div id="box2" class="box"></div>
+  <div id="box3" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-attributes-expected.txt b/LayoutTests/transitions/transition-end-event-attributes-expected.txt
new file mode 100644
index 0000000..dae8e17
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-attributes-expected.txt
@@ -0,0 +1,4 @@
+Initiating a 500ms transition on the left property of box1.
+
+Expected Property: left Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-attributes.html b/LayoutTests/transitions/transition-end-event-attributes.html
new file mode 100644
index 0000000..4bac84e
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-attributes.html
@@ -0,0 +1,51 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: left;
+      -webkit-transition-duration: 0.5s;
+    }
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+    
+    var expected = [
+      ['left', 'box1', 'webkitTransitionEnd', 0.5]
+    ];
+
+    function startTransition()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].style.left = '200px';
+      }
+      
+      window.setTimeout(cleanup, 700);
+    }
+    
+    window.addEventListener('load', startTransition, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating a 500ms transition on the left property of box1.</p>
+
+<div id="container">
+  <div id="box1" class="box" onwebkittransitionend="recordEvent(event);"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-container-expected.txt b/LayoutTests/transitions/transition-end-event-container-expected.txt
new file mode 100644
index 0000000..164c660
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-container-expected.txt
@@ -0,0 +1,4 @@
+Initiating a 500ms transition on the left property of box1 and catching it on the parent.
+
+Expected Property: left Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-container.html b/LayoutTests/transitions/transition-end-event-container.html
new file mode 100644
index 0000000..9494410
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-container.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: left;
+      -webkit-transition-duration: 0.5s;
+    }
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+
+    var expected = [
+      ["left", "box1", "webkitTransitionEnd", 0.5]
+    ];
+    
+    function startTransition()
+    {
+      document.getElementById("container").addEventListener("webkitTransitionEnd", recordEvent, false);
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].style.left = '200px';
+      }
+      
+      window.setTimeout(cleanup, 700);
+    }
+    
+    window.addEventListener('load', startTransition, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating a 500ms transition on the left property of box1 and catching it on the parent.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-left-expected.txt b/LayoutTests/transitions/transition-end-event-left-expected.txt
new file mode 100644
index 0000000..dae8e17
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-left-expected.txt
@@ -0,0 +1,4 @@
+Initiating a 500ms transition on the left property of box1.
+
+Expected Property: left Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-left.html b/LayoutTests/transitions/transition-end-event-left.html
new file mode 100644
index 0000000..d2d99e2
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-left.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: left;
+      -webkit-transition-duration: 0.5s;
+    }
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+
+    var expected = [
+      ["left", "box1", "webkitTransitionEnd", 0.5]
+    ];
+    
+    function startTransition()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].addEventListener("webkitTransitionEnd", recordEvent, false);
+        boxes[i].style.left = '200px';
+      }
+      
+      window.setTimeout(cleanup, 700);
+    }
+    
+    window.addEventListener('load', startTransition, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating a 500ms transition on the left property of box1.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-multiple-01-expected.txt b/LayoutTests/transitions/transition-end-event-multiple-01-expected.txt
new file mode 100644
index 0000000..3ba7b2a
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-multiple-01-expected.txt
@@ -0,0 +1,7 @@
+Initiating a 500ms transition on the left, background-color, width and height properties of box1.
+
+Expected Property: background-color Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: height Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: left Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: width Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-multiple-01.html b/LayoutTests/transitions/transition-end-event-multiple-01.html
new file mode 100644
index 0000000..6de228c
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-multiple-01.html
@@ -0,0 +1,58 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: width, left, background-color, height, top;
+      -webkit-transition-duration: 0.5s;
+    }
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+    
+    var expected = [
+      ["background-color", "box1", "webkitTransitionEnd", 0.5],
+      ["height", "box1", "webkitTransitionEnd", 0.5],
+      ["left", "box1", "webkitTransitionEnd", 0.5],
+      ["width", "box1", "webkitTransitionEnd", 0.5],
+    ];
+    
+    function startTransition()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].addEventListener("webkitTransitionEnd", recordEvent, false);
+        boxes[i].style.width = "150px";
+        boxes[i].style.left = '200px';
+        boxes[i].style.backgroundColor = 'red';
+        boxes[i].style.height = '80px';
+      }
+      
+      window.setTimeout(cleanup, 700);
+    }
+    
+    window.addEventListener('load', startTransition, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating a 500ms transition on the left, background-color, width and height properties of box1.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-multiple-02-expected.txt b/LayoutTests/transitions/transition-end-event-multiple-02-expected.txt
new file mode 100644
index 0000000..8c378c7
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-multiple-02-expected.txt
@@ -0,0 +1,10 @@
+Initiating transitions on various properties of all boxes.
+
+Expected Property: background-color Target: box2 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: background-color Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.7 -- PASS
+Expected Property: height Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.7 -- PASS
+Expected Property: left Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: left Target: box2 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: left Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.7 -- PASS
+Expected Property: width Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.7 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-multiple-02.html b/LayoutTests/transitions/transition-end-event-multiple-02.html
new file mode 100644
index 0000000..47a531f
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-multiple-02.html
@@ -0,0 +1,77 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: width, left, background-color, height, top;
+      -webkit-transition-duration: 0.5s;
+    }
+    
+    .box1 {
+      left: 50px;
+    }
+    
+    .box2 {
+      background-color: red;
+      left: 50px;
+    }
+    
+    .box3 {
+      width: 150px;
+      background-color: green;
+      left: 50px;
+      height: 120px;
+      -webkit-transition-duration: 0.7s;
+    }
+    
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+    var expected = [
+      ["background-color", "box2", "webkitTransitionEnd", 0.5],
+      ["background-color", "box3", "webkitTransitionEnd", 0.7],
+      ["height", "box3", "webkitTransitionEnd", 0.7],
+      ["left", "box1", "webkitTransitionEnd", 0.5],
+      ["left", "box2", "webkitTransitionEnd", 0.5],
+      ["left", "box3", "webkitTransitionEnd", 0.7],
+      ["width", "box3", "webkitTransitionEnd", 0.7],
+    ];
+
+    function startTransition()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].addEventListener("webkitTransitionEnd", recordEvent, false);
+        boxes[i].className = "box box" + (i+1);
+      }
+      
+      window.setTimeout(cleanup, 1000);
+    }
+    
+    window.addEventListener('load', startTransition, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating transitions on various properties of all boxes.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+  <div id="box2" class="box"></div>
+  <div id="box3" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-multiple-03-expected.txt b/LayoutTests/transitions/transition-end-event-multiple-03-expected.txt
new file mode 100644
index 0000000..7e73f99
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-multiple-03-expected.txt
@@ -0,0 +1,12 @@
+Initiating transitions on various properties of all boxes, with different start times on the transitions.
+
+Expected Property: background-color Target: box2 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: background-color Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.6 -- PASS
+Expected Property: height Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.6 -- PASS
+Expected Property: height Target: box4 Type: webkitTransitionEnd Elapsed Time: 0.3 -- PASS
+Expected Property: left Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: left Target: box2 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: left Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.6 -- PASS
+Expected Property: left Target: box4 Type: webkitTransitionEnd Elapsed Time: 0.3 -- PASS
+Expected Property: width Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.6 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-multiple-03.html b/LayoutTests/transitions/transition-end-event-multiple-03.html
new file mode 100644
index 0000000..86e5c95
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-multiple-03.html
@@ -0,0 +1,102 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: width, left, background-color, height, top;
+      -webkit-transition-duration: 0.5s;
+    }
+    
+    .box1 {
+      left: 50px;
+    }
+    
+    .box2 {
+      background-color: red;
+      left: 50px;
+    }
+    
+    .box3 {
+      width: 150px;
+      background-color: green;
+      left: 50px;
+      height: 120px;
+      -webkit-transition-duration: 0.6s;
+    }
+
+    .box4 {
+      left: 100px;
+      height: 140px;
+      -webkit-transition-duration: 0.3s;
+    }
+
+    .box5 {
+      /* nothing */
+    }
+
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+
+    var expected = [
+      ["background-color", "box2", "webkitTransitionEnd", 0.5],
+      ["background-color", "box3", "webkitTransitionEnd", 0.6],
+      ["height", "box3", "webkitTransitionEnd", 0.6],
+      ["height", "box4", "webkitTransitionEnd", 0.3],
+      ["left", "box1", "webkitTransitionEnd", 0.5],
+      ["left", "box2", "webkitTransitionEnd", 0.5],
+      ["left", "box3", "webkitTransitionEnd", 0.6],
+      ["left", "box4", "webkitTransitionEnd", 0.3],
+      ["width", "box3", "webkitTransitionEnd", 0.6]
+    ];
+    
+    function transitionElement(index) {
+      var boxes = document.body.getElementsByClassName('box');
+      boxes[index-1].className = "box box" + index;
+    }
+
+    function startTransitions()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].addEventListener("webkitTransitionEnd", recordEvent, false);
+      }
+
+      window.setTimeout(function() { transitionElement(1); }, 100);
+      window.setTimeout(function() { transitionElement(2); }, 150);
+      window.setTimeout(function() { transitionElement(3); }, 200);
+      window.setTimeout(function() { transitionElement(4); }, 50);
+      window.setTimeout(function() { transitionElement(5); }, 150);
+      
+      window.setTimeout(cleanup, 1000);
+    }
+    
+    window.addEventListener('load', startTransitions, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating transitions on various properties of all boxes, with different start times on the transitions.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+  <div id="box2" class="box"></div>
+  <div id="box3" class="box"></div>
+  <div id="box4" class="box"></div>
+  <div id="box5" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-multiple-04-expected.txt b/LayoutTests/transitions/transition-end-event-multiple-04-expected.txt
new file mode 100644
index 0000000..a62639d
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-multiple-04-expected.txt
@@ -0,0 +1,6 @@
+Initiating transitions on transform properties of all boxes, starting at different times and with different durations and values.
+
+Expected Property: -webkit-transform Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+Expected Property: -webkit-transform Target: box2 Type: webkitTransitionEnd Elapsed Time: 0.55 -- PASS
+Expected Property: -webkit-transform Target: box4 Type: webkitTransitionEnd Elapsed Time: 0.4 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-multiple-04.html b/LayoutTests/transitions/transition-end-event-multiple-04.html
new file mode 100644
index 0000000..5053c1c
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-multiple-04.html
@@ -0,0 +1,93 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transform: translate(0);
+      -webkit-transition-property: -webkit-transform;
+      -webkit-transition-duration: 0.5s;
+    }
+    
+    .box1 {
+      -webkit-transform: translate(50px);
+    }
+    
+    .box2 {
+      -webkit-transform: translate(50px) scale(1.05);
+      -webkit-transition-duration: 0.55s;
+    }
+    
+    .box3 {
+      -webkit-transform: translate(0); /* same as default */
+      -webkit-transition-duration: 0.3s;
+    }
+
+    .box4 {
+      -webkit-transform: translate(100px);
+      -webkit-transition-duration: 0.4s;
+    }
+
+    .box5 {
+      /* nothing */
+    }
+
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+  
+    var expected = [
+      ["-webkit-transform", "box1", "webkitTransitionEnd", 0.5],
+      ["-webkit-transform", "box2", "webkitTransitionEnd", 0.55],
+      ["-webkit-transform", "box4", "webkitTransitionEnd", 0.4]
+    ];
+  
+    function transitionElement(index) {
+      var boxes = document.body.getElementsByClassName('box');
+      boxes[index-1].className = "box box" + index;
+    }
+
+    function startTransitions()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].addEventListener("webkitTransitionEnd", recordEvent, false);
+      }
+
+      window.setTimeout(function() { transitionElement(1); }, 100);
+      window.setTimeout(function() { transitionElement(2); }, 150);
+      window.setTimeout(function() { transitionElement(3); }, 200);
+      window.setTimeout(function() { transitionElement(4); }, 50);
+      window.setTimeout(function() { transitionElement(5); }, 150);
+      
+      window.setTimeout(cleanup, 1000);
+    }
+    
+    window.addEventListener('load', startTransitions, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating transitions on transform properties of all boxes, starting at different times and with different durations and values.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+  <div id="box2" class="box"></div>
+  <div id="box3" class="box"></div>
+  <div id="box4" class="box"></div>
+  <div id="box5" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-nested-expected.txt b/LayoutTests/transitions/transition-end-event-nested-expected.txt
new file mode 100644
index 0000000..df4137e
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-nested-expected.txt
@@ -0,0 +1,6 @@
+Initiating transitions on various properties of all boxes.
+
+Expected Property: background-color Target: box2 Type: webkitTransitionEnd Elapsed Time: 0.2 -- PASS
+Expected Property: left Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.2 -- PASS
+Expected Property: width Target: box3 Type: webkitTransitionEnd Elapsed Time: 0.3 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-nested.html b/LayoutTests/transitions/transition-end-event-nested.html
new file mode 100644
index 0000000..a16569a
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-nested.html
@@ -0,0 +1,95 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: width, left, background-color, height, top;
+      -webkit-transition-duration: 0.2s;
+    }
+    
+    .box1 {
+      left: 50px;
+    }
+    
+    .box2 {
+      background-color: red;
+    }
+    
+    .box3 {
+      width: 150px;
+      -webkit-transition-duration: 0.3s;
+    }
+    
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+
+    var expected = [
+      ["background-color", "box2", "webkitTransitionEnd", 0.2],
+      ["left", "box1", "webkitTransitionEnd", 0.2],
+      ["width", "box3", "webkitTransitionEnd", 0.3],
+    ];
+    
+    function startTransition1()
+    {
+      var box = document.getElementById("box1");
+      box.addEventListener("webkitTransitionEnd", handleEndEvent1, false);
+      box.className = "box box1";
+    }
+
+    function handleEndEvent1(event) {
+      recordEvent(event);
+      setTimeout(startTransition2, 100);
+    }
+
+    function startTransition2()
+    {
+      var box = document.getElementById("box2");
+      box.addEventListener("webkitTransitionEnd", handleEndEvent2, false);
+      box.className = "box box2";
+    }
+
+    function handleEndEvent2(event) {
+      recordEvent(event);
+      setTimeout(startTransition3, 100);
+    }
+
+    function startTransition3()
+    {
+      var box = document.getElementById("box3");
+      box.addEventListener("webkitTransitionEnd", handleEndEvent3, false);
+      box.className = "box box3";
+    }
+
+    function handleEndEvent3(event) {
+      recordEvent(event);
+      window.setTimeout(cleanup, 100);
+    }
+
+    window.addEventListener('load', startTransition1, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating transitions on various properties of all boxes.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+  <div id="box2" class="box"></div>
+  <div id="box3" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-transform-expected.txt b/LayoutTests/transitions/transition-end-event-transform-expected.txt
new file mode 100644
index 0000000..872f5a7
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-transform-expected.txt
@@ -0,0 +1,4 @@
+Initiating a 500ms transition on the transform property of box1.
+
+Expected Property: -webkit-transform Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-transform.html b/LayoutTests/transitions/transition-end-event-transform.html
new file mode 100644
index 0000000..e674c35
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-transform.html
@@ -0,0 +1,53 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: -webkit-transform;
+      -webkit-transition-duration: 0.5s;
+      -webkit-transform: translate(100px);
+    }
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+
+    var expected = [
+      ["-webkit-transform", "box1", "webkitTransitionEnd", 0.5]
+    ];
+    
+    function startTransition()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        boxes[i].addEventListener("webkitTransitionEnd", recordEvent, false);
+        boxes[i].style.webkitTransform = 'translate(200px)';
+      }
+      
+      window.setTimeout(cleanup, 700);
+    }
+    
+    window.addEventListener('load', startTransition, false);
+  </script>
+</head>
+<body>
+
+<p>Initiating a 500ms transition on the transform property of box1.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/transitions/transition-end-event-window-expected.txt b/LayoutTests/transitions/transition-end-event-window-expected.txt
new file mode 100644
index 0000000..47aab59
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-window-expected.txt
@@ -0,0 +1,4 @@
+Initiating a 500ms transition on the left property of box1 and catching it on the window.
+
+Expected Property: left Target: box1 Type: webkitTransitionEnd Elapsed Time: 0.5 -- PASS
+
diff --git a/LayoutTests/transitions/transition-end-event-window.html b/LayoutTests/transitions/transition-end-event-window.html
new file mode 100644
index 0000000..4275292
--- /dev/null
+++ b/LayoutTests/transitions/transition-end-event-window.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+  <title>Transition End Events</title>
+  <style type="text/css" media="screen">
+    .box {
+      position: relative;
+      left: 0;
+      height: 100px;
+      width: 100px;
+      margin: 10px;
+      background-color: blue;
+      -webkit-transition-property: left;
+      -webkit-transition-duration: 0.5s;
+    }
+  </style>
+  <script src="end-event-helpers.js" type="text/javascript" charset="utf-8"></script>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+
+    var expected = [
+      ["left", "box1", "webkitTransitionEnd", 0.5]
+    ];
+    
+    function startTransition()
+    {
+      var boxes = document.body.getElementsByClassName('box');
+      for (var i = 0; i < boxes.length; ++i) {
+        // we have to attach an empty handler here otherwise the event isn't
+        // fired (WebCore looks at the document to see if there are any listeners
+        // and ignores the one on Window) - this should be fixed
+        boxes[i].addEventListener("webkitTransitionEnd", function () {}, false);
+        boxes[i].style.left = '200px';
+      }
+      
+      window.setTimeout(cleanup, 700);
+    }
+    
+    window.addEventListener('load', startTransition, false);
+    window.onwebkittransitionend = recordEvent;
+  </script>
+</head>
+<body>
+
+<p>Initiating a 500ms transition on the left property of box1 and catching it on the window.</p>
+
+<div id="container">
+  <div id="box1" class="box"></div>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index fc71803..7c2a30e 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,5 +1,30 @@
 2008-09-01  Dean Jackson  <dino@apple.com>
 
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=20571
+        Make sure Window object can assign Animation/Transition event
+        listeners via attributes.
+
+        Also added a bunch of transition event tests, although
+        only transition-end-event-window is directly relevant to this patch.
+
+        (WebCore::JSDOMWindowBase::put):
+
+        Tests: transitions/transition-end-event-all-properties.html
+               transitions/transition-end-event-attributes.html
+               transitions/transition-end-event-container.html
+               transitions/transition-end-event-left.html
+               transitions/transition-end-event-multiple-01.html
+               transitions/transition-end-event-multiple-02.html
+               transitions/transition-end-event-multiple-03.html
+               transitions/transition-end-event-multiple-04.html
+               transitions/transition-end-event-nested.html
+               transitions/transition-end-event-transform.html
+               transitions/transition-end-event-window.html
+
+2008-09-01  Dean Jackson  <dino@apple.com>
+
         Reviewed by Sam Weinig
 
         Code styling cleanup.
diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp
index 16677d9..51bca54 100644
--- a/WebCore/bindings/js/JSDOMWindowBase.cpp
+++ b/WebCore/bindings/js/JSDOMWindowBase.cpp
@@ -749,6 +749,22 @@
             if (allowsAccessFrom(exec))
                 setListener(exec, unloadEvent, value);
             return;
+        case OnWebKitAnimationStart:
+            if (allowsAccessFrom(exec))
+                setListener(exec, webkitAnimationStartEvent, value);
+            return;
+        case OnWebKitAnimationIteration:
+            if (allowsAccessFrom(exec))
+                setListener(exec, webkitAnimationIterationEvent, value);
+            return;
+        case OnWebKitAnimationEnd:
+            if (allowsAccessFrom(exec))
+                setListener(exec, webkitAnimationEndEvent, value);
+            return;
+        case OnWebKitTransitionEnd:
+            if (allowsAccessFrom(exec))
+                setListener(exec, webkitTransitionEndEvent, value);
+            return;
         default:
             break;
         }