Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: chrome/browser/resources/md_history/app.crisper.js

Issue 2270993003: MD History: Add icon in top right of page when showing synced results (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@downloads_wide_toolbar
Patch Set: IWYU and vulcaniz--whoops Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 function PromiseResolver() { 4 function PromiseResolver() {
5 this.resolve_; 5 this.resolve_;
6 this.reject_; 6 this.reject_;
7 this.promise_ = new Promise(function(resolve, reject) { 7 this.promise_ = new Promise(function(resolve, reject) {
8 this.resolve_ = resolve; 8 this.resolve_ = resolve;
9 this.reject_ = reject; 9 this.reject_ = reject;
10 }.bind(this)); 10 }.bind(this));
(...skipping 2247 matching lines...) Expand 10 before | Expand all | Expand 10 after
2258 this.tabIndex = this._oldTabIndex; 2258 this.tabIndex = this._oldTabIndex;
2259 } 2259 }
2260 }, 2260 },
2261 _changedControlState: function() { 2261 _changedControlState: function() {
2262 if (this._controlStateChanged) { 2262 if (this._controlStateChanged) {
2263 this._controlStateChanged(); 2263 this._controlStateChanged();
2264 } 2264 }
2265 } 2265 }
2266 }; 2266 };
2267 2267
2268 Polymer.IronButtonStateImpl = { 2268 Polymer.IronFitBehavior = {
2269 properties: { 2269 properties: {
2270 pressed: { 2270 sizingTarget: {
2271 type: Object,
2272 value: function() {
2273 return this;
2274 }
2275 },
2276 fitInto: {
2277 type: Object,
2278 value: window
2279 },
2280 noOverlap: {
2281 type: Boolean
2282 },
2283 positionTarget: {
2284 type: Element
2285 },
2286 horizontalAlign: {
2287 type: String
2288 },
2289 verticalAlign: {
2290 type: String
2291 },
2292 dynamicAlign: {
2293 type: Boolean
2294 },
2295 horizontalOffset: {
2296 type: Number,
2297 value: 0,
2298 notify: true
2299 },
2300 verticalOffset: {
2301 type: Number,
2302 value: 0,
2303 notify: true
2304 },
2305 autoFitOnAttach: {
2271 type: Boolean, 2306 type: Boolean,
2272 readOnly: true,
2273 value: false,
2274 reflectToAttribute: true,
2275 observer: '_pressedChanged'
2276 },
2277 toggles: {
2278 type: Boolean,
2279 value: false,
2280 reflectToAttribute: true
2281 },
2282 active: {
2283 type: Boolean,
2284 value: false,
2285 notify: true,
2286 reflectToAttribute: true
2287 },
2288 pointerDown: {
2289 type: Boolean,
2290 readOnly: true,
2291 value: false 2307 value: false
2292 }, 2308 },
2293 receivedFocusFromKeyboard: { 2309 _fitInfo: {
2294 type: Boolean, 2310 type: Object
2295 readOnly: true 2311 }
2296 }, 2312 },
2297 ariaActiveAttribute: { 2313 get _fitWidth() {
2298 type: String, 2314 var fitWidth;
2299 value: 'aria-pressed', 2315 if (this.fitInto === window) {
2300 observer: '_ariaActiveAttributeChanged' 2316 fitWidth = this.fitInto.innerWidth;
2301 }
2302 },
2303 listeners: {
2304 down: '_downHandler',
2305 up: '_upHandler',
2306 tap: '_tapHandler'
2307 },
2308 observers: [ '_detectKeyboardFocus(focused)', '_activeChanged(active, ariaActi veAttribute)' ],
2309 keyBindings: {
2310 'enter:keydown': '_asyncClick',
2311 'space:keydown': '_spaceKeyDownHandler',
2312 'space:keyup': '_spaceKeyUpHandler'
2313 },
2314 _mouseEventRe: /^mouse/,
2315 _tapHandler: function() {
2316 if (this.toggles) {
2317 this._userActivate(!this.active);
2318 } else { 2317 } else {
2319 this.active = false; 2318 fitWidth = this.fitInto.getBoundingClientRect().width;
2320 } 2319 }
2321 }, 2320 return fitWidth;
2322 _detectKeyboardFocus: function(focused) { 2321 },
2323 this._setReceivedFocusFromKeyboard(!this.pointerDown && focused); 2322 get _fitHeight() {
2324 }, 2323 var fitHeight;
2325 _userActivate: function(active) { 2324 if (this.fitInto === window) {
2326 if (this.active !== active) { 2325 fitHeight = this.fitInto.innerHeight;
2327 this.active = active;
2328 this.fire('change');
2329 }
2330 },
2331 _downHandler: function(event) {
2332 this._setPointerDown(true);
2333 this._setPressed(true);
2334 this._setReceivedFocusFromKeyboard(false);
2335 },
2336 _upHandler: function() {
2337 this._setPointerDown(false);
2338 this._setPressed(false);
2339 },
2340 _spaceKeyDownHandler: function(event) {
2341 var keyboardEvent = event.detail.keyboardEvent;
2342 var target = Polymer.dom(keyboardEvent).localTarget;
2343 if (this.isLightDescendant(target)) return;
2344 keyboardEvent.preventDefault();
2345 keyboardEvent.stopImmediatePropagation();
2346 this._setPressed(true);
2347 },
2348 _spaceKeyUpHandler: function(event) {
2349 var keyboardEvent = event.detail.keyboardEvent;
2350 var target = Polymer.dom(keyboardEvent).localTarget;
2351 if (this.isLightDescendant(target)) return;
2352 if (this.pressed) {
2353 this._asyncClick();
2354 }
2355 this._setPressed(false);
2356 },
2357 _asyncClick: function() {
2358 this.async(function() {
2359 this.click();
2360 }, 1);
2361 },
2362 _pressedChanged: function(pressed) {
2363 this._changedButtonState();
2364 },
2365 _ariaActiveAttributeChanged: function(value, oldValue) {
2366 if (oldValue && oldValue != value && this.hasAttribute(oldValue)) {
2367 this.removeAttribute(oldValue);
2368 }
2369 },
2370 _activeChanged: function(active, ariaActiveAttribute) {
2371 if (this.toggles) {
2372 this.setAttribute(this.ariaActiveAttribute, active ? 'true' : 'false');
2373 } else { 2326 } else {
2374 this.removeAttribute(this.ariaActiveAttribute); 2327 fitHeight = this.fitInto.getBoundingClientRect().height;
2375 } 2328 }
2376 this._changedButtonState(); 2329 return fitHeight;
2377 }, 2330 },
2378 _controlStateChanged: function() { 2331 get _fitLeft() {
2379 if (this.disabled) { 2332 var fitLeft;
2380 this._setPressed(false); 2333 if (this.fitInto === window) {
2334 fitLeft = 0;
2381 } else { 2335 } else {
2382 this._changedButtonState(); 2336 fitLeft = this.fitInto.getBoundingClientRect().left;
2383 } 2337 }
2384 }, 2338 return fitLeft;
2385 _changedButtonState: function() { 2339 },
2386 if (this._buttonStateChanged) { 2340 get _fitTop() {
2387 this._buttonStateChanged(); 2341 var fitTop;
2388 } 2342 if (this.fitInto === window) {
2343 fitTop = 0;
2344 } else {
2345 fitTop = this.fitInto.getBoundingClientRect().top;
2346 }
2347 return fitTop;
2348 },
2349 get _defaultPositionTarget() {
2350 var parent = Polymer.dom(this).parentNode;
2351 if (parent && parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
2352 parent = parent.host;
2353 }
2354 return parent;
2355 },
2356 get _localeHorizontalAlign() {
2357 if (this._isRTL) {
2358 if (this.horizontalAlign === 'right') {
2359 return 'left';
2360 }
2361 if (this.horizontalAlign === 'left') {
2362 return 'right';
2363 }
2364 }
2365 return this.horizontalAlign;
2366 },
2367 attached: function() {
2368 this._isRTL = window.getComputedStyle(this).direction == 'rtl';
2369 this.positionTarget = this.positionTarget || this._defaultPositionTarget;
2370 if (this.autoFitOnAttach) {
2371 if (window.getComputedStyle(this).display === 'none') {
2372 setTimeout(function() {
2373 this.fit();
2374 }.bind(this));
2375 } else {
2376 this.fit();
2377 }
2378 }
2379 },
2380 fit: function() {
2381 this.position();
2382 this.constrain();
2383 this.center();
2384 },
2385 _discoverInfo: function() {
2386 if (this._fitInfo) {
2387 return;
2388 }
2389 var target = window.getComputedStyle(this);
2390 var sizer = window.getComputedStyle(this.sizingTarget);
2391 this._fitInfo = {
2392 inlineStyle: {
2393 top: this.style.top || '',
2394 left: this.style.left || '',
2395 position: this.style.position || ''
2396 },
2397 sizerInlineStyle: {
2398 maxWidth: this.sizingTarget.style.maxWidth || '',
2399 maxHeight: this.sizingTarget.style.maxHeight || '',
2400 boxSizing: this.sizingTarget.style.boxSizing || ''
2401 },
2402 positionedBy: {
2403 vertically: target.top !== 'auto' ? 'top' : target.bottom !== 'auto' ? ' bottom' : null,
2404 horizontally: target.left !== 'auto' ? 'left' : target.right !== 'auto' ? 'right' : null
2405 },
2406 sizedBy: {
2407 height: sizer.maxHeight !== 'none',
2408 width: sizer.maxWidth !== 'none',
2409 minWidth: parseInt(sizer.minWidth, 10) || 0,
2410 minHeight: parseInt(sizer.minHeight, 10) || 0
2411 },
2412 margin: {
2413 top: parseInt(target.marginTop, 10) || 0,
2414 right: parseInt(target.marginRight, 10) || 0,
2415 bottom: parseInt(target.marginBottom, 10) || 0,
2416 left: parseInt(target.marginLeft, 10) || 0
2417 }
2418 };
2419 if (this.verticalOffset) {
2420 this._fitInfo.margin.top = this._fitInfo.margin.bottom = this.verticalOffs et;
2421 this._fitInfo.inlineStyle.marginTop = this.style.marginTop || '';
2422 this._fitInfo.inlineStyle.marginBottom = this.style.marginBottom || '';
2423 this.style.marginTop = this.style.marginBottom = this.verticalOffset + 'px ';
2424 }
2425 if (this.horizontalOffset) {
2426 this._fitInfo.margin.left = this._fitInfo.margin.right = this.horizontalOf fset;
2427 this._fitInfo.inlineStyle.marginLeft = this.style.marginLeft || '';
2428 this._fitInfo.inlineStyle.marginRight = this.style.marginRight || '';
2429 this.style.marginLeft = this.style.marginRight = this.horizontalOffset + ' px';
2430 }
2431 },
2432 resetFit: function() {
2433 var info = this._fitInfo || {};
2434 for (var property in info.sizerInlineStyle) {
2435 this.sizingTarget.style[property] = info.sizerInlineStyle[property];
2436 }
2437 for (var property in info.inlineStyle) {
2438 this.style[property] = info.inlineStyle[property];
2439 }
2440 this._fitInfo = null;
2441 },
2442 refit: function() {
2443 var scrollLeft = this.sizingTarget.scrollLeft;
2444 var scrollTop = this.sizingTarget.scrollTop;
2445 this.resetFit();
2446 this.fit();
2447 this.sizingTarget.scrollLeft = scrollLeft;
2448 this.sizingTarget.scrollTop = scrollTop;
2449 },
2450 position: function() {
2451 if (!this.horizontalAlign && !this.verticalAlign) {
2452 return;
2453 }
2454 this._discoverInfo();
2455 this.style.position = 'fixed';
2456 this.sizingTarget.style.boxSizing = 'border-box';
2457 this.style.left = '0px';
2458 this.style.top = '0px';
2459 var rect = this.getBoundingClientRect();
2460 var positionRect = this.__getNormalizedRect(this.positionTarget);
2461 var fitRect = this.__getNormalizedRect(this.fitInto);
2462 var margin = this._fitInfo.margin;
2463 var size = {
2464 width: rect.width + margin.left + margin.right,
2465 height: rect.height + margin.top + margin.bottom
2466 };
2467 var position = this.__getPosition(this._localeHorizontalAlign, this.vertical Align, size, positionRect, fitRect);
2468 var left = position.left + margin.left;
2469 var top = position.top + margin.top;
2470 var right = Math.min(fitRect.right - margin.right, left + rect.width);
2471 var bottom = Math.min(fitRect.bottom - margin.bottom, top + rect.height);
2472 var minWidth = this._fitInfo.sizedBy.minWidth;
2473 var minHeight = this._fitInfo.sizedBy.minHeight;
2474 if (left < margin.left) {
2475 left = margin.left;
2476 if (right - left < minWidth) {
2477 left = right - minWidth;
2478 }
2479 }
2480 if (top < margin.top) {
2481 top = margin.top;
2482 if (bottom - top < minHeight) {
2483 top = bottom - minHeight;
2484 }
2485 }
2486 this.sizingTarget.style.maxWidth = right - left + 'px';
2487 this.sizingTarget.style.maxHeight = bottom - top + 'px';
2488 this.style.left = left - rect.left + 'px';
2489 this.style.top = top - rect.top + 'px';
2490 },
2491 constrain: function() {
2492 if (this.horizontalAlign || this.verticalAlign) {
2493 return;
2494 }
2495 this._discoverInfo();
2496 var info = this._fitInfo;
2497 if (!info.positionedBy.vertically) {
2498 this.style.position = 'fixed';
2499 this.style.top = '0px';
2500 }
2501 if (!info.positionedBy.horizontally) {
2502 this.style.position = 'fixed';
2503 this.style.left = '0px';
2504 }
2505 this.sizingTarget.style.boxSizing = 'border-box';
2506 var rect = this.getBoundingClientRect();
2507 if (!info.sizedBy.height) {
2508 this.__sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
2509 }
2510 if (!info.sizedBy.width) {
2511 this.__sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right' , 'Width');
2512 }
2513 },
2514 _sizeDimension: function(rect, positionedBy, start, end, extent) {
2515 this.__sizeDimension(rect, positionedBy, start, end, extent);
2516 },
2517 __sizeDimension: function(rect, positionedBy, start, end, extent) {
2518 var info = this._fitInfo;
2519 var fitRect = this.__getNormalizedRect(this.fitInto);
2520 var max = extent === 'Width' ? fitRect.width : fitRect.height;
2521 var flip = positionedBy === end;
2522 var offset = flip ? max - rect[end] : rect[start];
2523 var margin = info.margin[flip ? start : end];
2524 var offsetExtent = 'offset' + extent;
2525 var sizingOffset = this[offsetExtent] - this.sizingTarget[offsetExtent];
2526 this.sizingTarget.style['max' + extent] = max - margin - offset - sizingOffs et + 'px';
2527 },
2528 center: function() {
2529 if (this.horizontalAlign || this.verticalAlign) {
2530 return;
2531 }
2532 this._discoverInfo();
2533 var positionedBy = this._fitInfo.positionedBy;
2534 if (positionedBy.vertically && positionedBy.horizontally) {
2535 return;
2536 }
2537 this.style.position = 'fixed';
2538 if (!positionedBy.vertically) {
2539 this.style.top = '0px';
2540 }
2541 if (!positionedBy.horizontally) {
2542 this.style.left = '0px';
2543 }
2544 var rect = this.getBoundingClientRect();
2545 var fitRect = this.__getNormalizedRect(this.fitInto);
2546 if (!positionedBy.vertically) {
2547 var top = fitRect.top - rect.top + (fitRect.height - rect.height) / 2;
2548 this.style.top = top + 'px';
2549 }
2550 if (!positionedBy.horizontally) {
2551 var left = fitRect.left - rect.left + (fitRect.width - rect.width) / 2;
2552 this.style.left = left + 'px';
2553 }
2554 },
2555 __getNormalizedRect: function(target) {
2556 if (target === document.documentElement || target === window) {
2557 return {
2558 top: 0,
2559 left: 0,
2560 width: window.innerWidth,
2561 height: window.innerHeight,
2562 right: window.innerWidth,
2563 bottom: window.innerHeight
2564 };
2565 }
2566 return target.getBoundingClientRect();
2567 },
2568 __getCroppedArea: function(position, size, fitRect) {
2569 var verticalCrop = Math.min(0, position.top) + Math.min(0, fitRect.bottom - (position.top + size.height));
2570 var horizontalCrop = Math.min(0, position.left) + Math.min(0, fitRect.right - (position.left + size.width));
2571 return Math.abs(verticalCrop) * size.width + Math.abs(horizontalCrop) * size .height;
2572 },
2573 __getPosition: function(hAlign, vAlign, size, positionRect, fitRect) {
2574 var positions = [ {
2575 verticalAlign: 'top',
2576 horizontalAlign: 'left',
2577 top: positionRect.top,
2578 left: positionRect.left
2579 }, {
2580 verticalAlign: 'top',
2581 horizontalAlign: 'right',
2582 top: positionRect.top,
2583 left: positionRect.right - size.width
2584 }, {
2585 verticalAlign: 'bottom',
2586 horizontalAlign: 'left',
2587 top: positionRect.bottom - size.height,
2588 left: positionRect.left
2589 }, {
2590 verticalAlign: 'bottom',
2591 horizontalAlign: 'right',
2592 top: positionRect.bottom - size.height,
2593 left: positionRect.right - size.width
2594 } ];
2595 if (this.noOverlap) {
2596 for (var i = 0, l = positions.length; i < l; i++) {
2597 var copy = {};
2598 for (var key in positions[i]) {
2599 copy[key] = positions[i][key];
2600 }
2601 positions.push(copy);
2602 }
2603 positions[0].top = positions[1].top += positionRect.height;
2604 positions[2].top = positions[3].top -= positionRect.height;
2605 positions[4].left = positions[6].left += positionRect.width;
2606 positions[5].left = positions[7].left -= positionRect.width;
2607 }
2608 vAlign = vAlign === 'auto' ? null : vAlign;
2609 hAlign = hAlign === 'auto' ? null : hAlign;
2610 var position;
2611 for (var i = 0; i < positions.length; i++) {
2612 var pos = positions[i];
2613 if (!this.dynamicAlign && !this.noOverlap && pos.verticalAlign === vAlign && pos.horizontalAlign === hAlign) {
2614 position = pos;
2615 break;
2616 }
2617 var alignOk = (!vAlign || pos.verticalAlign === vAlign) && (!hAlign || pos .horizontalAlign === hAlign);
2618 if (!this.dynamicAlign && !alignOk) {
2619 continue;
2620 }
2621 position = position || pos;
2622 pos.croppedArea = this.__getCroppedArea(pos, size, fitRect);
2623 var diff = pos.croppedArea - position.croppedArea;
2624 if (diff < 0 || diff === 0 && alignOk) {
2625 position = pos;
2626 }
2627 if (position.croppedArea === 0 && alignOk) {
2628 break;
2629 }
2630 }
2631 return position;
2389 } 2632 }
2390 }; 2633 };
2391 2634
2392 Polymer.IronButtonState = [ Polymer.IronA11yKeysBehavior, Polymer.IronButtonStat eImpl ];
2393
2394 (function() { 2635 (function() {
2395 var Utility = { 2636 'use strict';
2396 distance: function(x1, y1, x2, y2) {
2397 var xDelta = x1 - x2;
2398 var yDelta = y1 - y2;
2399 return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
2400 },
2401 now: window.performance && window.performance.now ? window.performance.now.b ind(window.performance) : Date.now
2402 };
2403 function ElementMetrics(element) {
2404 this.element = element;
2405 this.width = this.boundingRect.width;
2406 this.height = this.boundingRect.height;
2407 this.size = Math.max(this.width, this.height);
2408 }
2409 ElementMetrics.prototype = {
2410 get boundingRect() {
2411 return this.element.getBoundingClientRect();
2412 },
2413 furthestCornerDistanceFrom: function(x, y) {
2414 var topLeft = Utility.distance(x, y, 0, 0);
2415 var topRight = Utility.distance(x, y, this.width, 0);
2416 var bottomLeft = Utility.distance(x, y, 0, this.height);
2417 var bottomRight = Utility.distance(x, y, this.width, this.height);
2418 return Math.max(topLeft, topRight, bottomLeft, bottomRight);
2419 }
2420 };
2421 function Ripple(element) {
2422 this.element = element;
2423 this.color = window.getComputedStyle(element).color;
2424 this.wave = document.createElement('div');
2425 this.waveContainer = document.createElement('div');
2426 this.wave.style.backgroundColor = this.color;
2427 this.wave.classList.add('wave');
2428 this.waveContainer.classList.add('wave-container');
2429 Polymer.dom(this.waveContainer).appendChild(this.wave);
2430 this.resetInteractionState();
2431 }
2432 Ripple.MAX_RADIUS = 300;
2433 Ripple.prototype = {
2434 get recenters() {
2435 return this.element.recenters;
2436 },
2437 get center() {
2438 return this.element.center;
2439 },
2440 get mouseDownElapsed() {
2441 var elapsed;
2442 if (!this.mouseDownStart) {
2443 return 0;
2444 }
2445 elapsed = Utility.now() - this.mouseDownStart;
2446 if (this.mouseUpStart) {
2447 elapsed -= this.mouseUpElapsed;
2448 }
2449 return elapsed;
2450 },
2451 get mouseUpElapsed() {
2452 return this.mouseUpStart ? Utility.now() - this.mouseUpStart : 0;
2453 },
2454 get mouseDownElapsedSeconds() {
2455 return this.mouseDownElapsed / 1e3;
2456 },
2457 get mouseUpElapsedSeconds() {
2458 return this.mouseUpElapsed / 1e3;
2459 },
2460 get mouseInteractionSeconds() {
2461 return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds;
2462 },
2463 get initialOpacity() {
2464 return this.element.initialOpacity;
2465 },
2466 get opacityDecayVelocity() {
2467 return this.element.opacityDecayVelocity;
2468 },
2469 get radius() {
2470 var width2 = this.containerMetrics.width * this.containerMetrics.width;
2471 var height2 = this.containerMetrics.height * this.containerMetrics.height;
2472 var waveRadius = Math.min(Math.sqrt(width2 + height2), Ripple.MAX_RADIUS) * 1.1 + 5;
2473 var duration = 1.1 - .2 * (waveRadius / Ripple.MAX_RADIUS);
2474 var timeNow = this.mouseInteractionSeconds / duration;
2475 var size = waveRadius * (1 - Math.pow(80, -timeNow));
2476 return Math.abs(size);
2477 },
2478 get opacity() {
2479 if (!this.mouseUpStart) {
2480 return this.initialOpacity;
2481 }
2482 return Math.max(0, this.initialOpacity - this.mouseUpElapsedSeconds * this .opacityDecayVelocity);
2483 },
2484 get outerOpacity() {
2485 var outerOpacity = this.mouseUpElapsedSeconds * .3;
2486 var waveOpacity = this.opacity;
2487 return Math.max(0, Math.min(outerOpacity, waveOpacity));
2488 },
2489 get isOpacityFullyDecayed() {
2490 return this.opacity < .01 && this.radius >= Math.min(this.maxRadius, Rippl e.MAX_RADIUS);
2491 },
2492 get isRestingAtMaxRadius() {
2493 return this.opacity >= this.initialOpacity && this.radius >= Math.min(this .maxRadius, Ripple.MAX_RADIUS);
2494 },
2495 get isAnimationComplete() {
2496 return this.mouseUpStart ? this.isOpacityFullyDecayed : this.isRestingAtMa xRadius;
2497 },
2498 get translationFraction() {
2499 return Math.min(1, this.radius / this.containerMetrics.size * 2 / Math.sqr t(2));
2500 },
2501 get xNow() {
2502 if (this.xEnd) {
2503 return this.xStart + this.translationFraction * (this.xEnd - this.xStart );
2504 }
2505 return this.xStart;
2506 },
2507 get yNow() {
2508 if (this.yEnd) {
2509 return this.yStart + this.translationFraction * (this.yEnd - this.yStart );
2510 }
2511 return this.yStart;
2512 },
2513 get isMouseDown() {
2514 return this.mouseDownStart && !this.mouseUpStart;
2515 },
2516 resetInteractionState: function() {
2517 this.maxRadius = 0;
2518 this.mouseDownStart = 0;
2519 this.mouseUpStart = 0;
2520 this.xStart = 0;
2521 this.yStart = 0;
2522 this.xEnd = 0;
2523 this.yEnd = 0;
2524 this.slideDistance = 0;
2525 this.containerMetrics = new ElementMetrics(this.element);
2526 },
2527 draw: function() {
2528 var scale;
2529 var translateString;
2530 var dx;
2531 var dy;
2532 this.wave.style.opacity = this.opacity;
2533 scale = this.radius / (this.containerMetrics.size / 2);
2534 dx = this.xNow - this.containerMetrics.width / 2;
2535 dy = this.yNow - this.containerMetrics.height / 2;
2536 this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' + dy + 'px)';
2537 this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy + ' px, 0)';
2538 this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')';
2539 this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)';
2540 },
2541 downAction: function(event) {
2542 var xCenter = this.containerMetrics.width / 2;
2543 var yCenter = this.containerMetrics.height / 2;
2544 this.resetInteractionState();
2545 this.mouseDownStart = Utility.now();
2546 if (this.center) {
2547 this.xStart = xCenter;
2548 this.yStart = yCenter;
2549 this.slideDistance = Utility.distance(this.xStart, this.yStart, this.xEn d, this.yEnd);
2550 } else {
2551 this.xStart = event ? event.detail.x - this.containerMetrics.boundingRec t.left : this.containerMetrics.width / 2;
2552 this.yStart = event ? event.detail.y - this.containerMetrics.boundingRec t.top : this.containerMetrics.height / 2;
2553 }
2554 if (this.recenters) {
2555 this.xEnd = xCenter;
2556 this.yEnd = yCenter;
2557 this.slideDistance = Utility.distance(this.xStart, this.yStart, this.xEn d, this.yEnd);
2558 }
2559 this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom(this.xSt art, this.yStart);
2560 this.waveContainer.style.top = (this.containerMetrics.height - this.contai nerMetrics.size) / 2 + 'px';
2561 this.waveContainer.style.left = (this.containerMetrics.width - this.contai nerMetrics.size) / 2 + 'px';
2562 this.waveContainer.style.width = this.containerMetrics.size + 'px';
2563 this.waveContainer.style.height = this.containerMetrics.size + 'px';
2564 },
2565 upAction: function(event) {
2566 if (!this.isMouseDown) {
2567 return;
2568 }
2569 this.mouseUpStart = Utility.now();
2570 },
2571 remove: function() {
2572 Polymer.dom(this.waveContainer.parentNode).removeChild(this.waveContainer) ;
2573 }
2574 };
2575 Polymer({ 2637 Polymer({
2576 is: 'paper-ripple', 2638 is: 'iron-overlay-backdrop',
2577 behaviors: [ Polymer.IronA11yKeysBehavior ],
2578 properties: { 2639 properties: {
2579 initialOpacity: { 2640 opened: {
2580 type: Number,
2581 value: .25
2582 },
2583 opacityDecayVelocity: {
2584 type: Number,
2585 value: .8
2586 },
2587 recenters: {
2588 type: Boolean,
2589 value: false
2590 },
2591 center: {
2592 type: Boolean,
2593 value: false
2594 },
2595 ripples: {
2596 type: Array,
2597 value: function() {
2598 return [];
2599 }
2600 },
2601 animating: {
2602 type: Boolean,
2603 readOnly: true,
2604 reflectToAttribute: true, 2641 reflectToAttribute: true,
2605 value: false
2606 },
2607 holdDown: {
2608 type: Boolean, 2642 type: Boolean,
2609 value: false, 2643 value: false,
2610 observer: '_holdDownChanged' 2644 observer: '_openedChanged'
2611 }, 2645 }
2612 noink: { 2646 },
2613 type: Boolean, 2647 listeners: {
2614 value: false 2648 transitionend: '_onTransitionend'
2615 }, 2649 },
2616 _animating: { 2650 created: function() {
2617 type: Boolean 2651 this.__openedRaf = null;
2618 }, 2652 },
2619 _boundAnimate: { 2653 attached: function() {
2620 type: Function, 2654 this.opened && this._openedChanged(this.opened);
2621 value: function() { 2655 },
2622 return this.animate.bind(this); 2656 prepare: function() {
2657 if (this.opened && !this.parentNode) {
2658 Polymer.dom(document.body).appendChild(this);
2659 }
2660 },
2661 open: function() {
2662 this.opened = true;
2663 },
2664 close: function() {
2665 this.opened = false;
2666 },
2667 complete: function() {
2668 if (!this.opened && this.parentNode === document.body) {
2669 Polymer.dom(this.parentNode).removeChild(this);
2670 }
2671 },
2672 _onTransitionend: function(event) {
2673 if (event && event.target === this) {
2674 this.complete();
2675 }
2676 },
2677 _openedChanged: function(opened) {
2678 if (opened) {
2679 this.prepare();
2680 } else {
2681 var cs = window.getComputedStyle(this);
2682 if (cs.transitionDuration === '0s' || cs.opacity == 0) {
2683 this.complete();
2623 } 2684 }
2624 } 2685 }
2625 }, 2686 if (!this.isAttached) {
2626 get target() {
2627 return this.keyEventTarget;
2628 },
2629 keyBindings: {
2630 'enter:keydown': '_onEnterKeydown',
2631 'space:keydown': '_onSpaceKeydown',
2632 'space:keyup': '_onSpaceKeyup'
2633 },
2634 attached: function() {
2635 if (this.parentNode.nodeType == 11) {
2636 this.keyEventTarget = Polymer.dom(this).getOwnerRoot().host;
2637 } else {
2638 this.keyEventTarget = this.parentNode;
2639 }
2640 var keyEventTarget = this.keyEventTarget;
2641 this.listen(keyEventTarget, 'up', 'uiUpAction');
2642 this.listen(keyEventTarget, 'down', 'uiDownAction');
2643 },
2644 detached: function() {
2645 this.unlisten(this.keyEventTarget, 'up', 'uiUpAction');
2646 this.unlisten(this.keyEventTarget, 'down', 'uiDownAction');
2647 this.keyEventTarget = null;
2648 },
2649 get shouldKeepAnimating() {
2650 for (var index = 0; index < this.ripples.length; ++index) {
2651 if (!this.ripples[index].isAnimationComplete) {
2652 return true;
2653 }
2654 }
2655 return false;
2656 },
2657 simulatedRipple: function() {
2658 this.downAction(null);
2659 this.async(function() {
2660 this.upAction();
2661 }, 1);
2662 },
2663 uiDownAction: function(event) {
2664 if (!this.noink) {
2665 this.downAction(event);
2666 }
2667 },
2668 downAction: function(event) {
2669 if (this.holdDown && this.ripples.length > 0) {
2670 return; 2687 return;
2671 } 2688 }
2672 var ripple = this.addRipple(); 2689 if (this.__openedRaf) {
2673 ripple.downAction(event); 2690 window.cancelAnimationFrame(this.__openedRaf);
2674 if (!this._animating) { 2691 this.__openedRaf = null;
2675 this._animating = true; 2692 }
2676 this.animate(); 2693 this.scrollTop = this.scrollTop;
2677 } 2694 this.__openedRaf = window.requestAnimationFrame(function() {
2678 }, 2695 this.__openedRaf = null;
2679 uiUpAction: function(event) { 2696 this.toggleClass('opened', this.opened);
2680 if (!this.noink) { 2697 }.bind(this));
2681 this.upAction(event);
2682 }
2683 },
2684 upAction: function(event) {
2685 if (this.holdDown) {
2686 return;
2687 }
2688 this.ripples.forEach(function(ripple) {
2689 ripple.upAction(event);
2690 });
2691 this._animating = true;
2692 this.animate();
2693 },
2694 onAnimationComplete: function() {
2695 this._animating = false;
2696 this.$.background.style.backgroundColor = null;
2697 this.fire('transitionend');
2698 },
2699 addRipple: function() {
2700 var ripple = new Ripple(this);
2701 Polymer.dom(this.$.waves).appendChild(ripple.waveContainer);
2702 this.$.background.style.backgroundColor = ripple.color;
2703 this.ripples.push(ripple);
2704 this._setAnimating(true);
2705 return ripple;
2706 },
2707 removeRipple: function(ripple) {
2708 var rippleIndex = this.ripples.indexOf(ripple);
2709 if (rippleIndex < 0) {
2710 return;
2711 }
2712 this.ripples.splice(rippleIndex, 1);
2713 ripple.remove();
2714 if (!this.ripples.length) {
2715 this._setAnimating(false);
2716 }
2717 },
2718 animate: function() {
2719 if (!this._animating) {
2720 return;
2721 }
2722 var index;
2723 var ripple;
2724 for (index = 0; index < this.ripples.length; ++index) {
2725 ripple = this.ripples[index];
2726 ripple.draw();
2727 this.$.background.style.opacity = ripple.outerOpacity;
2728 if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) {
2729 this.removeRipple(ripple);
2730 }
2731 }
2732 if (!this.shouldKeepAnimating && this.ripples.length === 0) {
2733 this.onAnimationComplete();
2734 } else {
2735 window.requestAnimationFrame(this._boundAnimate);
2736 }
2737 },
2738 _onEnterKeydown: function() {
2739 this.uiDownAction();
2740 this.async(this.uiUpAction, 1);
2741 },
2742 _onSpaceKeydown: function() {
2743 this.uiDownAction();
2744 },
2745 _onSpaceKeyup: function() {
2746 this.uiUpAction();
2747 },
2748 _holdDownChanged: function(newVal, oldVal) {
2749 if (oldVal === undefined) {
2750 return;
2751 }
2752 if (newVal) {
2753 this.downAction();
2754 } else {
2755 this.upAction();
2756 }
2757 } 2698 }
2758 }); 2699 });
2759 })(); 2700 })();
2760 2701
2761 Polymer.PaperRippleBehavior = { 2702 Polymer.IronOverlayManagerClass = function() {
2762 properties: { 2703 this._overlays = [];
2763 noink: { 2704 this._minimumZ = 101;
2764 type: Boolean, 2705 this._backdropElement = null;
2765 observer: '_noinkChanged' 2706 Polymer.Gestures.add(document, 'tap', this._onCaptureClick.bind(this));
2766 }, 2707 document.addEventListener('focus', this._onCaptureFocus.bind(this), true);
2767 _rippleContainer: { 2708 document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true);
2768 type: Object 2709 };
2769 } 2710
2770 }, 2711 Polymer.IronOverlayManagerClass.prototype = {
2771 _buttonStateChanged: function() { 2712 constructor: Polymer.IronOverlayManagerClass,
2772 if (this.focused) { 2713 get backdropElement() {
2773 this.ensureRipple(); 2714 if (!this._backdropElement) {
2774 } 2715 this._backdropElement = document.createElement('iron-overlay-backdrop');
2775 }, 2716 }
2776 _downHandler: function(event) { 2717 return this._backdropElement;
2777 Polymer.IronButtonStateImpl._downHandler.call(this, event); 2718 },
2778 if (this.pressed) { 2719 get deepActiveElement() {
2779 this.ensureRipple(event); 2720 var active = document.activeElement || document.body;
2780 } 2721 while (active.root && Polymer.dom(active.root).activeElement) {
2781 }, 2722 active = Polymer.dom(active.root).activeElement;
2782 ensureRipple: function(optTriggeringEvent) { 2723 }
2783 if (!this.hasRipple()) { 2724 return active;
2784 this._ripple = this._createRipple(); 2725 },
2785 this._ripple.noink = this.noink; 2726 _bringOverlayAtIndexToFront: function(i) {
2786 var rippleContainer = this._rippleContainer || this.root; 2727 var overlay = this._overlays[i];
2787 if (rippleContainer) { 2728 if (!overlay) {
2788 Polymer.dom(rippleContainer).appendChild(this._ripple); 2729 return;
2789 } 2730 }
2790 if (optTriggeringEvent) { 2731 var lastI = this._overlays.length - 1;
2791 var domContainer = Polymer.dom(this._rippleContainer || this); 2732 var currentOverlay = this._overlays[lastI];
2792 var target = Polymer.dom(optTriggeringEvent).rootTarget; 2733 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
2793 if (domContainer.deepContains(target)) { 2734 lastI--;
2794 this._ripple.uiDownAction(optTriggeringEvent); 2735 }
2795 } 2736 if (i >= lastI) {
2796 } 2737 return;
2797 } 2738 }
2798 }, 2739 var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
2799 getRipple: function() { 2740 if (this._getZ(overlay) <= minimumZ) {
2800 this.ensureRipple(); 2741 this._applyOverlayZ(overlay, minimumZ);
2801 return this._ripple; 2742 }
2802 }, 2743 while (i < lastI) {
2803 hasRipple: function() { 2744 this._overlays[i] = this._overlays[i + 1];
2804 return Boolean(this._ripple); 2745 i++;
2805 }, 2746 }
2806 _createRipple: function() { 2747 this._overlays[lastI] = overlay;
2807 return document.createElement('paper-ripple'); 2748 },
2808 }, 2749 addOrRemoveOverlay: function(overlay) {
2809 _noinkChanged: function(noink) { 2750 if (overlay.opened) {
2810 if (this.hasRipple()) { 2751 this.addOverlay(overlay);
2811 this._ripple.noink = noink; 2752 } else {
2812 } 2753 this.removeOverlay(overlay);
2754 }
2755 },
2756 addOverlay: function(overlay) {
2757 var i = this._overlays.indexOf(overlay);
2758 if (i >= 0) {
2759 this._bringOverlayAtIndexToFront(i);
2760 this.trackBackdrop();
2761 return;
2762 }
2763 var insertionIndex = this._overlays.length;
2764 var currentOverlay = this._overlays[insertionIndex - 1];
2765 var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ);
2766 var newZ = this._getZ(overlay);
2767 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
2768 this._applyOverlayZ(currentOverlay, minimumZ);
2769 insertionIndex--;
2770 var previousOverlay = this._overlays[insertionIndex - 1];
2771 minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ);
2772 }
2773 if (newZ <= minimumZ) {
2774 this._applyOverlayZ(overlay, minimumZ);
2775 }
2776 this._overlays.splice(insertionIndex, 0, overlay);
2777 this.trackBackdrop();
2778 },
2779 removeOverlay: function(overlay) {
2780 var i = this._overlays.indexOf(overlay);
2781 if (i === -1) {
2782 return;
2783 }
2784 this._overlays.splice(i, 1);
2785 this.trackBackdrop();
2786 },
2787 currentOverlay: function() {
2788 var i = this._overlays.length - 1;
2789 return this._overlays[i];
2790 },
2791 currentOverlayZ: function() {
2792 return this._getZ(this.currentOverlay());
2793 },
2794 ensureMinimumZ: function(minimumZ) {
2795 this._minimumZ = Math.max(this._minimumZ, minimumZ);
2796 },
2797 focusOverlay: function() {
2798 var current = this.currentOverlay();
2799 if (current) {
2800 current._applyFocus();
2801 }
2802 },
2803 trackBackdrop: function() {
2804 var overlay = this._overlayWithBackdrop();
2805 if (!overlay && !this._backdropElement) {
2806 return;
2807 }
2808 this.backdropElement.style.zIndex = this._getZ(overlay) - 1;
2809 this.backdropElement.opened = !!overlay;
2810 },
2811 getBackdrops: function() {
2812 var backdrops = [];
2813 for (var i = 0; i < this._overlays.length; i++) {
2814 if (this._overlays[i].withBackdrop) {
2815 backdrops.push(this._overlays[i]);
2816 }
2817 }
2818 return backdrops;
2819 },
2820 backdropZ: function() {
2821 return this._getZ(this._overlayWithBackdrop()) - 1;
2822 },
2823 _overlayWithBackdrop: function() {
2824 for (var i = 0; i < this._overlays.length; i++) {
2825 if (this._overlays[i].withBackdrop) {
2826 return this._overlays[i];
2827 }
2828 }
2829 },
2830 _getZ: function(overlay) {
2831 var z = this._minimumZ;
2832 if (overlay) {
2833 var z1 = Number(overlay.style.zIndex || window.getComputedStyle(overlay).z Index);
2834 if (z1 === z1) {
2835 z = z1;
2836 }
2837 }
2838 return z;
2839 },
2840 _setZ: function(element, z) {
2841 element.style.zIndex = z;
2842 },
2843 _applyOverlayZ: function(overlay, aboveZ) {
2844 this._setZ(overlay, aboveZ + 2);
2845 },
2846 _overlayInPath: function(path) {
2847 path = path || [];
2848 for (var i = 0; i < path.length; i++) {
2849 if (path[i]._manager === this) {
2850 return path[i];
2851 }
2852 }
2853 },
2854 _onCaptureClick: function(event) {
2855 var overlay = this.currentOverlay();
2856 if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) {
2857 overlay._onCaptureClick(event);
2858 }
2859 },
2860 _onCaptureFocus: function(event) {
2861 var overlay = this.currentOverlay();
2862 if (overlay) {
2863 overlay._onCaptureFocus(event);
2864 }
2865 },
2866 _onCaptureKeyDown: function(event) {
2867 var overlay = this.currentOverlay();
2868 if (overlay) {
2869 if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'esc')) {
2870 overlay._onCaptureEsc(event);
2871 } else if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 't ab')) {
2872 overlay._onCaptureTab(event);
2873 }
2874 }
2875 },
2876 _shouldBeBehindOverlay: function(overlay1, overlay2) {
2877 return !overlay1.alwaysOnTop && overlay2.alwaysOnTop;
2813 } 2878 }
2814 }; 2879 };
2815 2880
2816 Polymer.PaperButtonBehaviorImpl = { 2881 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();
2817 properties: {
2818 elevation: {
2819 type: Number,
2820 reflectToAttribute: true,
2821 readOnly: true
2822 }
2823 },
2824 observers: [ '_calculateElevation(focused, disabled, active, pressed, received FocusFromKeyboard)', '_computeKeyboardClass(receivedFocusFromKeyboard)' ],
2825 hostAttributes: {
2826 role: 'button',
2827 tabindex: '0',
2828 animated: true
2829 },
2830 _calculateElevation: function() {
2831 var e = 1;
2832 if (this.disabled) {
2833 e = 0;
2834 } else if (this.active || this.pressed) {
2835 e = 4;
2836 } else if (this.receivedFocusFromKeyboard) {
2837 e = 3;
2838 }
2839 this._setElevation(e);
2840 },
2841 _computeKeyboardClass: function(receivedFocusFromKeyboard) {
2842 this.toggleClass('keyboard-focus', receivedFocusFromKeyboard);
2843 },
2844 _spaceKeyDownHandler: function(event) {
2845 Polymer.IronButtonStateImpl._spaceKeyDownHandler.call(this, event);
2846 if (this.hasRipple() && this.getRipple().ripples.length < 1) {
2847 this._ripple.uiDownAction();
2848 }
2849 },
2850 _spaceKeyUpHandler: function(event) {
2851 Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this, event);
2852 if (this.hasRipple()) {
2853 this._ripple.uiUpAction();
2854 }
2855 }
2856 };
2857 2882
2858 Polymer.PaperButtonBehavior = [ Polymer.IronButtonState, Polymer.IronControlStat e, Polymer.PaperRippleBehavior, Polymer.PaperButtonBehaviorImpl ]; 2883 (function() {
2859 2884 'use strict';
2860 Polymer({ 2885 Polymer.IronOverlayBehaviorImpl = {
2861 is: 'paper-button', 2886 properties: {
2862 behaviors: [ Polymer.PaperButtonBehavior ], 2887 opened: {
2863 properties: { 2888 observer: '_openedChanged',
2864 raised: { 2889 type: Boolean,
2865 type: Boolean, 2890 value: false,
2866 reflectToAttribute: true, 2891 notify: true
2867 value: false, 2892 },
2868 observer: '_calculateElevation' 2893 canceled: {
2869 } 2894 observer: '_canceledChanged',
2870 }, 2895 readOnly: true,
2871 _calculateElevation: function() { 2896 type: Boolean,
2872 if (!this.raised) { 2897 value: false
2873 this._setElevation(0); 2898 },
2874 } else { 2899 withBackdrop: {
2875 Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this); 2900 observer: '_withBackdropChanged',
2876 } 2901 type: Boolean
2877 } 2902 },
2878 }); 2903 noAutoFocus: {
2904 type: Boolean,
2905 value: false
2906 },
2907 noCancelOnEscKey: {
2908 type: Boolean,
2909 value: false
2910 },
2911 noCancelOnOutsideClick: {
2912 type: Boolean,
2913 value: false
2914 },
2915 closingReason: {
2916 type: Object
2917 },
2918 restoreFocusOnClose: {
2919 type: Boolean,
2920 value: false
2921 },
2922 alwaysOnTop: {
2923 type: Boolean
2924 },
2925 _manager: {
2926 type: Object,
2927 value: Polymer.IronOverlayManager
2928 },
2929 _focusedChild: {
2930 type: Object
2931 }
2932 },
2933 listeners: {
2934 'iron-resize': '_onIronResize'
2935 },
2936 get backdropElement() {
2937 return this._manager.backdropElement;
2938 },
2939 get _focusNode() {
2940 return this._focusedChild || Polymer.dom(this).querySelector('[autofocus]' ) || this;
2941 },
2942 get _focusableNodes() {
2943 var FOCUSABLE_WITH_DISABLED = [ 'a[href]', 'area[href]', 'iframe', '[tabin dex]', '[contentEditable=true]' ];
2944 var FOCUSABLE_WITHOUT_DISABLED = [ 'input', 'select', 'textarea', 'button' ];
2945 var selector = FOCUSABLE_WITH_DISABLED.join(':not([tabindex="-1"]),') + ': not([tabindex="-1"]),' + FOCUSABLE_WITHOUT_DISABLED.join(':not([disabled]):not([ tabindex="-1"]),') + ':not([disabled]):not([tabindex="-1"])';
2946 var focusables = Polymer.dom(this).querySelectorAll(selector);
2947 if (this.tabIndex >= 0) {
2948 focusables.splice(0, 0, this);
2949 }
2950 return focusables.sort(function(a, b) {
2951 if (a.tabIndex === b.tabIndex) {
2952 return 0;
2953 }
2954 if (a.tabIndex === 0 || a.tabIndex > b.tabIndex) {
2955 return 1;
2956 }
2957 return -1;
2958 });
2959 },
2960 ready: function() {
2961 this.__isAnimating = false;
2962 this.__shouldRemoveTabIndex = false;
2963 this.__firstFocusableNode = this.__lastFocusableNode = null;
2964 this.__raf = null;
2965 this.__restoreFocusNode = null;
2966 this._ensureSetup();
2967 },
2968 attached: function() {
2969 if (this.opened) {
2970 this._openedChanged(this.opened);
2971 }
2972 this._observer = Polymer.dom(this).observeNodes(this._onNodesChange);
2973 },
2974 detached: function() {
2975 Polymer.dom(this).unobserveNodes(this._observer);
2976 this._observer = null;
2977 if (this.__raf) {
2978 window.cancelAnimationFrame(this.__raf);
2979 this.__raf = null;
2980 }
2981 this._manager.removeOverlay(this);
2982 },
2983 toggle: function() {
2984 this._setCanceled(false);
2985 this.opened = !this.opened;
2986 },
2987 open: function() {
2988 this._setCanceled(false);
2989 this.opened = true;
2990 },
2991 close: function() {
2992 this._setCanceled(false);
2993 this.opened = false;
2994 },
2995 cancel: function(event) {
2996 var cancelEvent = this.fire('iron-overlay-canceled', event, {
2997 cancelable: true
2998 });
2999 if (cancelEvent.defaultPrevented) {
3000 return;
3001 }
3002 this._setCanceled(true);
3003 this.opened = false;
3004 },
3005 _ensureSetup: function() {
3006 if (this._overlaySetup) {
3007 return;
3008 }
3009 this._overlaySetup = true;
3010 this.style.outline = 'none';
3011 this.style.display = 'none';
3012 },
3013 _openedChanged: function(opened) {
3014 if (opened) {
3015 this.removeAttribute('aria-hidden');
3016 } else {
3017 this.setAttribute('aria-hidden', 'true');
3018 }
3019 if (!this.isAttached) {
3020 return;
3021 }
3022 this.__isAnimating = true;
3023 this.__onNextAnimationFrame(this.__openedChanged);
3024 },
3025 _canceledChanged: function() {
3026 this.closingReason = this.closingReason || {};
3027 this.closingReason.canceled = this.canceled;
3028 },
3029 _withBackdropChanged: function() {
3030 if (this.withBackdrop && !this.hasAttribute('tabindex')) {
3031 this.setAttribute('tabindex', '-1');
3032 this.__shouldRemoveTabIndex = true;
3033 } else if (this.__shouldRemoveTabIndex) {
3034 this.removeAttribute('tabindex');
3035 this.__shouldRemoveTabIndex = false;
3036 }
3037 if (this.opened && this.isAttached) {
3038 this._manager.trackBackdrop();
3039 }
3040 },
3041 _prepareRenderOpened: function() {
3042 this.__restoreFocusNode = this._manager.deepActiveElement;
3043 this._preparePositioning();
3044 this.refit();
3045 this._finishPositioning();
3046 if (this.noAutoFocus && document.activeElement === this._focusNode) {
3047 this._focusNode.blur();
3048 this.__restoreFocusNode.focus();
3049 }
3050 },
3051 _renderOpened: function() {
3052 this._finishRenderOpened();
3053 },
3054 _renderClosed: function() {
3055 this._finishRenderClosed();
3056 },
3057 _finishRenderOpened: function() {
3058 this.notifyResize();
3059 this.__isAnimating = false;
3060 var focusableNodes = this._focusableNodes;
3061 this.__firstFocusableNode = focusableNodes[0];
3062 this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1];
3063 this.fire('iron-overlay-opened');
3064 },
3065 _finishRenderClosed: function() {
3066 this.style.display = 'none';
3067 this.style.zIndex = '';
3068 this.notifyResize();
3069 this.__isAnimating = false;
3070 this.fire('iron-overlay-closed', this.closingReason);
3071 },
3072 _preparePositioning: function() {
3073 this.style.transition = this.style.webkitTransition = 'none';
3074 this.style.transform = this.style.webkitTransform = 'none';
3075 this.style.display = '';
3076 },
3077 _finishPositioning: function() {
3078 this.style.display = 'none';
3079 this.scrollTop = this.scrollTop;
3080 this.style.transition = this.style.webkitTransition = '';
3081 this.style.transform = this.style.webkitTransform = '';
3082 this.style.display = '';
3083 this.scrollTop = this.scrollTop;
3084 },
3085 _applyFocus: function() {
3086 if (this.opened) {
3087 if (!this.noAutoFocus) {
3088 this._focusNode.focus();
3089 }
3090 } else {
3091 this._focusNode.blur();
3092 this._focusedChild = null;
3093 if (this.restoreFocusOnClose && this.__restoreFocusNode) {
3094 this.__restoreFocusNode.focus();
3095 }
3096 this.__restoreFocusNode = null;
3097 var currentOverlay = this._manager.currentOverlay();
3098 if (currentOverlay && this !== currentOverlay) {
3099 currentOverlay._applyFocus();
3100 }
3101 }
3102 },
3103 _onCaptureClick: function(event) {
3104 if (!this.noCancelOnOutsideClick) {
3105 this.cancel(event);
3106 }
3107 },
3108 _onCaptureFocus: function(event) {
3109 if (!this.withBackdrop) {
3110 return;
3111 }
3112 var path = Polymer.dom(event).path;
3113 if (path.indexOf(this) === -1) {
3114 event.stopPropagation();
3115 this._applyFocus();
3116 } else {
3117 this._focusedChild = path[0];
3118 }
3119 },
3120 _onCaptureEsc: function(event) {
3121 if (!this.noCancelOnEscKey) {
3122 this.cancel(event);
3123 }
3124 },
3125 _onCaptureTab: function(event) {
3126 if (!this.withBackdrop) {
3127 return;
3128 }
3129 var shift = event.shiftKey;
3130 var nodeToCheck = shift ? this.__firstFocusableNode : this.__lastFocusable Node;
3131 var nodeToSet = shift ? this.__lastFocusableNode : this.__firstFocusableNo de;
3132 var shouldWrap = false;
3133 if (nodeToCheck === nodeToSet) {
3134 shouldWrap = true;
3135 } else {
3136 var focusedNode = this._manager.deepActiveElement;
3137 shouldWrap = focusedNode === nodeToCheck || focusedNode === this;
3138 }
3139 if (shouldWrap) {
3140 event.preventDefault();
3141 this._focusedChild = nodeToSet;
3142 this._applyFocus();
3143 }
3144 },
3145 _onIronResize: function() {
3146 if (this.opened && !this.__isAnimating) {
3147 this.__onNextAnimationFrame(this.refit);
3148 }
3149 },
3150 _onNodesChange: function() {
3151 if (this.opened && !this.__isAnimating) {
3152 this.notifyResize();
3153 }
3154 },
3155 __openedChanged: function() {
3156 if (this.opened) {
3157 this._prepareRenderOpened();
3158 this._manager.addOverlay(this);
3159 this._applyFocus();
3160 this._renderOpened();
3161 } else {
3162 this._manager.removeOverlay(this);
3163 this._applyFocus();
3164 this._renderClosed();
3165 }
3166 },
3167 __onNextAnimationFrame: function(callback) {
3168 if (this.__raf) {
3169 window.cancelAnimationFrame(this.__raf);
3170 }
3171 var self = this;
3172 this.__raf = window.requestAnimationFrame(function nextAnimationFrame() {
3173 self.__raf = null;
3174 callback.call(self);
3175 });
3176 }
3177 };
3178 Polymer.IronOverlayBehavior = [ Polymer.IronFitBehavior, Polymer.IronResizable Behavior, Polymer.IronOverlayBehaviorImpl ];
3179 })();
2879 3180
2880 (function() { 3181 (function() {
2881 var metaDatas = {}; 3182 var metaDatas = {};
2882 var metaArrays = {}; 3183 var metaArrays = {};
2883 var singleton = null; 3184 var singleton = null;
2884 Polymer.IronMeta = Polymer({ 3185 Polymer.IronMeta = Polymer({
2885 is: 'iron-meta', 3186 is: 'iron-meta',
2886 properties: { 3187 properties: {
2887 type: { 3188 type: {
2888 type: String, 3189 type: String,
2889 value: 'default', 3190 value: 'default',
2890 observer: '_typeChanged' 3191 observer: '_typeChanged'
2891 }, 3192 },
2892 key: { 3193 key: {
2893 type: String, 3194 type: String,
2894 observer: '_keyChanged'
2895 },
2896 value: {
2897 type: Object,
2898 notify: true,
2899 observer: '_valueChanged'
2900 },
2901 self: {
2902 type: Boolean,
2903 observer: '_selfChanged'
2904 },
2905 list: {
2906 type: Array,
2907 notify: true
2908 }
2909 },
2910 hostAttributes: {
2911 hidden: true
2912 },
2913 factoryImpl: function(config) {
2914 if (config) {
2915 for (var n in config) {
2916 switch (n) {
2917 case 'type':
2918 case 'key':
2919 case 'value':
2920 this[n] = config[n];
2921 break;
2922 }
2923 }
2924 }
2925 },
2926 created: function() {
2927 this._metaDatas = metaDatas;
2928 this._metaArrays = metaArrays;
2929 },
2930 _keyChanged: function(key, old) {
2931 this._resetRegistration(old);
2932 },
2933 _valueChanged: function(value) {
2934 this._resetRegistration(this.key);
2935 },
2936 _selfChanged: function(self) {
2937 if (self) {
2938 this.value = this;
2939 }
2940 },
2941 _typeChanged: function(type) {
2942 this._unregisterKey(this.key);
2943 if (!metaDatas[type]) {
2944 metaDatas[type] = {};
2945 }
2946 this._metaData = metaDatas[type];
2947 if (!metaArrays[type]) {
2948 metaArrays[type] = [];
2949 }
2950 this.list = metaArrays[type];
2951 this._registerKeyValue(this.key, this.value);
2952 },
2953 byKey: function(key) {
2954 return this._metaData && this._metaData[key];
2955 },
2956 _resetRegistration: function(oldKey) {
2957 this._unregisterKey(oldKey);
2958 this._registerKeyValue(this.key, this.value);
2959 },
2960 _unregisterKey: function(key) {
2961 this._unregister(key, this._metaData, this.list);
2962 },
2963 _registerKeyValue: function(key, value) {
2964 this._register(key, value, this._metaData, this.list);
2965 },
2966 _register: function(key, value, data, list) {
2967 if (key && data && value !== undefined) {
2968 data[key] = value;
2969 list.push(value);
2970 }
2971 },
2972 _unregister: function(key, data, list) {
2973 if (key && data) {
2974 if (key in data) {
2975 var value = data[key];
2976 delete data[key];
2977 this.arrayDelete(list, value);
2978 }
2979 }
2980 }
2981 });
2982 Polymer.IronMeta.getIronMeta = function getIronMeta() {
2983 if (singleton === null) {
2984 singleton = new Polymer.IronMeta();
2985 }
2986 return singleton;
2987 };
2988 Polymer.IronMetaQuery = Polymer({
2989 is: 'iron-meta-query',
2990 properties: {
2991 type: {
2992 type: String,
2993 value: 'default',
2994 observer: '_typeChanged'
2995 },
2996 key: {
2997 type: String,
2998 observer: '_keyChanged' 3195 observer: '_keyChanged'
2999 }, 3196 },
3000 value: { 3197 value: {
3001 type: Object, 3198 type: Object,
3002 notify: true, 3199 notify: true,
3003 readOnly: true 3200 observer: '_valueChanged'
3201 },
3202 self: {
3203 type: Boolean,
3204 observer: '_selfChanged'
3004 }, 3205 },
3005 list: { 3206 list: {
3006 type: Array, 3207 type: Array,
3007 notify: true 3208 notify: true
3008 } 3209 }
3009 }, 3210 },
3211 hostAttributes: {
3212 hidden: true
3213 },
3010 factoryImpl: function(config) { 3214 factoryImpl: function(config) {
3011 if (config) { 3215 if (config) {
3012 for (var n in config) { 3216 for (var n in config) {
3013 switch (n) { 3217 switch (n) {
3014 case 'type': 3218 case 'type':
3015 case 'key': 3219 case 'key':
3220 case 'value':
3016 this[n] = config[n]; 3221 this[n] = config[n];
3017 break; 3222 break;
3018 } 3223 }
3019 } 3224 }
3020 } 3225 }
3021 }, 3226 },
3022 created: function() { 3227 created: function() {
3023 this._metaDatas = metaDatas; 3228 this._metaDatas = metaDatas;
3024 this._metaArrays = metaArrays; 3229 this._metaArrays = metaArrays;
3025 }, 3230 },
3231 _keyChanged: function(key, old) {
3232 this._resetRegistration(old);
3233 },
3234 _valueChanged: function(value) {
3235 this._resetRegistration(this.key);
3236 },
3237 _selfChanged: function(self) {
3238 if (self) {
3239 this.value = this;
3240 }
3241 },
3242 _typeChanged: function(type) {
3243 this._unregisterKey(this.key);
3244 if (!metaDatas[type]) {
3245 metaDatas[type] = {};
3246 }
3247 this._metaData = metaDatas[type];
3248 if (!metaArrays[type]) {
3249 metaArrays[type] = [];
3250 }
3251 this.list = metaArrays[type];
3252 this._registerKeyValue(this.key, this.value);
3253 },
3254 byKey: function(key) {
3255 return this._metaData && this._metaData[key];
3256 },
3257 _resetRegistration: function(oldKey) {
3258 this._unregisterKey(oldKey);
3259 this._registerKeyValue(this.key, this.value);
3260 },
3261 _unregisterKey: function(key) {
3262 this._unregister(key, this._metaData, this.list);
3263 },
3264 _registerKeyValue: function(key, value) {
3265 this._register(key, value, this._metaData, this.list);
3266 },
3267 _register: function(key, value, data, list) {
3268 if (key && data && value !== undefined) {
3269 data[key] = value;
3270 list.push(value);
3271 }
3272 },
3273 _unregister: function(key, data, list) {
3274 if (key && data) {
3275 if (key in data) {
3276 var value = data[key];
3277 delete data[key];
3278 this.arrayDelete(list, value);
3279 }
3280 }
3281 }
3282 });
3283 Polymer.IronMeta.getIronMeta = function getIronMeta() {
3284 if (singleton === null) {
3285 singleton = new Polymer.IronMeta();
3286 }
3287 return singleton;
3288 };
3289 Polymer.IronMetaQuery = Polymer({
3290 is: 'iron-meta-query',
3291 properties: {
3292 type: {
3293 type: String,
3294 value: 'default',
3295 observer: '_typeChanged'
3296 },
3297 key: {
3298 type: String,
3299 observer: '_keyChanged'
3300 },
3301 value: {
3302 type: Object,
3303 notify: true,
3304 readOnly: true
3305 },
3306 list: {
3307 type: Array,
3308 notify: true
3309 }
3310 },
3311 factoryImpl: function(config) {
3312 if (config) {
3313 for (var n in config) {
3314 switch (n) {
3315 case 'type':
3316 case 'key':
3317 this[n] = config[n];
3318 break;
3319 }
3320 }
3321 }
3322 },
3323 created: function() {
3324 this._metaDatas = metaDatas;
3325 this._metaArrays = metaArrays;
3326 },
3026 _keyChanged: function(key) { 3327 _keyChanged: function(key) {
3027 this._setValue(this._metaData && this._metaData[key]); 3328 this._setValue(this._metaData && this._metaData[key]);
3028 }, 3329 },
3029 _typeChanged: function(type) { 3330 _typeChanged: function(type) {
3030 this._metaData = metaDatas[type]; 3331 this._metaData = metaDatas[type];
3031 this.list = metaArrays[type]; 3332 this.list = metaArrays[type];
3032 if (this.key) { 3333 if (this.key) {
3033 this._keyChanged(this.key); 3334 this._keyChanged(this.key);
3034 } 3335 }
3035 }, 3336 },
3036 byKey: function(key) { 3337 byKey: function(key) {
3037 return this._metaData && this._metaData[key]; 3338 return this._metaData && this._metaData[key];
3038 } 3339 }
3039 }); 3340 });
3040 })(); 3341 })();
3041 3342
3042 Polymer({
3043 is: 'iron-icon',
3044 properties: {
3045 icon: {
3046 type: String,
3047 observer: '_iconChanged'
3048 },
3049 theme: {
3050 type: String,
3051 observer: '_updateIcon'
3052 },
3053 src: {
3054 type: String,
3055 observer: '_srcChanged'
3056 },
3057 _meta: {
3058 value: Polymer.Base.create('iron-meta', {
3059 type: 'iconset'
3060 }),
3061 observer: '_updateIcon'
3062 }
3063 },
3064 _DEFAULT_ICONSET: 'icons',
3065 _iconChanged: function(icon) {
3066 var parts = (icon || '').split(':');
3067 this._iconName = parts.pop();
3068 this._iconsetName = parts.pop() || this._DEFAULT_ICONSET;
3069 this._updateIcon();
3070 },
3071 _srcChanged: function(src) {
3072 this._updateIcon();
3073 },
3074 _usesIconset: function() {
3075 return this.icon || !this.src;
3076 },
3077 _updateIcon: function() {
3078 if (this._usesIconset()) {
3079 if (this._img && this._img.parentNode) {
3080 Polymer.dom(this.root).removeChild(this._img);
3081 }
3082 if (this._iconName === "") {
3083 if (this._iconset) {
3084 this._iconset.removeIcon(this);
3085 }
3086 } else if (this._iconsetName && this._meta) {
3087 this._iconset = this._meta.byKey(this._iconsetName);
3088 if (this._iconset) {
3089 this._iconset.applyIcon(this, this._iconName, this.theme);
3090 this.unlisten(window, 'iron-iconset-added', '_updateIcon');
3091 } else {
3092 this.listen(window, 'iron-iconset-added', '_updateIcon');
3093 }
3094 }
3095 } else {
3096 if (this._iconset) {
3097 this._iconset.removeIcon(this);
3098 }
3099 if (!this._img) {
3100 this._img = document.createElement('img');
3101 this._img.style.width = '100%';
3102 this._img.style.height = '100%';
3103 this._img.draggable = false;
3104 }
3105 this._img.src = this.src;
3106 Polymer.dom(this.root).appendChild(this._img);
3107 }
3108 }
3109 });
3110
3111 Polymer.PaperInkyFocusBehaviorImpl = {
3112 observers: [ '_focusedChanged(receivedFocusFromKeyboard)' ],
3113 _focusedChanged: function(receivedFocusFromKeyboard) {
3114 if (receivedFocusFromKeyboard) {
3115 this.ensureRipple();
3116 }
3117 if (this.hasRipple()) {
3118 this._ripple.holdDown = receivedFocusFromKeyboard;
3119 }
3120 },
3121 _createRipple: function() {
3122 var ripple = Polymer.PaperRippleBehavior._createRipple();
3123 ripple.id = 'ink';
3124 ripple.setAttribute('center', '');
3125 ripple.classList.add('circle');
3126 return ripple;
3127 }
3128 };
3129
3130 Polymer.PaperInkyFocusBehavior = [ Polymer.IronButtonState, Polymer.IronControlS tate, Polymer.PaperRippleBehavior, Polymer.PaperInkyFocusBehaviorImpl ];
3131
3132 Polymer({
3133 is: 'paper-icon-button',
3134 hostAttributes: {
3135 role: 'button',
3136 tabindex: '0'
3137 },
3138 behaviors: [ Polymer.PaperInkyFocusBehavior ],
3139 properties: {
3140 src: {
3141 type: String
3142 },
3143 icon: {
3144 type: String
3145 },
3146 alt: {
3147 type: String,
3148 observer: "_altChanged"
3149 }
3150 },
3151 _altChanged: function(newValue, oldValue) {
3152 var label = this.getAttribute('aria-label');
3153 if (!label || oldValue == label) {
3154 this.setAttribute('aria-label', newValue);
3155 }
3156 }
3157 });
3158
3159 Polymer({
3160 is: 'paper-tab',
3161 behaviors: [ Polymer.IronControlState, Polymer.IronButtonState, Polymer.PaperR ippleBehavior ],
3162 properties: {
3163 link: {
3164 type: Boolean,
3165 value: false,
3166 reflectToAttribute: true
3167 }
3168 },
3169 hostAttributes: {
3170 role: 'tab'
3171 },
3172 listeners: {
3173 down: '_updateNoink',
3174 tap: '_onTap'
3175 },
3176 attached: function() {
3177 this._updateNoink();
3178 },
3179 get _parentNoink() {
3180 var parent = Polymer.dom(this).parentNode;
3181 return !!parent && !!parent.noink;
3182 },
3183 _updateNoink: function() {
3184 this.noink = !!this.noink || !!this._parentNoink;
3185 },
3186 _onTap: function(event) {
3187 if (this.link) {
3188 var anchor = this.queryEffectiveChildren('a');
3189 if (!anchor) {
3190 return;
3191 }
3192 if (event.target === anchor) {
3193 return;
3194 }
3195 anchor.click();
3196 }
3197 }
3198 });
3199
3200 Polymer.IronMultiSelectableBehaviorImpl = {
3201 properties: {
3202 multi: {
3203 type: Boolean,
3204 value: false,
3205 observer: 'multiChanged'
3206 },
3207 selectedValues: {
3208 type: Array,
3209 notify: true
3210 },
3211 selectedItems: {
3212 type: Array,
3213 readOnly: true,
3214 notify: true
3215 }
3216 },
3217 observers: [ '_updateSelected(selectedValues.splices)' ],
3218 select: function(value) {
3219 if (this.multi) {
3220 if (this.selectedValues) {
3221 this._toggleSelected(value);
3222 } else {
3223 this.selectedValues = [ value ];
3224 }
3225 } else {
3226 this.selected = value;
3227 }
3228 },
3229 multiChanged: function(multi) {
3230 this._selection.multi = multi;
3231 },
3232 get _shouldUpdateSelection() {
3233 return this.selected != null || this.selectedValues != null && this.selected Values.length;
3234 },
3235 _updateAttrForSelected: function() {
3236 if (!this.multi) {
3237 Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this);
3238 } else if (this._shouldUpdateSelection) {
3239 this.selectedValues = this.selectedItems.map(function(selectedItem) {
3240 return this._indexToValue(this.indexOf(selectedItem));
3241 }, this).filter(function(unfilteredValue) {
3242 return unfilteredValue != null;
3243 }, this);
3244 }
3245 },
3246 _updateSelected: function() {
3247 if (this.multi) {
3248 this._selectMulti(this.selectedValues);
3249 } else {
3250 this._selectSelected(this.selected);
3251 }
3252 },
3253 _selectMulti: function(values) {
3254 if (values) {
3255 var selectedItems = this._valuesToItems(values);
3256 this._selection.clear(selectedItems);
3257 for (var i = 0; i < selectedItems.length; i++) {
3258 this._selection.setItemSelected(selectedItems[i], true);
3259 }
3260 if (this.fallbackSelection && this.items.length && !this._selection.get(). length) {
3261 var fallback = this._valueToItem(this.fallbackSelection);
3262 if (fallback) {
3263 this.selectedValues = [ this.fallbackSelection ];
3264 }
3265 }
3266 } else {
3267 this._selection.clear();
3268 }
3269 },
3270 _selectionChange: function() {
3271 var s = this._selection.get();
3272 if (this.multi) {
3273 this._setSelectedItems(s);
3274 } else {
3275 this._setSelectedItems([ s ]);
3276 this._setSelectedItem(s);
3277 }
3278 },
3279 _toggleSelected: function(value) {
3280 var i = this.selectedValues.indexOf(value);
3281 var unselected = i < 0;
3282 if (unselected) {
3283 this.push('selectedValues', value);
3284 } else {
3285 this.splice('selectedValues', i, 1);
3286 }
3287 },
3288 _valuesToItems: function(values) {
3289 return values == null ? null : values.map(function(value) {
3290 return this._valueToItem(value);
3291 }, this);
3292 }
3293 };
3294
3295 Polymer.IronMultiSelectableBehavior = [ Polymer.IronSelectableBehavior, Polymer. IronMultiSelectableBehaviorImpl ];
3296
3297 Polymer.IronMenuBehaviorImpl = {
3298 properties: {
3299 focusedItem: {
3300 observer: '_focusedItemChanged',
3301 readOnly: true,
3302 type: Object
3303 },
3304 attrForItemTitle: {
3305 type: String
3306 }
3307 },
3308 hostAttributes: {
3309 role: 'menu',
3310 tabindex: '0'
3311 },
3312 observers: [ '_updateMultiselectable(multi)' ],
3313 listeners: {
3314 focus: '_onFocus',
3315 keydown: '_onKeydown',
3316 'iron-items-changed': '_onIronItemsChanged'
3317 },
3318 keyBindings: {
3319 up: '_onUpKey',
3320 down: '_onDownKey',
3321 esc: '_onEscKey',
3322 'shift+tab:keydown': '_onShiftTabDown'
3323 },
3324 attached: function() {
3325 this._resetTabindices();
3326 },
3327 select: function(value) {
3328 if (this._defaultFocusAsync) {
3329 this.cancelAsync(this._defaultFocusAsync);
3330 this._defaultFocusAsync = null;
3331 }
3332 var item = this._valueToItem(value);
3333 if (item && item.hasAttribute('disabled')) return;
3334 this._setFocusedItem(item);
3335 Polymer.IronMultiSelectableBehaviorImpl.select.apply(this, arguments);
3336 },
3337 _resetTabindices: function() {
3338 var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0] : this.selectedItem;
3339 this.items.forEach(function(item) {
3340 item.setAttribute('tabindex', item === selectedItem ? '0' : '-1');
3341 }, this);
3342 },
3343 _updateMultiselectable: function(multi) {
3344 if (multi) {
3345 this.setAttribute('aria-multiselectable', 'true');
3346 } else {
3347 this.removeAttribute('aria-multiselectable');
3348 }
3349 },
3350 _focusWithKeyboardEvent: function(event) {
3351 for (var i = 0, item; item = this.items[i]; i++) {
3352 var attr = this.attrForItemTitle || 'textContent';
3353 var title = item[attr] || item.getAttribute(attr);
3354 if (!item.hasAttribute('disabled') && title && title.trim().charAt(0).toLo werCase() === String.fromCharCode(event.keyCode).toLowerCase()) {
3355 this._setFocusedItem(item);
3356 break;
3357 }
3358 }
3359 },
3360 _focusPrevious: function() {
3361 var length = this.items.length;
3362 var curFocusIndex = Number(this.indexOf(this.focusedItem));
3363 for (var i = 1; i < length + 1; i++) {
3364 var item = this.items[(curFocusIndex - i + length) % length];
3365 if (!item.hasAttribute('disabled')) {
3366 this._setFocusedItem(item);
3367 return;
3368 }
3369 }
3370 },
3371 _focusNext: function() {
3372 var length = this.items.length;
3373 var curFocusIndex = Number(this.indexOf(this.focusedItem));
3374 for (var i = 1; i < length + 1; i++) {
3375 var item = this.items[(curFocusIndex + i) % length];
3376 if (!item.hasAttribute('disabled')) {
3377 this._setFocusedItem(item);
3378 return;
3379 }
3380 }
3381 },
3382 _applySelection: function(item, isSelected) {
3383 if (isSelected) {
3384 item.setAttribute('aria-selected', 'true');
3385 } else {
3386 item.removeAttribute('aria-selected');
3387 }
3388 Polymer.IronSelectableBehavior._applySelection.apply(this, arguments);
3389 },
3390 _focusedItemChanged: function(focusedItem, old) {
3391 old && old.setAttribute('tabindex', '-1');
3392 if (focusedItem) {
3393 focusedItem.setAttribute('tabindex', '0');
3394 focusedItem.focus();
3395 }
3396 },
3397 _onIronItemsChanged: function(event) {
3398 if (event.detail.addedNodes.length) {
3399 this._resetTabindices();
3400 }
3401 },
3402 _onShiftTabDown: function(event) {
3403 var oldTabIndex = this.getAttribute('tabindex');
3404 Polymer.IronMenuBehaviorImpl._shiftTabPressed = true;
3405 this._setFocusedItem(null);
3406 this.setAttribute('tabindex', '-1');
3407 this.async(function() {
3408 this.setAttribute('tabindex', oldTabIndex);
3409 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
3410 }, 1);
3411 },
3412 _onFocus: function(event) {
3413 if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) {
3414 return;
3415 }
3416 var rootTarget = Polymer.dom(event).rootTarget;
3417 if (rootTarget !== this && typeof rootTarget.tabIndex !== "undefined" && !th is.isLightDescendant(rootTarget)) {
3418 return;
3419 }
3420 this._defaultFocusAsync = this.async(function() {
3421 var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0 ] : this.selectedItem;
3422 this._setFocusedItem(null);
3423 if (selectedItem) {
3424 this._setFocusedItem(selectedItem);
3425 } else if (this.items[0]) {
3426 this._focusNext();
3427 }
3428 });
3429 },
3430 _onUpKey: function(event) {
3431 this._focusPrevious();
3432 event.detail.keyboardEvent.preventDefault();
3433 },
3434 _onDownKey: function(event) {
3435 this._focusNext();
3436 event.detail.keyboardEvent.preventDefault();
3437 },
3438 _onEscKey: function(event) {
3439 this.focusedItem.blur();
3440 },
3441 _onKeydown: function(event) {
3442 if (!this.keyboardEventMatchesKeys(event, 'up down esc')) {
3443 this._focusWithKeyboardEvent(event);
3444 }
3445 event.stopPropagation();
3446 },
3447 _activateHandler: function(event) {
3448 Polymer.IronSelectableBehavior._activateHandler.call(this, event);
3449 event.stopPropagation();
3450 }
3451 };
3452
3453 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
3454
3455 Polymer.IronMenuBehavior = [ Polymer.IronMultiSelectableBehavior, Polymer.IronA1 1yKeysBehavior, Polymer.IronMenuBehaviorImpl ];
3456
3457 Polymer.IronMenubarBehaviorImpl = {
3458 hostAttributes: {
3459 role: 'menubar'
3460 },
3461 keyBindings: {
3462 left: '_onLeftKey',
3463 right: '_onRightKey'
3464 },
3465 _onUpKey: function(event) {
3466 this.focusedItem.click();
3467 event.detail.keyboardEvent.preventDefault();
3468 },
3469 _onDownKey: function(event) {
3470 this.focusedItem.click();
3471 event.detail.keyboardEvent.preventDefault();
3472 },
3473 get _isRTL() {
3474 return window.getComputedStyle(this)['direction'] === 'rtl';
3475 },
3476 _onLeftKey: function(event) {
3477 if (this._isRTL) {
3478 this._focusNext();
3479 } else {
3480 this._focusPrevious();
3481 }
3482 event.detail.keyboardEvent.preventDefault();
3483 },
3484 _onRightKey: function(event) {
3485 if (this._isRTL) {
3486 this._focusPrevious();
3487 } else {
3488 this._focusNext();
3489 }
3490 event.detail.keyboardEvent.preventDefault();
3491 },
3492 _onKeydown: function(event) {
3493 if (this.keyboardEventMatchesKeys(event, 'up down left right esc')) {
3494 return;
3495 }
3496 this._focusWithKeyboardEvent(event);
3497 }
3498 };
3499
3500 Polymer.IronMenubarBehavior = [ Polymer.IronMenuBehavior, Polymer.IronMenubarBeh aviorImpl ];
3501
3502 Polymer({
3503 is: 'iron-iconset-svg',
3504 properties: {
3505 name: {
3506 type: String,
3507 observer: '_nameChanged'
3508 },
3509 size: {
3510 type: Number,
3511 value: 24
3512 }
3513 },
3514 attached: function() {
3515 this.style.display = 'none';
3516 },
3517 getIconNames: function() {
3518 this._icons = this._createIconMap();
3519 return Object.keys(this._icons).map(function(n) {
3520 return this.name + ':' + n;
3521 }, this);
3522 },
3523 applyIcon: function(element, iconName) {
3524 element = element.root || element;
3525 this.removeIcon(element);
3526 var svg = this._cloneIcon(iconName);
3527 if (svg) {
3528 var pde = Polymer.dom(element);
3529 pde.insertBefore(svg, pde.childNodes[0]);
3530 return element._svgIcon = svg;
3531 }
3532 return null;
3533 },
3534 removeIcon: function(element) {
3535 if (element._svgIcon) {
3536 Polymer.dom(element).removeChild(element._svgIcon);
3537 element._svgIcon = null;
3538 }
3539 },
3540 _nameChanged: function() {
3541 new Polymer.IronMeta({
3542 type: 'iconset',
3543 key: this.name,
3544 value: this
3545 });
3546 this.async(function() {
3547 this.fire('iron-iconset-added', this, {
3548 node: window
3549 });
3550 });
3551 },
3552 _createIconMap: function() {
3553 var icons = Object.create(null);
3554 Polymer.dom(this).querySelectorAll('[id]').forEach(function(icon) {
3555 icons[icon.id] = icon;
3556 });
3557 return icons;
3558 },
3559 _cloneIcon: function(id) {
3560 this._icons = this._icons || this._createIconMap();
3561 return this._prepareSvgClone(this._icons[id], this.size);
3562 },
3563 _prepareSvgClone: function(sourceSvg, size) {
3564 if (sourceSvg) {
3565 var content = sourceSvg.cloneNode(true), svg = document.createElementNS('h ttp://www.w3.org/2000/svg', 'svg'), viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size;
3566 svg.setAttribute('viewBox', viewBox);
3567 svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
3568 svg.style.cssText = 'pointer-events: none; display: block; width: 100%; he ight: 100%;';
3569 svg.appendChild(content).removeAttribute('id');
3570 return svg;
3571 }
3572 return null;
3573 }
3574 });
3575
3576 Polymer({
3577 is: 'paper-tabs',
3578 behaviors: [ Polymer.IronResizableBehavior, Polymer.IronMenubarBehavior ],
3579 properties: {
3580 noink: {
3581 type: Boolean,
3582 value: false,
3583 observer: '_noinkChanged'
3584 },
3585 noBar: {
3586 type: Boolean,
3587 value: false
3588 },
3589 noSlide: {
3590 type: Boolean,
3591 value: false
3592 },
3593 scrollable: {
3594 type: Boolean,
3595 value: false
3596 },
3597 fitContainer: {
3598 type: Boolean,
3599 value: false
3600 },
3601 disableDrag: {
3602 type: Boolean,
3603 value: false
3604 },
3605 hideScrollButtons: {
3606 type: Boolean,
3607 value: false
3608 },
3609 alignBottom: {
3610 type: Boolean,
3611 value: false
3612 },
3613 selectable: {
3614 type: String,
3615 value: 'paper-tab'
3616 },
3617 autoselect: {
3618 type: Boolean,
3619 value: false
3620 },
3621 autoselectDelay: {
3622 type: Number,
3623 value: 0
3624 },
3625 _step: {
3626 type: Number,
3627 value: 10
3628 },
3629 _holdDelay: {
3630 type: Number,
3631 value: 1
3632 },
3633 _leftHidden: {
3634 type: Boolean,
3635 value: false
3636 },
3637 _rightHidden: {
3638 type: Boolean,
3639 value: false
3640 },
3641 _previousTab: {
3642 type: Object
3643 }
3644 },
3645 hostAttributes: {
3646 role: 'tablist'
3647 },
3648 listeners: {
3649 'iron-resize': '_onTabSizingChanged',
3650 'iron-items-changed': '_onTabSizingChanged',
3651 'iron-select': '_onIronSelect',
3652 'iron-deselect': '_onIronDeselect'
3653 },
3654 keyBindings: {
3655 'left:keyup right:keyup': '_onArrowKeyup'
3656 },
3657 created: function() {
3658 this._holdJob = null;
3659 this._pendingActivationItem = undefined;
3660 this._pendingActivationTimeout = undefined;
3661 this._bindDelayedActivationHandler = this._delayedActivationHandler.bind(thi s);
3662 this.addEventListener('blur', this._onBlurCapture.bind(this), true);
3663 },
3664 ready: function() {
3665 this.setScrollDirection('y', this.$.tabsContainer);
3666 },
3667 detached: function() {
3668 this._cancelPendingActivation();
3669 },
3670 _noinkChanged: function(noink) {
3671 var childTabs = Polymer.dom(this).querySelectorAll('paper-tab');
3672 childTabs.forEach(noink ? this._setNoinkAttribute : this._removeNoinkAttribu te);
3673 },
3674 _setNoinkAttribute: function(element) {
3675 element.setAttribute('noink', '');
3676 },
3677 _removeNoinkAttribute: function(element) {
3678 element.removeAttribute('noink');
3679 },
3680 _computeScrollButtonClass: function(hideThisButton, scrollable, hideScrollButt ons) {
3681 if (!scrollable || hideScrollButtons) {
3682 return 'hidden';
3683 }
3684 if (hideThisButton) {
3685 return 'not-visible';
3686 }
3687 return '';
3688 },
3689 _computeTabsContentClass: function(scrollable, fitContainer) {
3690 return scrollable ? 'scrollable' + (fitContainer ? ' fit-container' : '') : ' fit-container';
3691 },
3692 _computeSelectionBarClass: function(noBar, alignBottom) {
3693 if (noBar) {
3694 return 'hidden';
3695 } else if (alignBottom) {
3696 return 'align-bottom';
3697 }
3698 return '';
3699 },
3700 _onTabSizingChanged: function() {
3701 this.debounce('_onTabSizingChanged', function() {
3702 this._scroll();
3703 this._tabChanged(this.selectedItem);
3704 }, 10);
3705 },
3706 _onIronSelect: function(event) {
3707 this._tabChanged(event.detail.item, this._previousTab);
3708 this._previousTab = event.detail.item;
3709 this.cancelDebouncer('tab-changed');
3710 },
3711 _onIronDeselect: function(event) {
3712 this.debounce('tab-changed', function() {
3713 this._tabChanged(null, this._previousTab);
3714 this._previousTab = null;
3715 }, 1);
3716 },
3717 _activateHandler: function() {
3718 this._cancelPendingActivation();
3719 Polymer.IronMenuBehaviorImpl._activateHandler.apply(this, arguments);
3720 },
3721 _scheduleActivation: function(item, delay) {
3722 this._pendingActivationItem = item;
3723 this._pendingActivationTimeout = this.async(this._bindDelayedActivationHandl er, delay);
3724 },
3725 _delayedActivationHandler: function() {
3726 var item = this._pendingActivationItem;
3727 this._pendingActivationItem = undefined;
3728 this._pendingActivationTimeout = undefined;
3729 item.fire(this.activateEvent, null, {
3730 bubbles: true,
3731 cancelable: true
3732 });
3733 },
3734 _cancelPendingActivation: function() {
3735 if (this._pendingActivationTimeout !== undefined) {
3736 this.cancelAsync(this._pendingActivationTimeout);
3737 this._pendingActivationItem = undefined;
3738 this._pendingActivationTimeout = undefined;
3739 }
3740 },
3741 _onArrowKeyup: function(event) {
3742 if (this.autoselect) {
3743 this._scheduleActivation(this.focusedItem, this.autoselectDelay);
3744 }
3745 },
3746 _onBlurCapture: function(event) {
3747 if (event.target === this._pendingActivationItem) {
3748 this._cancelPendingActivation();
3749 }
3750 },
3751 get _tabContainerScrollSize() {
3752 return Math.max(0, this.$.tabsContainer.scrollWidth - this.$.tabsContainer.o ffsetWidth);
3753 },
3754 _scroll: function(e, detail) {
3755 if (!this.scrollable) {
3756 return;
3757 }
3758 var ddx = detail && -detail.ddx || 0;
3759 this._affectScroll(ddx);
3760 },
3761 _down: function(e) {
3762 this.async(function() {
3763 if (this._defaultFocusAsync) {
3764 this.cancelAsync(this._defaultFocusAsync);
3765 this._defaultFocusAsync = null;
3766 }
3767 }, 1);
3768 },
3769 _affectScroll: function(dx) {
3770 this.$.tabsContainer.scrollLeft += dx;
3771 var scrollLeft = this.$.tabsContainer.scrollLeft;
3772 this._leftHidden = scrollLeft === 0;
3773 this._rightHidden = scrollLeft === this._tabContainerScrollSize;
3774 },
3775 _onLeftScrollButtonDown: function() {
3776 this._scrollToLeft();
3777 this._holdJob = setInterval(this._scrollToLeft.bind(this), this._holdDelay);
3778 },
3779 _onRightScrollButtonDown: function() {
3780 this._scrollToRight();
3781 this._holdJob = setInterval(this._scrollToRight.bind(this), this._holdDelay) ;
3782 },
3783 _onScrollButtonUp: function() {
3784 clearInterval(this._holdJob);
3785 this._holdJob = null;
3786 },
3787 _scrollToLeft: function() {
3788 this._affectScroll(-this._step);
3789 },
3790 _scrollToRight: function() {
3791 this._affectScroll(this._step);
3792 },
3793 _tabChanged: function(tab, old) {
3794 if (!tab) {
3795 this.$.selectionBar.classList.remove('expand');
3796 this.$.selectionBar.classList.remove('contract');
3797 this._positionBar(0, 0);
3798 return;
3799 }
3800 var r = this.$.tabsContent.getBoundingClientRect();
3801 var w = r.width;
3802 var tabRect = tab.getBoundingClientRect();
3803 var tabOffsetLeft = tabRect.left - r.left;
3804 this._pos = {
3805 width: this._calcPercent(tabRect.width, w),
3806 left: this._calcPercent(tabOffsetLeft, w)
3807 };
3808 if (this.noSlide || old == null) {
3809 this.$.selectionBar.classList.remove('expand');
3810 this.$.selectionBar.classList.remove('contract');
3811 this._positionBar(this._pos.width, this._pos.left);
3812 return;
3813 }
3814 var oldRect = old.getBoundingClientRect();
3815 var oldIndex = this.items.indexOf(old);
3816 var index = this.items.indexOf(tab);
3817 var m = 5;
3818 this.$.selectionBar.classList.add('expand');
3819 var moveRight = oldIndex < index;
3820 var isRTL = this._isRTL;
3821 if (isRTL) {
3822 moveRight = !moveRight;
3823 }
3824 if (moveRight) {
3825 this._positionBar(this._calcPercent(tabRect.left + tabRect.width - oldRect .left, w) - m, this._left);
3826 } else {
3827 this._positionBar(this._calcPercent(oldRect.left + oldRect.width - tabRect .left, w) - m, this._calcPercent(tabOffsetLeft, w) + m);
3828 }
3829 if (this.scrollable) {
3830 this._scrollToSelectedIfNeeded(tabRect.width, tabOffsetLeft);
3831 }
3832 },
3833 _scrollToSelectedIfNeeded: function(tabWidth, tabOffsetLeft) {
3834 var l = tabOffsetLeft - this.$.tabsContainer.scrollLeft;
3835 if (l < 0) {
3836 this.$.tabsContainer.scrollLeft += l;
3837 } else {
3838 l += tabWidth - this.$.tabsContainer.offsetWidth;
3839 if (l > 0) {
3840 this.$.tabsContainer.scrollLeft += l;
3841 }
3842 }
3843 },
3844 _calcPercent: function(w, w0) {
3845 return 100 * w / w0;
3846 },
3847 _positionBar: function(width, left) {
3848 width = width || 0;
3849 left = left || 0;
3850 this._width = width;
3851 this._left = left;
3852 this.transform('translateX(' + left + '%) scaleX(' + width / 100 + ')', this .$.selectionBar);
3853 },
3854 _onBarTransitionEnd: function(e) {
3855 var cl = this.$.selectionBar.classList;
3856 if (cl.contains('expand')) {
3857 cl.remove('expand');
3858 cl.add('contract');
3859 this._positionBar(this._pos.width, this._pos.left);
3860 } else if (cl.contains('contract')) {
3861 cl.remove('contract');
3862 }
3863 }
3864 });
3865
3866 (function() {
3867 'use strict';
3868 Polymer.IronA11yAnnouncer = Polymer({
3869 is: 'iron-a11y-announcer',
3870 properties: {
3871 mode: {
3872 type: String,
3873 value: 'polite'
3874 },
3875 _text: {
3876 type: String,
3877 value: ''
3878 }
3879 },
3880 created: function() {
3881 if (!Polymer.IronA11yAnnouncer.instance) {
3882 Polymer.IronA11yAnnouncer.instance = this;
3883 }
3884 document.body.addEventListener('iron-announce', this._onIronAnnounce.bind( this));
3885 },
3886 announce: function(text) {
3887 this._text = '';
3888 this.async(function() {
3889 this._text = text;
3890 }, 100);
3891 },
3892 _onIronAnnounce: function(event) {
3893 if (event.detail && event.detail.text) {
3894 this.announce(event.detail.text);
3895 }
3896 }
3897 });
3898 Polymer.IronA11yAnnouncer.instance = null;
3899 Polymer.IronA11yAnnouncer.requestAvailability = function() {
3900 if (!Polymer.IronA11yAnnouncer.instance) {
3901 Polymer.IronA11yAnnouncer.instance = document.createElement('iron-a11y-ann ouncer');
3902 }
3903 document.body.appendChild(Polymer.IronA11yAnnouncer.instance);
3904 };
3905 })();
3906
3907 Polymer.IronValidatableBehaviorMeta = null;
3908
3909 Polymer.IronValidatableBehavior = {
3910 properties: {
3911 validator: {
3912 type: String
3913 },
3914 invalid: {
3915 notify: true,
3916 reflectToAttribute: true,
3917 type: Boolean,
3918 value: false
3919 },
3920 _validatorMeta: {
3921 type: Object
3922 },
3923 validatorType: {
3924 type: String,
3925 value: 'validator'
3926 },
3927 _validator: {
3928 type: Object,
3929 computed: '__computeValidator(validator)'
3930 }
3931 },
3932 observers: [ '_invalidChanged(invalid)' ],
3933 registered: function() {
3934 Polymer.IronValidatableBehaviorMeta = new Polymer.IronMeta({
3935 type: 'validator'
3936 });
3937 },
3938 _invalidChanged: function() {
3939 if (this.invalid) {
3940 this.setAttribute('aria-invalid', 'true');
3941 } else {
3942 this.removeAttribute('aria-invalid');
3943 }
3944 },
3945 hasValidator: function() {
3946 return this._validator != null;
3947 },
3948 validate: function(value) {
3949 this.invalid = !this._getValidity(value);
3950 return !this.invalid;
3951 },
3952 _getValidity: function(value) {
3953 if (this.hasValidator()) {
3954 return this._validator.validate(value);
3955 }
3956 return true;
3957 },
3958 __computeValidator: function() {
3959 return Polymer.IronValidatableBehaviorMeta && Polymer.IronValidatableBehavio rMeta.byKey(this.validator);
3960 }
3961 };
3962
3963 Polymer({
3964 is: 'iron-input',
3965 "extends": 'input',
3966 behaviors: [ Polymer.IronValidatableBehavior ],
3967 properties: {
3968 bindValue: {
3969 observer: '_bindValueChanged',
3970 type: String
3971 },
3972 preventInvalidInput: {
3973 type: Boolean
3974 },
3975 allowedPattern: {
3976 type: String,
3977 observer: "_allowedPatternChanged"
3978 },
3979 _previousValidInput: {
3980 type: String,
3981 value: ''
3982 },
3983 _patternAlreadyChecked: {
3984 type: Boolean,
3985 value: false
3986 }
3987 },
3988 listeners: {
3989 input: '_onInput',
3990 keypress: '_onKeypress'
3991 },
3992 registered: function() {
3993 if (!this._canDispatchEventOnDisabled()) {
3994 this._origDispatchEvent = this.dispatchEvent;
3995 this.dispatchEvent = this._dispatchEventFirefoxIE;
3996 }
3997 },
3998 created: function() {
3999 Polymer.IronA11yAnnouncer.requestAvailability();
4000 },
4001 _canDispatchEventOnDisabled: function() {
4002 var input = document.createElement('input');
4003 var canDispatch = false;
4004 input.disabled = true;
4005 input.addEventListener('feature-check-dispatch-event', function() {
4006 canDispatch = true;
4007 });
4008 try {
4009 input.dispatchEvent(new Event('feature-check-dispatch-event'));
4010 } catch (e) {}
4011 return canDispatch;
4012 },
4013 _dispatchEventFirefoxIE: function() {
4014 var disabled = this.disabled;
4015 this.disabled = false;
4016 this._origDispatchEvent.apply(this, arguments);
4017 this.disabled = disabled;
4018 },
4019 get _patternRegExp() {
4020 var pattern;
4021 if (this.allowedPattern) {
4022 pattern = new RegExp(this.allowedPattern);
4023 } else {
4024 switch (this.type) {
4025 case 'number':
4026 pattern = /[0-9.,e-]/;
4027 break;
4028 }
4029 }
4030 return pattern;
4031 },
4032 ready: function() {
4033 this.bindValue = this.value;
4034 },
4035 _bindValueChanged: function() {
4036 if (this.value !== this.bindValue) {
4037 this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue == = false) ? '' : this.bindValue;
4038 }
4039 this.fire('bind-value-changed', {
4040 value: this.bindValue
4041 });
4042 },
4043 _allowedPatternChanged: function() {
4044 this.preventInvalidInput = this.allowedPattern ? true : false;
4045 },
4046 _onInput: function() {
4047 if (this.preventInvalidInput && !this._patternAlreadyChecked) {
4048 var valid = this._checkPatternValidity();
4049 if (!valid) {
4050 this._announceInvalidCharacter('Invalid string of characters not entered .');
4051 this.value = this._previousValidInput;
4052 }
4053 }
4054 this.bindValue = this.value;
4055 this._previousValidInput = this.value;
4056 this._patternAlreadyChecked = false;
4057 },
4058 _isPrintable: function(event) {
4059 var anyNonPrintable = event.keyCode == 8 || event.keyCode == 9 || event.keyC ode == 13 || event.keyCode == 27;
4060 var mozNonPrintable = event.keyCode == 19 || event.keyCode == 20 || event.ke yCode == 45 || event.keyCode == 46 || event.keyCode == 144 || event.keyCode == 1 45 || event.keyCode > 32 && event.keyCode < 41 || event.keyCode > 111 && event.k eyCode < 124;
4061 return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable);
4062 },
4063 _onKeypress: function(event) {
4064 if (!this.preventInvalidInput && this.type !== 'number') {
4065 return;
4066 }
4067 var regexp = this._patternRegExp;
4068 if (!regexp) {
4069 return;
4070 }
4071 if (event.metaKey || event.ctrlKey || event.altKey) return;
4072 this._patternAlreadyChecked = true;
4073 var thisChar = String.fromCharCode(event.charCode);
4074 if (this._isPrintable(event) && !regexp.test(thisChar)) {
4075 event.preventDefault();
4076 this._announceInvalidCharacter('Invalid character ' + thisChar + ' not ent ered.');
4077 }
4078 },
4079 _checkPatternValidity: function() {
4080 var regexp = this._patternRegExp;
4081 if (!regexp) {
4082 return true;
4083 }
4084 for (var i = 0; i < this.value.length; i++) {
4085 if (!regexp.test(this.value[i])) {
4086 return false;
4087 }
4088 }
4089 return true;
4090 },
4091 validate: function() {
4092 var valid = this.checkValidity();
4093 if (valid) {
4094 if (this.required && this.value === '') {
4095 valid = false;
4096 } else if (this.hasValidator()) {
4097 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
4098 }
4099 }
4100 this.invalid = !valid;
4101 this.fire('iron-input-validate');
4102 return valid;
4103 },
4104 _announceInvalidCharacter: function(message) {
4105 this.fire('iron-announce', {
4106 text: message
4107 });
4108 }
4109 });
4110
4111 Polymer({
4112 is: 'paper-input-container',
4113 properties: {
4114 noLabelFloat: {
4115 type: Boolean,
4116 value: false
4117 },
4118 alwaysFloatLabel: {
4119 type: Boolean,
4120 value: false
4121 },
4122 attrForValue: {
4123 type: String,
4124 value: 'bind-value'
4125 },
4126 autoValidate: {
4127 type: Boolean,
4128 value: false
4129 },
4130 invalid: {
4131 observer: '_invalidChanged',
4132 type: Boolean,
4133 value: false
4134 },
4135 focused: {
4136 readOnly: true,
4137 type: Boolean,
4138 value: false,
4139 notify: true
4140 },
4141 _addons: {
4142 type: Array
4143 },
4144 _inputHasContent: {
4145 type: Boolean,
4146 value: false
4147 },
4148 _inputSelector: {
4149 type: String,
4150 value: 'input,textarea,.paper-input-input'
4151 },
4152 _boundOnFocus: {
4153 type: Function,
4154 value: function() {
4155 return this._onFocus.bind(this);
4156 }
4157 },
4158 _boundOnBlur: {
4159 type: Function,
4160 value: function() {
4161 return this._onBlur.bind(this);
4162 }
4163 },
4164 _boundOnInput: {
4165 type: Function,
4166 value: function() {
4167 return this._onInput.bind(this);
4168 }
4169 },
4170 _boundValueChanged: {
4171 type: Function,
4172 value: function() {
4173 return this._onValueChanged.bind(this);
4174 }
4175 }
4176 },
4177 listeners: {
4178 'addon-attached': '_onAddonAttached',
4179 'iron-input-validate': '_onIronInputValidate'
4180 },
4181 get _valueChangedEvent() {
4182 return this.attrForValue + '-changed';
4183 },
4184 get _propertyForValue() {
4185 return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
4186 },
4187 get _inputElement() {
4188 return Polymer.dom(this).querySelector(this._inputSelector);
4189 },
4190 get _inputElementValue() {
4191 return this._inputElement[this._propertyForValue] || this._inputElement.valu e;
4192 },
4193 ready: function() {
4194 if (!this._addons) {
4195 this._addons = [];
4196 }
4197 this.addEventListener('focus', this._boundOnFocus, true);
4198 this.addEventListener('blur', this._boundOnBlur, true);
4199 },
4200 attached: function() {
4201 if (this.attrForValue) {
4202 this._inputElement.addEventListener(this._valueChangedEvent, this._boundVa lueChanged);
4203 } else {
4204 this.addEventListener('input', this._onInput);
4205 }
4206 if (this._inputElementValue != '') {
4207 this._handleValueAndAutoValidate(this._inputElement);
4208 } else {
4209 this._handleValue(this._inputElement);
4210 }
4211 },
4212 _onAddonAttached: function(event) {
4213 if (!this._addons) {
4214 this._addons = [];
4215 }
4216 var target = event.target;
4217 if (this._addons.indexOf(target) === -1) {
4218 this._addons.push(target);
4219 if (this.isAttached) {
4220 this._handleValue(this._inputElement);
4221 }
4222 }
4223 },
4224 _onFocus: function() {
4225 this._setFocused(true);
4226 },
4227 _onBlur: function() {
4228 this._setFocused(false);
4229 this._handleValueAndAutoValidate(this._inputElement);
4230 },
4231 _onInput: function(event) {
4232 this._handleValueAndAutoValidate(event.target);
4233 },
4234 _onValueChanged: function(event) {
4235 this._handleValueAndAutoValidate(event.target);
4236 },
4237 _handleValue: function(inputElement) {
4238 var value = this._inputElementValue;
4239 if (value || value === 0 || inputElement.type === 'number' && !inputElement. checkValidity()) {
4240 this._inputHasContent = true;
4241 } else {
4242 this._inputHasContent = false;
4243 }
4244 this.updateAddons({
4245 inputElement: inputElement,
4246 value: value,
4247 invalid: this.invalid
4248 });
4249 },
4250 _handleValueAndAutoValidate: function(inputElement) {
4251 if (this.autoValidate) {
4252 var valid;
4253 if (inputElement.validate) {
4254 valid = inputElement.validate(this._inputElementValue);
4255 } else {
4256 valid = inputElement.checkValidity();
4257 }
4258 this.invalid = !valid;
4259 }
4260 this._handleValue(inputElement);
4261 },
4262 _onIronInputValidate: function(event) {
4263 this.invalid = this._inputElement.invalid;
4264 },
4265 _invalidChanged: function() {
4266 if (this._addons) {
4267 this.updateAddons({
4268 invalid: this.invalid
4269 });
4270 }
4271 },
4272 updateAddons: function(state) {
4273 for (var addon, index = 0; addon = this._addons[index]; index++) {
4274 addon.update(state);
4275 }
4276 },
4277 _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, i nvalid, _inputHasContent) {
4278 var cls = 'input-content';
4279 if (!noLabelFloat) {
4280 var label = this.querySelector('label');
4281 if (alwaysFloatLabel || _inputHasContent) {
4282 cls += ' label-is-floating';
4283 this.$.labelAndInputContainer.style.position = 'static';
4284 if (invalid) {
4285 cls += ' is-invalid';
4286 } else if (focused) {
4287 cls += " label-is-highlighted";
4288 }
4289 } else {
4290 if (label) {
4291 this.$.labelAndInputContainer.style.position = 'relative';
4292 }
4293 }
4294 } else {
4295 if (_inputHasContent) {
4296 cls += ' label-is-hidden';
4297 }
4298 }
4299 return cls;
4300 },
4301 _computeUnderlineClass: function(focused, invalid) {
4302 var cls = 'underline';
4303 if (invalid) {
4304 cls += ' is-invalid';
4305 } else if (focused) {
4306 cls += ' is-highlighted';
4307 }
4308 return cls;
4309 },
4310 _computeAddOnContentClass: function(focused, invalid) {
4311 var cls = 'add-on-content';
4312 if (invalid) {
4313 cls += ' is-invalid';
4314 } else if (focused) {
4315 cls += ' is-highlighted';
4316 }
4317 return cls;
4318 }
4319 });
4320
4321 Polymer.PaperSpinnerBehavior = {
4322 listeners: {
4323 animationend: '__reset',
4324 webkitAnimationEnd: '__reset'
4325 },
4326 properties: {
4327 active: {
4328 type: Boolean,
4329 value: false,
4330 reflectToAttribute: true,
4331 observer: '__activeChanged'
4332 },
4333 alt: {
4334 type: String,
4335 value: 'loading',
4336 observer: '__altChanged'
4337 },
4338 __coolingDown: {
4339 type: Boolean,
4340 value: false
4341 }
4342 },
4343 __computeContainerClasses: function(active, coolingDown) {
4344 return [ active || coolingDown ? 'active' : '', coolingDown ? 'cooldown' : ' ' ].join(' ');
4345 },
4346 __activeChanged: function(active, old) {
4347 this.__setAriaHidden(!active);
4348 this.__coolingDown = !active && old;
4349 },
4350 __altChanged: function(alt) {
4351 if (alt === this.getPropertyInfo('alt').value) {
4352 this.alt = this.getAttribute('aria-label') || alt;
4353 } else {
4354 this.__setAriaHidden(alt === '');
4355 this.setAttribute('aria-label', alt);
4356 }
4357 },
4358 __setAriaHidden: function(hidden) {
4359 var attr = 'aria-hidden';
4360 if (hidden) {
4361 this.setAttribute(attr, 'true');
4362 } else {
4363 this.removeAttribute(attr);
4364 }
4365 },
4366 __reset: function() {
4367 this.active = false;
4368 this.__coolingDown = false;
4369 }
4370 };
4371
4372 Polymer({
4373 is: 'paper-spinner-lite',
4374 behaviors: [ Polymer.PaperSpinnerBehavior ]
4375 });
4376
4377 // Copyright 2016 The Chromium Authors. All rights reserved.
4378 // Use of this source code is governed by a BSD-style license that can be
4379 // found in the LICENSE file.
4380 var CrSearchFieldBehavior = {
4381 properties: {
4382 label: {
4383 type: String,
4384 value: ''
4385 },
4386 clearLabel: {
4387 type: String,
4388 value: ''
4389 },
4390 showingSearch: {
4391 type: Boolean,
4392 value: false,
4393 notify: true,
4394 observer: 'showingSearchChanged_',
4395 reflectToAttribute: true
4396 },
4397 lastValue_: {
4398 type: String,
4399 value: ''
4400 }
4401 },
4402 getSearchInput: function() {},
4403 getValue: function() {
4404 return this.getSearchInput().value;
4405 },
4406 setValue: function(value) {
4407 this.getSearchInput().bindValue = value;
4408 this.onValueChanged_(value);
4409 },
4410 showAndFocus: function() {
4411 this.showingSearch = true;
4412 this.focus_();
4413 },
4414 focus_: function() {
4415 this.getSearchInput().focus();
4416 },
4417 onSearchTermSearch: function() {
4418 this.onValueChanged_(this.getValue());
4419 },
4420 onValueChanged_: function(newValue) {
4421 if (newValue == this.lastValue_) return;
4422 this.fire('search-changed', newValue);
4423 this.lastValue_ = newValue;
4424 },
4425 onSearchTermKeydown: function(e) {
4426 if (e.key == 'Escape') this.showingSearch = false;
4427 },
4428 showingSearchChanged_: function() {
4429 if (this.showingSearch) {
4430 this.focus_();
4431 return;
4432 }
4433 this.setValue('');
4434 this.getSearchInput().blur();
4435 }
4436 };
4437
4438 // Copyright 2016 The Chromium Authors. All rights reserved.
4439 // Use of this source code is governed by a BSD-style license that can be
4440 // found in the LICENSE file.
4441 Polymer({
4442 is: 'cr-toolbar-search-field',
4443 behaviors: [ CrSearchFieldBehavior ],
4444 properties: {
4445 narrow: {
4446 type: Boolean,
4447 reflectToAttribute: true
4448 },
4449 label: String,
4450 clearLabel: String,
4451 spinnerActive: {
4452 type: Boolean,
4453 reflectToAttribute: true
4454 },
4455 hasSearchText_: Boolean
4456 },
4457 listeners: {
4458 tap: 'showSearch_',
4459 'searchInput.bind-value-changed': 'onBindValueChanged_'
4460 },
4461 getSearchInput: function() {
4462 return this.$.searchInput;
4463 },
4464 isSearchFocused: function() {
4465 return this.$.searchTerm.focused;
4466 },
4467 computeIconTabIndex_: function(narrow) {
4468 return narrow ? 0 : -1;
4469 },
4470 isSpinnerShown_: function(spinnerActive, showingSearch) {
4471 return spinnerActive && showingSearch;
4472 },
4473 onInputBlur_: function() {
4474 if (!this.hasSearchText_) this.showingSearch = false;
4475 },
4476 onBindValueChanged_: function() {
4477 var newValue = this.$.searchInput.bindValue;
4478 this.hasSearchText_ = newValue != '';
4479 if (newValue != '') this.showingSearch = true;
4480 },
4481 showSearch_: function(e) {
4482 if (e.target != this.$.clearSearch) this.showingSearch = true;
4483 },
4484 hideSearch_: function(e) {
4485 this.showingSearch = false;
4486 e.stopPropagation();
4487 }
4488 });
4489
4490 // Copyright 2016 The Chromium Authors. All rights reserved.
4491 // Use of this source code is governed by a BSD-style license that can be
4492 // found in the LICENSE file.
4493 Polymer({
4494 is: 'cr-toolbar',
4495 properties: {
4496 pageName: String,
4497 searchPrompt: String,
4498 clearLabel: String,
4499 menuLabel: String,
4500 spinnerActive: Boolean,
4501 showMenu: {
4502 type: Boolean,
4503 value: false
4504 },
4505 narrow_: {
4506 type: Boolean,
4507 reflectToAttribute: true
4508 },
4509 showingSearch_: {
4510 type: Boolean,
4511 reflectToAttribute: true
4512 }
4513 },
4514 getSearchField: function() {
4515 return this.$.search;
4516 },
4517 onMenuTap_: function(e) {
4518 this.fire('cr-menu-tap');
4519 }
4520 });
4521
4522 // Copyright 2015 The Chromium Authors. All rights reserved.
4523 // Use of this source code is governed by a BSD-style license that can be
4524 // found in the LICENSE file.
4525 Polymer({
4526 is: 'history-toolbar',
4527 properties: {
4528 count: {
4529 type: Number,
4530 value: 0,
4531 observer: 'changeToolbarView_'
4532 },
4533 itemsSelected_: {
4534 type: Boolean,
4535 value: false,
4536 reflectToAttribute: true
4537 },
4538 searchTerm: {
4539 type: String,
4540 notify: true
4541 },
4542 spinnerActive: {
4543 type: Boolean,
4544 value: false
4545 },
4546 hasDrawer: {
4547 type: Boolean,
4548 observer: 'hasDrawerChanged_',
4549 reflectToAttribute: true
4550 },
4551 isGroupedMode: {
4552 type: Boolean,
4553 reflectToAttribute: true
4554 },
4555 groupedRange: {
4556 type: Number,
4557 value: 0,
4558 reflectToAttribute: true,
4559 notify: true
4560 },
4561 queryStartTime: String,
4562 queryEndTime: String
4563 },
4564 changeToolbarView_: function() {
4565 this.itemsSelected_ = this.count > 0;
4566 },
4567 setSearchTerm: function(search) {
4568 if (this.searchTerm == search) return;
4569 this.searchTerm = search;
4570 var searchField = this.$['main-toolbar'].getSearchField();
4571 searchField.showAndFocus();
4572 searchField.setValue(search);
4573 },
4574 onSearchChanged_: function(event) {
4575 this.searchTerm = event.detail;
4576 },
4577 onClearSelectionTap_: function() {
4578 this.fire('unselect-all');
4579 },
4580 onDeleteTap_: function() {
4581 this.fire('delete-selected');
4582 },
4583 get searchBar() {
4584 return this.$['main-toolbar'].getSearchField();
4585 },
4586 showSearchField: function() {
4587 this.$['main-toolbar'].getSearchField().showAndFocus();
4588 },
4589 deletingAllowed_: function() {
4590 return loadTimeData.getBoolean('allowDeletingHistory');
4591 },
4592 numberOfItemsSelected_: function(count) {
4593 return count > 0 ? loadTimeData.getStringF('itemsSelected', count) : '';
4594 },
4595 getHistoryInterval_: function(queryStartTime, queryEndTime) {
4596 return loadTimeData.getStringF('historyInterval', queryStartTime, queryEndTi me);
4597 },
4598 hasDrawerChanged_: function() {
4599 this.updateStyles();
4600 }
4601 });
4602
4603 // Copyright 2016 The Chromium Authors. All rights reserved.
4604 // Use of this source code is governed by a BSD-style license that can be
4605 // found in the LICENSE file.
4606 Polymer({
4607 is: 'cr-dialog',
4608 "extends": 'dialog',
4609 created: function() {
4610 window.addEventListener('popstate', function() {
4611 if (this.open) this.cancel();
4612 }.bind(this));
4613 },
4614 cancel: function() {
4615 this.fire('cancel');
4616 HTMLDialogElement.prototype.close.call(this, '');
4617 },
4618 close: function(opt_returnValue) {
4619 HTMLDialogElement.prototype.close.call(this, 'success');
4620 },
4621 getCloseButton: function() {
4622 return this.$.close;
4623 }
4624 });
4625
4626 Polymer.IronFitBehavior = {
4627 properties: {
4628 sizingTarget: {
4629 type: Object,
4630 value: function() {
4631 return this;
4632 }
4633 },
4634 fitInto: {
4635 type: Object,
4636 value: window
4637 },
4638 noOverlap: {
4639 type: Boolean
4640 },
4641 positionTarget: {
4642 type: Element
4643 },
4644 horizontalAlign: {
4645 type: String
4646 },
4647 verticalAlign: {
4648 type: String
4649 },
4650 dynamicAlign: {
4651 type: Boolean
4652 },
4653 horizontalOffset: {
4654 type: Number,
4655 value: 0,
4656 notify: true
4657 },
4658 verticalOffset: {
4659 type: Number,
4660 value: 0,
4661 notify: true
4662 },
4663 autoFitOnAttach: {
4664 type: Boolean,
4665 value: false
4666 },
4667 _fitInfo: {
4668 type: Object
4669 }
4670 },
4671 get _fitWidth() {
4672 var fitWidth;
4673 if (this.fitInto === window) {
4674 fitWidth = this.fitInto.innerWidth;
4675 } else {
4676 fitWidth = this.fitInto.getBoundingClientRect().width;
4677 }
4678 return fitWidth;
4679 },
4680 get _fitHeight() {
4681 var fitHeight;
4682 if (this.fitInto === window) {
4683 fitHeight = this.fitInto.innerHeight;
4684 } else {
4685 fitHeight = this.fitInto.getBoundingClientRect().height;
4686 }
4687 return fitHeight;
4688 },
4689 get _fitLeft() {
4690 var fitLeft;
4691 if (this.fitInto === window) {
4692 fitLeft = 0;
4693 } else {
4694 fitLeft = this.fitInto.getBoundingClientRect().left;
4695 }
4696 return fitLeft;
4697 },
4698 get _fitTop() {
4699 var fitTop;
4700 if (this.fitInto === window) {
4701 fitTop = 0;
4702 } else {
4703 fitTop = this.fitInto.getBoundingClientRect().top;
4704 }
4705 return fitTop;
4706 },
4707 get _defaultPositionTarget() {
4708 var parent = Polymer.dom(this).parentNode;
4709 if (parent && parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
4710 parent = parent.host;
4711 }
4712 return parent;
4713 },
4714 get _localeHorizontalAlign() {
4715 if (this._isRTL) {
4716 if (this.horizontalAlign === 'right') {
4717 return 'left';
4718 }
4719 if (this.horizontalAlign === 'left') {
4720 return 'right';
4721 }
4722 }
4723 return this.horizontalAlign;
4724 },
4725 attached: function() {
4726 this._isRTL = window.getComputedStyle(this).direction == 'rtl';
4727 this.positionTarget = this.positionTarget || this._defaultPositionTarget;
4728 if (this.autoFitOnAttach) {
4729 if (window.getComputedStyle(this).display === 'none') {
4730 setTimeout(function() {
4731 this.fit();
4732 }.bind(this));
4733 } else {
4734 this.fit();
4735 }
4736 }
4737 },
4738 fit: function() {
4739 this.position();
4740 this.constrain();
4741 this.center();
4742 },
4743 _discoverInfo: function() {
4744 if (this._fitInfo) {
4745 return;
4746 }
4747 var target = window.getComputedStyle(this);
4748 var sizer = window.getComputedStyle(this.sizingTarget);
4749 this._fitInfo = {
4750 inlineStyle: {
4751 top: this.style.top || '',
4752 left: this.style.left || '',
4753 position: this.style.position || ''
4754 },
4755 sizerInlineStyle: {
4756 maxWidth: this.sizingTarget.style.maxWidth || '',
4757 maxHeight: this.sizingTarget.style.maxHeight || '',
4758 boxSizing: this.sizingTarget.style.boxSizing || ''
4759 },
4760 positionedBy: {
4761 vertically: target.top !== 'auto' ? 'top' : target.bottom !== 'auto' ? ' bottom' : null,
4762 horizontally: target.left !== 'auto' ? 'left' : target.right !== 'auto' ? 'right' : null
4763 },
4764 sizedBy: {
4765 height: sizer.maxHeight !== 'none',
4766 width: sizer.maxWidth !== 'none',
4767 minWidth: parseInt(sizer.minWidth, 10) || 0,
4768 minHeight: parseInt(sizer.minHeight, 10) || 0
4769 },
4770 margin: {
4771 top: parseInt(target.marginTop, 10) || 0,
4772 right: parseInt(target.marginRight, 10) || 0,
4773 bottom: parseInt(target.marginBottom, 10) || 0,
4774 left: parseInt(target.marginLeft, 10) || 0
4775 }
4776 };
4777 if (this.verticalOffset) {
4778 this._fitInfo.margin.top = this._fitInfo.margin.bottom = this.verticalOffs et;
4779 this._fitInfo.inlineStyle.marginTop = this.style.marginTop || '';
4780 this._fitInfo.inlineStyle.marginBottom = this.style.marginBottom || '';
4781 this.style.marginTop = this.style.marginBottom = this.verticalOffset + 'px ';
4782 }
4783 if (this.horizontalOffset) {
4784 this._fitInfo.margin.left = this._fitInfo.margin.right = this.horizontalOf fset;
4785 this._fitInfo.inlineStyle.marginLeft = this.style.marginLeft || '';
4786 this._fitInfo.inlineStyle.marginRight = this.style.marginRight || '';
4787 this.style.marginLeft = this.style.marginRight = this.horizontalOffset + ' px';
4788 }
4789 },
4790 resetFit: function() {
4791 var info = this._fitInfo || {};
4792 for (var property in info.sizerInlineStyle) {
4793 this.sizingTarget.style[property] = info.sizerInlineStyle[property];
4794 }
4795 for (var property in info.inlineStyle) {
4796 this.style[property] = info.inlineStyle[property];
4797 }
4798 this._fitInfo = null;
4799 },
4800 refit: function() {
4801 var scrollLeft = this.sizingTarget.scrollLeft;
4802 var scrollTop = this.sizingTarget.scrollTop;
4803 this.resetFit();
4804 this.fit();
4805 this.sizingTarget.scrollLeft = scrollLeft;
4806 this.sizingTarget.scrollTop = scrollTop;
4807 },
4808 position: function() {
4809 if (!this.horizontalAlign && !this.verticalAlign) {
4810 return;
4811 }
4812 this._discoverInfo();
4813 this.style.position = 'fixed';
4814 this.sizingTarget.style.boxSizing = 'border-box';
4815 this.style.left = '0px';
4816 this.style.top = '0px';
4817 var rect = this.getBoundingClientRect();
4818 var positionRect = this.__getNormalizedRect(this.positionTarget);
4819 var fitRect = this.__getNormalizedRect(this.fitInto);
4820 var margin = this._fitInfo.margin;
4821 var size = {
4822 width: rect.width + margin.left + margin.right,
4823 height: rect.height + margin.top + margin.bottom
4824 };
4825 var position = this.__getPosition(this._localeHorizontalAlign, this.vertical Align, size, positionRect, fitRect);
4826 var left = position.left + margin.left;
4827 var top = position.top + margin.top;
4828 var right = Math.min(fitRect.right - margin.right, left + rect.width);
4829 var bottom = Math.min(fitRect.bottom - margin.bottom, top + rect.height);
4830 var minWidth = this._fitInfo.sizedBy.minWidth;
4831 var minHeight = this._fitInfo.sizedBy.minHeight;
4832 if (left < margin.left) {
4833 left = margin.left;
4834 if (right - left < minWidth) {
4835 left = right - minWidth;
4836 }
4837 }
4838 if (top < margin.top) {
4839 top = margin.top;
4840 if (bottom - top < minHeight) {
4841 top = bottom - minHeight;
4842 }
4843 }
4844 this.sizingTarget.style.maxWidth = right - left + 'px';
4845 this.sizingTarget.style.maxHeight = bottom - top + 'px';
4846 this.style.left = left - rect.left + 'px';
4847 this.style.top = top - rect.top + 'px';
4848 },
4849 constrain: function() {
4850 if (this.horizontalAlign || this.verticalAlign) {
4851 return;
4852 }
4853 this._discoverInfo();
4854 var info = this._fitInfo;
4855 if (!info.positionedBy.vertically) {
4856 this.style.position = 'fixed';
4857 this.style.top = '0px';
4858 }
4859 if (!info.positionedBy.horizontally) {
4860 this.style.position = 'fixed';
4861 this.style.left = '0px';
4862 }
4863 this.sizingTarget.style.boxSizing = 'border-box';
4864 var rect = this.getBoundingClientRect();
4865 if (!info.sizedBy.height) {
4866 this.__sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
4867 }
4868 if (!info.sizedBy.width) {
4869 this.__sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right' , 'Width');
4870 }
4871 },
4872 _sizeDimension: function(rect, positionedBy, start, end, extent) {
4873 this.__sizeDimension(rect, positionedBy, start, end, extent);
4874 },
4875 __sizeDimension: function(rect, positionedBy, start, end, extent) {
4876 var info = this._fitInfo;
4877 var fitRect = this.__getNormalizedRect(this.fitInto);
4878 var max = extent === 'Width' ? fitRect.width : fitRect.height;
4879 var flip = positionedBy === end;
4880 var offset = flip ? max - rect[end] : rect[start];
4881 var margin = info.margin[flip ? start : end];
4882 var offsetExtent = 'offset' + extent;
4883 var sizingOffset = this[offsetExtent] - this.sizingTarget[offsetExtent];
4884 this.sizingTarget.style['max' + extent] = max - margin - offset - sizingOffs et + 'px';
4885 },
4886 center: function() {
4887 if (this.horizontalAlign || this.verticalAlign) {
4888 return;
4889 }
4890 this._discoverInfo();
4891 var positionedBy = this._fitInfo.positionedBy;
4892 if (positionedBy.vertically && positionedBy.horizontally) {
4893 return;
4894 }
4895 this.style.position = 'fixed';
4896 if (!positionedBy.vertically) {
4897 this.style.top = '0px';
4898 }
4899 if (!positionedBy.horizontally) {
4900 this.style.left = '0px';
4901 }
4902 var rect = this.getBoundingClientRect();
4903 var fitRect = this.__getNormalizedRect(this.fitInto);
4904 if (!positionedBy.vertically) {
4905 var top = fitRect.top - rect.top + (fitRect.height - rect.height) / 2;
4906 this.style.top = top + 'px';
4907 }
4908 if (!positionedBy.horizontally) {
4909 var left = fitRect.left - rect.left + (fitRect.width - rect.width) / 2;
4910 this.style.left = left + 'px';
4911 }
4912 },
4913 __getNormalizedRect: function(target) {
4914 if (target === document.documentElement || target === window) {
4915 return {
4916 top: 0,
4917 left: 0,
4918 width: window.innerWidth,
4919 height: window.innerHeight,
4920 right: window.innerWidth,
4921 bottom: window.innerHeight
4922 };
4923 }
4924 return target.getBoundingClientRect();
4925 },
4926 __getCroppedArea: function(position, size, fitRect) {
4927 var verticalCrop = Math.min(0, position.top) + Math.min(0, fitRect.bottom - (position.top + size.height));
4928 var horizontalCrop = Math.min(0, position.left) + Math.min(0, fitRect.right - (position.left + size.width));
4929 return Math.abs(verticalCrop) * size.width + Math.abs(horizontalCrop) * size .height;
4930 },
4931 __getPosition: function(hAlign, vAlign, size, positionRect, fitRect) {
4932 var positions = [ {
4933 verticalAlign: 'top',
4934 horizontalAlign: 'left',
4935 top: positionRect.top,
4936 left: positionRect.left
4937 }, {
4938 verticalAlign: 'top',
4939 horizontalAlign: 'right',
4940 top: positionRect.top,
4941 left: positionRect.right - size.width
4942 }, {
4943 verticalAlign: 'bottom',
4944 horizontalAlign: 'left',
4945 top: positionRect.bottom - size.height,
4946 left: positionRect.left
4947 }, {
4948 verticalAlign: 'bottom',
4949 horizontalAlign: 'right',
4950 top: positionRect.bottom - size.height,
4951 left: positionRect.right - size.width
4952 } ];
4953 if (this.noOverlap) {
4954 for (var i = 0, l = positions.length; i < l; i++) {
4955 var copy = {};
4956 for (var key in positions[i]) {
4957 copy[key] = positions[i][key];
4958 }
4959 positions.push(copy);
4960 }
4961 positions[0].top = positions[1].top += positionRect.height;
4962 positions[2].top = positions[3].top -= positionRect.height;
4963 positions[4].left = positions[6].left += positionRect.width;
4964 positions[5].left = positions[7].left -= positionRect.width;
4965 }
4966 vAlign = vAlign === 'auto' ? null : vAlign;
4967 hAlign = hAlign === 'auto' ? null : hAlign;
4968 var position;
4969 for (var i = 0; i < positions.length; i++) {
4970 var pos = positions[i];
4971 if (!this.dynamicAlign && !this.noOverlap && pos.verticalAlign === vAlign && pos.horizontalAlign === hAlign) {
4972 position = pos;
4973 break;
4974 }
4975 var alignOk = (!vAlign || pos.verticalAlign === vAlign) && (!hAlign || pos .horizontalAlign === hAlign);
4976 if (!this.dynamicAlign && !alignOk) {
4977 continue;
4978 }
4979 position = position || pos;
4980 pos.croppedArea = this.__getCroppedArea(pos, size, fitRect);
4981 var diff = pos.croppedArea - position.croppedArea;
4982 if (diff < 0 || diff === 0 && alignOk) {
4983 position = pos;
4984 }
4985 if (position.croppedArea === 0 && alignOk) {
4986 break;
4987 }
4988 }
4989 return position;
4990 }
4991 };
4992
4993 (function() {
4994 'use strict';
4995 Polymer({
4996 is: 'iron-overlay-backdrop',
4997 properties: {
4998 opened: {
4999 reflectToAttribute: true,
5000 type: Boolean,
5001 value: false,
5002 observer: '_openedChanged'
5003 }
5004 },
5005 listeners: {
5006 transitionend: '_onTransitionend'
5007 },
5008 created: function() {
5009 this.__openedRaf = null;
5010 },
5011 attached: function() {
5012 this.opened && this._openedChanged(this.opened);
5013 },
5014 prepare: function() {
5015 if (this.opened && !this.parentNode) {
5016 Polymer.dom(document.body).appendChild(this);
5017 }
5018 },
5019 open: function() {
5020 this.opened = true;
5021 },
5022 close: function() {
5023 this.opened = false;
5024 },
5025 complete: function() {
5026 if (!this.opened && this.parentNode === document.body) {
5027 Polymer.dom(this.parentNode).removeChild(this);
5028 }
5029 },
5030 _onTransitionend: function(event) {
5031 if (event && event.target === this) {
5032 this.complete();
5033 }
5034 },
5035 _openedChanged: function(opened) {
5036 if (opened) {
5037 this.prepare();
5038 } else {
5039 var cs = window.getComputedStyle(this);
5040 if (cs.transitionDuration === '0s' || cs.opacity == 0) {
5041 this.complete();
5042 }
5043 }
5044 if (!this.isAttached) {
5045 return;
5046 }
5047 if (this.__openedRaf) {
5048 window.cancelAnimationFrame(this.__openedRaf);
5049 this.__openedRaf = null;
5050 }
5051 this.scrollTop = this.scrollTop;
5052 this.__openedRaf = window.requestAnimationFrame(function() {
5053 this.__openedRaf = null;
5054 this.toggleClass('opened', this.opened);
5055 }.bind(this));
5056 }
5057 });
5058 })();
5059
5060 Polymer.IronOverlayManagerClass = function() {
5061 this._overlays = [];
5062 this._minimumZ = 101;
5063 this._backdropElement = null;
5064 Polymer.Gestures.add(document, 'tap', this._onCaptureClick.bind(this));
5065 document.addEventListener('focus', this._onCaptureFocus.bind(this), true);
5066 document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true);
5067 };
5068
5069 Polymer.IronOverlayManagerClass.prototype = {
5070 constructor: Polymer.IronOverlayManagerClass,
5071 get backdropElement() {
5072 if (!this._backdropElement) {
5073 this._backdropElement = document.createElement('iron-overlay-backdrop');
5074 }
5075 return this._backdropElement;
5076 },
5077 get deepActiveElement() {
5078 var active = document.activeElement || document.body;
5079 while (active.root && Polymer.dom(active.root).activeElement) {
5080 active = Polymer.dom(active.root).activeElement;
5081 }
5082 return active;
5083 },
5084 _bringOverlayAtIndexToFront: function(i) {
5085 var overlay = this._overlays[i];
5086 if (!overlay) {
5087 return;
5088 }
5089 var lastI = this._overlays.length - 1;
5090 var currentOverlay = this._overlays[lastI];
5091 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
5092 lastI--;
5093 }
5094 if (i >= lastI) {
5095 return;
5096 }
5097 var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
5098 if (this._getZ(overlay) <= minimumZ) {
5099 this._applyOverlayZ(overlay, minimumZ);
5100 }
5101 while (i < lastI) {
5102 this._overlays[i] = this._overlays[i + 1];
5103 i++;
5104 }
5105 this._overlays[lastI] = overlay;
5106 },
5107 addOrRemoveOverlay: function(overlay) {
5108 if (overlay.opened) {
5109 this.addOverlay(overlay);
5110 } else {
5111 this.removeOverlay(overlay);
5112 }
5113 },
5114 addOverlay: function(overlay) {
5115 var i = this._overlays.indexOf(overlay);
5116 if (i >= 0) {
5117 this._bringOverlayAtIndexToFront(i);
5118 this.trackBackdrop();
5119 return;
5120 }
5121 var insertionIndex = this._overlays.length;
5122 var currentOverlay = this._overlays[insertionIndex - 1];
5123 var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ);
5124 var newZ = this._getZ(overlay);
5125 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
5126 this._applyOverlayZ(currentOverlay, minimumZ);
5127 insertionIndex--;
5128 var previousOverlay = this._overlays[insertionIndex - 1];
5129 minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ);
5130 }
5131 if (newZ <= minimumZ) {
5132 this._applyOverlayZ(overlay, minimumZ);
5133 }
5134 this._overlays.splice(insertionIndex, 0, overlay);
5135 this.trackBackdrop();
5136 },
5137 removeOverlay: function(overlay) {
5138 var i = this._overlays.indexOf(overlay);
5139 if (i === -1) {
5140 return;
5141 }
5142 this._overlays.splice(i, 1);
5143 this.trackBackdrop();
5144 },
5145 currentOverlay: function() {
5146 var i = this._overlays.length - 1;
5147 return this._overlays[i];
5148 },
5149 currentOverlayZ: function() {
5150 return this._getZ(this.currentOverlay());
5151 },
5152 ensureMinimumZ: function(minimumZ) {
5153 this._minimumZ = Math.max(this._minimumZ, minimumZ);
5154 },
5155 focusOverlay: function() {
5156 var current = this.currentOverlay();
5157 if (current) {
5158 current._applyFocus();
5159 }
5160 },
5161 trackBackdrop: function() {
5162 var overlay = this._overlayWithBackdrop();
5163 if (!overlay && !this._backdropElement) {
5164 return;
5165 }
5166 this.backdropElement.style.zIndex = this._getZ(overlay) - 1;
5167 this.backdropElement.opened = !!overlay;
5168 },
5169 getBackdrops: function() {
5170 var backdrops = [];
5171 for (var i = 0; i < this._overlays.length; i++) {
5172 if (this._overlays[i].withBackdrop) {
5173 backdrops.push(this._overlays[i]);
5174 }
5175 }
5176 return backdrops;
5177 },
5178 backdropZ: function() {
5179 return this._getZ(this._overlayWithBackdrop()) - 1;
5180 },
5181 _overlayWithBackdrop: function() {
5182 for (var i = 0; i < this._overlays.length; i++) {
5183 if (this._overlays[i].withBackdrop) {
5184 return this._overlays[i];
5185 }
5186 }
5187 },
5188 _getZ: function(overlay) {
5189 var z = this._minimumZ;
5190 if (overlay) {
5191 var z1 = Number(overlay.style.zIndex || window.getComputedStyle(overlay).z Index);
5192 if (z1 === z1) {
5193 z = z1;
5194 }
5195 }
5196 return z;
5197 },
5198 _setZ: function(element, z) {
5199 element.style.zIndex = z;
5200 },
5201 _applyOverlayZ: function(overlay, aboveZ) {
5202 this._setZ(overlay, aboveZ + 2);
5203 },
5204 _overlayInPath: function(path) {
5205 path = path || [];
5206 for (var i = 0; i < path.length; i++) {
5207 if (path[i]._manager === this) {
5208 return path[i];
5209 }
5210 }
5211 },
5212 _onCaptureClick: function(event) {
5213 var overlay = this.currentOverlay();
5214 if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) {
5215 overlay._onCaptureClick(event);
5216 }
5217 },
5218 _onCaptureFocus: function(event) {
5219 var overlay = this.currentOverlay();
5220 if (overlay) {
5221 overlay._onCaptureFocus(event);
5222 }
5223 },
5224 _onCaptureKeyDown: function(event) {
5225 var overlay = this.currentOverlay();
5226 if (overlay) {
5227 if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'esc')) {
5228 overlay._onCaptureEsc(event);
5229 } else if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 't ab')) {
5230 overlay._onCaptureTab(event);
5231 }
5232 }
5233 },
5234 _shouldBeBehindOverlay: function(overlay1, overlay2) {
5235 return !overlay1.alwaysOnTop && overlay2.alwaysOnTop;
5236 }
5237 };
5238
5239 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();
5240
5241 (function() {
5242 'use strict';
5243 Polymer.IronOverlayBehaviorImpl = {
5244 properties: {
5245 opened: {
5246 observer: '_openedChanged',
5247 type: Boolean,
5248 value: false,
5249 notify: true
5250 },
5251 canceled: {
5252 observer: '_canceledChanged',
5253 readOnly: true,
5254 type: Boolean,
5255 value: false
5256 },
5257 withBackdrop: {
5258 observer: '_withBackdropChanged',
5259 type: Boolean
5260 },
5261 noAutoFocus: {
5262 type: Boolean,
5263 value: false
5264 },
5265 noCancelOnEscKey: {
5266 type: Boolean,
5267 value: false
5268 },
5269 noCancelOnOutsideClick: {
5270 type: Boolean,
5271 value: false
5272 },
5273 closingReason: {
5274 type: Object
5275 },
5276 restoreFocusOnClose: {
5277 type: Boolean,
5278 value: false
5279 },
5280 alwaysOnTop: {
5281 type: Boolean
5282 },
5283 _manager: {
5284 type: Object,
5285 value: Polymer.IronOverlayManager
5286 },
5287 _focusedChild: {
5288 type: Object
5289 }
5290 },
5291 listeners: {
5292 'iron-resize': '_onIronResize'
5293 },
5294 get backdropElement() {
5295 return this._manager.backdropElement;
5296 },
5297 get _focusNode() {
5298 return this._focusedChild || Polymer.dom(this).querySelector('[autofocus]' ) || this;
5299 },
5300 get _focusableNodes() {
5301 var FOCUSABLE_WITH_DISABLED = [ 'a[href]', 'area[href]', 'iframe', '[tabin dex]', '[contentEditable=true]' ];
5302 var FOCUSABLE_WITHOUT_DISABLED = [ 'input', 'select', 'textarea', 'button' ];
5303 var selector = FOCUSABLE_WITH_DISABLED.join(':not([tabindex="-1"]),') + ': not([tabindex="-1"]),' + FOCUSABLE_WITHOUT_DISABLED.join(':not([disabled]):not([ tabindex="-1"]),') + ':not([disabled]):not([tabindex="-1"])';
5304 var focusables = Polymer.dom(this).querySelectorAll(selector);
5305 if (this.tabIndex >= 0) {
5306 focusables.splice(0, 0, this);
5307 }
5308 return focusables.sort(function(a, b) {
5309 if (a.tabIndex === b.tabIndex) {
5310 return 0;
5311 }
5312 if (a.tabIndex === 0 || a.tabIndex > b.tabIndex) {
5313 return 1;
5314 }
5315 return -1;
5316 });
5317 },
5318 ready: function() {
5319 this.__isAnimating = false;
5320 this.__shouldRemoveTabIndex = false;
5321 this.__firstFocusableNode = this.__lastFocusableNode = null;
5322 this.__raf = null;
5323 this.__restoreFocusNode = null;
5324 this._ensureSetup();
5325 },
5326 attached: function() {
5327 if (this.opened) {
5328 this._openedChanged(this.opened);
5329 }
5330 this._observer = Polymer.dom(this).observeNodes(this._onNodesChange);
5331 },
5332 detached: function() {
5333 Polymer.dom(this).unobserveNodes(this._observer);
5334 this._observer = null;
5335 if (this.__raf) {
5336 window.cancelAnimationFrame(this.__raf);
5337 this.__raf = null;
5338 }
5339 this._manager.removeOverlay(this);
5340 },
5341 toggle: function() {
5342 this._setCanceled(false);
5343 this.opened = !this.opened;
5344 },
5345 open: function() {
5346 this._setCanceled(false);
5347 this.opened = true;
5348 },
5349 close: function() {
5350 this._setCanceled(false);
5351 this.opened = false;
5352 },
5353 cancel: function(event) {
5354 var cancelEvent = this.fire('iron-overlay-canceled', event, {
5355 cancelable: true
5356 });
5357 if (cancelEvent.defaultPrevented) {
5358 return;
5359 }
5360 this._setCanceled(true);
5361 this.opened = false;
5362 },
5363 _ensureSetup: function() {
5364 if (this._overlaySetup) {
5365 return;
5366 }
5367 this._overlaySetup = true;
5368 this.style.outline = 'none';
5369 this.style.display = 'none';
5370 },
5371 _openedChanged: function(opened) {
5372 if (opened) {
5373 this.removeAttribute('aria-hidden');
5374 } else {
5375 this.setAttribute('aria-hidden', 'true');
5376 }
5377 if (!this.isAttached) {
5378 return;
5379 }
5380 this.__isAnimating = true;
5381 this.__onNextAnimationFrame(this.__openedChanged);
5382 },
5383 _canceledChanged: function() {
5384 this.closingReason = this.closingReason || {};
5385 this.closingReason.canceled = this.canceled;
5386 },
5387 _withBackdropChanged: function() {
5388 if (this.withBackdrop && !this.hasAttribute('tabindex')) {
5389 this.setAttribute('tabindex', '-1');
5390 this.__shouldRemoveTabIndex = true;
5391 } else if (this.__shouldRemoveTabIndex) {
5392 this.removeAttribute('tabindex');
5393 this.__shouldRemoveTabIndex = false;
5394 }
5395 if (this.opened && this.isAttached) {
5396 this._manager.trackBackdrop();
5397 }
5398 },
5399 _prepareRenderOpened: function() {
5400 this.__restoreFocusNode = this._manager.deepActiveElement;
5401 this._preparePositioning();
5402 this.refit();
5403 this._finishPositioning();
5404 if (this.noAutoFocus && document.activeElement === this._focusNode) {
5405 this._focusNode.blur();
5406 this.__restoreFocusNode.focus();
5407 }
5408 },
5409 _renderOpened: function() {
5410 this._finishRenderOpened();
5411 },
5412 _renderClosed: function() {
5413 this._finishRenderClosed();
5414 },
5415 _finishRenderOpened: function() {
5416 this.notifyResize();
5417 this.__isAnimating = false;
5418 var focusableNodes = this._focusableNodes;
5419 this.__firstFocusableNode = focusableNodes[0];
5420 this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1];
5421 this.fire('iron-overlay-opened');
5422 },
5423 _finishRenderClosed: function() {
5424 this.style.display = 'none';
5425 this.style.zIndex = '';
5426 this.notifyResize();
5427 this.__isAnimating = false;
5428 this.fire('iron-overlay-closed', this.closingReason);
5429 },
5430 _preparePositioning: function() {
5431 this.style.transition = this.style.webkitTransition = 'none';
5432 this.style.transform = this.style.webkitTransform = 'none';
5433 this.style.display = '';
5434 },
5435 _finishPositioning: function() {
5436 this.style.display = 'none';
5437 this.scrollTop = this.scrollTop;
5438 this.style.transition = this.style.webkitTransition = '';
5439 this.style.transform = this.style.webkitTransform = '';
5440 this.style.display = '';
5441 this.scrollTop = this.scrollTop;
5442 },
5443 _applyFocus: function() {
5444 if (this.opened) {
5445 if (!this.noAutoFocus) {
5446 this._focusNode.focus();
5447 }
5448 } else {
5449 this._focusNode.blur();
5450 this._focusedChild = null;
5451 if (this.restoreFocusOnClose && this.__restoreFocusNode) {
5452 this.__restoreFocusNode.focus();
5453 }
5454 this.__restoreFocusNode = null;
5455 var currentOverlay = this._manager.currentOverlay();
5456 if (currentOverlay && this !== currentOverlay) {
5457 currentOverlay._applyFocus();
5458 }
5459 }
5460 },
5461 _onCaptureClick: function(event) {
5462 if (!this.noCancelOnOutsideClick) {
5463 this.cancel(event);
5464 }
5465 },
5466 _onCaptureFocus: function(event) {
5467 if (!this.withBackdrop) {
5468 return;
5469 }
5470 var path = Polymer.dom(event).path;
5471 if (path.indexOf(this) === -1) {
5472 event.stopPropagation();
5473 this._applyFocus();
5474 } else {
5475 this._focusedChild = path[0];
5476 }
5477 },
5478 _onCaptureEsc: function(event) {
5479 if (!this.noCancelOnEscKey) {
5480 this.cancel(event);
5481 }
5482 },
5483 _onCaptureTab: function(event) {
5484 if (!this.withBackdrop) {
5485 return;
5486 }
5487 var shift = event.shiftKey;
5488 var nodeToCheck = shift ? this.__firstFocusableNode : this.__lastFocusable Node;
5489 var nodeToSet = shift ? this.__lastFocusableNode : this.__firstFocusableNo de;
5490 var shouldWrap = false;
5491 if (nodeToCheck === nodeToSet) {
5492 shouldWrap = true;
5493 } else {
5494 var focusedNode = this._manager.deepActiveElement;
5495 shouldWrap = focusedNode === nodeToCheck || focusedNode === this;
5496 }
5497 if (shouldWrap) {
5498 event.preventDefault();
5499 this._focusedChild = nodeToSet;
5500 this._applyFocus();
5501 }
5502 },
5503 _onIronResize: function() {
5504 if (this.opened && !this.__isAnimating) {
5505 this.__onNextAnimationFrame(this.refit);
5506 }
5507 },
5508 _onNodesChange: function() {
5509 if (this.opened && !this.__isAnimating) {
5510 this.notifyResize();
5511 }
5512 },
5513 __openedChanged: function() {
5514 if (this.opened) {
5515 this._prepareRenderOpened();
5516 this._manager.addOverlay(this);
5517 this._applyFocus();
5518 this._renderOpened();
5519 } else {
5520 this._manager.removeOverlay(this);
5521 this._applyFocus();
5522 this._renderClosed();
5523 }
5524 },
5525 __onNextAnimationFrame: function(callback) {
5526 if (this.__raf) {
5527 window.cancelAnimationFrame(this.__raf);
5528 }
5529 var self = this;
5530 this.__raf = window.requestAnimationFrame(function nextAnimationFrame() {
5531 self.__raf = null;
5532 callback.call(self);
5533 });
5534 }
5535 };
5536 Polymer.IronOverlayBehavior = [ Polymer.IronFitBehavior, Polymer.IronResizable Behavior, Polymer.IronOverlayBehaviorImpl ];
5537 })();
5538
5539 Polymer.NeonAnimatableBehavior = { 3343 Polymer.NeonAnimatableBehavior = {
5540 properties: { 3344 properties: {
5541 animationConfig: { 3345 animationConfig: {
5542 type: Object 3346 type: Object
5543 }, 3347 },
5544 entryAnimation: { 3348 entryAnimation: {
5545 observer: '_entryAnimationChanged', 3349 observer: '_entryAnimationChanged',
5546 type: String 3350 type: String
5547 }, 3351 },
5548 exitAnimation: { 3352 exitAnimation: {
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
6097 if (focusTarget && this.opened && !this.noAutoFocus) { 3901 if (focusTarget && this.opened && !this.noAutoFocus) {
6098 focusTarget.focus(); 3902 focusTarget.focus();
6099 } else { 3903 } else {
6100 Polymer.IronOverlayBehaviorImpl._applyFocus.apply(this, arguments); 3904 Polymer.IronOverlayBehaviorImpl._applyFocus.apply(this, arguments);
6101 } 3905 }
6102 } 3906 }
6103 }); 3907 });
6104 })(); 3908 })();
6105 3909
6106 Polymer({ 3910 Polymer({
3911 is: 'iron-icon',
3912 properties: {
3913 icon: {
3914 type: String,
3915 observer: '_iconChanged'
3916 },
3917 theme: {
3918 type: String,
3919 observer: '_updateIcon'
3920 },
3921 src: {
3922 type: String,
3923 observer: '_srcChanged'
3924 },
3925 _meta: {
3926 value: Polymer.Base.create('iron-meta', {
3927 type: 'iconset'
3928 }),
3929 observer: '_updateIcon'
3930 }
3931 },
3932 _DEFAULT_ICONSET: 'icons',
3933 _iconChanged: function(icon) {
3934 var parts = (icon || '').split(':');
3935 this._iconName = parts.pop();
3936 this._iconsetName = parts.pop() || this._DEFAULT_ICONSET;
3937 this._updateIcon();
3938 },
3939 _srcChanged: function(src) {
3940 this._updateIcon();
3941 },
3942 _usesIconset: function() {
3943 return this.icon || !this.src;
3944 },
3945 _updateIcon: function() {
3946 if (this._usesIconset()) {
3947 if (this._img && this._img.parentNode) {
3948 Polymer.dom(this.root).removeChild(this._img);
3949 }
3950 if (this._iconName === "") {
3951 if (this._iconset) {
3952 this._iconset.removeIcon(this);
3953 }
3954 } else if (this._iconsetName && this._meta) {
3955 this._iconset = this._meta.byKey(this._iconsetName);
3956 if (this._iconset) {
3957 this._iconset.applyIcon(this, this._iconName, this.theme);
3958 this.unlisten(window, 'iron-iconset-added', '_updateIcon');
3959 } else {
3960 this.listen(window, 'iron-iconset-added', '_updateIcon');
3961 }
3962 }
3963 } else {
3964 if (this._iconset) {
3965 this._iconset.removeIcon(this);
3966 }
3967 if (!this._img) {
3968 this._img = document.createElement('img');
3969 this._img.style.width = '100%';
3970 this._img.style.height = '100%';
3971 this._img.draggable = false;
3972 }
3973 this._img.src = this.src;
3974 Polymer.dom(this.root).appendChild(this._img);
3975 }
3976 }
3977 });
3978
3979 Polymer.IronButtonStateImpl = {
3980 properties: {
3981 pressed: {
3982 type: Boolean,
3983 readOnly: true,
3984 value: false,
3985 reflectToAttribute: true,
3986 observer: '_pressedChanged'
3987 },
3988 toggles: {
3989 type: Boolean,
3990 value: false,
3991 reflectToAttribute: true
3992 },
3993 active: {
3994 type: Boolean,
3995 value: false,
3996 notify: true,
3997 reflectToAttribute: true
3998 },
3999 pointerDown: {
4000 type: Boolean,
4001 readOnly: true,
4002 value: false
4003 },
4004 receivedFocusFromKeyboard: {
4005 type: Boolean,
4006 readOnly: true
4007 },
4008 ariaActiveAttribute: {
4009 type: String,
4010 value: 'aria-pressed',
4011 observer: '_ariaActiveAttributeChanged'
4012 }
4013 },
4014 listeners: {
4015 down: '_downHandler',
4016 up: '_upHandler',
4017 tap: '_tapHandler'
4018 },
4019 observers: [ '_detectKeyboardFocus(focused)', '_activeChanged(active, ariaActi veAttribute)' ],
4020 keyBindings: {
4021 'enter:keydown': '_asyncClick',
4022 'space:keydown': '_spaceKeyDownHandler',
4023 'space:keyup': '_spaceKeyUpHandler'
4024 },
4025 _mouseEventRe: /^mouse/,
4026 _tapHandler: function() {
4027 if (this.toggles) {
4028 this._userActivate(!this.active);
4029 } else {
4030 this.active = false;
4031 }
4032 },
4033 _detectKeyboardFocus: function(focused) {
4034 this._setReceivedFocusFromKeyboard(!this.pointerDown && focused);
4035 },
4036 _userActivate: function(active) {
4037 if (this.active !== active) {
4038 this.active = active;
4039 this.fire('change');
4040 }
4041 },
4042 _downHandler: function(event) {
4043 this._setPointerDown(true);
4044 this._setPressed(true);
4045 this._setReceivedFocusFromKeyboard(false);
4046 },
4047 _upHandler: function() {
4048 this._setPointerDown(false);
4049 this._setPressed(false);
4050 },
4051 _spaceKeyDownHandler: function(event) {
4052 var keyboardEvent = event.detail.keyboardEvent;
4053 var target = Polymer.dom(keyboardEvent).localTarget;
4054 if (this.isLightDescendant(target)) return;
4055 keyboardEvent.preventDefault();
4056 keyboardEvent.stopImmediatePropagation();
4057 this._setPressed(true);
4058 },
4059 _spaceKeyUpHandler: function(event) {
4060 var keyboardEvent = event.detail.keyboardEvent;
4061 var target = Polymer.dom(keyboardEvent).localTarget;
4062 if (this.isLightDescendant(target)) return;
4063 if (this.pressed) {
4064 this._asyncClick();
4065 }
4066 this._setPressed(false);
4067 },
4068 _asyncClick: function() {
4069 this.async(function() {
4070 this.click();
4071 }, 1);
4072 },
4073 _pressedChanged: function(pressed) {
4074 this._changedButtonState();
4075 },
4076 _ariaActiveAttributeChanged: function(value, oldValue) {
4077 if (oldValue && oldValue != value && this.hasAttribute(oldValue)) {
4078 this.removeAttribute(oldValue);
4079 }
4080 },
4081 _activeChanged: function(active, ariaActiveAttribute) {
4082 if (this.toggles) {
4083 this.setAttribute(this.ariaActiveAttribute, active ? 'true' : 'false');
4084 } else {
4085 this.removeAttribute(this.ariaActiveAttribute);
4086 }
4087 this._changedButtonState();
4088 },
4089 _controlStateChanged: function() {
4090 if (this.disabled) {
4091 this._setPressed(false);
4092 } else {
4093 this._changedButtonState();
4094 }
4095 },
4096 _changedButtonState: function() {
4097 if (this._buttonStateChanged) {
4098 this._buttonStateChanged();
4099 }
4100 }
4101 };
4102
4103 Polymer.IronButtonState = [ Polymer.IronA11yKeysBehavior, Polymer.IronButtonStat eImpl ];
4104
4105 (function() {
4106 var Utility = {
4107 distance: function(x1, y1, x2, y2) {
4108 var xDelta = x1 - x2;
4109 var yDelta = y1 - y2;
4110 return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
4111 },
4112 now: window.performance && window.performance.now ? window.performance.now.b ind(window.performance) : Date.now
4113 };
4114 function ElementMetrics(element) {
4115 this.element = element;
4116 this.width = this.boundingRect.width;
4117 this.height = this.boundingRect.height;
4118 this.size = Math.max(this.width, this.height);
4119 }
4120 ElementMetrics.prototype = {
4121 get boundingRect() {
4122 return this.element.getBoundingClientRect();
4123 },
4124 furthestCornerDistanceFrom: function(x, y) {
4125 var topLeft = Utility.distance(x, y, 0, 0);
4126 var topRight = Utility.distance(x, y, this.width, 0);
4127 var bottomLeft = Utility.distance(x, y, 0, this.height);
4128 var bottomRight = Utility.distance(x, y, this.width, this.height);
4129 return Math.max(topLeft, topRight, bottomLeft, bottomRight);
4130 }
4131 };
4132 function Ripple(element) {
4133 this.element = element;
4134 this.color = window.getComputedStyle(element).color;
4135 this.wave = document.createElement('div');
4136 this.waveContainer = document.createElement('div');
4137 this.wave.style.backgroundColor = this.color;
4138 this.wave.classList.add('wave');
4139 this.waveContainer.classList.add('wave-container');
4140 Polymer.dom(this.waveContainer).appendChild(this.wave);
4141 this.resetInteractionState();
4142 }
4143 Ripple.MAX_RADIUS = 300;
4144 Ripple.prototype = {
4145 get recenters() {
4146 return this.element.recenters;
4147 },
4148 get center() {
4149 return this.element.center;
4150 },
4151 get mouseDownElapsed() {
4152 var elapsed;
4153 if (!this.mouseDownStart) {
4154 return 0;
4155 }
4156 elapsed = Utility.now() - this.mouseDownStart;
4157 if (this.mouseUpStart) {
4158 elapsed -= this.mouseUpElapsed;
4159 }
4160 return elapsed;
4161 },
4162 get mouseUpElapsed() {
4163 return this.mouseUpStart ? Utility.now() - this.mouseUpStart : 0;
4164 },
4165 get mouseDownElapsedSeconds() {
4166 return this.mouseDownElapsed / 1e3;
4167 },
4168 get mouseUpElapsedSeconds() {
4169 return this.mouseUpElapsed / 1e3;
4170 },
4171 get mouseInteractionSeconds() {
4172 return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds;
4173 },
4174 get initialOpacity() {
4175 return this.element.initialOpacity;
4176 },
4177 get opacityDecayVelocity() {
4178 return this.element.opacityDecayVelocity;
4179 },
4180 get radius() {
4181 var width2 = this.containerMetrics.width * this.containerMetrics.width;
4182 var height2 = this.containerMetrics.height * this.containerMetrics.height;
4183 var waveRadius = Math.min(Math.sqrt(width2 + height2), Ripple.MAX_RADIUS) * 1.1 + 5;
4184 var duration = 1.1 - .2 * (waveRadius / Ripple.MAX_RADIUS);
4185 var timeNow = this.mouseInteractionSeconds / duration;
4186 var size = waveRadius * (1 - Math.pow(80, -timeNow));
4187 return Math.abs(size);
4188 },
4189 get opacity() {
4190 if (!this.mouseUpStart) {
4191 return this.initialOpacity;
4192 }
4193 return Math.max(0, this.initialOpacity - this.mouseUpElapsedSeconds * this .opacityDecayVelocity);
4194 },
4195 get outerOpacity() {
4196 var outerOpacity = this.mouseUpElapsedSeconds * .3;
4197 var waveOpacity = this.opacity;
4198 return Math.max(0, Math.min(outerOpacity, waveOpacity));
4199 },
4200 get isOpacityFullyDecayed() {
4201 return this.opacity < .01 && this.radius >= Math.min(this.maxRadius, Rippl e.MAX_RADIUS);
4202 },
4203 get isRestingAtMaxRadius() {
4204 return this.opacity >= this.initialOpacity && this.radius >= Math.min(this .maxRadius, Ripple.MAX_RADIUS);
4205 },
4206 get isAnimationComplete() {
4207 return this.mouseUpStart ? this.isOpacityFullyDecayed : this.isRestingAtMa xRadius;
4208 },
4209 get translationFraction() {
4210 return Math.min(1, this.radius / this.containerMetrics.size * 2 / Math.sqr t(2));
4211 },
4212 get xNow() {
4213 if (this.xEnd) {
4214 return this.xStart + this.translationFraction * (this.xEnd - this.xStart );
4215 }
4216 return this.xStart;
4217 },
4218 get yNow() {
4219 if (this.yEnd) {
4220 return this.yStart + this.translationFraction * (this.yEnd - this.yStart );
4221 }
4222 return this.yStart;
4223 },
4224 get isMouseDown() {
4225 return this.mouseDownStart && !this.mouseUpStart;
4226 },
4227 resetInteractionState: function() {
4228 this.maxRadius = 0;
4229 this.mouseDownStart = 0;
4230 this.mouseUpStart = 0;
4231 this.xStart = 0;
4232 this.yStart = 0;
4233 this.xEnd = 0;
4234 this.yEnd = 0;
4235 this.slideDistance = 0;
4236 this.containerMetrics = new ElementMetrics(this.element);
4237 },
4238 draw: function() {
4239 var scale;
4240 var translateString;
4241 var dx;
4242 var dy;
4243 this.wave.style.opacity = this.opacity;
4244 scale = this.radius / (this.containerMetrics.size / 2);
4245 dx = this.xNow - this.containerMetrics.width / 2;
4246 dy = this.yNow - this.containerMetrics.height / 2;
4247 this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' + dy + 'px)';
4248 this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy + ' px, 0)';
4249 this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')';
4250 this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)';
4251 },
4252 downAction: function(event) {
4253 var xCenter = this.containerMetrics.width / 2;
4254 var yCenter = this.containerMetrics.height / 2;
4255 this.resetInteractionState();
4256 this.mouseDownStart = Utility.now();
4257 if (this.center) {
4258 this.xStart = xCenter;
4259 this.yStart = yCenter;
4260 this.slideDistance = Utility.distance(this.xStart, this.yStart, this.xEn d, this.yEnd);
4261 } else {
4262 this.xStart = event ? event.detail.x - this.containerMetrics.boundingRec t.left : this.containerMetrics.width / 2;
4263 this.yStart = event ? event.detail.y - this.containerMetrics.boundingRec t.top : this.containerMetrics.height / 2;
4264 }
4265 if (this.recenters) {
4266 this.xEnd = xCenter;
4267 this.yEnd = yCenter;
4268 this.slideDistance = Utility.distance(this.xStart, this.yStart, this.xEn d, this.yEnd);
4269 }
4270 this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom(this.xSt art, this.yStart);
4271 this.waveContainer.style.top = (this.containerMetrics.height - this.contai nerMetrics.size) / 2 + 'px';
4272 this.waveContainer.style.left = (this.containerMetrics.width - this.contai nerMetrics.size) / 2 + 'px';
4273 this.waveContainer.style.width = this.containerMetrics.size + 'px';
4274 this.waveContainer.style.height = this.containerMetrics.size + 'px';
4275 },
4276 upAction: function(event) {
4277 if (!this.isMouseDown) {
4278 return;
4279 }
4280 this.mouseUpStart = Utility.now();
4281 },
4282 remove: function() {
4283 Polymer.dom(this.waveContainer.parentNode).removeChild(this.waveContainer) ;
4284 }
4285 };
4286 Polymer({
4287 is: 'paper-ripple',
4288 behaviors: [ Polymer.IronA11yKeysBehavior ],
4289 properties: {
4290 initialOpacity: {
4291 type: Number,
4292 value: .25
4293 },
4294 opacityDecayVelocity: {
4295 type: Number,
4296 value: .8
4297 },
4298 recenters: {
4299 type: Boolean,
4300 value: false
4301 },
4302 center: {
4303 type: Boolean,
4304 value: false
4305 },
4306 ripples: {
4307 type: Array,
4308 value: function() {
4309 return [];
4310 }
4311 },
4312 animating: {
4313 type: Boolean,
4314 readOnly: true,
4315 reflectToAttribute: true,
4316 value: false
4317 },
4318 holdDown: {
4319 type: Boolean,
4320 value: false,
4321 observer: '_holdDownChanged'
4322 },
4323 noink: {
4324 type: Boolean,
4325 value: false
4326 },
4327 _animating: {
4328 type: Boolean
4329 },
4330 _boundAnimate: {
4331 type: Function,
4332 value: function() {
4333 return this.animate.bind(this);
4334 }
4335 }
4336 },
4337 get target() {
4338 return this.keyEventTarget;
4339 },
4340 keyBindings: {
4341 'enter:keydown': '_onEnterKeydown',
4342 'space:keydown': '_onSpaceKeydown',
4343 'space:keyup': '_onSpaceKeyup'
4344 },
4345 attached: function() {
4346 if (this.parentNode.nodeType == 11) {
4347 this.keyEventTarget = Polymer.dom(this).getOwnerRoot().host;
4348 } else {
4349 this.keyEventTarget = this.parentNode;
4350 }
4351 var keyEventTarget = this.keyEventTarget;
4352 this.listen(keyEventTarget, 'up', 'uiUpAction');
4353 this.listen(keyEventTarget, 'down', 'uiDownAction');
4354 },
4355 detached: function() {
4356 this.unlisten(this.keyEventTarget, 'up', 'uiUpAction');
4357 this.unlisten(this.keyEventTarget, 'down', 'uiDownAction');
4358 this.keyEventTarget = null;
4359 },
4360 get shouldKeepAnimating() {
4361 for (var index = 0; index < this.ripples.length; ++index) {
4362 if (!this.ripples[index].isAnimationComplete) {
4363 return true;
4364 }
4365 }
4366 return false;
4367 },
4368 simulatedRipple: function() {
4369 this.downAction(null);
4370 this.async(function() {
4371 this.upAction();
4372 }, 1);
4373 },
4374 uiDownAction: function(event) {
4375 if (!this.noink) {
4376 this.downAction(event);
4377 }
4378 },
4379 downAction: function(event) {
4380 if (this.holdDown && this.ripples.length > 0) {
4381 return;
4382 }
4383 var ripple = this.addRipple();
4384 ripple.downAction(event);
4385 if (!this._animating) {
4386 this._animating = true;
4387 this.animate();
4388 }
4389 },
4390 uiUpAction: function(event) {
4391 if (!this.noink) {
4392 this.upAction(event);
4393 }
4394 },
4395 upAction: function(event) {
4396 if (this.holdDown) {
4397 return;
4398 }
4399 this.ripples.forEach(function(ripple) {
4400 ripple.upAction(event);
4401 });
4402 this._animating = true;
4403 this.animate();
4404 },
4405 onAnimationComplete: function() {
4406 this._animating = false;
4407 this.$.background.style.backgroundColor = null;
4408 this.fire('transitionend');
4409 },
4410 addRipple: function() {
4411 var ripple = new Ripple(this);
4412 Polymer.dom(this.$.waves).appendChild(ripple.waveContainer);
4413 this.$.background.style.backgroundColor = ripple.color;
4414 this.ripples.push(ripple);
4415 this._setAnimating(true);
4416 return ripple;
4417 },
4418 removeRipple: function(ripple) {
4419 var rippleIndex = this.ripples.indexOf(ripple);
4420 if (rippleIndex < 0) {
4421 return;
4422 }
4423 this.ripples.splice(rippleIndex, 1);
4424 ripple.remove();
4425 if (!this.ripples.length) {
4426 this._setAnimating(false);
4427 }
4428 },
4429 animate: function() {
4430 if (!this._animating) {
4431 return;
4432 }
4433 var index;
4434 var ripple;
4435 for (index = 0; index < this.ripples.length; ++index) {
4436 ripple = this.ripples[index];
4437 ripple.draw();
4438 this.$.background.style.opacity = ripple.outerOpacity;
4439 if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) {
4440 this.removeRipple(ripple);
4441 }
4442 }
4443 if (!this.shouldKeepAnimating && this.ripples.length === 0) {
4444 this.onAnimationComplete();
4445 } else {
4446 window.requestAnimationFrame(this._boundAnimate);
4447 }
4448 },
4449 _onEnterKeydown: function() {
4450 this.uiDownAction();
4451 this.async(this.uiUpAction, 1);
4452 },
4453 _onSpaceKeydown: function() {
4454 this.uiDownAction();
4455 },
4456 _onSpaceKeyup: function() {
4457 this.uiUpAction();
4458 },
4459 _holdDownChanged: function(newVal, oldVal) {
4460 if (oldVal === undefined) {
4461 return;
4462 }
4463 if (newVal) {
4464 this.downAction();
4465 } else {
4466 this.upAction();
4467 }
4468 }
4469 });
4470 })();
4471
4472 Polymer.PaperRippleBehavior = {
4473 properties: {
4474 noink: {
4475 type: Boolean,
4476 observer: '_noinkChanged'
4477 },
4478 _rippleContainer: {
4479 type: Object
4480 }
4481 },
4482 _buttonStateChanged: function() {
4483 if (this.focused) {
4484 this.ensureRipple();
4485 }
4486 },
4487 _downHandler: function(event) {
4488 Polymer.IronButtonStateImpl._downHandler.call(this, event);
4489 if (this.pressed) {
4490 this.ensureRipple(event);
4491 }
4492 },
4493 ensureRipple: function(optTriggeringEvent) {
4494 if (!this.hasRipple()) {
4495 this._ripple = this._createRipple();
4496 this._ripple.noink = this.noink;
4497 var rippleContainer = this._rippleContainer || this.root;
4498 if (rippleContainer) {
4499 Polymer.dom(rippleContainer).appendChild(this._ripple);
4500 }
4501 if (optTriggeringEvent) {
4502 var domContainer = Polymer.dom(this._rippleContainer || this);
4503 var target = Polymer.dom(optTriggeringEvent).rootTarget;
4504 if (domContainer.deepContains(target)) {
4505 this._ripple.uiDownAction(optTriggeringEvent);
4506 }
4507 }
4508 }
4509 },
4510 getRipple: function() {
4511 this.ensureRipple();
4512 return this._ripple;
4513 },
4514 hasRipple: function() {
4515 return Boolean(this._ripple);
4516 },
4517 _createRipple: function() {
4518 return document.createElement('paper-ripple');
4519 },
4520 _noinkChanged: function(noink) {
4521 if (this.hasRipple()) {
4522 this._ripple.noink = noink;
4523 }
4524 }
4525 };
4526
4527 Polymer.PaperButtonBehaviorImpl = {
4528 properties: {
4529 elevation: {
4530 type: Number,
4531 reflectToAttribute: true,
4532 readOnly: true
4533 }
4534 },
4535 observers: [ '_calculateElevation(focused, disabled, active, pressed, received FocusFromKeyboard)', '_computeKeyboardClass(receivedFocusFromKeyboard)' ],
4536 hostAttributes: {
4537 role: 'button',
4538 tabindex: '0',
4539 animated: true
4540 },
4541 _calculateElevation: function() {
4542 var e = 1;
4543 if (this.disabled) {
4544 e = 0;
4545 } else if (this.active || this.pressed) {
4546 e = 4;
4547 } else if (this.receivedFocusFromKeyboard) {
4548 e = 3;
4549 }
4550 this._setElevation(e);
4551 },
4552 _computeKeyboardClass: function(receivedFocusFromKeyboard) {
4553 this.toggleClass('keyboard-focus', receivedFocusFromKeyboard);
4554 },
4555 _spaceKeyDownHandler: function(event) {
4556 Polymer.IronButtonStateImpl._spaceKeyDownHandler.call(this, event);
4557 if (this.hasRipple() && this.getRipple().ripples.length < 1) {
4558 this._ripple.uiDownAction();
4559 }
4560 },
4561 _spaceKeyUpHandler: function(event) {
4562 Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this, event);
4563 if (this.hasRipple()) {
4564 this._ripple.uiUpAction();
4565 }
4566 }
4567 };
4568
4569 Polymer.PaperButtonBehavior = [ Polymer.IronButtonState, Polymer.IronControlStat e, Polymer.PaperRippleBehavior, Polymer.PaperButtonBehaviorImpl ];
4570
4571 Polymer({
4572 is: 'paper-button',
4573 behaviors: [ Polymer.PaperButtonBehavior ],
4574 properties: {
4575 raised: {
4576 type: Boolean,
4577 reflectToAttribute: true,
4578 value: false,
4579 observer: '_calculateElevation'
4580 }
4581 },
4582 _calculateElevation: function() {
4583 if (!this.raised) {
4584 this._setElevation(0);
4585 } else {
4586 Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this);
4587 }
4588 }
4589 });
4590
4591 Polymer({
4592 is: 'paper-icon-button-light',
4593 "extends": 'button',
4594 behaviors: [ Polymer.PaperRippleBehavior ],
4595 listeners: {
4596 down: '_rippleDown',
4597 up: '_rippleUp',
4598 focus: '_rippleDown',
4599 blur: '_rippleUp'
4600 },
4601 _rippleDown: function() {
4602 this.getRipple().downAction();
4603 },
4604 _rippleUp: function() {
4605 this.getRipple().upAction();
4606 },
4607 ensureRipple: function(var_args) {
4608 var lastRipple = this._ripple;
4609 Polymer.PaperRippleBehavior.ensureRipple.apply(this, arguments);
4610 if (this._ripple && this._ripple !== lastRipple) {
4611 this._ripple.center = true;
4612 this._ripple.classList.add('circle');
4613 }
4614 }
4615 });
4616
4617 Polymer.PaperInkyFocusBehaviorImpl = {
4618 observers: [ '_focusedChanged(receivedFocusFromKeyboard)' ],
4619 _focusedChanged: function(receivedFocusFromKeyboard) {
4620 if (receivedFocusFromKeyboard) {
4621 this.ensureRipple();
4622 }
4623 if (this.hasRipple()) {
4624 this._ripple.holdDown = receivedFocusFromKeyboard;
4625 }
4626 },
4627 _createRipple: function() {
4628 var ripple = Polymer.PaperRippleBehavior._createRipple();
4629 ripple.id = 'ink';
4630 ripple.setAttribute('center', '');
4631 ripple.classList.add('circle');
4632 return ripple;
4633 }
4634 };
4635
4636 Polymer.PaperInkyFocusBehavior = [ Polymer.IronButtonState, Polymer.IronControlS tate, Polymer.PaperRippleBehavior, Polymer.PaperInkyFocusBehaviorImpl ];
4637
4638 Polymer({
4639 is: 'paper-icon-button',
4640 hostAttributes: {
4641 role: 'button',
4642 tabindex: '0'
4643 },
4644 behaviors: [ Polymer.PaperInkyFocusBehavior ],
4645 properties: {
4646 src: {
4647 type: String
4648 },
4649 icon: {
4650 type: String
4651 },
4652 alt: {
4653 type: String,
4654 observer: "_altChanged"
4655 }
4656 },
4657 _altChanged: function(newValue, oldValue) {
4658 var label = this.getAttribute('aria-label');
4659 if (!label || oldValue == label) {
4660 this.setAttribute('aria-label', newValue);
4661 }
4662 }
4663 });
4664
4665 Polymer({
4666 is: 'paper-tab',
4667 behaviors: [ Polymer.IronControlState, Polymer.IronButtonState, Polymer.PaperR ippleBehavior ],
4668 properties: {
4669 link: {
4670 type: Boolean,
4671 value: false,
4672 reflectToAttribute: true
4673 }
4674 },
4675 hostAttributes: {
4676 role: 'tab'
4677 },
4678 listeners: {
4679 down: '_updateNoink',
4680 tap: '_onTap'
4681 },
4682 attached: function() {
4683 this._updateNoink();
4684 },
4685 get _parentNoink() {
4686 var parent = Polymer.dom(this).parentNode;
4687 return !!parent && !!parent.noink;
4688 },
4689 _updateNoink: function() {
4690 this.noink = !!this.noink || !!this._parentNoink;
4691 },
4692 _onTap: function(event) {
4693 if (this.link) {
4694 var anchor = this.queryEffectiveChildren('a');
4695 if (!anchor) {
4696 return;
4697 }
4698 if (event.target === anchor) {
4699 return;
4700 }
4701 anchor.click();
4702 }
4703 }
4704 });
4705
4706 Polymer.IronMultiSelectableBehaviorImpl = {
4707 properties: {
4708 multi: {
4709 type: Boolean,
4710 value: false,
4711 observer: 'multiChanged'
4712 },
4713 selectedValues: {
4714 type: Array,
4715 notify: true
4716 },
4717 selectedItems: {
4718 type: Array,
4719 readOnly: true,
4720 notify: true
4721 }
4722 },
4723 observers: [ '_updateSelected(selectedValues.splices)' ],
4724 select: function(value) {
4725 if (this.multi) {
4726 if (this.selectedValues) {
4727 this._toggleSelected(value);
4728 } else {
4729 this.selectedValues = [ value ];
4730 }
4731 } else {
4732 this.selected = value;
4733 }
4734 },
4735 multiChanged: function(multi) {
4736 this._selection.multi = multi;
4737 },
4738 get _shouldUpdateSelection() {
4739 return this.selected != null || this.selectedValues != null && this.selected Values.length;
4740 },
4741 _updateAttrForSelected: function() {
4742 if (!this.multi) {
4743 Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this);
4744 } else if (this._shouldUpdateSelection) {
4745 this.selectedValues = this.selectedItems.map(function(selectedItem) {
4746 return this._indexToValue(this.indexOf(selectedItem));
4747 }, this).filter(function(unfilteredValue) {
4748 return unfilteredValue != null;
4749 }, this);
4750 }
4751 },
4752 _updateSelected: function() {
4753 if (this.multi) {
4754 this._selectMulti(this.selectedValues);
4755 } else {
4756 this._selectSelected(this.selected);
4757 }
4758 },
4759 _selectMulti: function(values) {
4760 if (values) {
4761 var selectedItems = this._valuesToItems(values);
4762 this._selection.clear(selectedItems);
4763 for (var i = 0; i < selectedItems.length; i++) {
4764 this._selection.setItemSelected(selectedItems[i], true);
4765 }
4766 if (this.fallbackSelection && this.items.length && !this._selection.get(). length) {
4767 var fallback = this._valueToItem(this.fallbackSelection);
4768 if (fallback) {
4769 this.selectedValues = [ this.fallbackSelection ];
4770 }
4771 }
4772 } else {
4773 this._selection.clear();
4774 }
4775 },
4776 _selectionChange: function() {
4777 var s = this._selection.get();
4778 if (this.multi) {
4779 this._setSelectedItems(s);
4780 } else {
4781 this._setSelectedItems([ s ]);
4782 this._setSelectedItem(s);
4783 }
4784 },
4785 _toggleSelected: function(value) {
4786 var i = this.selectedValues.indexOf(value);
4787 var unselected = i < 0;
4788 if (unselected) {
4789 this.push('selectedValues', value);
4790 } else {
4791 this.splice('selectedValues', i, 1);
4792 }
4793 },
4794 _valuesToItems: function(values) {
4795 return values == null ? null : values.map(function(value) {
4796 return this._valueToItem(value);
4797 }, this);
4798 }
4799 };
4800
4801 Polymer.IronMultiSelectableBehavior = [ Polymer.IronSelectableBehavior, Polymer. IronMultiSelectableBehaviorImpl ];
4802
4803 Polymer.IronMenuBehaviorImpl = {
4804 properties: {
4805 focusedItem: {
4806 observer: '_focusedItemChanged',
4807 readOnly: true,
4808 type: Object
4809 },
4810 attrForItemTitle: {
4811 type: String
4812 }
4813 },
4814 hostAttributes: {
4815 role: 'menu',
4816 tabindex: '0'
4817 },
4818 observers: [ '_updateMultiselectable(multi)' ],
4819 listeners: {
4820 focus: '_onFocus',
4821 keydown: '_onKeydown',
4822 'iron-items-changed': '_onIronItemsChanged'
4823 },
4824 keyBindings: {
4825 up: '_onUpKey',
4826 down: '_onDownKey',
4827 esc: '_onEscKey',
4828 'shift+tab:keydown': '_onShiftTabDown'
4829 },
4830 attached: function() {
4831 this._resetTabindices();
4832 },
4833 select: function(value) {
4834 if (this._defaultFocusAsync) {
4835 this.cancelAsync(this._defaultFocusAsync);
4836 this._defaultFocusAsync = null;
4837 }
4838 var item = this._valueToItem(value);
4839 if (item && item.hasAttribute('disabled')) return;
4840 this._setFocusedItem(item);
4841 Polymer.IronMultiSelectableBehaviorImpl.select.apply(this, arguments);
4842 },
4843 _resetTabindices: function() {
4844 var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0] : this.selectedItem;
4845 this.items.forEach(function(item) {
4846 item.setAttribute('tabindex', item === selectedItem ? '0' : '-1');
4847 }, this);
4848 },
4849 _updateMultiselectable: function(multi) {
4850 if (multi) {
4851 this.setAttribute('aria-multiselectable', 'true');
4852 } else {
4853 this.removeAttribute('aria-multiselectable');
4854 }
4855 },
4856 _focusWithKeyboardEvent: function(event) {
4857 for (var i = 0, item; item = this.items[i]; i++) {
4858 var attr = this.attrForItemTitle || 'textContent';
4859 var title = item[attr] || item.getAttribute(attr);
4860 if (!item.hasAttribute('disabled') && title && title.trim().charAt(0).toLo werCase() === String.fromCharCode(event.keyCode).toLowerCase()) {
4861 this._setFocusedItem(item);
4862 break;
4863 }
4864 }
4865 },
4866 _focusPrevious: function() {
4867 var length = this.items.length;
4868 var curFocusIndex = Number(this.indexOf(this.focusedItem));
4869 for (var i = 1; i < length + 1; i++) {
4870 var item = this.items[(curFocusIndex - i + length) % length];
4871 if (!item.hasAttribute('disabled')) {
4872 this._setFocusedItem(item);
4873 return;
4874 }
4875 }
4876 },
4877 _focusNext: function() {
4878 var length = this.items.length;
4879 var curFocusIndex = Number(this.indexOf(this.focusedItem));
4880 for (var i = 1; i < length + 1; i++) {
4881 var item = this.items[(curFocusIndex + i) % length];
4882 if (!item.hasAttribute('disabled')) {
4883 this._setFocusedItem(item);
4884 return;
4885 }
4886 }
4887 },
4888 _applySelection: function(item, isSelected) {
4889 if (isSelected) {
4890 item.setAttribute('aria-selected', 'true');
4891 } else {
4892 item.removeAttribute('aria-selected');
4893 }
4894 Polymer.IronSelectableBehavior._applySelection.apply(this, arguments);
4895 },
4896 _focusedItemChanged: function(focusedItem, old) {
4897 old && old.setAttribute('tabindex', '-1');
4898 if (focusedItem) {
4899 focusedItem.setAttribute('tabindex', '0');
4900 focusedItem.focus();
4901 }
4902 },
4903 _onIronItemsChanged: function(event) {
4904 if (event.detail.addedNodes.length) {
4905 this._resetTabindices();
4906 }
4907 },
4908 _onShiftTabDown: function(event) {
4909 var oldTabIndex = this.getAttribute('tabindex');
4910 Polymer.IronMenuBehaviorImpl._shiftTabPressed = true;
4911 this._setFocusedItem(null);
4912 this.setAttribute('tabindex', '-1');
4913 this.async(function() {
4914 this.setAttribute('tabindex', oldTabIndex);
4915 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
4916 }, 1);
4917 },
4918 _onFocus: function(event) {
4919 if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) {
4920 return;
4921 }
4922 var rootTarget = Polymer.dom(event).rootTarget;
4923 if (rootTarget !== this && typeof rootTarget.tabIndex !== "undefined" && !th is.isLightDescendant(rootTarget)) {
4924 return;
4925 }
4926 this._defaultFocusAsync = this.async(function() {
4927 var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0 ] : this.selectedItem;
4928 this._setFocusedItem(null);
4929 if (selectedItem) {
4930 this._setFocusedItem(selectedItem);
4931 } else if (this.items[0]) {
4932 this._focusNext();
4933 }
4934 });
4935 },
4936 _onUpKey: function(event) {
4937 this._focusPrevious();
4938 event.detail.keyboardEvent.preventDefault();
4939 },
4940 _onDownKey: function(event) {
4941 this._focusNext();
4942 event.detail.keyboardEvent.preventDefault();
4943 },
4944 _onEscKey: function(event) {
4945 this.focusedItem.blur();
4946 },
4947 _onKeydown: function(event) {
4948 if (!this.keyboardEventMatchesKeys(event, 'up down esc')) {
4949 this._focusWithKeyboardEvent(event);
4950 }
4951 event.stopPropagation();
4952 },
4953 _activateHandler: function(event) {
4954 Polymer.IronSelectableBehavior._activateHandler.call(this, event);
4955 event.stopPropagation();
4956 }
4957 };
4958
4959 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
4960
4961 Polymer.IronMenuBehavior = [ Polymer.IronMultiSelectableBehavior, Polymer.IronA1 1yKeysBehavior, Polymer.IronMenuBehaviorImpl ];
4962
4963 Polymer.IronMenubarBehaviorImpl = {
4964 hostAttributes: {
4965 role: 'menubar'
4966 },
4967 keyBindings: {
4968 left: '_onLeftKey',
4969 right: '_onRightKey'
4970 },
4971 _onUpKey: function(event) {
4972 this.focusedItem.click();
4973 event.detail.keyboardEvent.preventDefault();
4974 },
4975 _onDownKey: function(event) {
4976 this.focusedItem.click();
4977 event.detail.keyboardEvent.preventDefault();
4978 },
4979 get _isRTL() {
4980 return window.getComputedStyle(this)['direction'] === 'rtl';
4981 },
4982 _onLeftKey: function(event) {
4983 if (this._isRTL) {
4984 this._focusNext();
4985 } else {
4986 this._focusPrevious();
4987 }
4988 event.detail.keyboardEvent.preventDefault();
4989 },
4990 _onRightKey: function(event) {
4991 if (this._isRTL) {
4992 this._focusPrevious();
4993 } else {
4994 this._focusNext();
4995 }
4996 event.detail.keyboardEvent.preventDefault();
4997 },
4998 _onKeydown: function(event) {
4999 if (this.keyboardEventMatchesKeys(event, 'up down left right esc')) {
5000 return;
5001 }
5002 this._focusWithKeyboardEvent(event);
5003 }
5004 };
5005
5006 Polymer.IronMenubarBehavior = [ Polymer.IronMenuBehavior, Polymer.IronMenubarBeh aviorImpl ];
5007
5008 Polymer({
5009 is: 'iron-iconset-svg',
5010 properties: {
5011 name: {
5012 type: String,
5013 observer: '_nameChanged'
5014 },
5015 size: {
5016 type: Number,
5017 value: 24
5018 }
5019 },
5020 attached: function() {
5021 this.style.display = 'none';
5022 },
5023 getIconNames: function() {
5024 this._icons = this._createIconMap();
5025 return Object.keys(this._icons).map(function(n) {
5026 return this.name + ':' + n;
5027 }, this);
5028 },
5029 applyIcon: function(element, iconName) {
5030 element = element.root || element;
5031 this.removeIcon(element);
5032 var svg = this._cloneIcon(iconName);
5033 if (svg) {
5034 var pde = Polymer.dom(element);
5035 pde.insertBefore(svg, pde.childNodes[0]);
5036 return element._svgIcon = svg;
5037 }
5038 return null;
5039 },
5040 removeIcon: function(element) {
5041 if (element._svgIcon) {
5042 Polymer.dom(element).removeChild(element._svgIcon);
5043 element._svgIcon = null;
5044 }
5045 },
5046 _nameChanged: function() {
5047 new Polymer.IronMeta({
5048 type: 'iconset',
5049 key: this.name,
5050 value: this
5051 });
5052 this.async(function() {
5053 this.fire('iron-iconset-added', this, {
5054 node: window
5055 });
5056 });
5057 },
5058 _createIconMap: function() {
5059 var icons = Object.create(null);
5060 Polymer.dom(this).querySelectorAll('[id]').forEach(function(icon) {
5061 icons[icon.id] = icon;
5062 });
5063 return icons;
5064 },
5065 _cloneIcon: function(id) {
5066 this._icons = this._icons || this._createIconMap();
5067 return this._prepareSvgClone(this._icons[id], this.size);
5068 },
5069 _prepareSvgClone: function(sourceSvg, size) {
5070 if (sourceSvg) {
5071 var content = sourceSvg.cloneNode(true), svg = document.createElementNS('h ttp://www.w3.org/2000/svg', 'svg'), viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size;
5072 svg.setAttribute('viewBox', viewBox);
5073 svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
5074 svg.style.cssText = 'pointer-events: none; display: block; width: 100%; he ight: 100%;';
5075 svg.appendChild(content).removeAttribute('id');
5076 return svg;
5077 }
5078 return null;
5079 }
5080 });
5081
5082 Polymer({
5083 is: 'paper-tabs',
5084 behaviors: [ Polymer.IronResizableBehavior, Polymer.IronMenubarBehavior ],
5085 properties: {
5086 noink: {
5087 type: Boolean,
5088 value: false,
5089 observer: '_noinkChanged'
5090 },
5091 noBar: {
5092 type: Boolean,
5093 value: false
5094 },
5095 noSlide: {
5096 type: Boolean,
5097 value: false
5098 },
5099 scrollable: {
5100 type: Boolean,
5101 value: false
5102 },
5103 fitContainer: {
5104 type: Boolean,
5105 value: false
5106 },
5107 disableDrag: {
5108 type: Boolean,
5109 value: false
5110 },
5111 hideScrollButtons: {
5112 type: Boolean,
5113 value: false
5114 },
5115 alignBottom: {
5116 type: Boolean,
5117 value: false
5118 },
5119 selectable: {
5120 type: String,
5121 value: 'paper-tab'
5122 },
5123 autoselect: {
5124 type: Boolean,
5125 value: false
5126 },
5127 autoselectDelay: {
5128 type: Number,
5129 value: 0
5130 },
5131 _step: {
5132 type: Number,
5133 value: 10
5134 },
5135 _holdDelay: {
5136 type: Number,
5137 value: 1
5138 },
5139 _leftHidden: {
5140 type: Boolean,
5141 value: false
5142 },
5143 _rightHidden: {
5144 type: Boolean,
5145 value: false
5146 },
5147 _previousTab: {
5148 type: Object
5149 }
5150 },
5151 hostAttributes: {
5152 role: 'tablist'
5153 },
5154 listeners: {
5155 'iron-resize': '_onTabSizingChanged',
5156 'iron-items-changed': '_onTabSizingChanged',
5157 'iron-select': '_onIronSelect',
5158 'iron-deselect': '_onIronDeselect'
5159 },
5160 keyBindings: {
5161 'left:keyup right:keyup': '_onArrowKeyup'
5162 },
5163 created: function() {
5164 this._holdJob = null;
5165 this._pendingActivationItem = undefined;
5166 this._pendingActivationTimeout = undefined;
5167 this._bindDelayedActivationHandler = this._delayedActivationHandler.bind(thi s);
5168 this.addEventListener('blur', this._onBlurCapture.bind(this), true);
5169 },
5170 ready: function() {
5171 this.setScrollDirection('y', this.$.tabsContainer);
5172 },
5173 detached: function() {
5174 this._cancelPendingActivation();
5175 },
5176 _noinkChanged: function(noink) {
5177 var childTabs = Polymer.dom(this).querySelectorAll('paper-tab');
5178 childTabs.forEach(noink ? this._setNoinkAttribute : this._removeNoinkAttribu te);
5179 },
5180 _setNoinkAttribute: function(element) {
5181 element.setAttribute('noink', '');
5182 },
5183 _removeNoinkAttribute: function(element) {
5184 element.removeAttribute('noink');
5185 },
5186 _computeScrollButtonClass: function(hideThisButton, scrollable, hideScrollButt ons) {
5187 if (!scrollable || hideScrollButtons) {
5188 return 'hidden';
5189 }
5190 if (hideThisButton) {
5191 return 'not-visible';
5192 }
5193 return '';
5194 },
5195 _computeTabsContentClass: function(scrollable, fitContainer) {
5196 return scrollable ? 'scrollable' + (fitContainer ? ' fit-container' : '') : ' fit-container';
5197 },
5198 _computeSelectionBarClass: function(noBar, alignBottom) {
5199 if (noBar) {
5200 return 'hidden';
5201 } else if (alignBottom) {
5202 return 'align-bottom';
5203 }
5204 return '';
5205 },
5206 _onTabSizingChanged: function() {
5207 this.debounce('_onTabSizingChanged', function() {
5208 this._scroll();
5209 this._tabChanged(this.selectedItem);
5210 }, 10);
5211 },
5212 _onIronSelect: function(event) {
5213 this._tabChanged(event.detail.item, this._previousTab);
5214 this._previousTab = event.detail.item;
5215 this.cancelDebouncer('tab-changed');
5216 },
5217 _onIronDeselect: function(event) {
5218 this.debounce('tab-changed', function() {
5219 this._tabChanged(null, this._previousTab);
5220 this._previousTab = null;
5221 }, 1);
5222 },
5223 _activateHandler: function() {
5224 this._cancelPendingActivation();
5225 Polymer.IronMenuBehaviorImpl._activateHandler.apply(this, arguments);
5226 },
5227 _scheduleActivation: function(item, delay) {
5228 this._pendingActivationItem = item;
5229 this._pendingActivationTimeout = this.async(this._bindDelayedActivationHandl er, delay);
5230 },
5231 _delayedActivationHandler: function() {
5232 var item = this._pendingActivationItem;
5233 this._pendingActivationItem = undefined;
5234 this._pendingActivationTimeout = undefined;
5235 item.fire(this.activateEvent, null, {
5236 bubbles: true,
5237 cancelable: true
5238 });
5239 },
5240 _cancelPendingActivation: function() {
5241 if (this._pendingActivationTimeout !== undefined) {
5242 this.cancelAsync(this._pendingActivationTimeout);
5243 this._pendingActivationItem = undefined;
5244 this._pendingActivationTimeout = undefined;
5245 }
5246 },
5247 _onArrowKeyup: function(event) {
5248 if (this.autoselect) {
5249 this._scheduleActivation(this.focusedItem, this.autoselectDelay);
5250 }
5251 },
5252 _onBlurCapture: function(event) {
5253 if (event.target === this._pendingActivationItem) {
5254 this._cancelPendingActivation();
5255 }
5256 },
5257 get _tabContainerScrollSize() {
5258 return Math.max(0, this.$.tabsContainer.scrollWidth - this.$.tabsContainer.o ffsetWidth);
5259 },
5260 _scroll: function(e, detail) {
5261 if (!this.scrollable) {
5262 return;
5263 }
5264 var ddx = detail && -detail.ddx || 0;
5265 this._affectScroll(ddx);
5266 },
5267 _down: function(e) {
5268 this.async(function() {
5269 if (this._defaultFocusAsync) {
5270 this.cancelAsync(this._defaultFocusAsync);
5271 this._defaultFocusAsync = null;
5272 }
5273 }, 1);
5274 },
5275 _affectScroll: function(dx) {
5276 this.$.tabsContainer.scrollLeft += dx;
5277 var scrollLeft = this.$.tabsContainer.scrollLeft;
5278 this._leftHidden = scrollLeft === 0;
5279 this._rightHidden = scrollLeft === this._tabContainerScrollSize;
5280 },
5281 _onLeftScrollButtonDown: function() {
5282 this._scrollToLeft();
5283 this._holdJob = setInterval(this._scrollToLeft.bind(this), this._holdDelay);
5284 },
5285 _onRightScrollButtonDown: function() {
5286 this._scrollToRight();
5287 this._holdJob = setInterval(this._scrollToRight.bind(this), this._holdDelay) ;
5288 },
5289 _onScrollButtonUp: function() {
5290 clearInterval(this._holdJob);
5291 this._holdJob = null;
5292 },
5293 _scrollToLeft: function() {
5294 this._affectScroll(-this._step);
5295 },
5296 _scrollToRight: function() {
5297 this._affectScroll(this._step);
5298 },
5299 _tabChanged: function(tab, old) {
5300 if (!tab) {
5301 this.$.selectionBar.classList.remove('expand');
5302 this.$.selectionBar.classList.remove('contract');
5303 this._positionBar(0, 0);
5304 return;
5305 }
5306 var r = this.$.tabsContent.getBoundingClientRect();
5307 var w = r.width;
5308 var tabRect = tab.getBoundingClientRect();
5309 var tabOffsetLeft = tabRect.left - r.left;
5310 this._pos = {
5311 width: this._calcPercent(tabRect.width, w),
5312 left: this._calcPercent(tabOffsetLeft, w)
5313 };
5314 if (this.noSlide || old == null) {
5315 this.$.selectionBar.classList.remove('expand');
5316 this.$.selectionBar.classList.remove('contract');
5317 this._positionBar(this._pos.width, this._pos.left);
5318 return;
5319 }
5320 var oldRect = old.getBoundingClientRect();
5321 var oldIndex = this.items.indexOf(old);
5322 var index = this.items.indexOf(tab);
5323 var m = 5;
5324 this.$.selectionBar.classList.add('expand');
5325 var moveRight = oldIndex < index;
5326 var isRTL = this._isRTL;
5327 if (isRTL) {
5328 moveRight = !moveRight;
5329 }
5330 if (moveRight) {
5331 this._positionBar(this._calcPercent(tabRect.left + tabRect.width - oldRect .left, w) - m, this._left);
5332 } else {
5333 this._positionBar(this._calcPercent(oldRect.left + oldRect.width - tabRect .left, w) - m, this._calcPercent(tabOffsetLeft, w) + m);
5334 }
5335 if (this.scrollable) {
5336 this._scrollToSelectedIfNeeded(tabRect.width, tabOffsetLeft);
5337 }
5338 },
5339 _scrollToSelectedIfNeeded: function(tabWidth, tabOffsetLeft) {
5340 var l = tabOffsetLeft - this.$.tabsContainer.scrollLeft;
5341 if (l < 0) {
5342 this.$.tabsContainer.scrollLeft += l;
5343 } else {
5344 l += tabWidth - this.$.tabsContainer.offsetWidth;
5345 if (l > 0) {
5346 this.$.tabsContainer.scrollLeft += l;
5347 }
5348 }
5349 },
5350 _calcPercent: function(w, w0) {
5351 return 100 * w / w0;
5352 },
5353 _positionBar: function(width, left) {
5354 width = width || 0;
5355 left = left || 0;
5356 this._width = width;
5357 this._left = left;
5358 this.transform('translateX(' + left + '%) scaleX(' + width / 100 + ')', this .$.selectionBar);
5359 },
5360 _onBarTransitionEnd: function(e) {
5361 var cl = this.$.selectionBar.classList;
5362 if (cl.contains('expand')) {
5363 cl.remove('expand');
5364 cl.add('contract');
5365 this._positionBar(this._pos.width, this._pos.left);
5366 } else if (cl.contains('contract')) {
5367 cl.remove('contract');
5368 }
5369 }
5370 });
5371
5372 (function() {
5373 'use strict';
5374 Polymer.IronA11yAnnouncer = Polymer({
5375 is: 'iron-a11y-announcer',
5376 properties: {
5377 mode: {
5378 type: String,
5379 value: 'polite'
5380 },
5381 _text: {
5382 type: String,
5383 value: ''
5384 }
5385 },
5386 created: function() {
5387 if (!Polymer.IronA11yAnnouncer.instance) {
5388 Polymer.IronA11yAnnouncer.instance = this;
5389 }
5390 document.body.addEventListener('iron-announce', this._onIronAnnounce.bind( this));
5391 },
5392 announce: function(text) {
5393 this._text = '';
5394 this.async(function() {
5395 this._text = text;
5396 }, 100);
5397 },
5398 _onIronAnnounce: function(event) {
5399 if (event.detail && event.detail.text) {
5400 this.announce(event.detail.text);
5401 }
5402 }
5403 });
5404 Polymer.IronA11yAnnouncer.instance = null;
5405 Polymer.IronA11yAnnouncer.requestAvailability = function() {
5406 if (!Polymer.IronA11yAnnouncer.instance) {
5407 Polymer.IronA11yAnnouncer.instance = document.createElement('iron-a11y-ann ouncer');
5408 }
5409 document.body.appendChild(Polymer.IronA11yAnnouncer.instance);
5410 };
5411 })();
5412
5413 Polymer.IronValidatableBehaviorMeta = null;
5414
5415 Polymer.IronValidatableBehavior = {
5416 properties: {
5417 validator: {
5418 type: String
5419 },
5420 invalid: {
5421 notify: true,
5422 reflectToAttribute: true,
5423 type: Boolean,
5424 value: false
5425 },
5426 _validatorMeta: {
5427 type: Object
5428 },
5429 validatorType: {
5430 type: String,
5431 value: 'validator'
5432 },
5433 _validator: {
5434 type: Object,
5435 computed: '__computeValidator(validator)'
5436 }
5437 },
5438 observers: [ '_invalidChanged(invalid)' ],
5439 registered: function() {
5440 Polymer.IronValidatableBehaviorMeta = new Polymer.IronMeta({
5441 type: 'validator'
5442 });
5443 },
5444 _invalidChanged: function() {
5445 if (this.invalid) {
5446 this.setAttribute('aria-invalid', 'true');
5447 } else {
5448 this.removeAttribute('aria-invalid');
5449 }
5450 },
5451 hasValidator: function() {
5452 return this._validator != null;
5453 },
5454 validate: function(value) {
5455 this.invalid = !this._getValidity(value);
5456 return !this.invalid;
5457 },
5458 _getValidity: function(value) {
5459 if (this.hasValidator()) {
5460 return this._validator.validate(value);
5461 }
5462 return true;
5463 },
5464 __computeValidator: function() {
5465 return Polymer.IronValidatableBehaviorMeta && Polymer.IronValidatableBehavio rMeta.byKey(this.validator);
5466 }
5467 };
5468
5469 Polymer({
5470 is: 'iron-input',
5471 "extends": 'input',
5472 behaviors: [ Polymer.IronValidatableBehavior ],
5473 properties: {
5474 bindValue: {
5475 observer: '_bindValueChanged',
5476 type: String
5477 },
5478 preventInvalidInput: {
5479 type: Boolean
5480 },
5481 allowedPattern: {
5482 type: String,
5483 observer: "_allowedPatternChanged"
5484 },
5485 _previousValidInput: {
5486 type: String,
5487 value: ''
5488 },
5489 _patternAlreadyChecked: {
5490 type: Boolean,
5491 value: false
5492 }
5493 },
5494 listeners: {
5495 input: '_onInput',
5496 keypress: '_onKeypress'
5497 },
5498 registered: function() {
5499 if (!this._canDispatchEventOnDisabled()) {
5500 this._origDispatchEvent = this.dispatchEvent;
5501 this.dispatchEvent = this._dispatchEventFirefoxIE;
5502 }
5503 },
5504 created: function() {
5505 Polymer.IronA11yAnnouncer.requestAvailability();
5506 },
5507 _canDispatchEventOnDisabled: function() {
5508 var input = document.createElement('input');
5509 var canDispatch = false;
5510 input.disabled = true;
5511 input.addEventListener('feature-check-dispatch-event', function() {
5512 canDispatch = true;
5513 });
5514 try {
5515 input.dispatchEvent(new Event('feature-check-dispatch-event'));
5516 } catch (e) {}
5517 return canDispatch;
5518 },
5519 _dispatchEventFirefoxIE: function() {
5520 var disabled = this.disabled;
5521 this.disabled = false;
5522 this._origDispatchEvent.apply(this, arguments);
5523 this.disabled = disabled;
5524 },
5525 get _patternRegExp() {
5526 var pattern;
5527 if (this.allowedPattern) {
5528 pattern = new RegExp(this.allowedPattern);
5529 } else {
5530 switch (this.type) {
5531 case 'number':
5532 pattern = /[0-9.,e-]/;
5533 break;
5534 }
5535 }
5536 return pattern;
5537 },
5538 ready: function() {
5539 this.bindValue = this.value;
5540 },
5541 _bindValueChanged: function() {
5542 if (this.value !== this.bindValue) {
5543 this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue == = false) ? '' : this.bindValue;
5544 }
5545 this.fire('bind-value-changed', {
5546 value: this.bindValue
5547 });
5548 },
5549 _allowedPatternChanged: function() {
5550 this.preventInvalidInput = this.allowedPattern ? true : false;
5551 },
5552 _onInput: function() {
5553 if (this.preventInvalidInput && !this._patternAlreadyChecked) {
5554 var valid = this._checkPatternValidity();
5555 if (!valid) {
5556 this._announceInvalidCharacter('Invalid string of characters not entered .');
5557 this.value = this._previousValidInput;
5558 }
5559 }
5560 this.bindValue = this.value;
5561 this._previousValidInput = this.value;
5562 this._patternAlreadyChecked = false;
5563 },
5564 _isPrintable: function(event) {
5565 var anyNonPrintable = event.keyCode == 8 || event.keyCode == 9 || event.keyC ode == 13 || event.keyCode == 27;
5566 var mozNonPrintable = event.keyCode == 19 || event.keyCode == 20 || event.ke yCode == 45 || event.keyCode == 46 || event.keyCode == 144 || event.keyCode == 1 45 || event.keyCode > 32 && event.keyCode < 41 || event.keyCode > 111 && event.k eyCode < 124;
5567 return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable);
5568 },
5569 _onKeypress: function(event) {
5570 if (!this.preventInvalidInput && this.type !== 'number') {
5571 return;
5572 }
5573 var regexp = this._patternRegExp;
5574 if (!regexp) {
5575 return;
5576 }
5577 if (event.metaKey || event.ctrlKey || event.altKey) return;
5578 this._patternAlreadyChecked = true;
5579 var thisChar = String.fromCharCode(event.charCode);
5580 if (this._isPrintable(event) && !regexp.test(thisChar)) {
5581 event.preventDefault();
5582 this._announceInvalidCharacter('Invalid character ' + thisChar + ' not ent ered.');
5583 }
5584 },
5585 _checkPatternValidity: function() {
5586 var regexp = this._patternRegExp;
5587 if (!regexp) {
5588 return true;
5589 }
5590 for (var i = 0; i < this.value.length; i++) {
5591 if (!regexp.test(this.value[i])) {
5592 return false;
5593 }
5594 }
5595 return true;
5596 },
5597 validate: function() {
5598 var valid = this.checkValidity();
5599 if (valid) {
5600 if (this.required && this.value === '') {
5601 valid = false;
5602 } else if (this.hasValidator()) {
5603 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
5604 }
5605 }
5606 this.invalid = !valid;
5607 this.fire('iron-input-validate');
5608 return valid;
5609 },
5610 _announceInvalidCharacter: function(message) {
5611 this.fire('iron-announce', {
5612 text: message
5613 });
5614 }
5615 });
5616
5617 Polymer({
5618 is: 'paper-input-container',
5619 properties: {
5620 noLabelFloat: {
5621 type: Boolean,
5622 value: false
5623 },
5624 alwaysFloatLabel: {
5625 type: Boolean,
5626 value: false
5627 },
5628 attrForValue: {
5629 type: String,
5630 value: 'bind-value'
5631 },
5632 autoValidate: {
5633 type: Boolean,
5634 value: false
5635 },
5636 invalid: {
5637 observer: '_invalidChanged',
5638 type: Boolean,
5639 value: false
5640 },
5641 focused: {
5642 readOnly: true,
5643 type: Boolean,
5644 value: false,
5645 notify: true
5646 },
5647 _addons: {
5648 type: Array
5649 },
5650 _inputHasContent: {
5651 type: Boolean,
5652 value: false
5653 },
5654 _inputSelector: {
5655 type: String,
5656 value: 'input,textarea,.paper-input-input'
5657 },
5658 _boundOnFocus: {
5659 type: Function,
5660 value: function() {
5661 return this._onFocus.bind(this);
5662 }
5663 },
5664 _boundOnBlur: {
5665 type: Function,
5666 value: function() {
5667 return this._onBlur.bind(this);
5668 }
5669 },
5670 _boundOnInput: {
5671 type: Function,
5672 value: function() {
5673 return this._onInput.bind(this);
5674 }
5675 },
5676 _boundValueChanged: {
5677 type: Function,
5678 value: function() {
5679 return this._onValueChanged.bind(this);
5680 }
5681 }
5682 },
5683 listeners: {
5684 'addon-attached': '_onAddonAttached',
5685 'iron-input-validate': '_onIronInputValidate'
5686 },
5687 get _valueChangedEvent() {
5688 return this.attrForValue + '-changed';
5689 },
5690 get _propertyForValue() {
5691 return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
5692 },
5693 get _inputElement() {
5694 return Polymer.dom(this).querySelector(this._inputSelector);
5695 },
5696 get _inputElementValue() {
5697 return this._inputElement[this._propertyForValue] || this._inputElement.valu e;
5698 },
5699 ready: function() {
5700 if (!this._addons) {
5701 this._addons = [];
5702 }
5703 this.addEventListener('focus', this._boundOnFocus, true);
5704 this.addEventListener('blur', this._boundOnBlur, true);
5705 },
5706 attached: function() {
5707 if (this.attrForValue) {
5708 this._inputElement.addEventListener(this._valueChangedEvent, this._boundVa lueChanged);
5709 } else {
5710 this.addEventListener('input', this._onInput);
5711 }
5712 if (this._inputElementValue != '') {
5713 this._handleValueAndAutoValidate(this._inputElement);
5714 } else {
5715 this._handleValue(this._inputElement);
5716 }
5717 },
5718 _onAddonAttached: function(event) {
5719 if (!this._addons) {
5720 this._addons = [];
5721 }
5722 var target = event.target;
5723 if (this._addons.indexOf(target) === -1) {
5724 this._addons.push(target);
5725 if (this.isAttached) {
5726 this._handleValue(this._inputElement);
5727 }
5728 }
5729 },
5730 _onFocus: function() {
5731 this._setFocused(true);
5732 },
5733 _onBlur: function() {
5734 this._setFocused(false);
5735 this._handleValueAndAutoValidate(this._inputElement);
5736 },
5737 _onInput: function(event) {
5738 this._handleValueAndAutoValidate(event.target);
5739 },
5740 _onValueChanged: function(event) {
5741 this._handleValueAndAutoValidate(event.target);
5742 },
5743 _handleValue: function(inputElement) {
5744 var value = this._inputElementValue;
5745 if (value || value === 0 || inputElement.type === 'number' && !inputElement. checkValidity()) {
5746 this._inputHasContent = true;
5747 } else {
5748 this._inputHasContent = false;
5749 }
5750 this.updateAddons({
5751 inputElement: inputElement,
5752 value: value,
5753 invalid: this.invalid
5754 });
5755 },
5756 _handleValueAndAutoValidate: function(inputElement) {
5757 if (this.autoValidate) {
5758 var valid;
5759 if (inputElement.validate) {
5760 valid = inputElement.validate(this._inputElementValue);
5761 } else {
5762 valid = inputElement.checkValidity();
5763 }
5764 this.invalid = !valid;
5765 }
5766 this._handleValue(inputElement);
5767 },
5768 _onIronInputValidate: function(event) {
5769 this.invalid = this._inputElement.invalid;
5770 },
5771 _invalidChanged: function() {
5772 if (this._addons) {
5773 this.updateAddons({
5774 invalid: this.invalid
5775 });
5776 }
5777 },
5778 updateAddons: function(state) {
5779 for (var addon, index = 0; addon = this._addons[index]; index++) {
5780 addon.update(state);
5781 }
5782 },
5783 _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, i nvalid, _inputHasContent) {
5784 var cls = 'input-content';
5785 if (!noLabelFloat) {
5786 var label = this.querySelector('label');
5787 if (alwaysFloatLabel || _inputHasContent) {
5788 cls += ' label-is-floating';
5789 this.$.labelAndInputContainer.style.position = 'static';
5790 if (invalid) {
5791 cls += ' is-invalid';
5792 } else if (focused) {
5793 cls += " label-is-highlighted";
5794 }
5795 } else {
5796 if (label) {
5797 this.$.labelAndInputContainer.style.position = 'relative';
5798 }
5799 }
5800 } else {
5801 if (_inputHasContent) {
5802 cls += ' label-is-hidden';
5803 }
5804 }
5805 return cls;
5806 },
5807 _computeUnderlineClass: function(focused, invalid) {
5808 var cls = 'underline';
5809 if (invalid) {
5810 cls += ' is-invalid';
5811 } else if (focused) {
5812 cls += ' is-highlighted';
5813 }
5814 return cls;
5815 },
5816 _computeAddOnContentClass: function(focused, invalid) {
5817 var cls = 'add-on-content';
5818 if (invalid) {
5819 cls += ' is-invalid';
5820 } else if (focused) {
5821 cls += ' is-highlighted';
5822 }
5823 return cls;
5824 }
5825 });
5826
5827 Polymer.PaperSpinnerBehavior = {
5828 listeners: {
5829 animationend: '__reset',
5830 webkitAnimationEnd: '__reset'
5831 },
5832 properties: {
5833 active: {
5834 type: Boolean,
5835 value: false,
5836 reflectToAttribute: true,
5837 observer: '__activeChanged'
5838 },
5839 alt: {
5840 type: String,
5841 value: 'loading',
5842 observer: '__altChanged'
5843 },
5844 __coolingDown: {
5845 type: Boolean,
5846 value: false
5847 }
5848 },
5849 __computeContainerClasses: function(active, coolingDown) {
5850 return [ active || coolingDown ? 'active' : '', coolingDown ? 'cooldown' : ' ' ].join(' ');
5851 },
5852 __activeChanged: function(active, old) {
5853 this.__setAriaHidden(!active);
5854 this.__coolingDown = !active && old;
5855 },
5856 __altChanged: function(alt) {
5857 if (alt === this.getPropertyInfo('alt').value) {
5858 this.alt = this.getAttribute('aria-label') || alt;
5859 } else {
5860 this.__setAriaHidden(alt === '');
5861 this.setAttribute('aria-label', alt);
5862 }
5863 },
5864 __setAriaHidden: function(hidden) {
5865 var attr = 'aria-hidden';
5866 if (hidden) {
5867 this.setAttribute(attr, 'true');
5868 } else {
5869 this.removeAttribute(attr);
5870 }
5871 },
5872 __reset: function() {
5873 this.active = false;
5874 this.__coolingDown = false;
5875 }
5876 };
5877
5878 Polymer({
5879 is: 'paper-spinner-lite',
5880 behaviors: [ Polymer.PaperSpinnerBehavior ]
5881 });
5882
5883 // Copyright 2016 The Chromium Authors. All rights reserved.
5884 // Use of this source code is governed by a BSD-style license that can be
5885 // found in the LICENSE file.
5886 var CrSearchFieldBehavior = {
5887 properties: {
5888 label: {
5889 type: String,
5890 value: ''
5891 },
5892 clearLabel: {
5893 type: String,
5894 value: ''
5895 },
5896 showingSearch: {
5897 type: Boolean,
5898 value: false,
5899 notify: true,
5900 observer: 'showingSearchChanged_',
5901 reflectToAttribute: true
5902 },
5903 lastValue_: {
5904 type: String,
5905 value: ''
5906 }
5907 },
5908 getSearchInput: function() {},
5909 getValue: function() {
5910 return this.getSearchInput().value;
5911 },
5912 setValue: function(value) {
5913 this.getSearchInput().bindValue = value;
5914 this.onValueChanged_(value);
5915 },
5916 showAndFocus: function() {
5917 this.showingSearch = true;
5918 this.focus_();
5919 },
5920 focus_: function() {
5921 this.getSearchInput().focus();
5922 },
5923 onSearchTermSearch: function() {
5924 this.onValueChanged_(this.getValue());
5925 },
5926 onValueChanged_: function(newValue) {
5927 if (newValue == this.lastValue_) return;
5928 this.fire('search-changed', newValue);
5929 this.lastValue_ = newValue;
5930 },
5931 onSearchTermKeydown: function(e) {
5932 if (e.key == 'Escape') this.showingSearch = false;
5933 },
5934 showingSearchChanged_: function() {
5935 if (this.showingSearch) {
5936 this.focus_();
5937 return;
5938 }
5939 this.setValue('');
5940 this.getSearchInput().blur();
5941 }
5942 };
5943
5944 // Copyright 2016 The Chromium Authors. All rights reserved.
5945 // Use of this source code is governed by a BSD-style license that can be
5946 // found in the LICENSE file.
5947 Polymer({
5948 is: 'cr-toolbar-search-field',
5949 behaviors: [ CrSearchFieldBehavior ],
5950 properties: {
5951 narrow: {
5952 type: Boolean,
5953 reflectToAttribute: true
5954 },
5955 label: String,
5956 clearLabel: String,
5957 spinnerActive: {
5958 type: Boolean,
5959 reflectToAttribute: true
5960 },
5961 hasSearchText_: Boolean
5962 },
5963 listeners: {
5964 tap: 'showSearch_',
5965 'searchInput.bind-value-changed': 'onBindValueChanged_'
5966 },
5967 getSearchInput: function() {
5968 return this.$.searchInput;
5969 },
5970 isSearchFocused: function() {
5971 return this.$.searchTerm.focused;
5972 },
5973 computeIconTabIndex_: function(narrow) {
5974 return narrow ? 0 : -1;
5975 },
5976 isSpinnerShown_: function(spinnerActive, showingSearch) {
5977 return spinnerActive && showingSearch;
5978 },
5979 onInputBlur_: function() {
5980 if (!this.hasSearchText_) this.showingSearch = false;
5981 },
5982 onBindValueChanged_: function() {
5983 var newValue = this.$.searchInput.bindValue;
5984 this.hasSearchText_ = newValue != '';
5985 if (newValue != '') this.showingSearch = true;
5986 },
5987 showSearch_: function(e) {
5988 if (e.target != this.$.clearSearch) this.showingSearch = true;
5989 },
5990 hideSearch_: function(e) {
5991 this.showingSearch = false;
5992 e.stopPropagation();
5993 }
5994 });
5995
5996 // Copyright 2016 The Chromium Authors. All rights reserved.
5997 // Use of this source code is governed by a BSD-style license that can be
5998 // found in the LICENSE file.
5999 Polymer({
6000 is: 'cr-toolbar',
6001 properties: {
6002 pageName: String,
6003 searchPrompt: String,
6004 clearLabel: String,
6005 menuLabel: String,
6006 spinnerActive: Boolean,
6007 showMenu: {
6008 type: Boolean,
6009 value: false
6010 },
6011 narrow_: {
6012 type: Boolean,
6013 reflectToAttribute: true
6014 },
6015 showingSearch_: {
6016 type: Boolean,
6017 reflectToAttribute: true
6018 }
6019 },
6020 getSearchField: function() {
6021 return this.$.search;
6022 },
6023 onMenuTap_: function(e) {
6024 this.fire('cr-menu-tap');
6025 }
6026 });
6027
6028 // Copyright 2016 The Chromium Authors. All rights reserved.
6029 // Use of this source code is governed by a BSD-style license that can be
6030 // found in the LICENSE file.
6031 Polymer({
6032 is: 'history-lazy-render',
6033 "extends": 'template',
6034 behaviors: [ Polymer.Templatizer ],
6035 _renderPromise: null,
6036 _instance: null,
6037 get: function() {
6038 if (!this._renderPromise) {
6039 this._renderPromise = new Promise(function(resolve) {
6040 this._debounceTemplate(function() {
6041 this._render();
6042 this._renderPromise = null;
6043 resolve(this.getIfExists());
6044 }.bind(this));
6045 }.bind(this));
6046 }
6047 return this._renderPromise;
6048 },
6049 getIfExists: function() {
6050 if (this._instance) {
6051 var children = this._instance._children;
6052 for (var i = 0; i < children.length; i++) {
6053 if (children[i].nodeType == Node.ELEMENT_NODE) return children[i];
6054 }
6055 }
6056 return null;
6057 },
6058 _render: function() {
6059 if (!this.ctor) this.templatize(this);
6060 var parentNode = this.parentNode;
6061 if (parentNode && !this._instance) {
6062 this._instance = this.stamp({});
6063 var root = this._instance.root;
6064 parentNode.insertBefore(root, this);
6065 }
6066 },
6067 _forwardParentProp: function(prop, value) {
6068 if (this._instance) this._instance.__setProperty(prop, value, true);
6069 },
6070 _forwardParentPath: function(path, value) {
6071 if (this._instance) this._instance._notifyPath(path, value, true);
6072 }
6073 });
6074
6075 // Copyright 2015 The Chromium Authors. All rights reserved.
6076 // Use of this source code is governed by a BSD-style license that can be
6077 // found in the LICENSE file.
6078 Polymer({
6079 is: 'history-toolbar',
6080 properties: {
6081 count: {
6082 type: Number,
6083 value: 0,
6084 observer: 'changeToolbarView_'
6085 },
6086 itemsSelected_: {
6087 type: Boolean,
6088 value: false,
6089 reflectToAttribute: true
6090 },
6091 searchTerm: {
6092 type: String,
6093 notify: true
6094 },
6095 spinnerActive: {
6096 type: Boolean,
6097 value: false
6098 },
6099 hasDrawer: {
6100 type: Boolean,
6101 observer: 'hasDrawerChanged_',
6102 reflectToAttribute: true
6103 },
6104 showSyncNotice: Boolean,
6105 isGroupedMode: {
6106 type: Boolean,
6107 reflectToAttribute: true
6108 },
6109 groupedRange: {
6110 type: Number,
6111 value: 0,
6112 reflectToAttribute: true,
6113 notify: true
6114 },
6115 queryStartTime: String,
6116 queryEndTime: String
6117 },
6118 changeToolbarView_: function() {
6119 this.itemsSelected_ = this.count > 0;
6120 },
6121 setSearchTerm: function(search) {
6122 if (this.searchTerm == search) return;
6123 this.searchTerm = search;
6124 var searchField = this.$['main-toolbar'].getSearchField();
6125 searchField.showAndFocus();
6126 searchField.setValue(search);
6127 },
6128 onSearchChanged_: function(event) {
6129 this.searchTerm = event.detail;
6130 },
6131 onInfoButtonTap_: function() {
6132 this.$.syncNotice.get().then(function(dropdown) {
6133 dropdown.positionTarget = this.$$('#info-button-icon');
6134 if (dropdown.style.display == 'none') dropdown.open();
6135 }.bind(this));
6136 },
6137 onClearSelectionTap_: function() {
6138 this.fire('unselect-all');
6139 },
6140 onDeleteTap_: function() {
6141 this.fire('delete-selected');
6142 },
6143 get searchBar() {
6144 return this.$['main-toolbar'].getSearchField();
6145 },
6146 showSearchField: function() {
6147 this.$['main-toolbar'].getSearchField().showAndFocus();
6148 },
6149 deletingAllowed_: function() {
6150 return loadTimeData.getBoolean('allowDeletingHistory');
6151 },
6152 numberOfItemsSelected_: function(count) {
6153 return count > 0 ? loadTimeData.getStringF('itemsSelected', count) : '';
6154 },
6155 getHistoryInterval_: function(queryStartTime, queryEndTime) {
6156 return loadTimeData.getStringF('historyInterval', queryStartTime, queryEndTi me);
6157 },
6158 hasDrawerChanged_: function() {
6159 this.updateStyles();
6160 }
6161 });
6162
6163 // Copyright 2016 The Chromium Authors. All rights reserved.
6164 // Use of this source code is governed by a BSD-style license that can be
6165 // found in the LICENSE file.
6166 Polymer({
6167 is: 'cr-dialog',
6168 "extends": 'dialog',
6169 created: function() {
6170 window.addEventListener('popstate', function() {
6171 if (this.open) this.cancel();
6172 }.bind(this));
6173 },
6174 cancel: function() {
6175 this.fire('cancel');
6176 HTMLDialogElement.prototype.close.call(this, '');
6177 },
6178 close: function(opt_returnValue) {
6179 HTMLDialogElement.prototype.close.call(this, 'success');
6180 },
6181 getCloseButton: function() {
6182 return this.$.close;
6183 }
6184 });
6185
6186 Polymer({
6107 is: 'fade-in-animation', 6187 is: 'fade-in-animation',
6108 behaviors: [ Polymer.NeonAnimationBehavior ], 6188 behaviors: [ Polymer.NeonAnimationBehavior ],
6109 configure: function(config) { 6189 configure: function(config) {
6110 var node = config.node; 6190 var node = config.node;
6111 this._effect = new KeyframeEffect(node, [ { 6191 this._effect = new KeyframeEffect(node, [ {
6112 opacity: '0' 6192 opacity: '0'
6113 }, { 6193 }, {
6114 opacity: '1' 6194 opacity: '1'
6115 } ], this.timingFromConfig(config)); 6195 } ], this.timingFromConfig(config));
6116 return this._effect; 6196 return this._effect;
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
6646 }, 6726 },
6647 _computeCheckmarkClass: function(checked) { 6727 _computeCheckmarkClass: function(checked) {
6648 return checked ? '' : 'hidden'; 6728 return checked ? '' : 'hidden';
6649 }, 6729 },
6650 _createRipple: function() { 6730 _createRipple: function() {
6651 this._rippleContainer = this.$.checkboxContainer; 6731 this._rippleContainer = this.$.checkboxContainer;
6652 return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this); 6732 return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this);
6653 } 6733 }
6654 }); 6734 });
6655 6735
6656 Polymer({
6657 is: 'paper-icon-button-light',
6658 "extends": 'button',
6659 behaviors: [ Polymer.PaperRippleBehavior ],
6660 listeners: {
6661 down: '_rippleDown',
6662 up: '_rippleUp',
6663 focus: '_rippleDown',
6664 blur: '_rippleUp'
6665 },
6666 _rippleDown: function() {
6667 this.getRipple().downAction();
6668 },
6669 _rippleUp: function() {
6670 this.getRipple().upAction();
6671 },
6672 ensureRipple: function(var_args) {
6673 var lastRipple = this._ripple;
6674 Polymer.PaperRippleBehavior.ensureRipple.apply(this, arguments);
6675 if (this._ripple && this._ripple !== lastRipple) {
6676 this._ripple.center = true;
6677 this._ripple.classList.add('circle');
6678 }
6679 }
6680 });
6681
6682 // Copyright 2016 The Chromium Authors. All rights reserved. 6736 // Copyright 2016 The Chromium Authors. All rights reserved.
6683 // Use of this source code is governed by a BSD-style license that can be 6737 // Use of this source code is governed by a BSD-style license that can be
6684 // found in the LICENSE file. 6738 // found in the LICENSE file.
6685 cr.define('cr.icon', function() { 6739 cr.define('cr.icon', function() {
6686 function getSupportedScaleFactors() { 6740 function getSupportedScaleFactors() {
6687 var supportedScaleFactors = []; 6741 var supportedScaleFactors = [];
6742 if (!cr.isIOS) {
6743 supportedScaleFactors.push(1);
6744 }
6688 if (cr.isMac || cr.isChromeOS || cr.isWindows || cr.isLinux) { 6745 if (cr.isMac || cr.isChromeOS || cr.isWindows || cr.isLinux) {
6689 supportedScaleFactors.push(1);
6690 supportedScaleFactors.push(2); 6746 supportedScaleFactors.push(2);
6691 } else { 6747 } else {
6692 supportedScaleFactors.push(window.devicePixelRatio); 6748 supportedScaleFactors.push(window.devicePixelRatio);
6693 } 6749 }
6694 return supportedScaleFactors; 6750 return supportedScaleFactors;
6695 } 6751 }
6696 function getProfileAvatarIcon(path) { 6752 function getImageSet(path) {
6697 var chromeThemePath = 'chrome://theme';
6698 var isDefaultAvatar = path.slice(0, chromeThemePath.length) == chromeThemePa th;
6699 return isDefaultAvatar ? imageset(path + '@scalefactorx') : url(path);
6700 }
6701 function imageset(path) {
6702 var supportedScaleFactors = getSupportedScaleFactors(); 6753 var supportedScaleFactors = getSupportedScaleFactors();
6703 var replaceStartIndex = path.indexOf('scalefactor'); 6754 var replaceStartIndex = path.indexOf('scalefactor');
6704 if (replaceStartIndex < 0) return url(path); 6755 if (replaceStartIndex < 0) return url(path);
6705 var s = ''; 6756 var s = '';
6706 for (var i = 0; i < supportedScaleFactors.length; ++i) { 6757 for (var i = 0; i < supportedScaleFactors.length; ++i) {
6707 var scaleFactor = supportedScaleFactors[i]; 6758 var scaleFactor = supportedScaleFactors[i];
6708 var pathWithScaleFactor = path.substr(0, replaceStartIndex) + scaleFactor + path.substr(replaceStartIndex + 'scalefactor'.length); 6759 var pathWithScaleFactor = path.substr(0, replaceStartIndex) + scaleFactor + path.substr(replaceStartIndex + 'scalefactor'.length);
6709 s += url(pathWithScaleFactor) + ' ' + scaleFactor + 'x'; 6760 s += url(pathWithScaleFactor) + ' ' + scaleFactor + 'x';
6710 if (i != supportedScaleFactors.length - 1) s += ', '; 6761 if (i != supportedScaleFactors.length - 1) s += ', ';
6711 } 6762 }
6712 return '-webkit-image-set(' + s + ')'; 6763 return '-webkit-image-set(' + s + ')';
6713 } 6764 }
6765 function getImage(path) {
6766 var chromeThemePath = 'chrome://theme';
6767 var isChromeThemeUrl = path.slice(0, chromeThemePath.length) == chromeThemeP ath;
6768 return isChromeThemeUrl ? getImageSet(path + '@scalefactorx') : url(path);
6769 }
6714 var FAVICON_URL_REGEX = /\.ico$/i; 6770 var FAVICON_URL_REGEX = /\.ico$/i;
6715 function getFaviconImageSet(url, opt_size, opt_type) { 6771 function getFavicon(url, opt_size, opt_type) {
6716 var size = opt_size || 16; 6772 var size = opt_size || 16;
6717 var type = opt_type || 'favicon'; 6773 var type = opt_type || 'favicon';
6718 return imageset('chrome://' + type + '/size/' + size + '@scalefactorx/' + (F AVICON_URL_REGEX.test(url) ? 'iconurl/' : '') + url); 6774 return getImageSet('chrome://' + type + '/size/' + size + '@scalefactorx/' + (FAVICON_URL_REGEX.test(url) ? 'iconurl/' : '') + url);
6719 } 6775 }
6720 return { 6776 return {
6721 getSupportedScaleFactors: getSupportedScaleFactors, 6777 getImage: getImage,
6722 getProfileAvatarIcon: getProfileAvatarIcon, 6778 getFavicon: getFavicon
6723 getFaviconImageSet: getFaviconImageSet
6724 }; 6779 };
6725 }); 6780 });
6726 6781
6727 // Copyright 2016 The Chromium Authors. All rights reserved. 6782 // Copyright 2016 The Chromium Authors. All rights reserved.
6728 // Use of this source code is governed by a BSD-style license that can be 6783 // Use of this source code is governed by a BSD-style license that can be
6729 // found in the LICENSE file. 6784 // found in the LICENSE file.
6730 Polymer({ 6785 Polymer({
6731 is: 'history-searched-label', 6786 is: 'history-searched-label',
6732 properties: { 6787 properties: {
6733 title: String, 6788 title: String,
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
6837 if (this.index == undefined) return; 6892 if (this.index == undefined) return;
6838 browserService.recordHistogram('HistoryPage.ClickPosition', this.index, UM A_MAX_BUCKET_VALUE); 6893 browserService.recordHistogram('HistoryPage.ClickPosition', this.index, UM A_MAX_BUCKET_VALUE);
6839 if (this.index <= UMA_MAX_SUBSET_BUCKET_VALUE) { 6894 if (this.index <= UMA_MAX_SUBSET_BUCKET_VALUE) {
6840 browserService.recordHistogram('HistoryPage.ClickPositionSubset', this.i ndex, UMA_MAX_SUBSET_BUCKET_VALUE); 6895 browserService.recordHistogram('HistoryPage.ClickPositionSubset', this.i ndex, UMA_MAX_SUBSET_BUCKET_VALUE);
6841 } 6896 }
6842 }, 6897 },
6843 onLinkRightClick_: function() { 6898 onLinkRightClick_: function() {
6844 md_history.BrowserService.getInstance().recordAction('EntryLinkRightClick' ); 6899 md_history.BrowserService.getInstance().recordAction('EntryLinkRightClick' );
6845 }, 6900 },
6846 showIcon_: function() { 6901 showIcon_: function() {
6847 this.$.icon.style.backgroundImage = cr.icon.getFaviconImageSet(this.item.u rl); 6902 this.$.icon.style.backgroundImage = cr.icon.getFavicon(this.item.url);
6848 }, 6903 },
6849 selectionNotAllowed_: function() { 6904 selectionNotAllowed_: function() {
6850 return !loadTimeData.getBoolean('allowDeletingHistory'); 6905 return !loadTimeData.getBoolean('allowDeletingHistory');
6851 }, 6906 },
6852 cardTitle_: function(numberOfItems, historyDate, search) { 6907 cardTitle_: function(numberOfItems, historyDate, search) {
6853 if (!search) return this.item.dateRelativeDay; 6908 if (!search) return this.item.dateRelativeDay;
6854 var resultId = numberOfItems == 1 ? 'searchResult' : 'searchResults'; 6909 var resultId = numberOfItems == 1 ? 'searchResult' : 'searchResults';
6855 return loadTimeData.getStringF('foundSearchResults', numberOfItems, loadTi meData.getString(resultId), search); 6910 return loadTimeData.getStringF('foundSearchResults', numberOfItems, loadTi meData.getString(resultId), search);
6856 }, 6911 },
6857 cropItemTitle_: function(title) { 6912 cropItemTitle_: function(title) {
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
7086 }, 0); 7141 }, 0);
7087 }, 7142 },
7088 needsTimeGap_: function(groupIndex, domainIndex, itemIndex) { 7143 needsTimeGap_: function(groupIndex, domainIndex, itemIndex) {
7089 var visits = this.groupedHistoryData_[groupIndex].domains[domainIndex].visit s; 7144 var visits = this.groupedHistoryData_[groupIndex].domains[domainIndex].visit s;
7090 return md_history.HistoryItem.needsTimeGap(visits, itemIndex, this.searchedT erm); 7145 return md_history.HistoryItem.needsTimeGap(visits, itemIndex, this.searchedT erm);
7091 }, 7146 },
7092 pathForItem_: function(groupIndex, domainIndex, itemIndex) { 7147 pathForItem_: function(groupIndex, domainIndex, itemIndex) {
7093 return [ 'groupedHistoryData_', groupIndex, 'domains', domainIndex, 'visits' , itemIndex ].join('.'); 7148 return [ 'groupedHistoryData_', groupIndex, 'domains', domainIndex, 'visits' , itemIndex ].join('.');
7094 }, 7149 },
7095 getWebsiteIconStyle_: function(domain) { 7150 getWebsiteIconStyle_: function(domain) {
7096 return 'background-image: ' + cr.icon.getFaviconImageSet(domain.visits[0].ur l); 7151 return 'background-image: ' + cr.icon.getFavicon(domain.visits[0].url);
7097 }, 7152 },
7098 getDropdownIcon_: function(expanded) { 7153 getDropdownIcon_: function(expanded) {
7099 return expanded ? 'cr:expand-less' : 'cr:expand-more'; 7154 return expanded ? 'cr:expand-less' : 'cr:expand-more';
7100 } 7155 }
7101 }); 7156 });
7102 7157
7103 (function() { 7158 (function() {
7104 var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/); 7159 var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/);
7105 var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8; 7160 var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8;
7106 var DEFAULT_PHYSICAL_COUNT = 3; 7161 var DEFAULT_PHYSICAL_COUNT = 3;
(...skipping 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after
8116 }, 8171 },
8117 pathForItem_: function(index) { 8172 pathForItem_: function(index) {
8118 return 'historyData_.' + index; 8173 return 'historyData_.' + index;
8119 } 8174 }
8120 }); 8175 });
8121 8176
8122 // Copyright 2016 The Chromium Authors. All rights reserved. 8177 // Copyright 2016 The Chromium Authors. All rights reserved.
8123 // Use of this source code is governed by a BSD-style license that can be 8178 // Use of this source code is governed by a BSD-style license that can be
8124 // found in the LICENSE file. 8179 // found in the LICENSE file.
8125 Polymer({ 8180 Polymer({
8126 is: 'history-lazy-render',
8127 "extends": 'template',
8128 behaviors: [ Polymer.Templatizer ],
8129 _renderPromise: null,
8130 _instance: null,
8131 get: function() {
8132 if (!this._renderPromise) {
8133 this._renderPromise = new Promise(function(resolve) {
8134 this._debounceTemplate(function() {
8135 this._render();
8136 this._renderPromise = null;
8137 resolve(this.getIfExists());
8138 }.bind(this));
8139 }.bind(this));
8140 }
8141 return this._renderPromise;
8142 },
8143 getIfExists: function() {
8144 if (this._instance) {
8145 var children = this._instance._children;
8146 for (var i = 0; i < children.length; i++) {
8147 if (children[i].nodeType == Node.ELEMENT_NODE) return children[i];
8148 }
8149 }
8150 return null;
8151 },
8152 _render: function() {
8153 if (!this.ctor) this.templatize(this);
8154 var parentNode = this.parentNode;
8155 if (parentNode && !this._instance) {
8156 this._instance = this.stamp({});
8157 var root = this._instance.root;
8158 parentNode.insertBefore(root, this);
8159 }
8160 },
8161 _forwardParentProp: function(prop, value) {
8162 if (this._instance) this._instance.__setProperty(prop, value, true);
8163 },
8164 _forwardParentPath: function(path, value) {
8165 if (this._instance) this._instance._notifyPath(path, value, true);
8166 }
8167 });
8168
8169 // Copyright 2016 The Chromium Authors. All rights reserved.
8170 // Use of this source code is governed by a BSD-style license that can be
8171 // found in the LICENSE file.
8172 Polymer({
8173 is: 'history-list-container', 8181 is: 'history-list-container',
8174 properties: { 8182 properties: {
8175 selectedPage_: String, 8183 selectedPage_: String,
8176 grouped: Boolean, 8184 grouped: Boolean,
8177 groupedRange: { 8185 groupedRange: {
8178 type: Number, 8186 type: Number,
8179 observer: 'groupedRangeChanged_' 8187 observer: 'groupedRangeChanged_'
8180 }, 8188 },
8181 queryState: Object, 8189 queryState: Object,
8182 queryResult: Object 8190 queryResult: Object
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
8340 toggleTabCard: function() { 8348 toggleTabCard: function() {
8341 var histogramValue = this.$.collapse.opened ? SyncedTabsHistogram.COLLAPSE_S ESSION : SyncedTabsHistogram.EXPAND_SESSION; 8349 var histogramValue = this.$.collapse.opened ? SyncedTabsHistogram.COLLAPSE_S ESSION : SyncedTabsHistogram.EXPAND_SESSION;
8342 md_history.BrowserService.getInstance().recordHistogram(SYNCED_TABS_HISTOGRA M_NAME, histogramValue, SyncedTabsHistogram.LIMIT); 8350 md_history.BrowserService.getInstance().recordHistogram(SYNCED_TABS_HISTOGRA M_NAME, histogramValue, SyncedTabsHistogram.LIMIT);
8343 this.$.collapse.toggle(); 8351 this.$.collapse.toggle();
8344 this.$['dropdown-indicator'].icon = this.$.collapse.opened ? 'cr:expand-less ' : 'cr:expand-more'; 8352 this.$['dropdown-indicator'].icon = this.$.collapse.opened ? 'cr:expand-less ' : 'cr:expand-more';
8345 }, 8353 },
8346 updateIcons_: function() { 8354 updateIcons_: function() {
8347 this.async(function() { 8355 this.async(function() {
8348 var icons = Polymer.dom(this.root).querySelectorAll('.website-icon'); 8356 var icons = Polymer.dom(this.root).querySelectorAll('.website-icon');
8349 for (var i = 0; i < this.tabs.length; i++) { 8357 for (var i = 0; i < this.tabs.length; i++) {
8350 icons[i].style.backgroundImage = cr.icon.getFaviconImageSet(this.tabs[i] .url); 8358 icons[i].style.backgroundImage = cr.icon.getFavicon(this.tabs[i].url);
8351 } 8359 }
8352 }); 8360 });
8353 }, 8361 },
8354 isWindowSeparatorIndex_: function(index, separatorIndexes) { 8362 isWindowSeparatorIndex_: function(index, separatorIndexes) {
8355 return this.separatorIndexes.indexOf(index) != -1; 8363 return this.separatorIndexes.indexOf(index) != -1;
8356 }, 8364 },
8357 getCollapseIcon_: function(opened) { 8365 getCollapseIcon_: function(opened) {
8358 return opened ? 'cr:expand-less' : 'cr:expand-more'; 8366 return opened ? 'cr:expand-less' : 'cr:expand-more';
8359 }, 8367 },
8360 getCollapseTitle_: function(opened) { 8368 getCollapseTitle_: function(opened) {
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
8585 }); 8593 });
8586 8594
8587 // Copyright 2016 The Chromium Authors. All rights reserved. 8595 // Copyright 2016 The Chromium Authors. All rights reserved.
8588 // Use of this source code is governed by a BSD-style license that can be 8596 // Use of this source code is governed by a BSD-style license that can be
8589 // found in the LICENSE file. 8597 // found in the LICENSE file.
8590 Polymer({ 8598 Polymer({
8591 is: 'history-app', 8599 is: 'history-app',
8592 behaviors: [ Polymer.IronScrollTargetBehavior ], 8600 behaviors: [ Polymer.IronScrollTargetBehavior ],
8593 properties: { 8601 properties: {
8594 showSidebarFooter: Boolean, 8602 showSidebarFooter: Boolean,
8603 hasSyncedResults: Boolean,
8595 selectedPage_: { 8604 selectedPage_: {
8596 type: String, 8605 type: String,
8597 observer: 'unselectAll' 8606 observer: 'unselectAll'
8598 }, 8607 },
8599 grouped_: { 8608 grouped_: {
8600 type: Boolean, 8609 type: Boolean,
8601 reflectToAttribute: true 8610 reflectToAttribute: true
8602 }, 8611 },
8603 queryState_: { 8612 queryState_: {
8604 type: Object, 8613 type: Object,
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
8743 }, 8752 },
8744 updateSignInState: function(isUserSignedIn) { 8753 updateSignInState: function(isUserSignedIn) {
8745 this.isUserSignedIn_ = isUserSignedIn; 8754 this.isUserSignedIn_ = isUserSignedIn;
8746 }, 8755 },
8747 syncedTabsSelected_: function(selectedPage) { 8756 syncedTabsSelected_: function(selectedPage) {
8748 return selectedPage == 'syncedTabs'; 8757 return selectedPage == 'syncedTabs';
8749 }, 8758 },
8750 shouldShowSpinner_: function(querying, incremental, searchTerm) { 8759 shouldShowSpinner_: function(querying, incremental, searchTerm) {
8751 return querying && !incremental && searchTerm != ''; 8760 return querying && !incremental && searchTerm != '';
8752 }, 8761 },
8762 showSyncNotice_: function(hasSyncedResults, selectedPage) {
8763 return hasSyncedResults && selectedPage != 'syncedTabs';
8764 },
8753 routeDataChanged_: function(page) { 8765 routeDataChanged_: function(page) {
8754 this.selectedPage_ = page; 8766 this.selectedPage_ = page;
8755 }, 8767 },
8756 selectedPageChanged_: function(selectedPage) { 8768 selectedPageChanged_: function(selectedPage) {
8757 this.set('routeData_.page', selectedPage); 8769 this.set('routeData_.page', selectedPage);
8758 this.historyViewChanged_(); 8770 this.historyViewChanged_();
8759 }, 8771 },
8760 historyViewChanged_: function() { 8772 historyViewChanged_: function() {
8761 requestAnimationFrame(function() { 8773 requestAnimationFrame(function() {
8762 this.scrollTarget = this.$.content.selectedItem.getContentScrollTarget(); 8774 this.scrollTarget = this.$.content.selectedItem.getContentScrollTarget();
(...skipping 27 matching lines...) Expand all
8790 8802
8791 case HistoryRange.MONTH: 8803 case HistoryRange.MONTH:
8792 histogramValue = HistoryPageViewHistogram.GROUPED_MONTH; 8804 histogramValue = HistoryPageViewHistogram.GROUPED_MONTH;
8793 break; 8805 break;
8794 } 8806 }
8795 break; 8807 break;
8796 } 8808 }
8797 md_history.BrowserService.getInstance().recordHistogram('History.HistoryPage View', histogramValue, HistoryPageViewHistogram.END); 8809 md_history.BrowserService.getInstance().recordHistogram('History.HistoryPage View', histogramValue, HistoryPageViewHistogram.END);
8798 } 8810 }
8799 }); 8811 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698