1197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// found in the LICENSE file. 4197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 5197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch'use strict'; 6197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 7e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)installClass('HTMLMarqueeElement', function(HTMLMarqueeElementPrototype) { 8197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 9197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kDefaultScrollAmount = 6; 10197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kDefaultScrollDelayMS = 85; 11197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kMinimumScrollDelayMS = 60; 12197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 13197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kDefaultLoopLimit = -1; 14197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 15197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kBehaviorScroll = 'scroll'; 16197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kBehaviorSlide = 'slide'; 17197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kBehaviorAlternate = 'alternate'; 18197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 19197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kDirectionLeft = 'left'; 20197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kDirectionRight = 'right'; 21197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kDirectionUp = 'up'; 22197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kDirectionDown = 'down'; 23197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 24197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kPresentationalAttributes = [ 25197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 'bgcolor', 26197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 'height', 27197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 'hspace', 28197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 'vspace', 29197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 'width', 30197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ]; 31197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 32197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var pixelLengthRegexp = /^\s*([\d.]+)\s*$/; 33197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var percentageLengthRegexp = /^\s*([\d.]+)\s*%\s*$/; 34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch function convertHTMLLengthToCSSLength(value) { 36197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var pixelMatch = value.match(pixelLengthRegexp); 37197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (pixelMatch) 38197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return pixelMatch[1] + 'px'; 39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var percentageMatch = value.match(percentageLengthRegexp); 40197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (percentageMatch) 41197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return percentageMatch[1] + '%'; 42197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return null; 43197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 44197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 45197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // FIXME: Consider moving these utility functions to PrivateScriptRunner.js. 46197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var kInt32Max = Math.pow(2, 31); 47197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 48197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch function convertToLong(n) { 49197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Using parseInt() is wrong but this aligns with the existing behavior of StringImpl::toInt(). 50197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // FIXME: Implement a correct algorithm of the Web IDL value conversion. 51197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var value = parseInt(n); 52197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (!isNaN(value) && -kInt32Max <= value && value < kInt32Max) 53197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return value; 54197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return NaN; 55197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 56197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 57197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch function reflectAttribute(prototype, attributeName, propertyName) { 58197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Object.defineProperty(prototype, propertyName, { 59197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch get: function() { 60197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return this.getAttribute(attributeName) || ''; 61197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 62197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch set: function(value) { 63197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.setAttribute(attributeName, value); 64197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 65197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch configurable: true, 66197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch enumerable: true, 67197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }); 68197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 69197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 70197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch function reflectBooleanAttribute(prototype, attributeName, propertyName) { 71197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Object.defineProperty(prototype, propertyName, { 72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch get: function() { 73197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return this.hasAttribute(attributeName); 74197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch set: function(value) { 76197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (value) 77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.setAttribute(attributeName, ''); 78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch else 79197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.removeAttribute(attributeName); 80197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 81197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }); 82197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 83197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 84197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch function defineInlineEventHandler(prototype, eventName) { 85197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var propertyName = 'on' + eventName; 86197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // FIXME: We should use symbols here instead. 87197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var functionPropertyName = propertyName + 'Function_'; 88197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var eventHandlerPropertyName = propertyName + 'EventHandler_'; 89197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Object.defineProperty(prototype, propertyName, { 90197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch get: function() { 91197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var func = this[functionPropertyName]; 92197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return func || null; 93197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch set: function(value) { 95197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var oldEventHandler = this[eventHandlerPropertyName]; 96197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (oldEventHandler) 97197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.removeEventListener(eventName, oldEventHandler); 98197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Notice that we wrap |value| in an anonymous function so that the 99197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // author can't call removeEventListener themselves to unregister the 100197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // inline event handler. 101197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var newEventHandler = value ? function() { value.apply(this, arguments) } : null; 102197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (newEventHandler) 103197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.addEventListener(eventName, newEventHandler); 104197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this[functionPropertyName] = value; 105197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this[eventHandlerPropertyName] = newEventHandler; 106197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 107197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }); 108197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 109197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 110197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch reflectAttribute(HTMLMarqueeElementPrototype, 'behavior', 'behavior'); 111197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch reflectAttribute(HTMLMarqueeElementPrototype, 'bgcolor', 'bgColor'); 112197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch reflectAttribute(HTMLMarqueeElementPrototype, 'direction', 'direction'); 113197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch reflectAttribute(HTMLMarqueeElementPrototype, 'height', 'height'); 114197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch reflectAttribute(HTMLMarqueeElementPrototype, 'hspace', 'hspace'); 115197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch reflectAttribute(HTMLMarqueeElementPrototype, 'vspace', 'vspace'); 116197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch reflectAttribute(HTMLMarqueeElementPrototype, 'width', 'width'); 117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch reflectBooleanAttribute(HTMLMarqueeElementPrototype, 'truespeed', 'trueSpeed'); 118197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 119197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch defineInlineEventHandler(HTMLMarqueeElementPrototype, 'start'); 120197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch defineInlineEventHandler(HTMLMarqueeElementPrototype, 'finish'); 121197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch defineInlineEventHandler(HTMLMarqueeElementPrototype, 'bounce'); 122197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 123197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.createdCallback = function() { 124197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var shadow = this.createShadowRoot(); 125e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) var style = document.createElement('style'); 126197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch style.textContent = ':host { display: inline-block; width: -webkit-fill-available; overflow: hidden; text-align: initial; }' + 127197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ':host([direction="up"]), :host([direction="down"]) { height: 200px; }'; 128197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch shadow.appendChild(style); 129197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 130e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) var mover = document.createElement('div'); 131197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch shadow.appendChild(mover); 132197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 133e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) mover.appendChild(document.createElement('content')); 134197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 135197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.loopCount_ = 0; 136197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.mover_ = mover; 137197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.player_ = null; 138197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.continueCallback_ = null; 139197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 140197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch for (var i = 0; i < kPresentationalAttributes.length; ++i) 141197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.initializeAttribute_(kPresentationalAttributes[i]); 142197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 143197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 144197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.attachedCallback = function() { 145197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.start(); 146197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 147197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 148197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.detachedCallback = function() { 149197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.stop(); 150197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 151197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 152197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.attributeChangedCallback = function(name, oldValue, newValue) { 153197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch switch (name) { 154197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case 'bgcolor': 155197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.style.backgroundColor = newValue; 156197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 157197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case 'height': 158197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.style.height = convertHTMLLengthToCSSLength(newValue); 159197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 160197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case 'hspace': 161197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var margin = convertHTMLLengthToCSSLength(newValue); 162197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.style.marginLeft = margin; 163197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.style.marginRight = margin; 164197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 165197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case 'vspace': 166197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var margin = convertHTMLLengthToCSSLength(newValue); 167197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.style.marginTop = margin; 168197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.style.marginBottom = margin; 169197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 170197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case 'width': 171197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.style.width = convertHTMLLengthToCSSLength(newValue); 172197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 173197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case 'behavior': 174197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case 'direction': 175197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.stop(); 176197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.loopCount_ = 0; 177197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.start(); 178197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 179197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 180197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 181197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 182197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.initializeAttribute_ = function(name) { 183197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var value = this.getAttribute(name); 184197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (value === null) 185197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return; 186197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.attributeChangedCallback(name, null, value); 187197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 188197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 189197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Object.defineProperty(HTMLMarqueeElementPrototype, 'scrollAmount', { 190197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch get: function() { 191197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var value = this.getAttribute('scrollamount'); 192197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var scrollAmount = convertToLong(value); 193197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (isNaN(scrollAmount) || scrollAmount < 0) 194197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return kDefaultScrollAmount; 195197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return scrollAmount; 196197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 197197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch set: function(value) { 198197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (value < 0) 1997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci throwException(PrivateScriptDOMException.IndexSizeError, "The provided value (" + value + ") is negative."); 200197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.setAttribute('scrollamount', value); 201197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 202197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }); 203197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 204197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Object.defineProperty(HTMLMarqueeElementPrototype, 'scrollDelay', { 205197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch get: function() { 206197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var value = this.getAttribute('scrolldelay'); 207197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var scrollDelay = convertToLong(value); 208197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (isNaN(scrollDelay) || scrollDelay < 0) 209197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return kDefaultScrollDelayMS; 210197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return scrollDelay; 211197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 212197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch set: function(value) { 213197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (value < 0) 2147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci throwException(PrivateScriptDOMException.IndexSizeError, "The provided value (" + value + ") is negative."); 215197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.setAttribute('scrolldelay', value); 216197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 217197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }); 218197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 219197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch Object.defineProperty(HTMLMarqueeElementPrototype, 'loop', { 220197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch get: function() { 221197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var value = this.getAttribute('loop'); 222197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var loop = convertToLong(value); 223197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (isNaN(loop) || loop <= 0) 224197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return kDefaultLoopLimit; 225197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return loop; 226197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 227197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch set: function(value) { 228197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (value <= 0 && value != -1) 2297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci throwException(PrivateScriptDOMException.IndexSizeError, "The provided value (" + value + ") is neither positive nor -1."); 230197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.setAttribute('loop', value); 231197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }, 232197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }); 233197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 234197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.getGetMetrics_ = function() { 235197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.mover_.style.width = '-webkit-max-content'; 236197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 237e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) var moverStyle = getComputedStyle(this.mover_); 238e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) var marqueeStyle = getComputedStyle(this); 239197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 240197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var metrics = {}; 241197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch metrics.contentWidth = parseInt(moverStyle.width); 242197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch metrics.contentHeight = parseInt(moverStyle.height); 243197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch metrics.marqueeWidth = parseInt(marqueeStyle.width); 244197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch metrics.marqueeHeight = parseInt(marqueeStyle.height); 245197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 246197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.mover_.style.width = ''; 247197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return metrics; 248197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 249197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 250197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.getAnimationParameters_ = function() { 251197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var metrics = this.getGetMetrics_(); 252197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 253197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var totalWidth = metrics.marqueeWidth + metrics.contentWidth; 254197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var totalHeight = metrics.marqueeHeight + metrics.contentHeight; 255197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 256197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var innerWidth = metrics.marqueeWidth - metrics.contentWidth; 257197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var innerHeight = metrics.marqueeHeight - metrics.contentHeight; 258197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 259197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var parameters = {}; 260197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 261197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch switch (this.behavior) { 262197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kBehaviorScroll: 263197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch default: 264197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch switch (this.direction) { 265197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionLeft: 266197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch default: 267197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateX(' + metrics.marqueeWidth + 'px)'; 268197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateX(-100%)'; 269197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = totalWidth; 270197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 271197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionRight: 272197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateX(-' + metrics.contentWidth + 'px)'; 273197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateX(' + metrics.marqueeWidth + 'px)'; 274197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = totalWidth; 275197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 276197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionUp: 277197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateY(' + metrics.marqueeHeight + 'px)'; 278197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateY(-' + metrics.contentHeight + 'px)'; 279197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = totalHeight; 280197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 281197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionDown: 282197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateY(-' + metrics.contentHeight + 'px)'; 283197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateY(' + metrics.marqueeHeight + 'px)'; 284197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = totalHeight; 285197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 286197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 287197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 288197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kBehaviorAlternate: 289197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch switch (this.direction) { 290197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionLeft: 291197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch default: 292197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateX(' + innerWidth + 'px)'; 293197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateX(0)'; 294197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = innerWidth; 295197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 296197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionRight: 297197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateX(0)'; 298197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateX(' + innerWidth + 'px)'; 299197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = innerWidth; 300197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 301197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionUp: 302197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateY(' + innerHeight + 'px)'; 303197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateY(0)'; 304197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = innerHeight; 305197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 306197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionDown: 307197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateY(0)'; 308197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateY(' + innerHeight + 'px)'; 309197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = innerHeight; 310197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 311197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 312197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 313197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (this.loopCount_ % 2) { 314197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var transform = parameters.transformBegin; 315197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = parameters.transformEnd; 316197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = transform; 317197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 318197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 319197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 320197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kBehaviorSlide: 321197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch switch (this.direction) { 322197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionLeft: 323197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch default: 324197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateX(' + metrics.marqueeWidth + 'px)'; 325197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateX(0)'; 326197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = metrics.marqueeWidth; 327197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 328197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionRight: 329197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateX(-' + metrics.contentWidth + 'px)'; 330197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateX(' + innerWidth + 'px)'; 331197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = metrics.marqueeWidth; 332197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 333197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionUp: 334197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateY(' + metrics.marqueeHeight + 'px)'; 335197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateY(0)'; 336197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = metrics.marqueeHeight; 337197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 338197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case kDirectionDown: 339197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformBegin = 'translateY(-' + metrics.contentHeight + 'px)'; 340197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.transformEnd = 'translateY(' + innerHeight + 'px)'; 341197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch parameters.distance = metrics.marqueeHeight; 342197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 343197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 344197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch break; 345197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 346197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 347197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return parameters 348197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 349197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 350197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.shouldContinue_ = function() { 351197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var loop = this.loop; 352197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 353197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // By default, slide loops only once. 354197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (loop <= 0 && this.behavior === kBehaviorSlide) 355197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch loop = 1; 356197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 357197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (loop <= 0) 358197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return true; 359197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return this.loopCount_ < loop; 360197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 361197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 362197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.continue_ = function() { 363197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (!this.shouldContinue_()) { 364197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.player_ = null; 365197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.dispatchEvent(new Event('finish', false, true)); 366197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return; 367197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 368197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 369197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var parameters = this.getAnimationParameters_(); 370197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 371197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var player = this.mover_.animate([ 372197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch { transform: parameters.transformBegin }, 373197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch { transform: parameters.transformEnd }, 374197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ], { 375197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch duration: parameters.distance * this.scrollDelay / this.scrollAmount, 376197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch fill: 'forwards', 377197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }); 378197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 379197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.player_ = player; 380197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 381197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch player.addEventListener('finish', function() { 382197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (player != this.player_) 383197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return; 384197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch ++this.loopCount_; 385197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.continue_(); 386197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (this.player_ && this.behavior === kBehaviorAlternate) 387197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.dispatchEvent(new Event('bounce', false, true)); 388197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }.bind(this)); 389197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 390197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 391197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.start = function() { 392197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (this.continueCallback_ || this.player_) 393197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return; 394e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) this.continueCallback_ = requestAnimationFrame(function() { 395197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.continueCallback_ = null; 396197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.continue_(); 397197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }.bind(this)); 398197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.dispatchEvent(new Event('start', false, true)); 399197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 400197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 401197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch HTMLMarqueeElementPrototype.stop = function() { 402197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (!this.continueCallback_ && !this.player_) 403197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return; 404197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 405197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (this.continueCallback_) { 406e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) cancelAnimationFrame(this.continueCallback_); 407197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.continueCallback_ = null; 408197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return; 409197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 410197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 411197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // FIXME: Rather than canceling the animation, we really should just 412197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // pause the animation, but the pause function is still flagged as 413197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // experimental. 414197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (this.player_) { 415197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch var player = this.player_; 416197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch this.player_ = null; 417197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch player.cancel(); 418197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 419197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch }; 420197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 421197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // FIXME: We have to inject this HTMLMarqueeElement as a custom element in order to make 422197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // createdCallback, attachedCallback, detachedCallback and attributeChangedCallback workable. 423e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // document.registerElement('i-marquee', { 424197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // prototype: HTMLMarqueeElementPrototype, 425197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // }); 426197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}); 427