trigger-scope-add.tentative.html (7296B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <link rel="help" src="https://drafts.csswg.org/css-animations-2/#trigger-scope"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/web-animations/testcommon.js"></script> 8 <script src="/dom/events/scrolling/scroll_support.js"></script> 9 <script src="support/support.js"></script> 10 <script src="support/trigger-scope-support.js"></script> 11 </head> 12 <body> 13 <style> 14 @keyframes expand { 15 from { transform: scaleX(1) } 16 to { transform: scaleX(2) } 17 } 18 #outerscroller { 19 position: relative; 20 overflow-y: scroll; 21 border: solid 1px; 22 height: 400px; 23 width: 400px; 24 } 25 #innerscroller { 26 position: relative; 27 overflow-y: scroll; 28 height: 200px; 29 width: 200px; 30 border: solid 1px; 31 display: block; 32 } 33 #source { 34 position: absolute; 35 top: 100%; 36 height: 100px; 37 width: 100px; 38 background-color: blue; 39 timeline-trigger: --trigger view() contain; 40 } 41 .target { 42 background-color: red; 43 height: 100px; 44 width: 100px; 45 animation: expand linear 1s both; 46 animation-trigger: --trigger play-forwards; 47 } 48 49 #inner_target { 50 /* Let's it be in view when the trigger source comes into view */ 51 margin-top: 50%; 52 } 53 54 .long { 55 width: 50%; 56 height: 100%; 57 } 58 </style> 59 <div id="outerscroller"> 60 <div id="innerscroller"> 61 <div id="inner_target" class="target">In-scope Target</div> 62 <div class="long"></div> 63 <div class="long"></div> 64 </div> 65 <div id="source">SOURCE</div> 66 <div id="outer_target" class="target"> 67 Out-of-scope Target 68 </div> 69 <div class="long"></div> 70 <div class="long"></div> 71 </div> 72 73 <script> 74 let inner_target = document.getElementById("inner_target"); 75 let outer_target = document.getElementById("outer_target"); 76 let source = document.getElementById("source"); 77 78 let current_scroller = outerscroller; 79 80 async function scrollToTrigger() { 81 const scrollend_promise = 82 waitForScrollEndFallbackToDelayWithoutScrollEvent(current_scroller); 83 source.scrollIntoView({block: "center"}); 84 await scrollend_promise; 85 await waitForCompositorReady(); 86 } 87 88 async function resetScrollPositionAndElements(test) { 89 await waitForScrollReset(test, current_scroller); 90 91 // Reset the animations, so we can detect when they trigger again. 92 inner_target.getAnimations()[0].pause(); 93 inner_target.getAnimations()[0].currentTime = 0; 94 95 outer_target.getAnimations()[0].pause(); 96 outer_target.getAnimations()[0].currentTime = 0; 97 98 await waitForCompositorCommit(); 99 100 // Both inner and outer animations should once again be paused. 101 await assert_playstate_and_current_time( 102 inner_target.id, inner_target.getAnimations()[0], "paused"); 103 await assert_playstate_and_current_time(outer_target.id, 104 outer_target.getAnimations()[0], 105 "paused"); 106 assert_equals(current_scroller.scrollTop, 0, "scroll position reset"); 107 } 108 109 async function scrollAndAssert(inner_play_state, outer_play_state) { 110 await scrollToTrigger(); 111 assert_greater_than(current_scroller.scrollTop, 0, "did scroll"); 112 113 // Both the inner and outer targets should be triggered as there is no 114 // scope and they are both attached to the trigger. 115 await assert_playstate_and_current_time(inner_target.id, 116 inner_target.getAnimations()[0], 117 inner_play_state); 118 await assert_playstate_and_current_time(outer_target.id, 119 outer_target.getAnimations()[0], 120 outer_play_state); 121 } 122 123 promise_test(async(test) => { 124 assert_equals(getComputedStyle(innerscroller).triggerScope, "none"); 125 await assert_playstate_and_current_time( 126 inner_target.id, inner_target.getAnimations()[0], "paused"); 127 await assert_playstate_and_current_time(outer_target.id, 128 outer_target.getAnimations()[0], 129 "paused"); 130 131 // Scroll to make the trigger fire. 132 // Both the inner and outer targets should be triggered as there is no 133 // scope and they are both attached to the trigger. 134 await scrollAndAssert(/*inner=*/"running", /*outer=*/"running"); 135 136 // Now, insert a scope. 137 innerscroller.style.triggerScope = "--trigger"; 138 139 await resetScrollPositionAndElements(test); 140 141 // Scroll to make the trigger fire again. 142 // Only the outer animation should be triggered as the inner is 143 // prevented from seeing the trigger sue to the scope. 144 await scrollAndAssert(/*inner=*/"paused", /*outer=*/"running"); 145 146 // Now, remove the scope. 147 innerscroller.style.triggerScope = "initial"; 148 149 await resetScrollPositionAndElements(test); 150 151 // Scroll to make the trigger fire again. 152 // Both the inner and outer targets should be triggered as there is no 153 // scope and they are both attached to the trigger. 154 await scrollAndAssert(/*inner=*/"running", /*outer=*/"running"); 155 }, "Added scope prevents subtree from searching for external trigger"); 156 157 promise_test(async(test) => { 158 // Move the source within the scope so that inner_target sees the 159 // trigger when the scope is inserted. And set the scroller to watch to 160 // innerscroller. 161 outerscroller.removeChild(source); 162 innerscroller.append(source); 163 current_scroller = innerscroller; 164 165 await resetScrollPositionAndElements(test); 166 167 // Scroll to make the trigger fire. 168 // Both the inner and outer targets should be triggered as there is no 169 // scope and they are both attached to the trigger. 170 await scrollAndAssert(/*inner=*/"running", /*outer=*/"running"); 171 172 // Now, insert a scope. 173 innerscroller.style.triggerScope = "--trigger"; 174 175 await resetScrollPositionAndElements(test); 176 177 // Scroll to make the trigger fire again. 178 // Only the inner animation should be triggered as the outer is 179 // prevented from seeing the trigger due to the scope. 180 await scrollAndAssert(/*inner=*/"running", /*outer=*/"paused"); 181 182 // Now, remove the scope. 183 innerscroller.style.triggerScope = "initial"; 184 185 await resetScrollPositionAndElements(test); 186 187 // Scroll to make the trigger fire again. 188 // Both the inner and outer targets should be triggered as there is no 189 // scope and they are both attached to the trigger. 190 await scrollAndAssert(/*inner=*/"running", /*outer=*/"running"); 191 }, "Added scope prevents external references from finding trigger " + 192 "within scope."); 193 </script> 194 </body> 195 </html>