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

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: Move to MD-specific strings 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 var owner = Polymer.dom(item).getOwnerRoot() || document;
3367 this._setFocusedItem(item);
3368 if (Polymer.dom(owner).activeElement == item) {
3369 return;
3370 }
3371 }
3372 }
3373 },
3374 _focusNext: function() {
3375 var length = this.items.length;
3376 var curFocusIndex = Number(this.indexOf(this.focusedItem));
3377 for (var i = 1; i < length + 1; i++) {
3378 var item = this.items[(curFocusIndex + i) % length];
3379 if (!item.hasAttribute('disabled')) {
3380 var owner = Polymer.dom(item).getOwnerRoot() || document;
3381 this._setFocusedItem(item);
3382 if (Polymer.dom(owner).activeElement == item) {
3383 return;
3384 }
3385 }
3386 }
3387 },
3388 _applySelection: function(item, isSelected) {
3389 if (isSelected) {
3390 item.setAttribute('aria-selected', 'true');
3391 } else {
3392 item.removeAttribute('aria-selected');
3393 }
3394 Polymer.IronSelectableBehavior._applySelection.apply(this, arguments);
3395 },
3396 _focusedItemChanged: function(focusedItem, old) {
3397 old && old.setAttribute('tabindex', '-1');
3398 if (focusedItem) {
3399 focusedItem.setAttribute('tabindex', '0');
3400 focusedItem.focus();
3401 }
3402 },
3403 _onIronItemsChanged: function(event) {
3404 if (event.detail.addedNodes.length) {
3405 this._resetTabindices();
3406 }
3407 },
3408 _onShiftTabDown: function(event) {
3409 var oldTabIndex = this.getAttribute('tabindex');
3410 Polymer.IronMenuBehaviorImpl._shiftTabPressed = true;
3411 this._setFocusedItem(null);
3412 this.setAttribute('tabindex', '-1');
3413 this.async(function() {
3414 this.setAttribute('tabindex', oldTabIndex);
3415 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
3416 }, 1);
3417 },
3418 _onFocus: function(event) {
3419 if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) {
3420 return;
3421 }
3422 var rootTarget = Polymer.dom(event).rootTarget;
3423 if (rootTarget !== this && typeof rootTarget.tabIndex !== "undefined" && !th is.isLightDescendant(rootTarget)) {
3424 return;
3425 }
3426 this._defaultFocusAsync = this.async(function() {
3427 var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0 ] : this.selectedItem;
3428 this._setFocusedItem(null);
3429 if (selectedItem) {
3430 this._setFocusedItem(selectedItem);
3431 } else if (this.items[0]) {
3432 this._focusNext();
3433 }
3434 });
3435 },
3436 _onUpKey: function(event) {
3437 this._focusPrevious();
3438 event.detail.keyboardEvent.preventDefault();
3439 },
3440 _onDownKey: function(event) {
3441 this._focusNext();
3442 event.detail.keyboardEvent.preventDefault();
3443 },
3444 _onEscKey: function(event) {
3445 this.focusedItem.blur();
3446 },
3447 _onKeydown: function(event) {
3448 if (!this.keyboardEventMatchesKeys(event, 'up down esc')) {
3449 this._focusWithKeyboardEvent(event);
3450 }
3451 event.stopPropagation();
3452 },
3453 _activateHandler: function(event) {
3454 Polymer.IronSelectableBehavior._activateHandler.call(this, event);
3455 event.stopPropagation();
3456 }
3457 };
3458
3459 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
3460
3461 Polymer.IronMenuBehavior = [ Polymer.IronMultiSelectableBehavior, Polymer.IronA1 1yKeysBehavior, Polymer.IronMenuBehaviorImpl ];
3462
3463 Polymer.IronMenubarBehaviorImpl = {
3464 hostAttributes: {
3465 role: 'menubar'
3466 },
3467 keyBindings: {
3468 left: '_onLeftKey',
3469 right: '_onRightKey'
3470 },
3471 _onUpKey: function(event) {
3472 this.focusedItem.click();
3473 event.detail.keyboardEvent.preventDefault();
3474 },
3475 _onDownKey: function(event) {
3476 this.focusedItem.click();
3477 event.detail.keyboardEvent.preventDefault();
3478 },
3479 get _isRTL() {
3480 return window.getComputedStyle(this)['direction'] === 'rtl';
3481 },
3482 _onLeftKey: function(event) {
3483 if (this._isRTL) {
3484 this._focusNext();
3485 } else {
3486 this._focusPrevious();
3487 }
3488 event.detail.keyboardEvent.preventDefault();
3489 },
3490 _onRightKey: function(event) {
3491 if (this._isRTL) {
3492 this._focusPrevious();
3493 } else {
3494 this._focusNext();
3495 }
3496 event.detail.keyboardEvent.preventDefault();
3497 },
3498 _onKeydown: function(event) {
3499 if (this.keyboardEventMatchesKeys(event, 'up down left right esc')) {
3500 return;
3501 }
3502 this._focusWithKeyboardEvent(event);
3503 }
3504 };
3505
3506 Polymer.IronMenubarBehavior = [ Polymer.IronMenuBehavior, Polymer.IronMenubarBeh aviorImpl ];
3507
3508 Polymer({
3509 is: 'iron-iconset-svg',
3510 properties: {
3511 name: {
3512 type: String,
3513 observer: '_nameChanged'
3514 },
3515 size: {
3516 type: Number,
3517 value: 24
3518 }
3519 },
3520 attached: function() {
3521 this.style.display = 'none';
3522 },
3523 getIconNames: function() {
3524 this._icons = this._createIconMap();
3525 return Object.keys(this._icons).map(function(n) {
3526 return this.name + ':' + n;
3527 }, this);
3528 },
3529 applyIcon: function(element, iconName) {
3530 element = element.root || element;
3531 this.removeIcon(element);
3532 var svg = this._cloneIcon(iconName);
3533 if (svg) {
3534 var pde = Polymer.dom(element);
3535 pde.insertBefore(svg, pde.childNodes[0]);
3536 return element._svgIcon = svg;
3537 }
3538 return null;
3539 },
3540 removeIcon: function(element) {
3541 if (element._svgIcon) {
3542 Polymer.dom(element).removeChild(element._svgIcon);
3543 element._svgIcon = null;
3544 }
3545 },
3546 _nameChanged: function() {
3547 new Polymer.IronMeta({
3548 type: 'iconset',
3549 key: this.name,
3550 value: this
3551 });
3552 this.async(function() {
3553 this.fire('iron-iconset-added', this, {
3554 node: window
3555 });
3556 });
3557 },
3558 _createIconMap: function() {
3559 var icons = Object.create(null);
3560 Polymer.dom(this).querySelectorAll('[id]').forEach(function(icon) {
3561 icons[icon.id] = icon;
3562 });
3563 return icons;
3564 },
3565 _cloneIcon: function(id) {
3566 this._icons = this._icons || this._createIconMap();
3567 return this._prepareSvgClone(this._icons[id], this.size);
3568 },
3569 _prepareSvgClone: function(sourceSvg, size) {
3570 if (sourceSvg) {
3571 var content = sourceSvg.cloneNode(true), svg = document.createElementNS('h ttp://www.w3.org/2000/svg', 'svg'), viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size;
3572 svg.setAttribute('viewBox', viewBox);
3573 svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
3574 svg.style.cssText = 'pointer-events: none; display: block; width: 100%; he ight: 100%;';
3575 svg.appendChild(content).removeAttribute('id');
3576 return svg;
3577 }
3578 return null;
3579 }
3580 });
3581
3582 Polymer({
3583 is: 'paper-tabs',
3584 behaviors: [ Polymer.IronResizableBehavior, Polymer.IronMenubarBehavior ],
3585 properties: {
3586 noink: {
3587 type: Boolean,
3588 value: false,
3589 observer: '_noinkChanged'
3590 },
3591 noBar: {
3592 type: Boolean,
3593 value: false
3594 },
3595 noSlide: {
3596 type: Boolean,
3597 value: false
3598 },
3599 scrollable: {
3600 type: Boolean,
3601 value: false
3602 },
3603 fitContainer: {
3604 type: Boolean,
3605 value: false
3606 },
3607 disableDrag: {
3608 type: Boolean,
3609 value: false
3610 },
3611 hideScrollButtons: {
3612 type: Boolean,
3613 value: false
3614 },
3615 alignBottom: {
3616 type: Boolean,
3617 value: false
3618 },
3619 selectable: {
3620 type: String,
3621 value: 'paper-tab'
3622 },
3623 autoselect: {
3624 type: Boolean,
3625 value: false
3626 },
3627 autoselectDelay: {
3628 type: Number,
3629 value: 0
3630 },
3631 _step: {
3632 type: Number,
3633 value: 10
3634 },
3635 _holdDelay: {
3636 type: Number,
3637 value: 1
3638 },
3639 _leftHidden: {
3640 type: Boolean,
3641 value: false
3642 },
3643 _rightHidden: {
3644 type: Boolean,
3645 value: false
3646 },
3647 _previousTab: {
3648 type: Object
3649 }
3650 },
3651 hostAttributes: {
3652 role: 'tablist'
3653 },
3654 listeners: {
3655 'iron-resize': '_onTabSizingChanged',
3656 'iron-items-changed': '_onTabSizingChanged',
3657 'iron-select': '_onIronSelect',
3658 'iron-deselect': '_onIronDeselect'
3659 },
3660 keyBindings: {
3661 'left:keyup right:keyup': '_onArrowKeyup'
3662 },
3663 created: function() {
3664 this._holdJob = null;
3665 this._pendingActivationItem = undefined;
3666 this._pendingActivationTimeout = undefined;
3667 this._bindDelayedActivationHandler = this._delayedActivationHandler.bind(thi s);
3668 this.addEventListener('blur', this._onBlurCapture.bind(this), true);
3669 },
3670 ready: function() {
3671 this.setScrollDirection('y', this.$.tabsContainer);
3672 },
3673 detached: function() {
3674 this._cancelPendingActivation();
3675 },
3676 _noinkChanged: function(noink) {
3677 var childTabs = Polymer.dom(this).querySelectorAll('paper-tab');
3678 childTabs.forEach(noink ? this._setNoinkAttribute : this._removeNoinkAttribu te);
3679 },
3680 _setNoinkAttribute: function(element) {
3681 element.setAttribute('noink', '');
3682 },
3683 _removeNoinkAttribute: function(element) {
3684 element.removeAttribute('noink');
3685 },
3686 _computeScrollButtonClass: function(hideThisButton, scrollable, hideScrollButt ons) {
3687 if (!scrollable || hideScrollButtons) {
3688 return 'hidden';
3689 }
3690 if (hideThisButton) {
3691 return 'not-visible';
3692 }
3693 return '';
3694 },
3695 _computeTabsContentClass: function(scrollable, fitContainer) {
3696 return scrollable ? 'scrollable' + (fitContainer ? ' fit-container' : '') : ' fit-container';
3697 },
3698 _computeSelectionBarClass: function(noBar, alignBottom) {
3699 if (noBar) {
3700 return 'hidden';
3701 } else if (alignBottom) {
3702 return 'align-bottom';
3703 }
3704 return '';
3705 },
3706 _onTabSizingChanged: function() {
3707 this.debounce('_onTabSizingChanged', function() {
3708 this._scroll();
3709 this._tabChanged(this.selectedItem);
3710 }, 10);
3711 },
3712 _onIronSelect: function(event) {
3713 this._tabChanged(event.detail.item, this._previousTab);
3714 this._previousTab = event.detail.item;
3715 this.cancelDebouncer('tab-changed');
3716 },
3717 _onIronDeselect: function(event) {
3718 this.debounce('tab-changed', function() {
3719 this._tabChanged(null, this._previousTab);
3720 this._previousTab = null;
3721 }, 1);
3722 },
3723 _activateHandler: function() {
3724 this._cancelPendingActivation();
3725 Polymer.IronMenuBehaviorImpl._activateHandler.apply(this, arguments);
3726 },
3727 _scheduleActivation: function(item, delay) {
3728 this._pendingActivationItem = item;
3729 this._pendingActivationTimeout = this.async(this._bindDelayedActivationHandl er, delay);
3730 },
3731 _delayedActivationHandler: function() {
3732 var item = this._pendingActivationItem;
3733 this._pendingActivationItem = undefined;
3734 this._pendingActivationTimeout = undefined;
3735 item.fire(this.activateEvent, null, {
3736 bubbles: true,
3737 cancelable: true
3738 });
3739 },
3740 _cancelPendingActivation: function() {
3741 if (this._pendingActivationTimeout !== undefined) {
3742 this.cancelAsync(this._pendingActivationTimeout);
3743 this._pendingActivationItem = undefined;
3744 this._pendingActivationTimeout = undefined;
3745 }
3746 },
3747 _onArrowKeyup: function(event) {
3748 if (this.autoselect) {
3749 this._scheduleActivation(this.focusedItem, this.autoselectDelay);
3750 }
3751 },
3752 _onBlurCapture: function(event) {
3753 if (event.target === this._pendingActivationItem) {
3754 this._cancelPendingActivation();
3755 }
3756 },
3757 get _tabContainerScrollSize() {
3758 return Math.max(0, this.$.tabsContainer.scrollWidth - this.$.tabsContainer.o ffsetWidth);
3759 },
3760 _scroll: function(e, detail) {
3761 if (!this.scrollable) {
3762 return;
3763 }
3764 var ddx = detail && -detail.ddx || 0;
3765 this._affectScroll(ddx);
3766 },
3767 _down: function(e) {
3768 this.async(function() {
3769 if (this._defaultFocusAsync) {
3770 this.cancelAsync(this._defaultFocusAsync);
3771 this._defaultFocusAsync = null;
3772 }
3773 }, 1);
3774 },
3775 _affectScroll: function(dx) {
3776 this.$.tabsContainer.scrollLeft += dx;
3777 var scrollLeft = this.$.tabsContainer.scrollLeft;
3778 this._leftHidden = scrollLeft === 0;
3779 this._rightHidden = scrollLeft === this._tabContainerScrollSize;
3780 },
3781 _onLeftScrollButtonDown: function() {
3782 this._scrollToLeft();
3783 this._holdJob = setInterval(this._scrollToLeft.bind(this), this._holdDelay);
3784 },
3785 _onRightScrollButtonDown: function() {
3786 this._scrollToRight();
3787 this._holdJob = setInterval(this._scrollToRight.bind(this), this._holdDelay) ;
3788 },
3789 _onScrollButtonUp: function() {
3790 clearInterval(this._holdJob);
3791 this._holdJob = null;
3792 },
3793 _scrollToLeft: function() {
3794 this._affectScroll(-this._step);
3795 },
3796 _scrollToRight: function() {
3797 this._affectScroll(this._step);
3798 },
3799 _tabChanged: function(tab, old) {
3800 if (!tab) {
3801 this.$.selectionBar.classList.remove('expand');
3802 this.$.selectionBar.classList.remove('contract');
3803 this._positionBar(0, 0);
3804 return;
3805 }
3806 var r = this.$.tabsContent.getBoundingClientRect();
3807 var w = r.width;
3808 var tabRect = tab.getBoundingClientRect();
3809 var tabOffsetLeft = tabRect.left - r.left;
3810 this._pos = {
3811 width: this._calcPercent(tabRect.width, w),
3812 left: this._calcPercent(tabOffsetLeft, w)
3813 };
3814 if (this.noSlide || old == null) {
3815 this.$.selectionBar.classList.remove('expand');
3816 this.$.selectionBar.classList.remove('contract');
3817 this._positionBar(this._pos.width, this._pos.left);
3818 return;
3819 }
3820 var oldRect = old.getBoundingClientRect();
3821 var oldIndex = this.items.indexOf(old);
3822 var index = this.items.indexOf(tab);
3823 var m = 5;
3824 this.$.selectionBar.classList.add('expand');
3825 var moveRight = oldIndex < index;
3826 var isRTL = this._isRTL;
3827 if (isRTL) {
3828 moveRight = !moveRight;
3829 }
3830 if (moveRight) {
3831 this._positionBar(this._calcPercent(tabRect.left + tabRect.width - oldRect .left, w) - m, this._left);
3832 } else {
3833 this._positionBar(this._calcPercent(oldRect.left + oldRect.width - tabRect .left, w) - m, this._calcPercent(tabOffsetLeft, w) + m);
3834 }
3835 if (this.scrollable) {
3836 this._scrollToSelectedIfNeeded(tabRect.width, tabOffsetLeft);
3837 }
3838 },
3839 _scrollToSelectedIfNeeded: function(tabWidth, tabOffsetLeft) {
3840 var l = tabOffsetLeft - this.$.tabsContainer.scrollLeft;
3841 if (l < 0) {
3842 this.$.tabsContainer.scrollLeft += l;
3843 } else {
3844 l += tabWidth - this.$.tabsContainer.offsetWidth;
3845 if (l > 0) {
3846 this.$.tabsContainer.scrollLeft += l;
3847 }
3848 }
3849 },
3850 _calcPercent: function(w, w0) {
3851 return 100 * w / w0;
3852 },
3853 _positionBar: function(width, left) {
3854 width = width || 0;
3855 left = left || 0;
3856 this._width = width;
3857 this._left = left;
3858 this.transform('translateX(' + left + '%) scaleX(' + width / 100 + ')', this .$.selectionBar);
3859 },
3860 _onBarTransitionEnd: function(e) {
3861 var cl = this.$.selectionBar.classList;
3862 if (cl.contains('expand')) {
3863 cl.remove('expand');
3864 cl.add('contract');
3865 this._positionBar(this._pos.width, this._pos.left);
3866 } else if (cl.contains('contract')) {
3867 cl.remove('contract');
3868 }
3869 }
3870 });
3871
3872 (function() {
3873 'use strict';
3874 Polymer.IronA11yAnnouncer = Polymer({
3875 is: 'iron-a11y-announcer',
3876 properties: {
3877 mode: {
3878 type: String,
3879 value: 'polite'
3880 },
3881 _text: {
3882 type: String,
3883 value: ''
3884 }
3885 },
3886 created: function() {
3887 if (!Polymer.IronA11yAnnouncer.instance) {
3888 Polymer.IronA11yAnnouncer.instance = this;
3889 }
3890 document.body.addEventListener('iron-announce', this._onIronAnnounce.bind( this));
3891 },
3892 announce: function(text) {
3893 this._text = '';
3894 this.async(function() {
3895 this._text = text;
3896 }, 100);
3897 },
3898 _onIronAnnounce: function(event) {
3899 if (event.detail && event.detail.text) {
3900 this.announce(event.detail.text);
3901 }
3902 }
3903 });
3904 Polymer.IronA11yAnnouncer.instance = null;
3905 Polymer.IronA11yAnnouncer.requestAvailability = function() {
3906 if (!Polymer.IronA11yAnnouncer.instance) {
3907 Polymer.IronA11yAnnouncer.instance = document.createElement('iron-a11y-ann ouncer');
3908 }
3909 document.body.appendChild(Polymer.IronA11yAnnouncer.instance);
3910 };
3911 })();
3912
3913 Polymer.IronValidatableBehaviorMeta = null;
3914
3915 Polymer.IronValidatableBehavior = {
3916 properties: {
3917 validator: {
3918 type: String
3919 },
3920 invalid: {
3921 notify: true,
3922 reflectToAttribute: true,
3923 type: Boolean,
3924 value: false
3925 },
3926 _validatorMeta: {
3927 type: Object
3928 },
3929 validatorType: {
3930 type: String,
3931 value: 'validator'
3932 },
3933 _validator: {
3934 type: Object,
3935 computed: '__computeValidator(validator)'
3936 }
3937 },
3938 observers: [ '_invalidChanged(invalid)' ],
3939 registered: function() {
3940 Polymer.IronValidatableBehaviorMeta = new Polymer.IronMeta({
3941 type: 'validator'
3942 });
3943 },
3944 _invalidChanged: function() {
3945 if (this.invalid) {
3946 this.setAttribute('aria-invalid', 'true');
3947 } else {
3948 this.removeAttribute('aria-invalid');
3949 }
3950 },
3951 hasValidator: function() {
3952 return this._validator != null;
3953 },
3954 validate: function(value) {
3955 this.invalid = !this._getValidity(value);
3956 return !this.invalid;
3957 },
3958 _getValidity: function(value) {
3959 if (this.hasValidator()) {
3960 return this._validator.validate(value);
3961 }
3962 return true;
3963 },
3964 __computeValidator: function() {
3965 return Polymer.IronValidatableBehaviorMeta && Polymer.IronValidatableBehavio rMeta.byKey(this.validator);
3966 }
3967 };
3968
3969 Polymer({
3970 is: 'iron-input',
3971 "extends": 'input',
3972 behaviors: [ Polymer.IronValidatableBehavior ],
3973 properties: {
3974 bindValue: {
3975 observer: '_bindValueChanged',
3976 type: String
3977 },
3978 preventInvalidInput: {
3979 type: Boolean
3980 },
3981 allowedPattern: {
3982 type: String,
3983 observer: "_allowedPatternChanged"
3984 },
3985 _previousValidInput: {
3986 type: String,
3987 value: ''
3988 },
3989 _patternAlreadyChecked: {
3990 type: Boolean,
3991 value: false
3992 }
3993 },
3994 listeners: {
3995 input: '_onInput',
3996 keypress: '_onKeypress'
3997 },
3998 registered: function() {
3999 if (!this._canDispatchEventOnDisabled()) {
4000 this._origDispatchEvent = this.dispatchEvent;
4001 this.dispatchEvent = this._dispatchEventFirefoxIE;
4002 }
4003 },
4004 created: function() {
4005 Polymer.IronA11yAnnouncer.requestAvailability();
4006 },
4007 _canDispatchEventOnDisabled: function() {
4008 var input = document.createElement('input');
4009 var canDispatch = false;
4010 input.disabled = true;
4011 input.addEventListener('feature-check-dispatch-event', function() {
4012 canDispatch = true;
4013 });
4014 try {
4015 input.dispatchEvent(new Event('feature-check-dispatch-event'));
4016 } catch (e) {}
4017 return canDispatch;
4018 },
4019 _dispatchEventFirefoxIE: function() {
4020 var disabled = this.disabled;
4021 this.disabled = false;
4022 this._origDispatchEvent.apply(this, arguments);
4023 this.disabled = disabled;
4024 },
4025 get _patternRegExp() {
4026 var pattern;
4027 if (this.allowedPattern) {
4028 pattern = new RegExp(this.allowedPattern);
4029 } else {
4030 switch (this.type) {
4031 case 'number':
4032 pattern = /[0-9.,e-]/;
4033 break;
4034 }
4035 }
4036 return pattern;
4037 },
4038 ready: function() {
4039 this.bindValue = this.value;
4040 },
4041 _bindValueChanged: function() {
4042 if (this.value !== this.bindValue) {
4043 this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue == = false) ? '' : this.bindValue;
4044 }
4045 this.fire('bind-value-changed', {
4046 value: this.bindValue
4047 });
4048 },
4049 _allowedPatternChanged: function() {
4050 this.preventInvalidInput = this.allowedPattern ? true : false;
4051 },
4052 _onInput: function() {
4053 if (this.preventInvalidInput && !this._patternAlreadyChecked) {
4054 var valid = this._checkPatternValidity();
4055 if (!valid) {
4056 this._announceInvalidCharacter('Invalid string of characters not entered .');
4057 this.value = this._previousValidInput;
4058 }
4059 }
4060 this.bindValue = this.value;
4061 this._previousValidInput = this.value;
4062 this._patternAlreadyChecked = false;
4063 },
4064 _isPrintable: function(event) {
4065 var anyNonPrintable = event.keyCode == 8 || event.keyCode == 9 || event.keyC ode == 13 || event.keyCode == 27;
4066 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;
4067 return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable);
4068 },
4069 _onKeypress: function(event) {
4070 if (!this.preventInvalidInput && this.type !== 'number') {
4071 return;
4072 }
4073 var regexp = this._patternRegExp;
4074 if (!regexp) {
4075 return;
4076 }
4077 if (event.metaKey || event.ctrlKey || event.altKey) return;
4078 this._patternAlreadyChecked = true;
4079 var thisChar = String.fromCharCode(event.charCode);
4080 if (this._isPrintable(event) && !regexp.test(thisChar)) {
4081 event.preventDefault();
4082 this._announceInvalidCharacter('Invalid character ' + thisChar + ' not ent ered.');
4083 }
4084 },
4085 _checkPatternValidity: function() {
4086 var regexp = this._patternRegExp;
4087 if (!regexp) {
4088 return true;
4089 }
4090 for (var i = 0; i < this.value.length; i++) {
4091 if (!regexp.test(this.value[i])) {
4092 return false;
4093 }
4094 }
4095 return true;
4096 },
4097 validate: function() {
4098 var valid = this.checkValidity();
4099 if (valid) {
4100 if (this.required && this.value === '') {
4101 valid = false;
4102 } else if (this.hasValidator()) {
4103 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
4104 }
4105 }
4106 this.invalid = !valid;
4107 this.fire('iron-input-validate');
4108 return valid;
4109 },
4110 _announceInvalidCharacter: function(message) {
4111 this.fire('iron-announce', {
4112 text: message
4113 });
4114 }
4115 });
4116
4117 Polymer({
4118 is: 'paper-input-container',
4119 properties: {
4120 noLabelFloat: {
4121 type: Boolean,
4122 value: false
4123 },
4124 alwaysFloatLabel: {
4125 type: Boolean,
4126 value: false
4127 },
4128 attrForValue: {
4129 type: String,
4130 value: 'bind-value'
4131 },
4132 autoValidate: {
4133 type: Boolean,
4134 value: false
4135 },
4136 invalid: {
4137 observer: '_invalidChanged',
4138 type: Boolean,
4139 value: false
4140 },
4141 focused: {
4142 readOnly: true,
4143 type: Boolean,
4144 value: false,
4145 notify: true
4146 },
4147 _addons: {
4148 type: Array
4149 },
4150 _inputHasContent: {
4151 type: Boolean,
4152 value: false
4153 },
4154 _inputSelector: {
4155 type: String,
4156 value: 'input,textarea,.paper-input-input'
4157 },
4158 _boundOnFocus: {
4159 type: Function,
4160 value: function() {
4161 return this._onFocus.bind(this);
4162 }
4163 },
4164 _boundOnBlur: {
4165 type: Function,
4166 value: function() {
4167 return this._onBlur.bind(this);
4168 }
4169 },
4170 _boundOnInput: {
4171 type: Function,
4172 value: function() {
4173 return this._onInput.bind(this);
4174 }
4175 },
4176 _boundValueChanged: {
4177 type: Function,
4178 value: function() {
4179 return this._onValueChanged.bind(this);
4180 }
4181 }
4182 },
4183 listeners: {
4184 'addon-attached': '_onAddonAttached',
4185 'iron-input-validate': '_onIronInputValidate'
4186 },
4187 get _valueChangedEvent() {
4188 return this.attrForValue + '-changed';
4189 },
4190 get _propertyForValue() {
4191 return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
4192 },
4193 get _inputElement() {
4194 return Polymer.dom(this).querySelector(this._inputSelector);
4195 },
4196 get _inputElementValue() {
4197 return this._inputElement[this._propertyForValue] || this._inputElement.valu e;
4198 },
4199 ready: function() {
4200 if (!this._addons) {
4201 this._addons = [];
4202 }
4203 this.addEventListener('focus', this._boundOnFocus, true);
4204 this.addEventListener('blur', this._boundOnBlur, true);
4205 },
4206 attached: function() {
4207 if (this.attrForValue) {
4208 this._inputElement.addEventListener(this._valueChangedEvent, this._boundVa lueChanged);
4209 } else {
4210 this.addEventListener('input', this._onInput);
4211 }
4212 if (this._inputElementValue != '') {
4213 this._handleValueAndAutoValidate(this._inputElement);
4214 } else {
4215 this._handleValue(this._inputElement);
4216 }
4217 },
4218 _onAddonAttached: function(event) {
4219 if (!this._addons) {
4220 this._addons = [];
4221 }
4222 var target = event.target;
4223 if (this._addons.indexOf(target) === -1) {
4224 this._addons.push(target);
4225 if (this.isAttached) {
4226 this._handleValue(this._inputElement);
4227 }
4228 }
4229 },
4230 _onFocus: function() {
4231 this._setFocused(true);
4232 },
4233 _onBlur: function() {
4234 this._setFocused(false);
4235 this._handleValueAndAutoValidate(this._inputElement);
4236 },
4237 _onInput: function(event) {
4238 this._handleValueAndAutoValidate(event.target);
4239 },
4240 _onValueChanged: function(event) {
4241 this._handleValueAndAutoValidate(event.target);
4242 },
4243 _handleValue: function(inputElement) {
4244 var value = this._inputElementValue;
4245 if (value || value === 0 || inputElement.type === 'number' && !inputElement. checkValidity()) {
4246 this._inputHasContent = true;
4247 } else {
4248 this._inputHasContent = false;
4249 }
4250 this.updateAddons({
4251 inputElement: inputElement,
4252 value: value,
4253 invalid: this.invalid
4254 });
4255 },
4256 _handleValueAndAutoValidate: function(inputElement) {
4257 if (this.autoValidate) {
4258 var valid;
4259 if (inputElement.validate) {
4260 valid = inputElement.validate(this._inputElementValue);
4261 } else {
4262 valid = inputElement.checkValidity();
4263 }
4264 this.invalid = !valid;
4265 }
4266 this._handleValue(inputElement);
4267 },
4268 _onIronInputValidate: function(event) {
4269 this.invalid = this._inputElement.invalid;
4270 },
4271 _invalidChanged: function() {
4272 if (this._addons) {
4273 this.updateAddons({
4274 invalid: this.invalid
4275 });
4276 }
4277 },
4278 updateAddons: function(state) {
4279 for (var addon, index = 0; addon = this._addons[index]; index++) {
4280 addon.update(state);
4281 }
4282 },
4283 _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, i nvalid, _inputHasContent) {
4284 var cls = 'input-content';
4285 if (!noLabelFloat) {
4286 var label = this.querySelector('label');
4287 if (alwaysFloatLabel || _inputHasContent) {
4288 cls += ' label-is-floating';
4289 this.$.labelAndInputContainer.style.position = 'static';
4290 if (invalid) {
4291 cls += ' is-invalid';
4292 } else if (focused) {
4293 cls += " label-is-highlighted";
4294 }
4295 } else {
4296 if (label) {
4297 this.$.labelAndInputContainer.style.position = 'relative';
4298 }
4299 }
4300 } else {
4301 if (_inputHasContent) {
4302 cls += ' label-is-hidden';
4303 }
4304 }
4305 return cls;
4306 },
4307 _computeUnderlineClass: function(focused, invalid) {
4308 var cls = 'underline';
4309 if (invalid) {
4310 cls += ' is-invalid';
4311 } else if (focused) {
4312 cls += ' is-highlighted';
4313 }
4314 return cls;
4315 },
4316 _computeAddOnContentClass: function(focused, invalid) {
4317 var cls = 'add-on-content';
4318 if (invalid) {
4319 cls += ' is-invalid';
4320 } else if (focused) {
4321 cls += ' is-highlighted';
4322 }
4323 return cls;
4324 }
4325 });
4326
4327 Polymer.PaperSpinnerBehavior = {
4328 listeners: {
4329 animationend: '__reset',
4330 webkitAnimationEnd: '__reset'
4331 },
4332 properties: {
4333 active: {
4334 type: Boolean,
4335 value: false,
4336 reflectToAttribute: true,
4337 observer: '__activeChanged'
4338 },
4339 alt: {
4340 type: String,
4341 value: 'loading',
4342 observer: '__altChanged'
4343 },
4344 __coolingDown: {
4345 type: Boolean,
4346 value: false
4347 }
4348 },
4349 __computeContainerClasses: function(active, coolingDown) {
4350 return [ active || coolingDown ? 'active' : '', coolingDown ? 'cooldown' : ' ' ].join(' ');
4351 },
4352 __activeChanged: function(active, old) {
4353 this.__setAriaHidden(!active);
4354 this.__coolingDown = !active && old;
4355 },
4356 __altChanged: function(alt) {
4357 if (alt === this.getPropertyInfo('alt').value) {
4358 this.alt = this.getAttribute('aria-label') || alt;
4359 } else {
4360 this.__setAriaHidden(alt === '');
4361 this.setAttribute('aria-label', alt);
4362 }
4363 },
4364 __setAriaHidden: function(hidden) {
4365 var attr = 'aria-hidden';
4366 if (hidden) {
4367 this.setAttribute(attr, 'true');
4368 } else {
4369 this.removeAttribute(attr);
4370 }
4371 },
4372 __reset: function() {
4373 this.active = false;
4374 this.__coolingDown = false;
4375 }
4376 };
4377
4378 Polymer({
4379 is: 'paper-spinner-lite',
4380 behaviors: [ Polymer.PaperSpinnerBehavior ]
4381 });
4382
4383 // Copyright 2016 The Chromium Authors. All rights reserved.
4384 // Use of this source code is governed by a BSD-style license that can be
4385 // found in the LICENSE file.
4386 var CrSearchFieldBehavior = {
4387 properties: {
4388 label: {
4389 type: String,
4390 value: ''
4391 },
4392 clearLabel: {
4393 type: String,
4394 value: ''
4395 },
4396 showingSearch: {
4397 type: Boolean,
4398 value: false,
4399 notify: true,
4400 observer: 'showingSearchChanged_',
4401 reflectToAttribute: true
4402 },
4403 lastValue_: {
4404 type: String,
4405 value: ''
4406 }
4407 },
4408 getSearchInput: function() {},
4409 getValue: function() {
4410 return this.getSearchInput().value;
4411 },
4412 setValue: function(value) {
4413 this.getSearchInput().bindValue = value;
4414 this.onValueChanged_(value);
4415 },
4416 showAndFocus: function() {
4417 this.showingSearch = true;
4418 this.focus_();
4419 },
4420 focus_: function() {
4421 this.getSearchInput().focus();
4422 },
4423 onSearchTermSearch: function() {
4424 this.onValueChanged_(this.getValue());
4425 },
4426 onValueChanged_: function(newValue) {
4427 if (newValue == this.lastValue_) return;
4428 this.fire('search-changed', newValue);
4429 this.lastValue_ = newValue;
4430 },
4431 onSearchTermKeydown: function(e) {
4432 if (e.key == 'Escape') this.showingSearch = false;
4433 },
4434 showingSearchChanged_: function() {
4435 if (this.showingSearch) {
4436 this.focus_();
4437 return;
4438 }
4439 this.setValue('');
4440 this.getSearchInput().blur();
4441 }
4442 };
4443
4444 // Copyright 2016 The Chromium Authors. All rights reserved.
4445 // Use of this source code is governed by a BSD-style license that can be
4446 // found in the LICENSE file.
4447 Polymer({
4448 is: 'cr-toolbar-search-field',
4449 behaviors: [ CrSearchFieldBehavior ],
4450 properties: {
4451 narrow: {
4452 type: Boolean,
4453 reflectToAttribute: true
4454 },
4455 label: String,
4456 clearLabel: String,
4457 spinnerActive: {
4458 type: Boolean,
4459 reflectToAttribute: true
4460 },
4461 hasSearchText_: Boolean,
4462 isSpinnerShown_: {
4463 type: Boolean,
4464 computed: 'computeIsSpinnerShown_(spinnerActive, showingSearch)'
4465 }
4466 },
4467 listeners: {
4468 tap: 'showSearch_',
4469 'searchInput.bind-value-changed': 'onBindValueChanged_'
4470 },
4471 getSearchInput: function() {
4472 return this.$.searchInput;
4473 },
4474 isSearchFocused: function() {
4475 return this.$.searchTerm.focused;
4476 },
4477 computeIconTabIndex_: function(narrow) {
4478 return narrow ? 0 : -1;
4479 },
4480 computeIsSpinnerShown_: function() {
4481 return this.spinnerActive && this.showingSearch;
4482 },
4483 onInputBlur_: function() {
4484 if (!this.hasSearchText_) this.showingSearch = false;
4485 },
4486 onBindValueChanged_: function() {
4487 var newValue = this.$.searchInput.bindValue;
4488 this.hasSearchText_ = newValue != '';
4489 if (newValue != '') this.showingSearch = true;
4490 },
4491 showSearch_: function(e) {
4492 if (e.target != this.$.clearSearch) this.showingSearch = true;
4493 },
4494 hideSearch_: function(e) {
4495 this.showingSearch = false;
4496 e.stopPropagation();
4497 }
4498 });
4499
4500 // Copyright 2016 The Chromium Authors. All rights reserved.
4501 // Use of this source code is governed by a BSD-style license that can be
4502 // found in the LICENSE file.
4503 Polymer({
4504 is: 'cr-toolbar',
4505 properties: {
4506 pageName: String,
4507 searchPrompt: String,
4508 clearLabel: String,
4509 menuLabel: String,
4510 spinnerActive: Boolean,
4511 showMenu: {
4512 type: Boolean,
4513 value: false
4514 },
4515 narrow_: {
4516 type: Boolean,
4517 reflectToAttribute: true
4518 },
4519 showingSearch_: {
4520 type: Boolean,
4521 reflectToAttribute: true
4522 }
4523 },
4524 getSearchField: function() {
4525 return this.$.search;
4526 },
4527 onMenuTap_: function(e) {
4528 this.fire('cr-menu-tap');
4529 }
4530 });
4531
4532 // Copyright 2015 The Chromium Authors. All rights reserved.
4533 // Use of this source code is governed by a BSD-style license that can be
4534 // found in the LICENSE file.
4535 Polymer({
4536 is: 'history-toolbar',
4537 properties: {
4538 count: {
4539 type: Number,
4540 value: 0,
4541 observer: 'changeToolbarView_'
4542 },
4543 itemsSelected_: {
4544 type: Boolean,
4545 value: false,
4546 reflectToAttribute: true
4547 },
4548 searchTerm: {
4549 type: String,
4550 notify: true
4551 },
4552 spinnerActive: {
4553 type: Boolean,
4554 value: false
4555 },
4556 hasDrawer: {
4557 type: Boolean,
4558 observer: 'hasDrawerChanged_',
4559 reflectToAttribute: true
4560 },
4561 isGroupedMode: {
4562 type: Boolean,
4563 reflectToAttribute: true
4564 },
4565 groupedRange: {
4566 type: Number,
4567 value: 0,
4568 reflectToAttribute: true,
4569 notify: true
4570 },
4571 queryStartTime: String,
4572 queryEndTime: String
4573 },
4574 changeToolbarView_: function() {
4575 this.itemsSelected_ = this.count > 0;
4576 },
4577 setSearchTerm: function(search) {
4578 if (this.searchTerm == search) return;
4579 this.searchTerm = search;
4580 var searchField = this.$['main-toolbar'].getSearchField();
4581 searchField.showAndFocus();
4582 searchField.setValue(search);
4583 },
4584 onSearchChanged_: function(event) {
4585 this.searchTerm = event.detail;
4586 },
4587 onClearSelectionTap_: function() {
4588 this.fire('unselect-all');
4589 },
4590 onDeleteTap_: function() {
4591 this.fire('delete-selected');
4592 },
4593 get searchBar() {
4594 return this.$['main-toolbar'].getSearchField();
4595 },
4596 showSearchField: function() {
4597 this.$['main-toolbar'].getSearchField().showAndFocus();
4598 },
4599 deletingAllowed_: function() {
4600 return loadTimeData.getBoolean('allowDeletingHistory');
4601 },
4602 numberOfItemsSelected_: function(count) {
4603 return count > 0 ? loadTimeData.getStringF('itemsSelected', count) : '';
4604 },
4605 getHistoryInterval_: function(queryStartTime, queryEndTime) {
4606 return loadTimeData.getStringF('historyInterval', queryStartTime, queryEndTi me);
4607 },
4608 hasDrawerChanged_: function() {
4609 this.updateStyles();
4610 }
4611 });
4612
4613 // Copyright 2016 The Chromium Authors. All rights reserved.
4614 // Use of this source code is governed by a BSD-style license that can be
4615 // found in the LICENSE file.
4616 Polymer({
4617 is: 'cr-dialog',
4618 "extends": 'dialog',
4619 created: function() {
4620 window.addEventListener('popstate', function() {
4621 if (this.open) this.cancel();
4622 }.bind(this));
4623 },
4624 cancel: function() {
4625 this.fire('cancel');
4626 HTMLDialogElement.prototype.close.call(this, '');
4627 },
4628 close: function(opt_returnValue) {
4629 HTMLDialogElement.prototype.close.call(this, 'success');
4630 },
4631 getCloseButton: function() {
4632 return this.$.close;
4633 }
4634 });
4635
4636 Polymer.IronFitBehavior = {
4637 properties: {
4638 sizingTarget: {
4639 type: Object,
4640 value: function() {
4641 return this;
4642 }
4643 },
4644 fitInto: {
4645 type: Object,
4646 value: window
4647 },
4648 noOverlap: {
4649 type: Boolean
4650 },
4651 positionTarget: {
4652 type: Element
4653 },
4654 horizontalAlign: {
4655 type: String
4656 },
4657 verticalAlign: {
4658 type: String
4659 },
4660 dynamicAlign: {
4661 type: Boolean
4662 },
4663 horizontalOffset: {
4664 type: Number,
4665 value: 0,
4666 notify: true
4667 },
4668 verticalOffset: {
4669 type: Number,
4670 value: 0,
4671 notify: true
4672 },
4673 autoFitOnAttach: {
4674 type: Boolean,
4675 value: false
4676 },
4677 _fitInfo: {
4678 type: Object
4679 }
4680 },
4681 get _fitWidth() {
4682 var fitWidth;
4683 if (this.fitInto === window) {
4684 fitWidth = this.fitInto.innerWidth;
4685 } else {
4686 fitWidth = this.fitInto.getBoundingClientRect().width;
4687 }
4688 return fitWidth;
4689 },
4690 get _fitHeight() {
4691 var fitHeight;
4692 if (this.fitInto === window) {
4693 fitHeight = this.fitInto.innerHeight;
4694 } else {
4695 fitHeight = this.fitInto.getBoundingClientRect().height;
4696 }
4697 return fitHeight;
4698 },
4699 get _fitLeft() {
4700 var fitLeft;
4701 if (this.fitInto === window) {
4702 fitLeft = 0;
4703 } else {
4704 fitLeft = this.fitInto.getBoundingClientRect().left;
4705 }
4706 return fitLeft;
4707 },
4708 get _fitTop() {
4709 var fitTop;
4710 if (this.fitInto === window) {
4711 fitTop = 0;
4712 } else {
4713 fitTop = this.fitInto.getBoundingClientRect().top;
4714 }
4715 return fitTop;
4716 },
4717 get _defaultPositionTarget() {
4718 var parent = Polymer.dom(this).parentNode;
4719 if (parent && parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
4720 parent = parent.host;
4721 }
4722 return parent;
4723 },
4724 get _localeHorizontalAlign() {
4725 if (this._isRTL) {
4726 if (this.horizontalAlign === 'right') {
4727 return 'left';
4728 }
4729 if (this.horizontalAlign === 'left') {
4730 return 'right';
4731 }
4732 }
4733 return this.horizontalAlign;
4734 },
4735 attached: function() {
4736 this._isRTL = window.getComputedStyle(this).direction == 'rtl';
4737 this.positionTarget = this.positionTarget || this._defaultPositionTarget;
4738 if (this.autoFitOnAttach) {
4739 if (window.getComputedStyle(this).display === 'none') {
4740 setTimeout(function() {
4741 this.fit();
4742 }.bind(this));
4743 } else {
4744 this.fit();
4745 }
4746 }
4747 },
4748 fit: function() {
4749 this.position();
4750 this.constrain();
4751 this.center();
4752 },
4753 _discoverInfo: function() {
4754 if (this._fitInfo) {
4755 return;
4756 }
4757 var target = window.getComputedStyle(this);
4758 var sizer = window.getComputedStyle(this.sizingTarget);
4759 this._fitInfo = {
4760 inlineStyle: {
4761 top: this.style.top || '',
4762 left: this.style.left || '',
4763 position: this.style.position || ''
4764 },
4765 sizerInlineStyle: {
4766 maxWidth: this.sizingTarget.style.maxWidth || '',
4767 maxHeight: this.sizingTarget.style.maxHeight || '',
4768 boxSizing: this.sizingTarget.style.boxSizing || ''
4769 },
4770 positionedBy: {
4771 vertically: target.top !== 'auto' ? 'top' : target.bottom !== 'auto' ? ' bottom' : null,
4772 horizontally: target.left !== 'auto' ? 'left' : target.right !== 'auto' ? 'right' : null
4773 },
4774 sizedBy: {
4775 height: sizer.maxHeight !== 'none',
4776 width: sizer.maxWidth !== 'none',
4777 minWidth: parseInt(sizer.minWidth, 10) || 0,
4778 minHeight: parseInt(sizer.minHeight, 10) || 0
4779 },
4780 margin: {
4781 top: parseInt(target.marginTop, 10) || 0,
4782 right: parseInt(target.marginRight, 10) || 0,
4783 bottom: parseInt(target.marginBottom, 10) || 0,
4784 left: parseInt(target.marginLeft, 10) || 0
4785 }
4786 };
4787 if (this.verticalOffset) {
4788 this._fitInfo.margin.top = this._fitInfo.margin.bottom = this.verticalOffs et;
4789 this._fitInfo.inlineStyle.marginTop = this.style.marginTop || '';
4790 this._fitInfo.inlineStyle.marginBottom = this.style.marginBottom || '';
4791 this.style.marginTop = this.style.marginBottom = this.verticalOffset + 'px ';
4792 }
4793 if (this.horizontalOffset) {
4794 this._fitInfo.margin.left = this._fitInfo.margin.right = this.horizontalOf fset;
4795 this._fitInfo.inlineStyle.marginLeft = this.style.marginLeft || '';
4796 this._fitInfo.inlineStyle.marginRight = this.style.marginRight || '';
4797 this.style.marginLeft = this.style.marginRight = this.horizontalOffset + ' px';
4798 }
4799 },
4800 resetFit: function() {
4801 var info = this._fitInfo || {};
4802 for (var property in info.sizerInlineStyle) {
4803 this.sizingTarget.style[property] = info.sizerInlineStyle[property];
4804 }
4805 for (var property in info.inlineStyle) {
4806 this.style[property] = info.inlineStyle[property];
4807 }
4808 this._fitInfo = null;
4809 },
4810 refit: function() {
4811 var scrollLeft = this.sizingTarget.scrollLeft;
4812 var scrollTop = this.sizingTarget.scrollTop;
4813 this.resetFit();
4814 this.fit();
4815 this.sizingTarget.scrollLeft = scrollLeft;
4816 this.sizingTarget.scrollTop = scrollTop;
4817 },
4818 position: function() {
4819 if (!this.horizontalAlign && !this.verticalAlign) {
4820 return;
4821 }
4822 this._discoverInfo();
4823 this.style.position = 'fixed';
4824 this.sizingTarget.style.boxSizing = 'border-box';
4825 this.style.left = '0px';
4826 this.style.top = '0px';
4827 var rect = this.getBoundingClientRect();
4828 var positionRect = this.__getNormalizedRect(this.positionTarget);
4829 var fitRect = this.__getNormalizedRect(this.fitInto);
4830 var margin = this._fitInfo.margin;
4831 var size = {
4832 width: rect.width + margin.left + margin.right,
4833 height: rect.height + margin.top + margin.bottom
4834 };
4835 var position = this.__getPosition(this._localeHorizontalAlign, this.vertical Align, size, positionRect, fitRect);
4836 var left = position.left + margin.left;
4837 var top = position.top + margin.top;
4838 var right = Math.min(fitRect.right - margin.right, left + rect.width);
4839 var bottom = Math.min(fitRect.bottom - margin.bottom, top + rect.height);
4840 var minWidth = this._fitInfo.sizedBy.minWidth;
4841 var minHeight = this._fitInfo.sizedBy.minHeight;
4842 if (left < margin.left) {
4843 left = margin.left;
4844 if (right - left < minWidth) {
4845 left = right - minWidth;
4846 }
4847 }
4848 if (top < margin.top) {
4849 top = margin.top;
4850 if (bottom - top < minHeight) {
4851 top = bottom - minHeight;
4852 }
4853 }
4854 this.sizingTarget.style.maxWidth = right - left + 'px';
4855 this.sizingTarget.style.maxHeight = bottom - top + 'px';
4856 this.style.left = left - rect.left + 'px';
4857 this.style.top = top - rect.top + 'px';
4858 },
4859 constrain: function() {
4860 if (this.horizontalAlign || this.verticalAlign) {
4861 return;
4862 }
4863 this._discoverInfo();
4864 var info = this._fitInfo;
4865 if (!info.positionedBy.vertically) {
4866 this.style.position = 'fixed';
4867 this.style.top = '0px';
4868 }
4869 if (!info.positionedBy.horizontally) {
4870 this.style.position = 'fixed';
4871 this.style.left = '0px';
4872 }
4873 this.sizingTarget.style.boxSizing = 'border-box';
4874 var rect = this.getBoundingClientRect();
4875 if (!info.sizedBy.height) {
4876 this.__sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
4877 }
4878 if (!info.sizedBy.width) {
4879 this.__sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right' , 'Width');
4880 }
4881 },
4882 _sizeDimension: function(rect, positionedBy, start, end, extent) {
4883 this.__sizeDimension(rect, positionedBy, start, end, extent);
4884 },
4885 __sizeDimension: function(rect, positionedBy, start, end, extent) {
4886 var info = this._fitInfo;
4887 var fitRect = this.__getNormalizedRect(this.fitInto);
4888 var max = extent === 'Width' ? fitRect.width : fitRect.height;
4889 var flip = positionedBy === end;
4890 var offset = flip ? max - rect[end] : rect[start];
4891 var margin = info.margin[flip ? start : end];
4892 var offsetExtent = 'offset' + extent;
4893 var sizingOffset = this[offsetExtent] - this.sizingTarget[offsetExtent];
4894 this.sizingTarget.style['max' + extent] = max - margin - offset - sizingOffs et + 'px';
4895 },
4896 center: function() {
4897 if (this.horizontalAlign || this.verticalAlign) {
4898 return;
4899 }
4900 this._discoverInfo();
4901 var positionedBy = this._fitInfo.positionedBy;
4902 if (positionedBy.vertically && positionedBy.horizontally) {
4903 return;
4904 }
4905 this.style.position = 'fixed';
4906 if (!positionedBy.vertically) {
4907 this.style.top = '0px';
4908 }
4909 if (!positionedBy.horizontally) {
4910 this.style.left = '0px';
4911 }
4912 var rect = this.getBoundingClientRect();
4913 var fitRect = this.__getNormalizedRect(this.fitInto);
4914 if (!positionedBy.vertically) {
4915 var top = fitRect.top - rect.top + (fitRect.height - rect.height) / 2;
4916 this.style.top = top + 'px';
4917 }
4918 if (!positionedBy.horizontally) {
4919 var left = fitRect.left - rect.left + (fitRect.width - rect.width) / 2;
4920 this.style.left = left + 'px';
4921 }
4922 },
4923 __getNormalizedRect: function(target) {
4924 if (target === document.documentElement || target === window) {
4925 return {
4926 top: 0,
4927 left: 0,
4928 width: window.innerWidth,
4929 height: window.innerHeight,
4930 right: window.innerWidth,
4931 bottom: window.innerHeight
4932 };
4933 }
4934 return target.getBoundingClientRect();
4935 },
4936 __getCroppedArea: function(position, size, fitRect) {
4937 var verticalCrop = Math.min(0, position.top) + Math.min(0, fitRect.bottom - (position.top + size.height));
4938 var horizontalCrop = Math.min(0, position.left) + Math.min(0, fitRect.right - (position.left + size.width));
4939 return Math.abs(verticalCrop) * size.width + Math.abs(horizontalCrop) * size .height;
4940 },
4941 __getPosition: function(hAlign, vAlign, size, positionRect, fitRect) {
4942 var positions = [ {
4943 verticalAlign: 'top',
4944 horizontalAlign: 'left',
4945 top: positionRect.top,
4946 left: positionRect.left
4947 }, {
4948 verticalAlign: 'top',
4949 horizontalAlign: 'right',
4950 top: positionRect.top,
4951 left: positionRect.right - size.width
4952 }, {
4953 verticalAlign: 'bottom',
4954 horizontalAlign: 'left',
4955 top: positionRect.bottom - size.height,
4956 left: positionRect.left
4957 }, {
4958 verticalAlign: 'bottom',
4959 horizontalAlign: 'right',
4960 top: positionRect.bottom - size.height,
4961 left: positionRect.right - size.width
4962 } ];
4963 if (this.noOverlap) {
4964 for (var i = 0, l = positions.length; i < l; i++) {
4965 var copy = {};
4966 for (var key in positions[i]) {
4967 copy[key] = positions[i][key];
4968 }
4969 positions.push(copy);
4970 }
4971 positions[0].top = positions[1].top += positionRect.height;
4972 positions[2].top = positions[3].top -= positionRect.height;
4973 positions[4].left = positions[6].left += positionRect.width;
4974 positions[5].left = positions[7].left -= positionRect.width;
4975 }
4976 vAlign = vAlign === 'auto' ? null : vAlign;
4977 hAlign = hAlign === 'auto' ? null : hAlign;
4978 var position;
4979 for (var i = 0; i < positions.length; i++) {
4980 var pos = positions[i];
4981 if (!this.dynamicAlign && !this.noOverlap && pos.verticalAlign === vAlign && pos.horizontalAlign === hAlign) {
4982 position = pos;
4983 break;
4984 }
4985 var alignOk = (!vAlign || pos.verticalAlign === vAlign) && (!hAlign || pos .horizontalAlign === hAlign);
4986 if (!this.dynamicAlign && !alignOk) {
4987 continue;
4988 }
4989 position = position || pos;
4990 pos.croppedArea = this.__getCroppedArea(pos, size, fitRect);
4991 var diff = pos.croppedArea - position.croppedArea;
4992 if (diff < 0 || diff === 0 && alignOk) {
4993 position = pos;
4994 }
4995 if (position.croppedArea === 0 && alignOk) {
4996 break;
4997 }
4998 }
4999 return position;
5000 }
5001 };
5002
5003 (function() {
5004 'use strict';
5005 Polymer({
5006 is: 'iron-overlay-backdrop',
5007 properties: {
5008 opened: {
5009 reflectToAttribute: true,
5010 type: Boolean,
5011 value: false,
5012 observer: '_openedChanged'
5013 }
5014 },
5015 listeners: {
5016 transitionend: '_onTransitionend'
5017 },
5018 created: function() {
5019 this.__openedRaf = null;
5020 },
5021 attached: function() {
5022 this.opened && this._openedChanged(this.opened);
5023 },
5024 prepare: function() {
5025 if (this.opened && !this.parentNode) {
5026 Polymer.dom(document.body).appendChild(this);
5027 }
5028 },
5029 open: function() {
5030 this.opened = true;
5031 },
5032 close: function() {
5033 this.opened = false;
5034 },
5035 complete: function() {
5036 if (!this.opened && this.parentNode === document.body) {
5037 Polymer.dom(this.parentNode).removeChild(this);
5038 }
5039 },
5040 _onTransitionend: function(event) {
5041 if (event && event.target === this) {
5042 this.complete();
5043 }
5044 },
5045 _openedChanged: function(opened) {
5046 if (opened) {
5047 this.prepare();
5048 } else {
5049 var cs = window.getComputedStyle(this);
5050 if (cs.transitionDuration === '0s' || cs.opacity == 0) {
5051 this.complete();
5052 }
5053 }
5054 if (!this.isAttached) {
5055 return;
5056 }
5057 if (this.__openedRaf) {
5058 window.cancelAnimationFrame(this.__openedRaf);
5059 this.__openedRaf = null;
5060 }
5061 this.scrollTop = this.scrollTop;
5062 this.__openedRaf = window.requestAnimationFrame(function() {
5063 this.__openedRaf = null;
5064 this.toggleClass('opened', this.opened);
5065 }.bind(this));
5066 }
5067 });
5068 })();
5069
5070 Polymer.IronOverlayManagerClass = function() {
5071 this._overlays = [];
5072 this._minimumZ = 101;
5073 this._backdropElement = null;
5074 Polymer.Gestures.add(document, 'tap', this._onCaptureClick.bind(this));
5075 document.addEventListener('focus', this._onCaptureFocus.bind(this), true);
5076 document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true);
5077 };
5078
5079 Polymer.IronOverlayManagerClass.prototype = {
5080 constructor: Polymer.IronOverlayManagerClass,
5081 get backdropElement() {
5082 if (!this._backdropElement) {
5083 this._backdropElement = document.createElement('iron-overlay-backdrop');
5084 }
5085 return this._backdropElement;
5086 },
5087 get deepActiveElement() {
5088 var active = document.activeElement || document.body;
5089 while (active.root && Polymer.dom(active.root).activeElement) {
5090 active = Polymer.dom(active.root).activeElement;
5091 }
5092 return active;
5093 },
5094 _bringOverlayAtIndexToFront: function(i) {
5095 var overlay = this._overlays[i];
5096 if (!overlay) {
5097 return;
5098 }
5099 var lastI = this._overlays.length - 1;
5100 var currentOverlay = this._overlays[lastI];
5101 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
5102 lastI--;
5103 }
5104 if (i >= lastI) {
5105 return;
5106 }
5107 var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
5108 if (this._getZ(overlay) <= minimumZ) {
5109 this._applyOverlayZ(overlay, minimumZ);
5110 }
5111 while (i < lastI) {
5112 this._overlays[i] = this._overlays[i + 1];
5113 i++;
5114 }
5115 this._overlays[lastI] = overlay;
5116 },
5117 addOrRemoveOverlay: function(overlay) {
5118 if (overlay.opened) {
5119 this.addOverlay(overlay);
5120 } else {
5121 this.removeOverlay(overlay);
5122 }
5123 },
5124 addOverlay: function(overlay) {
5125 var i = this._overlays.indexOf(overlay);
5126 if (i >= 0) {
5127 this._bringOverlayAtIndexToFront(i);
5128 this.trackBackdrop();
5129 return;
5130 }
5131 var insertionIndex = this._overlays.length;
5132 var currentOverlay = this._overlays[insertionIndex - 1];
5133 var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ);
5134 var newZ = this._getZ(overlay);
5135 if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
5136 this._applyOverlayZ(currentOverlay, minimumZ);
5137 insertionIndex--;
5138 var previousOverlay = this._overlays[insertionIndex - 1];
5139 minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ);
5140 }
5141 if (newZ <= minimumZ) {
5142 this._applyOverlayZ(overlay, minimumZ);
5143 }
5144 this._overlays.splice(insertionIndex, 0, overlay);
5145 this.trackBackdrop();
5146 },
5147 removeOverlay: function(overlay) {
5148 var i = this._overlays.indexOf(overlay);
5149 if (i === -1) {
5150 return;
5151 }
5152 this._overlays.splice(i, 1);
5153 this.trackBackdrop();
5154 },
5155 currentOverlay: function() {
5156 var i = this._overlays.length - 1;
5157 return this._overlays[i];
5158 },
5159 currentOverlayZ: function() {
5160 return this._getZ(this.currentOverlay());
5161 },
5162 ensureMinimumZ: function(minimumZ) {
5163 this._minimumZ = Math.max(this._minimumZ, minimumZ);
5164 },
5165 focusOverlay: function() {
5166 var current = this.currentOverlay();
5167 if (current) {
5168 current._applyFocus();
5169 }
5170 },
5171 trackBackdrop: function() {
5172 var overlay = this._overlayWithBackdrop();
5173 if (!overlay && !this._backdropElement) {
5174 return;
5175 }
5176 this.backdropElement.style.zIndex = this._getZ(overlay) - 1;
5177 this.backdropElement.opened = !!overlay;
5178 },
5179 getBackdrops: function() {
5180 var backdrops = [];
5181 for (var i = 0; i < this._overlays.length; i++) {
5182 if (this._overlays[i].withBackdrop) {
5183 backdrops.push(this._overlays[i]);
5184 }
5185 }
5186 return backdrops;
5187 },
5188 backdropZ: function() {
5189 return this._getZ(this._overlayWithBackdrop()) - 1;
5190 },
5191 _overlayWithBackdrop: function() {
5192 for (var i = 0; i < this._overlays.length; i++) {
5193 if (this._overlays[i].withBackdrop) {
5194 return this._overlays[i];
5195 }
5196 }
5197 },
5198 _getZ: function(overlay) {
5199 var z = this._minimumZ;
5200 if (overlay) {
5201 var z1 = Number(overlay.style.zIndex || window.getComputedStyle(overlay).z Index);
5202 if (z1 === z1) {
5203 z = z1;
5204 }
5205 }
5206 return z;
5207 },
5208 _setZ: function(element, z) {
5209 element.style.zIndex = z;
5210 },
5211 _applyOverlayZ: function(overlay, aboveZ) {
5212 this._setZ(overlay, aboveZ + 2);
5213 },
5214 _overlayInPath: function(path) {
5215 path = path || [];
5216 for (var i = 0; i < path.length; i++) {
5217 if (path[i]._manager === this) {
5218 return path[i];
5219 }
5220 }
5221 },
5222 _onCaptureClick: function(event) {
5223 var overlay = this.currentOverlay();
5224 if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) {
5225 overlay._onCaptureClick(event);
5226 }
5227 },
5228 _onCaptureFocus: function(event) {
5229 var overlay = this.currentOverlay();
5230 if (overlay) {
5231 overlay._onCaptureFocus(event);
5232 }
5233 },
5234 _onCaptureKeyDown: function(event) {
5235 var overlay = this.currentOverlay();
5236 if (overlay) {
5237 if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'esc')) {
5238 overlay._onCaptureEsc(event);
5239 } else if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 't ab')) {
5240 overlay._onCaptureTab(event);
5241 }
5242 }
5243 },
5244 _shouldBeBehindOverlay: function(overlay1, overlay2) {
5245 return !overlay1.alwaysOnTop && overlay2.alwaysOnTop;
5246 }
5247 };
5248
5249 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();
5250
5251 (function() {
5252 'use strict';
5253 Polymer.IronOverlayBehaviorImpl = {
5254 properties: {
5255 opened: {
5256 observer: '_openedChanged',
5257 type: Boolean,
5258 value: false,
5259 notify: true
5260 },
5261 canceled: {
5262 observer: '_canceledChanged',
5263 readOnly: true,
5264 type: Boolean,
5265 value: false
5266 },
5267 withBackdrop: {
5268 observer: '_withBackdropChanged',
5269 type: Boolean
5270 },
5271 noAutoFocus: {
5272 type: Boolean,
5273 value: false
5274 },
5275 noCancelOnEscKey: {
5276 type: Boolean,
5277 value: false
5278 },
5279 noCancelOnOutsideClick: {
5280 type: Boolean,
5281 value: false
5282 },
5283 closingReason: {
5284 type: Object
5285 },
5286 restoreFocusOnClose: {
5287 type: Boolean,
5288 value: false
5289 },
5290 alwaysOnTop: {
5291 type: Boolean
5292 },
5293 _manager: {
5294 type: Object,
5295 value: Polymer.IronOverlayManager
5296 },
5297 _focusedChild: {
5298 type: Object
5299 }
5300 },
5301 listeners: {
5302 'iron-resize': '_onIronResize'
5303 },
5304 get backdropElement() {
5305 return this._manager.backdropElement;
5306 },
5307 get _focusNode() {
5308 return this._focusedChild || Polymer.dom(this).querySelector('[autofocus]' ) || this;
5309 },
5310 get _focusableNodes() {
5311 var FOCUSABLE_WITH_DISABLED = [ 'a[href]', 'area[href]', 'iframe', '[tabin dex]', '[contentEditable=true]' ];
5312 var FOCUSABLE_WITHOUT_DISABLED = [ 'input', 'select', 'textarea', 'button' ];
5313 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"])';
5314 var focusables = Polymer.dom(this).querySelectorAll(selector);
5315 if (this.tabIndex >= 0) {
5316 focusables.splice(0, 0, this);
5317 }
5318 return focusables.sort(function(a, b) {
5319 if (a.tabIndex === b.tabIndex) {
5320 return 0;
5321 }
5322 if (a.tabIndex === 0 || a.tabIndex > b.tabIndex) {
5323 return 1;
5324 }
5325 return -1;
5326 });
5327 },
5328 ready: function() {
5329 this.__isAnimating = false;
5330 this.__shouldRemoveTabIndex = false;
5331 this.__firstFocusableNode = this.__lastFocusableNode = null;
5332 this.__raf = null;
5333 this.__restoreFocusNode = null;
5334 this._ensureSetup();
5335 },
5336 attached: function() {
5337 if (this.opened) {
5338 this._openedChanged(this.opened);
5339 }
5340 this._observer = Polymer.dom(this).observeNodes(this._onNodesChange);
5341 },
5342 detached: function() {
5343 Polymer.dom(this).unobserveNodes(this._observer);
5344 this._observer = null;
5345 if (this.__raf) {
5346 window.cancelAnimationFrame(this.__raf);
5347 this.__raf = null;
5348 }
5349 this._manager.removeOverlay(this);
5350 },
5351 toggle: function() {
5352 this._setCanceled(false);
5353 this.opened = !this.opened;
5354 },
5355 open: function() {
5356 this._setCanceled(false);
5357 this.opened = true;
5358 },
5359 close: function() {
5360 this._setCanceled(false);
5361 this.opened = false;
5362 },
5363 cancel: function(event) {
5364 var cancelEvent = this.fire('iron-overlay-canceled', event, {
5365 cancelable: true
5366 });
5367 if (cancelEvent.defaultPrevented) {
5368 return;
5369 }
5370 this._setCanceled(true);
5371 this.opened = false;
5372 },
5373 _ensureSetup: function() {
5374 if (this._overlaySetup) {
5375 return;
5376 }
5377 this._overlaySetup = true;
5378 this.style.outline = 'none';
5379 this.style.display = 'none';
5380 },
5381 _openedChanged: function(opened) {
5382 if (opened) {
5383 this.removeAttribute('aria-hidden');
5384 } else {
5385 this.setAttribute('aria-hidden', 'true');
5386 }
5387 if (!this.isAttached) {
5388 return;
5389 }
5390 this.__isAnimating = true;
5391 this.__onNextAnimationFrame(this.__openedChanged);
5392 },
5393 _canceledChanged: function() {
5394 this.closingReason = this.closingReason || {};
5395 this.closingReason.canceled = this.canceled;
5396 },
5397 _withBackdropChanged: function() {
5398 if (this.withBackdrop && !this.hasAttribute('tabindex')) {
5399 this.setAttribute('tabindex', '-1');
5400 this.__shouldRemoveTabIndex = true;
5401 } else if (this.__shouldRemoveTabIndex) {
5402 this.removeAttribute('tabindex');
5403 this.__shouldRemoveTabIndex = false;
5404 }
5405 if (this.opened && this.isAttached) {
5406 this._manager.trackBackdrop();
5407 }
5408 },
5409 _prepareRenderOpened: function() {
5410 this.__restoreFocusNode = this._manager.deepActiveElement;
5411 this._preparePositioning();
5412 this.refit();
5413 this._finishPositioning();
5414 if (this.noAutoFocus && document.activeElement === this._focusNode) {
5415 this._focusNode.blur();
5416 this.__restoreFocusNode.focus();
5417 }
5418 },
5419 _renderOpened: function() {
5420 this._finishRenderOpened();
5421 },
5422 _renderClosed: function() {
5423 this._finishRenderClosed();
5424 },
5425 _finishRenderOpened: function() {
5426 this.notifyResize();
5427 this.__isAnimating = false;
5428 var focusableNodes = this._focusableNodes;
5429 this.__firstFocusableNode = focusableNodes[0];
5430 this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1];
5431 this.fire('iron-overlay-opened');
5432 },
5433 _finishRenderClosed: function() {
5434 this.style.display = 'none';
5435 this.style.zIndex = '';
5436 this.notifyResize();
5437 this.__isAnimating = false;
5438 this.fire('iron-overlay-closed', this.closingReason);
5439 },
5440 _preparePositioning: function() {
5441 this.style.transition = this.style.webkitTransition = 'none';
5442 this.style.transform = this.style.webkitTransform = 'none';
5443 this.style.display = '';
5444 },
5445 _finishPositioning: function() {
5446 this.style.display = 'none';
5447 this.scrollTop = this.scrollTop;
5448 this.style.transition = this.style.webkitTransition = '';
5449 this.style.transform = this.style.webkitTransform = '';
5450 this.style.display = '';
5451 this.scrollTop = this.scrollTop;
5452 },
5453 _applyFocus: function() {
5454 if (this.opened) {
5455 if (!this.noAutoFocus) {
5456 this._focusNode.focus();
5457 }
5458 } else {
5459 this._focusNode.blur();
5460 this._focusedChild = null;
5461 if (this.restoreFocusOnClose && this.__restoreFocusNode) {
5462 this.__restoreFocusNode.focus();
5463 }
5464 this.__restoreFocusNode = null;
5465 var currentOverlay = this._manager.currentOverlay();
5466 if (currentOverlay && this !== currentOverlay) {
5467 currentOverlay._applyFocus();
5468 }
5469 }
5470 },
5471 _onCaptureClick: function(event) {
5472 if (!this.noCancelOnOutsideClick) {
5473 this.cancel(event);
5474 }
5475 },
5476 _onCaptureFocus: function(event) {
5477 if (!this.withBackdrop) {
5478 return;
5479 }
5480 var path = Polymer.dom(event).path;
5481 if (path.indexOf(this) === -1) {
5482 event.stopPropagation();
5483 this._applyFocus();
5484 } else {
5485 this._focusedChild = path[0];
5486 }
5487 },
5488 _onCaptureEsc: function(event) {
5489 if (!this.noCancelOnEscKey) {
5490 this.cancel(event);
5491 }
5492 },
5493 _onCaptureTab: function(event) {
5494 if (!this.withBackdrop) {
5495 return;
5496 }
5497 var shift = event.shiftKey;
5498 var nodeToCheck = shift ? this.__firstFocusableNode : this.__lastFocusable Node;
5499 var nodeToSet = shift ? this.__lastFocusableNode : this.__firstFocusableNo de;
5500 var shouldWrap = false;
5501 if (nodeToCheck === nodeToSet) {
5502 shouldWrap = true;
5503 } else {
5504 var focusedNode = this._manager.deepActiveElement;
5505 shouldWrap = focusedNode === nodeToCheck || focusedNode === this;
5506 }
5507 if (shouldWrap) {
5508 event.preventDefault();
5509 this._focusedChild = nodeToSet;
5510 this._applyFocus();
5511 }
5512 },
5513 _onIronResize: function() {
5514 if (this.opened && !this.__isAnimating) {
5515 this.__onNextAnimationFrame(this.refit);
5516 }
5517 },
5518 _onNodesChange: function() {
5519 if (this.opened && !this.__isAnimating) {
5520 this.notifyResize();
5521 }
5522 },
5523 __openedChanged: function() {
5524 if (this.opened) {
5525 this._prepareRenderOpened();
5526 this._manager.addOverlay(this);
5527 this._applyFocus();
5528 this._renderOpened();
5529 } else {
5530 this._manager.removeOverlay(this);
5531 this._applyFocus();
5532 this._renderClosed();
5533 }
5534 },
5535 __onNextAnimationFrame: function(callback) {
5536 if (this.__raf) {
5537 window.cancelAnimationFrame(this.__raf);
5538 }
5539 var self = this;
5540 this.__raf = window.requestAnimationFrame(function nextAnimationFrame() {
5541 self.__raf = null;
5542 callback.call(self);
5543 });
5544 }
5545 };
5546 Polymer.IronOverlayBehavior = [ Polymer.IronFitBehavior, Polymer.IronResizable Behavior, Polymer.IronOverlayBehaviorImpl ];
5547 })();
5548
5549 Polymer.NeonAnimatableBehavior = { 3343 Polymer.NeonAnimatableBehavior = {
5550 properties: { 3344 properties: {
5551 animationConfig: { 3345 animationConfig: {
5552 type: Object 3346 type: Object
5553 }, 3347 },
5554 entryAnimation: { 3348 entryAnimation: {
5555 observer: '_entryAnimationChanged', 3349 observer: '_entryAnimationChanged',
5556 type: String 3350 type: String
5557 }, 3351 },
5558 exitAnimation: { 3352 exitAnimation: {
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
6112 if (focusTarget && this.opened && !this.noAutoFocus) { 3906 if (focusTarget && this.opened && !this.noAutoFocus) {
6113 focusTarget.focus(); 3907 focusTarget.focus();
6114 } else { 3908 } else {
6115 Polymer.IronOverlayBehaviorImpl._applyFocus.apply(this, arguments); 3909 Polymer.IronOverlayBehaviorImpl._applyFocus.apply(this, arguments);
6116 } 3910 }
6117 } 3911 }
6118 }); 3912 });
6119 })(); 3913 })();
6120 3914
6121 Polymer({ 3915 Polymer({
3916 is: 'iron-icon',
3917 properties: {
3918 icon: {
3919 type: String,
3920 observer: '_iconChanged'
3921 },
3922 theme: {
3923 type: String,
3924 observer: '_updateIcon'
3925 },
3926 src: {
3927 type: String,
3928 observer: '_srcChanged'
3929 },
3930 _meta: {
3931 value: Polymer.Base.create('iron-meta', {
3932 type: 'iconset'
3933 }),
3934 observer: '_updateIcon'
3935 }
3936 },
3937 _DEFAULT_ICONSET: 'icons',
3938 _iconChanged: function(icon) {
3939 var parts = (icon || '').split(':');
3940 this._iconName = parts.pop();
3941 this._iconsetName = parts.pop() || this._DEFAULT_ICONSET;
3942 this._updateIcon();
3943 },
3944 _srcChanged: function(src) {
3945 this._updateIcon();
3946 },
3947 _usesIconset: function() {
3948 return this.icon || !this.src;
3949 },
3950 _updateIcon: function() {
3951 if (this._usesIconset()) {
3952 if (this._img && this._img.parentNode) {
3953 Polymer.dom(this.root).removeChild(this._img);
3954 }
3955 if (this._iconName === "") {
3956 if (this._iconset) {
3957 this._iconset.removeIcon(this);
3958 }
3959 } else if (this._iconsetName && this._meta) {
3960 this._iconset = this._meta.byKey(this._iconsetName);
3961 if (this._iconset) {
3962 this._iconset.applyIcon(this, this._iconName, this.theme);
3963 this.unlisten(window, 'iron-iconset-added', '_updateIcon');
3964 } else {
3965 this.listen(window, 'iron-iconset-added', '_updateIcon');
3966 }
3967 }
3968 } else {
3969 if (this._iconset) {
3970 this._iconset.removeIcon(this);
3971 }
3972 if (!this._img) {
3973 this._img = document.createElement('img');
3974 this._img.style.width = '100%';
3975 this._img.style.height = '100%';
3976 this._img.draggable = false;
3977 }
3978 this._img.src = this.src;
3979 Polymer.dom(this.root).appendChild(this._img);
3980 }
3981 }
3982 });
3983
3984 Polymer.IronButtonStateImpl = {
3985 properties: {
3986 pressed: {
3987 type: Boolean,
3988 readOnly: true,
3989 value: false,
3990 reflectToAttribute: true,
3991 observer: '_pressedChanged'
3992 },
3993 toggles: {
3994 type: Boolean,
3995 value: false,
3996 reflectToAttribute: true
3997 },
3998 active: {
3999 type: Boolean,
4000 value: false,
4001 notify: true,
4002 reflectToAttribute: true
4003 },
4004 pointerDown: {
4005 type: Boolean,
4006 readOnly: true,
4007 value: false
4008 },
4009 receivedFocusFromKeyboard: {
4010 type: Boolean,
4011 readOnly: true
4012 },
4013 ariaActiveAttribute: {
4014 type: String,
4015 value: 'aria-pressed',
4016 observer: '_ariaActiveAttributeChanged'
4017 }
4018 },
4019 listeners: {
4020 down: '_downHandler',
4021 up: '_upHandler',
4022 tap: '_tapHandler'
4023 },
4024 observers: [ '_detectKeyboardFocus(focused)', '_activeChanged(active, ariaActi veAttribute)' ],
4025 keyBindings: {
4026 'enter:keydown': '_asyncClick',
4027 'space:keydown': '_spaceKeyDownHandler',
4028 'space:keyup': '_spaceKeyUpHandler'
4029 },
4030 _mouseEventRe: /^mouse/,
4031 _tapHandler: function() {
4032 if (this.toggles) {
4033 this._userActivate(!this.active);
4034 } else {
4035 this.active = false;
4036 }
4037 },
4038 _detectKeyboardFocus: function(focused) {
4039 this._setReceivedFocusFromKeyboard(!this.pointerDown && focused);
4040 },
4041 _userActivate: function(active) {
4042 if (this.active !== active) {
4043 this.active = active;
4044 this.fire('change');
4045 }
4046 },
4047 _downHandler: function(event) {
4048 this._setPointerDown(true);
4049 this._setPressed(true);
4050 this._setReceivedFocusFromKeyboard(false);
4051 },
4052 _upHandler: function() {
4053 this._setPointerDown(false);
4054 this._setPressed(false);
4055 },
4056 _spaceKeyDownHandler: function(event) {
4057 var keyboardEvent = event.detail.keyboardEvent;
4058 var target = Polymer.dom(keyboardEvent).localTarget;
4059 if (this.isLightDescendant(target)) return;
4060 keyboardEvent.preventDefault();
4061 keyboardEvent.stopImmediatePropagation();
4062 this._setPressed(true);
4063 },
4064 _spaceKeyUpHandler: function(event) {
4065 var keyboardEvent = event.detail.keyboardEvent;
4066 var target = Polymer.dom(keyboardEvent).localTarget;
4067 if (this.isLightDescendant(target)) return;
4068 if (this.pressed) {
4069 this._asyncClick();
4070 }
4071 this._setPressed(false);
4072 },
4073 _asyncClick: function() {
4074 this.async(function() {
4075 this.click();
4076 }, 1);
4077 },
4078 _pressedChanged: function(pressed) {
4079 this._changedButtonState();
4080 },
4081 _ariaActiveAttributeChanged: function(value, oldValue) {
4082 if (oldValue && oldValue != value && this.hasAttribute(oldValue)) {
4083 this.removeAttribute(oldValue);
4084 }
4085 },
4086 _activeChanged: function(active, ariaActiveAttribute) {
4087 if (this.toggles) {
4088 this.setAttribute(this.ariaActiveAttribute, active ? 'true' : 'false');
4089 } else {
4090 this.removeAttribute(this.ariaActiveAttribute);
4091 }
4092 this._changedButtonState();
4093 },
4094 _controlStateChanged: function() {
4095 if (this.disabled) {
4096 this._setPressed(false);
4097 } else {
4098 this._changedButtonState();
4099 }
4100 },
4101 _changedButtonState: function() {
4102 if (this._buttonStateChanged) {
4103 this._buttonStateChanged();
4104 }
4105 }
4106 };
4107
4108 Polymer.IronButtonState = [ Polymer.IronA11yKeysBehavior, Polymer.IronButtonStat eImpl ];
4109
4110 (function() {
4111 var Utility = {
4112 distance: function(x1, y1, x2, y2) {
4113 var xDelta = x1 - x2;
4114 var yDelta = y1 - y2;
4115 return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
4116 },
4117 now: window.performance && window.performance.now ? window.performance.now.b ind(window.performance) : Date.now
4118 };
4119 function ElementMetrics(element) {
4120 this.element = element;
4121 this.width = this.boundingRect.width;
4122 this.height = this.boundingRect.height;
4123 this.size = Math.max(this.width, this.height);
4124 }
4125 ElementMetrics.prototype = {
4126 get boundingRect() {
4127 return this.element.getBoundingClientRect();
4128 },
4129 furthestCornerDistanceFrom: function(x, y) {
4130 var topLeft = Utility.distance(x, y, 0, 0);
4131 var topRight = Utility.distance(x, y, this.width, 0);
4132 var bottomLeft = Utility.distance(x, y, 0, this.height);
4133 var bottomRight = Utility.distance(x, y, this.width, this.height);
4134 return Math.max(topLeft, topRight, bottomLeft, bottomRight);
4135 }
4136 };
4137 function Ripple(element) {
4138 this.element = element;
4139 this.color = window.getComputedStyle(element).color;
4140 this.wave = document.createElement('div');
4141 this.waveContainer = document.createElement('div');
4142 this.wave.style.backgroundColor = this.color;
4143 this.wave.classList.add('wave');
4144 this.waveContainer.classList.add('wave-container');
4145 Polymer.dom(this.waveContainer).appendChild(this.wave);
4146 this.resetInteractionState();
4147 }
4148 Ripple.MAX_RADIUS = 300;
4149 Ripple.prototype = {
4150 get recenters() {
4151 return this.element.recenters;
4152 },
4153 get center() {
4154 return this.element.center;
4155 },
4156 get mouseDownElapsed() {
4157 var elapsed;
4158 if (!this.mouseDownStart) {
4159 return 0;
4160 }
4161 elapsed = Utility.now() - this.mouseDownStart;
4162 if (this.mouseUpStart) {
4163 elapsed -= this.mouseUpElapsed;
4164 }
4165 return elapsed;
4166 },
4167 get mouseUpElapsed() {
4168 return this.mouseUpStart ? Utility.now() - this.mouseUpStart : 0;
4169 },
4170 get mouseDownElapsedSeconds() {
4171 return this.mouseDownElapsed / 1e3;
4172 },
4173 get mouseUpElapsedSeconds() {
4174 return this.mouseUpElapsed / 1e3;
4175 },
4176 get mouseInteractionSeconds() {
4177 return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds;
4178 },
4179 get initialOpacity() {
4180 return this.element.initialOpacity;
4181 },
4182 get opacityDecayVelocity() {
4183 return this.element.opacityDecayVelocity;
4184 },
4185 get radius() {
4186 var width2 = this.containerMetrics.width * this.containerMetrics.width;
4187 var height2 = this.containerMetrics.height * this.containerMetrics.height;
4188 var waveRadius = Math.min(Math.sqrt(width2 + height2), Ripple.MAX_RADIUS) * 1.1 + 5;
4189 var duration = 1.1 - .2 * (waveRadius / Ripple.MAX_RADIUS);
4190 var timeNow = this.mouseInteractionSeconds / duration;
4191 var size = waveRadius * (1 - Math.pow(80, -timeNow));
4192 return Math.abs(size);
4193 },
4194 get opacity() {
4195 if (!this.mouseUpStart) {
4196 return this.initialOpacity;
4197 }
4198 return Math.max(0, this.initialOpacity - this.mouseUpElapsedSeconds * this .opacityDecayVelocity);
4199 },
4200 get outerOpacity() {
4201 var outerOpacity = this.mouseUpElapsedSeconds * .3;
4202 var waveOpacity = this.opacity;
4203 return Math.max(0, Math.min(outerOpacity, waveOpacity));
4204 },
4205 get isOpacityFullyDecayed() {
4206 return this.opacity < .01 && this.radius >= Math.min(this.maxRadius, Rippl e.MAX_RADIUS);
4207 },
4208 get isRestingAtMaxRadius() {
4209 return this.opacity >= this.initialOpacity && this.radius >= Math.min(this .maxRadius, Ripple.MAX_RADIUS);
4210 },
4211 get isAnimationComplete() {
4212 return this.mouseUpStart ? this.isOpacityFullyDecayed : this.isRestingAtMa xRadius;
4213 },
4214 get translationFraction() {
4215 return Math.min(1, this.radius / this.containerMetrics.size * 2 / Math.sqr t(2));
4216 },
4217 get xNow() {
4218 if (this.xEnd) {
4219 return this.xStart + this.translationFraction * (this.xEnd - this.xStart );
4220 }
4221 return this.xStart;
4222 },
4223 get yNow() {
4224 if (this.yEnd) {
4225 return this.yStart + this.translationFraction * (this.yEnd - this.yStart );
4226 }
4227 return this.yStart;
4228 },
4229 get isMouseDown() {
4230 return this.mouseDownStart && !this.mouseUpStart;
4231 },
4232 resetInteractionState: function() {
4233 this.maxRadius = 0;
4234 this.mouseDownStart = 0;
4235 this.mouseUpStart = 0;
4236 this.xStart = 0;
4237 this.yStart = 0;
4238 this.xEnd = 0;
4239 this.yEnd = 0;
4240 this.slideDistance = 0;
4241 this.containerMetrics = new ElementMetrics(this.element);
4242 },
4243 draw: function() {
4244 var scale;
4245 var translateString;
4246 var dx;
4247 var dy;
4248 this.wave.style.opacity = this.opacity;
4249 scale = this.radius / (this.containerMetrics.size / 2);
4250 dx = this.xNow - this.containerMetrics.width / 2;
4251 dy = this.yNow - this.containerMetrics.height / 2;
4252 this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' + dy + 'px)';
4253 this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy + ' px, 0)';
4254 this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')';
4255 this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)';
4256 },
4257 downAction: function(event) {
4258 var xCenter = this.containerMetrics.width / 2;
4259 var yCenter = this.containerMetrics.height / 2;
4260 this.resetInteractionState();
4261 this.mouseDownStart = Utility.now();
4262 if (this.center) {
4263 this.xStart = xCenter;
4264 this.yStart = yCenter;
4265 this.slideDistance = Utility.distance(this.xStart, this.yStart, this.xEn d, this.yEnd);
4266 } else {
4267 this.xStart = event ? event.detail.x - this.containerMetrics.boundingRec t.left : this.containerMetrics.width / 2;
4268 this.yStart = event ? event.detail.y - this.containerMetrics.boundingRec t.top : this.containerMetrics.height / 2;
4269 }
4270 if (this.recenters) {
4271 this.xEnd = xCenter;
4272 this.yEnd = yCenter;
4273 this.slideDistance = Utility.distance(this.xStart, this.yStart, this.xEn d, this.yEnd);
4274 }
4275 this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom(this.xSt art, this.yStart);
4276 this.waveContainer.style.top = (this.containerMetrics.height - this.contai nerMetrics.size) / 2 + 'px';
4277 this.waveContainer.style.left = (this.containerMetrics.width - this.contai nerMetrics.size) / 2 + 'px';
4278 this.waveContainer.style.width = this.containerMetrics.size + 'px';
4279 this.waveContainer.style.height = this.containerMetrics.size + 'px';
4280 },
4281 upAction: function(event) {
4282 if (!this.isMouseDown) {
4283 return;
4284 }
4285 this.mouseUpStart = Utility.now();
4286 },
4287 remove: function() {
4288 Polymer.dom(this.waveContainer.parentNode).removeChild(this.waveContainer) ;
4289 }
4290 };
4291 Polymer({
4292 is: 'paper-ripple',
4293 behaviors: [ Polymer.IronA11yKeysBehavior ],
4294 properties: {
4295 initialOpacity: {
4296 type: Number,
4297 value: .25
4298 },
4299 opacityDecayVelocity: {
4300 type: Number,
4301 value: .8
4302 },
4303 recenters: {
4304 type: Boolean,
4305 value: false
4306 },
4307 center: {
4308 type: Boolean,
4309 value: false
4310 },
4311 ripples: {
4312 type: Array,
4313 value: function() {
4314 return [];
4315 }
4316 },
4317 animating: {
4318 type: Boolean,
4319 readOnly: true,
4320 reflectToAttribute: true,
4321 value: false
4322 },
4323 holdDown: {
4324 type: Boolean,
4325 value: false,
4326 observer: '_holdDownChanged'
4327 },
4328 noink: {
4329 type: Boolean,
4330 value: false
4331 },
4332 _animating: {
4333 type: Boolean
4334 },
4335 _boundAnimate: {
4336 type: Function,
4337 value: function() {
4338 return this.animate.bind(this);
4339 }
4340 }
4341 },
4342 get target() {
4343 return this.keyEventTarget;
4344 },
4345 keyBindings: {
4346 'enter:keydown': '_onEnterKeydown',
4347 'space:keydown': '_onSpaceKeydown',
4348 'space:keyup': '_onSpaceKeyup'
4349 },
4350 attached: function() {
4351 if (this.parentNode.nodeType == 11) {
4352 this.keyEventTarget = Polymer.dom(this).getOwnerRoot().host;
4353 } else {
4354 this.keyEventTarget = this.parentNode;
4355 }
4356 var keyEventTarget = this.keyEventTarget;
4357 this.listen(keyEventTarget, 'up', 'uiUpAction');
4358 this.listen(keyEventTarget, 'down', 'uiDownAction');
4359 },
4360 detached: function() {
4361 this.unlisten(this.keyEventTarget, 'up', 'uiUpAction');
4362 this.unlisten(this.keyEventTarget, 'down', 'uiDownAction');
4363 this.keyEventTarget = null;
4364 },
4365 get shouldKeepAnimating() {
4366 for (var index = 0; index < this.ripples.length; ++index) {
4367 if (!this.ripples[index].isAnimationComplete) {
4368 return true;
4369 }
4370 }
4371 return false;
4372 },
4373 simulatedRipple: function() {
4374 this.downAction(null);
4375 this.async(function() {
4376 this.upAction();
4377 }, 1);
4378 },
4379 uiDownAction: function(event) {
4380 if (!this.noink) {
4381 this.downAction(event);
4382 }
4383 },
4384 downAction: function(event) {
4385 if (this.holdDown && this.ripples.length > 0) {
4386 return;
4387 }
4388 var ripple = this.addRipple();
4389 ripple.downAction(event);
4390 if (!this._animating) {
4391 this._animating = true;
4392 this.animate();
4393 }
4394 },
4395 uiUpAction: function(event) {
4396 if (!this.noink) {
4397 this.upAction(event);
4398 }
4399 },
4400 upAction: function(event) {
4401 if (this.holdDown) {
4402 return;
4403 }
4404 this.ripples.forEach(function(ripple) {
4405 ripple.upAction(event);
4406 });
4407 this._animating = true;
4408 this.animate();
4409 },
4410 onAnimationComplete: function() {
4411 this._animating = false;
4412 this.$.background.style.backgroundColor = null;
4413 this.fire('transitionend');
4414 },
4415 addRipple: function() {
4416 var ripple = new Ripple(this);
4417 Polymer.dom(this.$.waves).appendChild(ripple.waveContainer);
4418 this.$.background.style.backgroundColor = ripple.color;
4419 this.ripples.push(ripple);
4420 this._setAnimating(true);
4421 return ripple;
4422 },
4423 removeRipple: function(ripple) {
4424 var rippleIndex = this.ripples.indexOf(ripple);
4425 if (rippleIndex < 0) {
4426 return;
4427 }
4428 this.ripples.splice(rippleIndex, 1);
4429 ripple.remove();
4430 if (!this.ripples.length) {
4431 this._setAnimating(false);
4432 }
4433 },
4434 animate: function() {
4435 if (!this._animating) {
4436 return;
4437 }
4438 var index;
4439 var ripple;
4440 for (index = 0; index < this.ripples.length; ++index) {
4441 ripple = this.ripples[index];
4442 ripple.draw();
4443 this.$.background.style.opacity = ripple.outerOpacity;
4444 if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) {
4445 this.removeRipple(ripple);
4446 }
4447 }
4448 if (!this.shouldKeepAnimating && this.ripples.length === 0) {
4449 this.onAnimationComplete();
4450 } else {
4451 window.requestAnimationFrame(this._boundAnimate);
4452 }
4453 },
4454 _onEnterKeydown: function() {
4455 this.uiDownAction();
4456 this.async(this.uiUpAction, 1);
4457 },
4458 _onSpaceKeydown: function() {
4459 this.uiDownAction();
4460 },
4461 _onSpaceKeyup: function() {
4462 this.uiUpAction();
4463 },
4464 _holdDownChanged: function(newVal, oldVal) {
4465 if (oldVal === undefined) {
4466 return;
4467 }
4468 if (newVal) {
4469 this.downAction();
4470 } else {
4471 this.upAction();
4472 }
4473 }
4474 });
4475 })();
4476
4477 Polymer.PaperRippleBehavior = {
4478 properties: {
4479 noink: {
4480 type: Boolean,
4481 observer: '_noinkChanged'
4482 },
4483 _rippleContainer: {
4484 type: Object
4485 }
4486 },
4487 _buttonStateChanged: function() {
4488 if (this.focused) {
4489 this.ensureRipple();
4490 }
4491 },
4492 _downHandler: function(event) {
4493 Polymer.IronButtonStateImpl._downHandler.call(this, event);
4494 if (this.pressed) {
4495 this.ensureRipple(event);
4496 }
4497 },
4498 ensureRipple: function(optTriggeringEvent) {
4499 if (!this.hasRipple()) {
4500 this._ripple = this._createRipple();
4501 this._ripple.noink = this.noink;
4502 var rippleContainer = this._rippleContainer || this.root;
4503 if (rippleContainer) {
4504 Polymer.dom(rippleContainer).appendChild(this._ripple);
4505 }
4506 if (optTriggeringEvent) {
4507 var domContainer = Polymer.dom(this._rippleContainer || this);
4508 var target = Polymer.dom(optTriggeringEvent).rootTarget;
4509 if (domContainer.deepContains(target)) {
4510 this._ripple.uiDownAction(optTriggeringEvent);
4511 }
4512 }
4513 }
4514 },
4515 getRipple: function() {
4516 this.ensureRipple();
4517 return this._ripple;
4518 },
4519 hasRipple: function() {
4520 return Boolean(this._ripple);
4521 },
4522 _createRipple: function() {
4523 return document.createElement('paper-ripple');
4524 },
4525 _noinkChanged: function(noink) {
4526 if (this.hasRipple()) {
4527 this._ripple.noink = noink;
4528 }
4529 }
4530 };
4531
4532 Polymer.PaperButtonBehaviorImpl = {
4533 properties: {
4534 elevation: {
4535 type: Number,
4536 reflectToAttribute: true,
4537 readOnly: true
4538 }
4539 },
4540 observers: [ '_calculateElevation(focused, disabled, active, pressed, received FocusFromKeyboard)', '_computeKeyboardClass(receivedFocusFromKeyboard)' ],
4541 hostAttributes: {
4542 role: 'button',
4543 tabindex: '0',
4544 animated: true
4545 },
4546 _calculateElevation: function() {
4547 var e = 1;
4548 if (this.disabled) {
4549 e = 0;
4550 } else if (this.active || this.pressed) {
4551 e = 4;
4552 } else if (this.receivedFocusFromKeyboard) {
4553 e = 3;
4554 }
4555 this._setElevation(e);
4556 },
4557 _computeKeyboardClass: function(receivedFocusFromKeyboard) {
4558 this.toggleClass('keyboard-focus', receivedFocusFromKeyboard);
4559 },
4560 _spaceKeyDownHandler: function(event) {
4561 Polymer.IronButtonStateImpl._spaceKeyDownHandler.call(this, event);
4562 if (this.hasRipple() && this.getRipple().ripples.length < 1) {
4563 this._ripple.uiDownAction();
4564 }
4565 },
4566 _spaceKeyUpHandler: function(event) {
4567 Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this, event);
4568 if (this.hasRipple()) {
4569 this._ripple.uiUpAction();
4570 }
4571 }
4572 };
4573
4574 Polymer.PaperButtonBehavior = [ Polymer.IronButtonState, Polymer.IronControlStat e, Polymer.PaperRippleBehavior, Polymer.PaperButtonBehaviorImpl ];
4575
4576 Polymer({
4577 is: 'paper-button',
4578 behaviors: [ Polymer.PaperButtonBehavior ],
4579 properties: {
4580 raised: {
4581 type: Boolean,
4582 reflectToAttribute: true,
4583 value: false,
4584 observer: '_calculateElevation'
4585 }
4586 },
4587 _calculateElevation: function() {
4588 if (!this.raised) {
4589 this._setElevation(0);
4590 } else {
4591 Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this);
4592 }
4593 }
4594 });
4595
4596 Polymer({
4597 is: 'paper-icon-button-light',
4598 "extends": 'button',
4599 behaviors: [ Polymer.PaperRippleBehavior ],
4600 listeners: {
4601 down: '_rippleDown',
4602 up: '_rippleUp',
4603 focus: '_rippleDown',
4604 blur: '_rippleUp'
4605 },
4606 _rippleDown: function() {
4607 this.getRipple().downAction();
4608 },
4609 _rippleUp: function() {
4610 this.getRipple().upAction();
4611 },
4612 ensureRipple: function(var_args) {
4613 var lastRipple = this._ripple;
4614 Polymer.PaperRippleBehavior.ensureRipple.apply(this, arguments);
4615 if (this._ripple && this._ripple !== lastRipple) {
4616 this._ripple.center = true;
4617 this._ripple.classList.add('circle');
4618 }
4619 }
4620 });
4621
4622 Polymer.PaperInkyFocusBehaviorImpl = {
4623 observers: [ '_focusedChanged(receivedFocusFromKeyboard)' ],
4624 _focusedChanged: function(receivedFocusFromKeyboard) {
4625 if (receivedFocusFromKeyboard) {
4626 this.ensureRipple();
4627 }
4628 if (this.hasRipple()) {
4629 this._ripple.holdDown = receivedFocusFromKeyboard;
4630 }
4631 },
4632 _createRipple: function() {
4633 var ripple = Polymer.PaperRippleBehavior._createRipple();
4634 ripple.id = 'ink';
4635 ripple.setAttribute('center', '');
4636 ripple.classList.add('circle');
4637 return ripple;
4638 }
4639 };
4640
4641 Polymer.PaperInkyFocusBehavior = [ Polymer.IronButtonState, Polymer.IronControlS tate, Polymer.PaperRippleBehavior, Polymer.PaperInkyFocusBehaviorImpl ];
4642
4643 Polymer({
4644 is: 'paper-icon-button',
4645 hostAttributes: {
4646 role: 'button',
4647 tabindex: '0'
4648 },
4649 behaviors: [ Polymer.PaperInkyFocusBehavior ],
4650 properties: {
4651 src: {
4652 type: String
4653 },
4654 icon: {
4655 type: String
4656 },
4657 alt: {
4658 type: String,
4659 observer: "_altChanged"
4660 }
4661 },
4662 _altChanged: function(newValue, oldValue) {
4663 var label = this.getAttribute('aria-label');
4664 if (!label || oldValue == label) {
4665 this.setAttribute('aria-label', newValue);
4666 }
4667 }
4668 });
4669
4670 Polymer({
4671 is: 'paper-tab',
4672 behaviors: [ Polymer.IronControlState, Polymer.IronButtonState, Polymer.PaperR ippleBehavior ],
4673 properties: {
4674 link: {
4675 type: Boolean,
4676 value: false,
4677 reflectToAttribute: true
4678 }
4679 },
4680 hostAttributes: {
4681 role: 'tab'
4682 },
4683 listeners: {
4684 down: '_updateNoink',
4685 tap: '_onTap'
4686 },
4687 attached: function() {
4688 this._updateNoink();
4689 },
4690 get _parentNoink() {
4691 var parent = Polymer.dom(this).parentNode;
4692 return !!parent && !!parent.noink;
4693 },
4694 _updateNoink: function() {
4695 this.noink = !!this.noink || !!this._parentNoink;
4696 },
4697 _onTap: function(event) {
4698 if (this.link) {
4699 var anchor = this.queryEffectiveChildren('a');
4700 if (!anchor) {
4701 return;
4702 }
4703 if (event.target === anchor) {
4704 return;
4705 }
4706 anchor.click();
4707 }
4708 }
4709 });
4710
4711 Polymer.IronMultiSelectableBehaviorImpl = {
4712 properties: {
4713 multi: {
4714 type: Boolean,
4715 value: false,
4716 observer: 'multiChanged'
4717 },
4718 selectedValues: {
4719 type: Array,
4720 notify: true
4721 },
4722 selectedItems: {
4723 type: Array,
4724 readOnly: true,
4725 notify: true
4726 }
4727 },
4728 observers: [ '_updateSelected(selectedValues.splices)' ],
4729 select: function(value) {
4730 if (this.multi) {
4731 if (this.selectedValues) {
4732 this._toggleSelected(value);
4733 } else {
4734 this.selectedValues = [ value ];
4735 }
4736 } else {
4737 this.selected = value;
4738 }
4739 },
4740 multiChanged: function(multi) {
4741 this._selection.multi = multi;
4742 },
4743 get _shouldUpdateSelection() {
4744 return this.selected != null || this.selectedValues != null && this.selected Values.length;
4745 },
4746 _updateAttrForSelected: function() {
4747 if (!this.multi) {
4748 Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this);
4749 } else if (this._shouldUpdateSelection) {
4750 this.selectedValues = this.selectedItems.map(function(selectedItem) {
4751 return this._indexToValue(this.indexOf(selectedItem));
4752 }, this).filter(function(unfilteredValue) {
4753 return unfilteredValue != null;
4754 }, this);
4755 }
4756 },
4757 _updateSelected: function() {
4758 if (this.multi) {
4759 this._selectMulti(this.selectedValues);
4760 } else {
4761 this._selectSelected(this.selected);
4762 }
4763 },
4764 _selectMulti: function(values) {
4765 if (values) {
4766 var selectedItems = this._valuesToItems(values);
4767 this._selection.clear(selectedItems);
4768 for (var i = 0; i < selectedItems.length; i++) {
4769 this._selection.setItemSelected(selectedItems[i], true);
4770 }
4771 if (this.fallbackSelection && this.items.length && !this._selection.get(). length) {
4772 var fallback = this._valueToItem(this.fallbackSelection);
4773 if (fallback) {
4774 this.selectedValues = [ this.fallbackSelection ];
4775 }
4776 }
4777 } else {
4778 this._selection.clear();
4779 }
4780 },
4781 _selectionChange: function() {
4782 var s = this._selection.get();
4783 if (this.multi) {
4784 this._setSelectedItems(s);
4785 } else {
4786 this._setSelectedItems([ s ]);
4787 this._setSelectedItem(s);
4788 }
4789 },
4790 _toggleSelected: function(value) {
4791 var i = this.selectedValues.indexOf(value);
4792 var unselected = i < 0;
4793 if (unselected) {
4794 this.push('selectedValues', value);
4795 } else {
4796 this.splice('selectedValues', i, 1);
4797 }
4798 },
4799 _valuesToItems: function(values) {
4800 return values == null ? null : values.map(function(value) {
4801 return this._valueToItem(value);
4802 }, this);
4803 }
4804 };
4805
4806 Polymer.IronMultiSelectableBehavior = [ Polymer.IronSelectableBehavior, Polymer. IronMultiSelectableBehaviorImpl ];
4807
4808 Polymer.IronMenuBehaviorImpl = {
4809 properties: {
4810 focusedItem: {
4811 observer: '_focusedItemChanged',
4812 readOnly: true,
4813 type: Object
4814 },
4815 attrForItemTitle: {
4816 type: String
4817 }
4818 },
4819 hostAttributes: {
4820 role: 'menu',
4821 tabindex: '0'
4822 },
4823 observers: [ '_updateMultiselectable(multi)' ],
4824 listeners: {
4825 focus: '_onFocus',
4826 keydown: '_onKeydown',
4827 'iron-items-changed': '_onIronItemsChanged'
4828 },
4829 keyBindings: {
4830 up: '_onUpKey',
4831 down: '_onDownKey',
4832 esc: '_onEscKey',
4833 'shift+tab:keydown': '_onShiftTabDown'
4834 },
4835 attached: function() {
4836 this._resetTabindices();
4837 },
4838 select: function(value) {
4839 if (this._defaultFocusAsync) {
4840 this.cancelAsync(this._defaultFocusAsync);
4841 this._defaultFocusAsync = null;
4842 }
4843 var item = this._valueToItem(value);
4844 if (item && item.hasAttribute('disabled')) return;
4845 this._setFocusedItem(item);
4846 Polymer.IronMultiSelectableBehaviorImpl.select.apply(this, arguments);
4847 },
4848 _resetTabindices: function() {
4849 var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0] : this.selectedItem;
4850 this.items.forEach(function(item) {
4851 item.setAttribute('tabindex', item === selectedItem ? '0' : '-1');
4852 }, this);
4853 },
4854 _updateMultiselectable: function(multi) {
4855 if (multi) {
4856 this.setAttribute('aria-multiselectable', 'true');
4857 } else {
4858 this.removeAttribute('aria-multiselectable');
4859 }
4860 },
4861 _focusWithKeyboardEvent: function(event) {
4862 for (var i = 0, item; item = this.items[i]; i++) {
4863 var attr = this.attrForItemTitle || 'textContent';
4864 var title = item[attr] || item.getAttribute(attr);
4865 if (!item.hasAttribute('disabled') && title && title.trim().charAt(0).toLo werCase() === String.fromCharCode(event.keyCode).toLowerCase()) {
4866 this._setFocusedItem(item);
4867 break;
4868 }
4869 }
4870 },
4871 _focusPrevious: function() {
4872 var length = this.items.length;
4873 var curFocusIndex = Number(this.indexOf(this.focusedItem));
4874 for (var i = 1; i < length + 1; i++) {
4875 var item = this.items[(curFocusIndex - i + length) % length];
4876 if (!item.hasAttribute('disabled')) {
4877 var owner = Polymer.dom(item).getOwnerRoot() || document;
4878 this._setFocusedItem(item);
4879 if (Polymer.dom(owner).activeElement == item) {
4880 return;
4881 }
4882 }
4883 }
4884 },
4885 _focusNext: function() {
4886 var length = this.items.length;
4887 var curFocusIndex = Number(this.indexOf(this.focusedItem));
4888 for (var i = 1; i < length + 1; i++) {
4889 var item = this.items[(curFocusIndex + i) % length];
4890 if (!item.hasAttribute('disabled')) {
4891 var owner = Polymer.dom(item).getOwnerRoot() || document;
4892 this._setFocusedItem(item);
4893 if (Polymer.dom(owner).activeElement == item) {
4894 return;
4895 }
4896 }
4897 }
4898 },
4899 _applySelection: function(item, isSelected) {
4900 if (isSelected) {
4901 item.setAttribute('aria-selected', 'true');
4902 } else {
4903 item.removeAttribute('aria-selected');
4904 }
4905 Polymer.IronSelectableBehavior._applySelection.apply(this, arguments);
4906 },
4907 _focusedItemChanged: function(focusedItem, old) {
4908 old && old.setAttribute('tabindex', '-1');
4909 if (focusedItem) {
4910 focusedItem.setAttribute('tabindex', '0');
4911 focusedItem.focus();
4912 }
4913 },
4914 _onIronItemsChanged: function(event) {
4915 if (event.detail.addedNodes.length) {
4916 this._resetTabindices();
4917 }
4918 },
4919 _onShiftTabDown: function(event) {
4920 var oldTabIndex = this.getAttribute('tabindex');
4921 Polymer.IronMenuBehaviorImpl._shiftTabPressed = true;
4922 this._setFocusedItem(null);
4923 this.setAttribute('tabindex', '-1');
4924 this.async(function() {
4925 this.setAttribute('tabindex', oldTabIndex);
4926 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
4927 }, 1);
4928 },
4929 _onFocus: function(event) {
4930 if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) {
4931 return;
4932 }
4933 var rootTarget = Polymer.dom(event).rootTarget;
4934 if (rootTarget !== this && typeof rootTarget.tabIndex !== "undefined" && !th is.isLightDescendant(rootTarget)) {
4935 return;
4936 }
4937 this._defaultFocusAsync = this.async(function() {
4938 var selectedItem = this.multi ? this.selectedItems && this.selectedItems[0 ] : this.selectedItem;
4939 this._setFocusedItem(null);
4940 if (selectedItem) {
4941 this._setFocusedItem(selectedItem);
4942 } else if (this.items[0]) {
4943 this._focusNext();
4944 }
4945 });
4946 },
4947 _onUpKey: function(event) {
4948 this._focusPrevious();
4949 event.detail.keyboardEvent.preventDefault();
4950 },
4951 _onDownKey: function(event) {
4952 this._focusNext();
4953 event.detail.keyboardEvent.preventDefault();
4954 },
4955 _onEscKey: function(event) {
4956 this.focusedItem.blur();
4957 },
4958 _onKeydown: function(event) {
4959 if (!this.keyboardEventMatchesKeys(event, 'up down esc')) {
4960 this._focusWithKeyboardEvent(event);
4961 }
4962 event.stopPropagation();
4963 },
4964 _activateHandler: function(event) {
4965 Polymer.IronSelectableBehavior._activateHandler.call(this, event);
4966 event.stopPropagation();
4967 }
4968 };
4969
4970 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
4971
4972 Polymer.IronMenuBehavior = [ Polymer.IronMultiSelectableBehavior, Polymer.IronA1 1yKeysBehavior, Polymer.IronMenuBehaviorImpl ];
4973
4974 Polymer.IronMenubarBehaviorImpl = {
4975 hostAttributes: {
4976 role: 'menubar'
4977 },
4978 keyBindings: {
4979 left: '_onLeftKey',
4980 right: '_onRightKey'
4981 },
4982 _onUpKey: function(event) {
4983 this.focusedItem.click();
4984 event.detail.keyboardEvent.preventDefault();
4985 },
4986 _onDownKey: function(event) {
4987 this.focusedItem.click();
4988 event.detail.keyboardEvent.preventDefault();
4989 },
4990 get _isRTL() {
4991 return window.getComputedStyle(this)['direction'] === 'rtl';
4992 },
4993 _onLeftKey: function(event) {
4994 if (this._isRTL) {
4995 this._focusNext();
4996 } else {
4997 this._focusPrevious();
4998 }
4999 event.detail.keyboardEvent.preventDefault();
5000 },
5001 _onRightKey: function(event) {
5002 if (this._isRTL) {
5003 this._focusPrevious();
5004 } else {
5005 this._focusNext();
5006 }
5007 event.detail.keyboardEvent.preventDefault();
5008 },
5009 _onKeydown: function(event) {
5010 if (this.keyboardEventMatchesKeys(event, 'up down left right esc')) {
5011 return;
5012 }
5013 this._focusWithKeyboardEvent(event);
5014 }
5015 };
5016
5017 Polymer.IronMenubarBehavior = [ Polymer.IronMenuBehavior, Polymer.IronMenubarBeh aviorImpl ];
5018
5019 Polymer({
5020 is: 'iron-iconset-svg',
5021 properties: {
5022 name: {
5023 type: String,
5024 observer: '_nameChanged'
5025 },
5026 size: {
5027 type: Number,
5028 value: 24
5029 }
5030 },
5031 attached: function() {
5032 this.style.display = 'none';
5033 },
5034 getIconNames: function() {
5035 this._icons = this._createIconMap();
5036 return Object.keys(this._icons).map(function(n) {
5037 return this.name + ':' + n;
5038 }, this);
5039 },
5040 applyIcon: function(element, iconName) {
5041 element = element.root || element;
5042 this.removeIcon(element);
5043 var svg = this._cloneIcon(iconName);
5044 if (svg) {
5045 var pde = Polymer.dom(element);
5046 pde.insertBefore(svg, pde.childNodes[0]);
5047 return element._svgIcon = svg;
5048 }
5049 return null;
5050 },
5051 removeIcon: function(element) {
5052 if (element._svgIcon) {
5053 Polymer.dom(element).removeChild(element._svgIcon);
5054 element._svgIcon = null;
5055 }
5056 },
5057 _nameChanged: function() {
5058 new Polymer.IronMeta({
5059 type: 'iconset',
5060 key: this.name,
5061 value: this
5062 });
5063 this.async(function() {
5064 this.fire('iron-iconset-added', this, {
5065 node: window
5066 });
5067 });
5068 },
5069 _createIconMap: function() {
5070 var icons = Object.create(null);
5071 Polymer.dom(this).querySelectorAll('[id]').forEach(function(icon) {
5072 icons[icon.id] = icon;
5073 });
5074 return icons;
5075 },
5076 _cloneIcon: function(id) {
5077 this._icons = this._icons || this._createIconMap();
5078 return this._prepareSvgClone(this._icons[id], this.size);
5079 },
5080 _prepareSvgClone: function(sourceSvg, size) {
5081 if (sourceSvg) {
5082 var content = sourceSvg.cloneNode(true), svg = document.createElementNS('h ttp://www.w3.org/2000/svg', 'svg'), viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size;
5083 svg.setAttribute('viewBox', viewBox);
5084 svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
5085 svg.style.cssText = 'pointer-events: none; display: block; width: 100%; he ight: 100%;';
5086 svg.appendChild(content).removeAttribute('id');
5087 return svg;
5088 }
5089 return null;
5090 }
5091 });
5092
5093 Polymer({
5094 is: 'paper-tabs',
5095 behaviors: [ Polymer.IronResizableBehavior, Polymer.IronMenubarBehavior ],
5096 properties: {
5097 noink: {
5098 type: Boolean,
5099 value: false,
5100 observer: '_noinkChanged'
5101 },
5102 noBar: {
5103 type: Boolean,
5104 value: false
5105 },
5106 noSlide: {
5107 type: Boolean,
5108 value: false
5109 },
5110 scrollable: {
5111 type: Boolean,
5112 value: false
5113 },
5114 fitContainer: {
5115 type: Boolean,
5116 value: false
5117 },
5118 disableDrag: {
5119 type: Boolean,
5120 value: false
5121 },
5122 hideScrollButtons: {
5123 type: Boolean,
5124 value: false
5125 },
5126 alignBottom: {
5127 type: Boolean,
5128 value: false
5129 },
5130 selectable: {
5131 type: String,
5132 value: 'paper-tab'
5133 },
5134 autoselect: {
5135 type: Boolean,
5136 value: false
5137 },
5138 autoselectDelay: {
5139 type: Number,
5140 value: 0
5141 },
5142 _step: {
5143 type: Number,
5144 value: 10
5145 },
5146 _holdDelay: {
5147 type: Number,
5148 value: 1
5149 },
5150 _leftHidden: {
5151 type: Boolean,
5152 value: false
5153 },
5154 _rightHidden: {
5155 type: Boolean,
5156 value: false
5157 },
5158 _previousTab: {
5159 type: Object
5160 }
5161 },
5162 hostAttributes: {
5163 role: 'tablist'
5164 },
5165 listeners: {
5166 'iron-resize': '_onTabSizingChanged',
5167 'iron-items-changed': '_onTabSizingChanged',
5168 'iron-select': '_onIronSelect',
5169 'iron-deselect': '_onIronDeselect'
5170 },
5171 keyBindings: {
5172 'left:keyup right:keyup': '_onArrowKeyup'
5173 },
5174 created: function() {
5175 this._holdJob = null;
5176 this._pendingActivationItem = undefined;
5177 this._pendingActivationTimeout = undefined;
5178 this._bindDelayedActivationHandler = this._delayedActivationHandler.bind(thi s);
5179 this.addEventListener('blur', this._onBlurCapture.bind(this), true);
5180 },
5181 ready: function() {
5182 this.setScrollDirection('y', this.$.tabsContainer);
5183 },
5184 detached: function() {
5185 this._cancelPendingActivation();
5186 },
5187 _noinkChanged: function(noink) {
5188 var childTabs = Polymer.dom(this).querySelectorAll('paper-tab');
5189 childTabs.forEach(noink ? this._setNoinkAttribute : this._removeNoinkAttribu te);
5190 },
5191 _setNoinkAttribute: function(element) {
5192 element.setAttribute('noink', '');
5193 },
5194 _removeNoinkAttribute: function(element) {
5195 element.removeAttribute('noink');
5196 },
5197 _computeScrollButtonClass: function(hideThisButton, scrollable, hideScrollButt ons) {
5198 if (!scrollable || hideScrollButtons) {
5199 return 'hidden';
5200 }
5201 if (hideThisButton) {
5202 return 'not-visible';
5203 }
5204 return '';
5205 },
5206 _computeTabsContentClass: function(scrollable, fitContainer) {
5207 return scrollable ? 'scrollable' + (fitContainer ? ' fit-container' : '') : ' fit-container';
5208 },
5209 _computeSelectionBarClass: function(noBar, alignBottom) {
5210 if (noBar) {
5211 return 'hidden';
5212 } else if (alignBottom) {
5213 return 'align-bottom';
5214 }
5215 return '';
5216 },
5217 _onTabSizingChanged: function() {
5218 this.debounce('_onTabSizingChanged', function() {
5219 this._scroll();
5220 this._tabChanged(this.selectedItem);
5221 }, 10);
5222 },
5223 _onIronSelect: function(event) {
5224 this._tabChanged(event.detail.item, this._previousTab);
5225 this._previousTab = event.detail.item;
5226 this.cancelDebouncer('tab-changed');
5227 },
5228 _onIronDeselect: function(event) {
5229 this.debounce('tab-changed', function() {
5230 this._tabChanged(null, this._previousTab);
5231 this._previousTab = null;
5232 }, 1);
5233 },
5234 _activateHandler: function() {
5235 this._cancelPendingActivation();
5236 Polymer.IronMenuBehaviorImpl._activateHandler.apply(this, arguments);
5237 },
5238 _scheduleActivation: function(item, delay) {
5239 this._pendingActivationItem = item;
5240 this._pendingActivationTimeout = this.async(this._bindDelayedActivationHandl er, delay);
5241 },
5242 _delayedActivationHandler: function() {
5243 var item = this._pendingActivationItem;
5244 this._pendingActivationItem = undefined;
5245 this._pendingActivationTimeout = undefined;
5246 item.fire(this.activateEvent, null, {
5247 bubbles: true,
5248 cancelable: true
5249 });
5250 },
5251 _cancelPendingActivation: function() {
5252 if (this._pendingActivationTimeout !== undefined) {
5253 this.cancelAsync(this._pendingActivationTimeout);
5254 this._pendingActivationItem = undefined;
5255 this._pendingActivationTimeout = undefined;
5256 }
5257 },
5258 _onArrowKeyup: function(event) {
5259 if (this.autoselect) {
5260 this._scheduleActivation(this.focusedItem, this.autoselectDelay);
5261 }
5262 },
5263 _onBlurCapture: function(event) {
5264 if (event.target === this._pendingActivationItem) {
5265 this._cancelPendingActivation();
5266 }
5267 },
5268 get _tabContainerScrollSize() {
5269 return Math.max(0, this.$.tabsContainer.scrollWidth - this.$.tabsContainer.o ffsetWidth);
5270 },
5271 _scroll: function(e, detail) {
5272 if (!this.scrollable) {
5273 return;
5274 }
5275 var ddx = detail && -detail.ddx || 0;
5276 this._affectScroll(ddx);
5277 },
5278 _down: function(e) {
5279 this.async(function() {
5280 if (this._defaultFocusAsync) {
5281 this.cancelAsync(this._defaultFocusAsync);
5282 this._defaultFocusAsync = null;
5283 }
5284 }, 1);
5285 },
5286 _affectScroll: function(dx) {
5287 this.$.tabsContainer.scrollLeft += dx;
5288 var scrollLeft = this.$.tabsContainer.scrollLeft;
5289 this._leftHidden = scrollLeft === 0;
5290 this._rightHidden = scrollLeft === this._tabContainerScrollSize;
5291 },
5292 _onLeftScrollButtonDown: function() {
5293 this._scrollToLeft();
5294 this._holdJob = setInterval(this._scrollToLeft.bind(this), this._holdDelay);
5295 },
5296 _onRightScrollButtonDown: function() {
5297 this._scrollToRight();
5298 this._holdJob = setInterval(this._scrollToRight.bind(this), this._holdDelay) ;
5299 },
5300 _onScrollButtonUp: function() {
5301 clearInterval(this._holdJob);
5302 this._holdJob = null;
5303 },
5304 _scrollToLeft: function() {
5305 this._affectScroll(-this._step);
5306 },
5307 _scrollToRight: function() {
5308 this._affectScroll(this._step);
5309 },
5310 _tabChanged: function(tab, old) {
5311 if (!tab) {
5312 this.$.selectionBar.classList.remove('expand');
5313 this.$.selectionBar.classList.remove('contract');
5314 this._positionBar(0, 0);
5315 return;
5316 }
5317 var r = this.$.tabsContent.getBoundingClientRect();
5318 var w = r.width;
5319 var tabRect = tab.getBoundingClientRect();
5320 var tabOffsetLeft = tabRect.left - r.left;
5321 this._pos = {
5322 width: this._calcPercent(tabRect.width, w),
5323 left: this._calcPercent(tabOffsetLeft, w)
5324 };
5325 if (this.noSlide || old == null) {
5326 this.$.selectionBar.classList.remove('expand');
5327 this.$.selectionBar.classList.remove('contract');
5328 this._positionBar(this._pos.width, this._pos.left);
5329 return;
5330 }
5331 var oldRect = old.getBoundingClientRect();
5332 var oldIndex = this.items.indexOf(old);
5333 var index = this.items.indexOf(tab);
5334 var m = 5;
5335 this.$.selectionBar.classList.add('expand');
5336 var moveRight = oldIndex < index;
5337 var isRTL = this._isRTL;
5338 if (isRTL) {
5339 moveRight = !moveRight;
5340 }
5341 if (moveRight) {
5342 this._positionBar(this._calcPercent(tabRect.left + tabRect.width - oldRect .left, w) - m, this._left);
5343 } else {
5344 this._positionBar(this._calcPercent(oldRect.left + oldRect.width - tabRect .left, w) - m, this._calcPercent(tabOffsetLeft, w) + m);
5345 }
5346 if (this.scrollable) {
5347 this._scrollToSelectedIfNeeded(tabRect.width, tabOffsetLeft);
5348 }
5349 },
5350 _scrollToSelectedIfNeeded: function(tabWidth, tabOffsetLeft) {
5351 var l = tabOffsetLeft - this.$.tabsContainer.scrollLeft;
5352 if (l < 0) {
5353 this.$.tabsContainer.scrollLeft += l;
5354 } else {
5355 l += tabWidth - this.$.tabsContainer.offsetWidth;
5356 if (l > 0) {
5357 this.$.tabsContainer.scrollLeft += l;
5358 }
5359 }
5360 },
5361 _calcPercent: function(w, w0) {
5362 return 100 * w / w0;
5363 },
5364 _positionBar: function(width, left) {
5365 width = width || 0;
5366 left = left || 0;
5367 this._width = width;
5368 this._left = left;
5369 this.transform('translateX(' + left + '%) scaleX(' + width / 100 + ')', this .$.selectionBar);
5370 },
5371 _onBarTransitionEnd: function(e) {
5372 var cl = this.$.selectionBar.classList;
5373 if (cl.contains('expand')) {
5374 cl.remove('expand');
5375 cl.add('contract');
5376 this._positionBar(this._pos.width, this._pos.left);
5377 } else if (cl.contains('contract')) {
5378 cl.remove('contract');
5379 }
5380 }
5381 });
5382
5383 (function() {
5384 'use strict';
5385 Polymer.IronA11yAnnouncer = Polymer({
5386 is: 'iron-a11y-announcer',
5387 properties: {
5388 mode: {
5389 type: String,
5390 value: 'polite'
5391 },
5392 _text: {
5393 type: String,
5394 value: ''
5395 }
5396 },
5397 created: function() {
5398 if (!Polymer.IronA11yAnnouncer.instance) {
5399 Polymer.IronA11yAnnouncer.instance = this;
5400 }
5401 document.body.addEventListener('iron-announce', this._onIronAnnounce.bind( this));
5402 },
5403 announce: function(text) {
5404 this._text = '';
5405 this.async(function() {
5406 this._text = text;
5407 }, 100);
5408 },
5409 _onIronAnnounce: function(event) {
5410 if (event.detail && event.detail.text) {
5411 this.announce(event.detail.text);
5412 }
5413 }
5414 });
5415 Polymer.IronA11yAnnouncer.instance = null;
5416 Polymer.IronA11yAnnouncer.requestAvailability = function() {
5417 if (!Polymer.IronA11yAnnouncer.instance) {
5418 Polymer.IronA11yAnnouncer.instance = document.createElement('iron-a11y-ann ouncer');
5419 }
5420 document.body.appendChild(Polymer.IronA11yAnnouncer.instance);
5421 };
5422 })();
5423
5424 Polymer.IronValidatableBehaviorMeta = null;
5425
5426 Polymer.IronValidatableBehavior = {
5427 properties: {
5428 validator: {
5429 type: String
5430 },
5431 invalid: {
5432 notify: true,
5433 reflectToAttribute: true,
5434 type: Boolean,
5435 value: false
5436 },
5437 _validatorMeta: {
5438 type: Object
5439 },
5440 validatorType: {
5441 type: String,
5442 value: 'validator'
5443 },
5444 _validator: {
5445 type: Object,
5446 computed: '__computeValidator(validator)'
5447 }
5448 },
5449 observers: [ '_invalidChanged(invalid)' ],
5450 registered: function() {
5451 Polymer.IronValidatableBehaviorMeta = new Polymer.IronMeta({
5452 type: 'validator'
5453 });
5454 },
5455 _invalidChanged: function() {
5456 if (this.invalid) {
5457 this.setAttribute('aria-invalid', 'true');
5458 } else {
5459 this.removeAttribute('aria-invalid');
5460 }
5461 },
5462 hasValidator: function() {
5463 return this._validator != null;
5464 },
5465 validate: function(value) {
5466 this.invalid = !this._getValidity(value);
5467 return !this.invalid;
5468 },
5469 _getValidity: function(value) {
5470 if (this.hasValidator()) {
5471 return this._validator.validate(value);
5472 }
5473 return true;
5474 },
5475 __computeValidator: function() {
5476 return Polymer.IronValidatableBehaviorMeta && Polymer.IronValidatableBehavio rMeta.byKey(this.validator);
5477 }
5478 };
5479
5480 Polymer({
5481 is: 'iron-input',
5482 "extends": 'input',
5483 behaviors: [ Polymer.IronValidatableBehavior ],
5484 properties: {
5485 bindValue: {
5486 observer: '_bindValueChanged',
5487 type: String
5488 },
5489 preventInvalidInput: {
5490 type: Boolean
5491 },
5492 allowedPattern: {
5493 type: String,
5494 observer: "_allowedPatternChanged"
5495 },
5496 _previousValidInput: {
5497 type: String,
5498 value: ''
5499 },
5500 _patternAlreadyChecked: {
5501 type: Boolean,
5502 value: false
5503 }
5504 },
5505 listeners: {
5506 input: '_onInput',
5507 keypress: '_onKeypress'
5508 },
5509 registered: function() {
5510 if (!this._canDispatchEventOnDisabled()) {
5511 this._origDispatchEvent = this.dispatchEvent;
5512 this.dispatchEvent = this._dispatchEventFirefoxIE;
5513 }
5514 },
5515 created: function() {
5516 Polymer.IronA11yAnnouncer.requestAvailability();
5517 },
5518 _canDispatchEventOnDisabled: function() {
5519 var input = document.createElement('input');
5520 var canDispatch = false;
5521 input.disabled = true;
5522 input.addEventListener('feature-check-dispatch-event', function() {
5523 canDispatch = true;
5524 });
5525 try {
5526 input.dispatchEvent(new Event('feature-check-dispatch-event'));
5527 } catch (e) {}
5528 return canDispatch;
5529 },
5530 _dispatchEventFirefoxIE: function() {
5531 var disabled = this.disabled;
5532 this.disabled = false;
5533 this._origDispatchEvent.apply(this, arguments);
5534 this.disabled = disabled;
5535 },
5536 get _patternRegExp() {
5537 var pattern;
5538 if (this.allowedPattern) {
5539 pattern = new RegExp(this.allowedPattern);
5540 } else {
5541 switch (this.type) {
5542 case 'number':
5543 pattern = /[0-9.,e-]/;
5544 break;
5545 }
5546 }
5547 return pattern;
5548 },
5549 ready: function() {
5550 this.bindValue = this.value;
5551 },
5552 _bindValueChanged: function() {
5553 if (this.value !== this.bindValue) {
5554 this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue == = false) ? '' : this.bindValue;
5555 }
5556 this.fire('bind-value-changed', {
5557 value: this.bindValue
5558 });
5559 },
5560 _allowedPatternChanged: function() {
5561 this.preventInvalidInput = this.allowedPattern ? true : false;
5562 },
5563 _onInput: function() {
5564 if (this.preventInvalidInput && !this._patternAlreadyChecked) {
5565 var valid = this._checkPatternValidity();
5566 if (!valid) {
5567 this._announceInvalidCharacter('Invalid string of characters not entered .');
5568 this.value = this._previousValidInput;
5569 }
5570 }
5571 this.bindValue = this.value;
5572 this._previousValidInput = this.value;
5573 this._patternAlreadyChecked = false;
5574 },
5575 _isPrintable: function(event) {
5576 var anyNonPrintable = event.keyCode == 8 || event.keyCode == 9 || event.keyC ode == 13 || event.keyCode == 27;
5577 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;
5578 return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable);
5579 },
5580 _onKeypress: function(event) {
5581 if (!this.preventInvalidInput && this.type !== 'number') {
5582 return;
5583 }
5584 var regexp = this._patternRegExp;
5585 if (!regexp) {
5586 return;
5587 }
5588 if (event.metaKey || event.ctrlKey || event.altKey) return;
5589 this._patternAlreadyChecked = true;
5590 var thisChar = String.fromCharCode(event.charCode);
5591 if (this._isPrintable(event) && !regexp.test(thisChar)) {
5592 event.preventDefault();
5593 this._announceInvalidCharacter('Invalid character ' + thisChar + ' not ent ered.');
5594 }
5595 },
5596 _checkPatternValidity: function() {
5597 var regexp = this._patternRegExp;
5598 if (!regexp) {
5599 return true;
5600 }
5601 for (var i = 0; i < this.value.length; i++) {
5602 if (!regexp.test(this.value[i])) {
5603 return false;
5604 }
5605 }
5606 return true;
5607 },
5608 validate: function() {
5609 var valid = this.checkValidity();
5610 if (valid) {
5611 if (this.required && this.value === '') {
5612 valid = false;
5613 } else if (this.hasValidator()) {
5614 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
5615 }
5616 }
5617 this.invalid = !valid;
5618 this.fire('iron-input-validate');
5619 return valid;
5620 },
5621 _announceInvalidCharacter: function(message) {
5622 this.fire('iron-announce', {
5623 text: message
5624 });
5625 }
5626 });
5627
5628 Polymer({
5629 is: 'paper-input-container',
5630 properties: {
5631 noLabelFloat: {
5632 type: Boolean,
5633 value: false
5634 },
5635 alwaysFloatLabel: {
5636 type: Boolean,
5637 value: false
5638 },
5639 attrForValue: {
5640 type: String,
5641 value: 'bind-value'
5642 },
5643 autoValidate: {
5644 type: Boolean,
5645 value: false
5646 },
5647 invalid: {
5648 observer: '_invalidChanged',
5649 type: Boolean,
5650 value: false
5651 },
5652 focused: {
5653 readOnly: true,
5654 type: Boolean,
5655 value: false,
5656 notify: true
5657 },
5658 _addons: {
5659 type: Array
5660 },
5661 _inputHasContent: {
5662 type: Boolean,
5663 value: false
5664 },
5665 _inputSelector: {
5666 type: String,
5667 value: 'input,textarea,.paper-input-input'
5668 },
5669 _boundOnFocus: {
5670 type: Function,
5671 value: function() {
5672 return this._onFocus.bind(this);
5673 }
5674 },
5675 _boundOnBlur: {
5676 type: Function,
5677 value: function() {
5678 return this._onBlur.bind(this);
5679 }
5680 },
5681 _boundOnInput: {
5682 type: Function,
5683 value: function() {
5684 return this._onInput.bind(this);
5685 }
5686 },
5687 _boundValueChanged: {
5688 type: Function,
5689 value: function() {
5690 return this._onValueChanged.bind(this);
5691 }
5692 }
5693 },
5694 listeners: {
5695 'addon-attached': '_onAddonAttached',
5696 'iron-input-validate': '_onIronInputValidate'
5697 },
5698 get _valueChangedEvent() {
5699 return this.attrForValue + '-changed';
5700 },
5701 get _propertyForValue() {
5702 return Polymer.CaseMap.dashToCamelCase(this.attrForValue);
5703 },
5704 get _inputElement() {
5705 return Polymer.dom(this).querySelector(this._inputSelector);
5706 },
5707 get _inputElementValue() {
5708 return this._inputElement[this._propertyForValue] || this._inputElement.valu e;
5709 },
5710 ready: function() {
5711 if (!this._addons) {
5712 this._addons = [];
5713 }
5714 this.addEventListener('focus', this._boundOnFocus, true);
5715 this.addEventListener('blur', this._boundOnBlur, true);
5716 },
5717 attached: function() {
5718 if (this.attrForValue) {
5719 this._inputElement.addEventListener(this._valueChangedEvent, this._boundVa lueChanged);
5720 } else {
5721 this.addEventListener('input', this._onInput);
5722 }
5723 if (this._inputElementValue != '') {
5724 this._handleValueAndAutoValidate(this._inputElement);
5725 } else {
5726 this._handleValue(this._inputElement);
5727 }
5728 },
5729 _onAddonAttached: function(event) {
5730 if (!this._addons) {
5731 this._addons = [];
5732 }
5733 var target = event.target;
5734 if (this._addons.indexOf(target) === -1) {
5735 this._addons.push(target);
5736 if (this.isAttached) {
5737 this._handleValue(this._inputElement);
5738 }
5739 }
5740 },
5741 _onFocus: function() {
5742 this._setFocused(true);
5743 },
5744 _onBlur: function() {
5745 this._setFocused(false);
5746 this._handleValueAndAutoValidate(this._inputElement);
5747 },
5748 _onInput: function(event) {
5749 this._handleValueAndAutoValidate(event.target);
5750 },
5751 _onValueChanged: function(event) {
5752 this._handleValueAndAutoValidate(event.target);
5753 },
5754 _handleValue: function(inputElement) {
5755 var value = this._inputElementValue;
5756 if (value || value === 0 || inputElement.type === 'number' && !inputElement. checkValidity()) {
5757 this._inputHasContent = true;
5758 } else {
5759 this._inputHasContent = false;
5760 }
5761 this.updateAddons({
5762 inputElement: inputElement,
5763 value: value,
5764 invalid: this.invalid
5765 });
5766 },
5767 _handleValueAndAutoValidate: function(inputElement) {
5768 if (this.autoValidate) {
5769 var valid;
5770 if (inputElement.validate) {
5771 valid = inputElement.validate(this._inputElementValue);
5772 } else {
5773 valid = inputElement.checkValidity();
5774 }
5775 this.invalid = !valid;
5776 }
5777 this._handleValue(inputElement);
5778 },
5779 _onIronInputValidate: function(event) {
5780 this.invalid = this._inputElement.invalid;
5781 },
5782 _invalidChanged: function() {
5783 if (this._addons) {
5784 this.updateAddons({
5785 invalid: this.invalid
5786 });
5787 }
5788 },
5789 updateAddons: function(state) {
5790 for (var addon, index = 0; addon = this._addons[index]; index++) {
5791 addon.update(state);
5792 }
5793 },
5794 _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused, i nvalid, _inputHasContent) {
5795 var cls = 'input-content';
5796 if (!noLabelFloat) {
5797 var label = this.querySelector('label');
5798 if (alwaysFloatLabel || _inputHasContent) {
5799 cls += ' label-is-floating';
5800 this.$.labelAndInputContainer.style.position = 'static';
5801 if (invalid) {
5802 cls += ' is-invalid';
5803 } else if (focused) {
5804 cls += " label-is-highlighted";
5805 }
5806 } else {
5807 if (label) {
5808 this.$.labelAndInputContainer.style.position = 'relative';
5809 }
5810 }
5811 } else {
5812 if (_inputHasContent) {
5813 cls += ' label-is-hidden';
5814 }
5815 }
5816 return cls;
5817 },
5818 _computeUnderlineClass: function(focused, invalid) {
5819 var cls = 'underline';
5820 if (invalid) {
5821 cls += ' is-invalid';
5822 } else if (focused) {
5823 cls += ' is-highlighted';
5824 }
5825 return cls;
5826 },
5827 _computeAddOnContentClass: function(focused, invalid) {
5828 var cls = 'add-on-content';
5829 if (invalid) {
5830 cls += ' is-invalid';
5831 } else if (focused) {
5832 cls += ' is-highlighted';
5833 }
5834 return cls;
5835 }
5836 });
5837
5838 Polymer.PaperSpinnerBehavior = {
5839 listeners: {
5840 animationend: '__reset',
5841 webkitAnimationEnd: '__reset'
5842 },
5843 properties: {
5844 active: {
5845 type: Boolean,
5846 value: false,
5847 reflectToAttribute: true,
5848 observer: '__activeChanged'
5849 },
5850 alt: {
5851 type: String,
5852 value: 'loading',
5853 observer: '__altChanged'
5854 },
5855 __coolingDown: {
5856 type: Boolean,
5857 value: false
5858 }
5859 },
5860 __computeContainerClasses: function(active, coolingDown) {
5861 return [ active || coolingDown ? 'active' : '', coolingDown ? 'cooldown' : ' ' ].join(' ');
5862 },
5863 __activeChanged: function(active, old) {
5864 this.__setAriaHidden(!active);
5865 this.__coolingDown = !active && old;
5866 },
5867 __altChanged: function(alt) {
5868 if (alt === this.getPropertyInfo('alt').value) {
5869 this.alt = this.getAttribute('aria-label') || alt;
5870 } else {
5871 this.__setAriaHidden(alt === '');
5872 this.setAttribute('aria-label', alt);
5873 }
5874 },
5875 __setAriaHidden: function(hidden) {
5876 var attr = 'aria-hidden';
5877 if (hidden) {
5878 this.setAttribute(attr, 'true');
5879 } else {
5880 this.removeAttribute(attr);
5881 }
5882 },
5883 __reset: function() {
5884 this.active = false;
5885 this.__coolingDown = false;
5886 }
5887 };
5888
5889 Polymer({
5890 is: 'paper-spinner-lite',
5891 behaviors: [ Polymer.PaperSpinnerBehavior ]
5892 });
5893
5894 // Copyright 2016 The Chromium Authors. All rights reserved.
5895 // Use of this source code is governed by a BSD-style license that can be
5896 // found in the LICENSE file.
5897 var CrSearchFieldBehavior = {
5898 properties: {
5899 label: {
5900 type: String,
5901 value: ''
5902 },
5903 clearLabel: {
5904 type: String,
5905 value: ''
5906 },
5907 showingSearch: {
5908 type: Boolean,
5909 value: false,
5910 notify: true,
5911 observer: 'showingSearchChanged_',
5912 reflectToAttribute: true
5913 },
5914 lastValue_: {
5915 type: String,
5916 value: ''
5917 }
5918 },
5919 getSearchInput: function() {},
5920 getValue: function() {
5921 return this.getSearchInput().value;
5922 },
5923 setValue: function(value) {
5924 this.getSearchInput().bindValue = value;
5925 this.onValueChanged_(value);
5926 },
5927 showAndFocus: function() {
5928 this.showingSearch = true;
5929 this.focus_();
5930 },
5931 focus_: function() {
5932 this.getSearchInput().focus();
5933 },
5934 onSearchTermSearch: function() {
5935 this.onValueChanged_(this.getValue());
5936 },
5937 onValueChanged_: function(newValue) {
5938 if (newValue == this.lastValue_) return;
5939 this.fire('search-changed', newValue);
5940 this.lastValue_ = newValue;
5941 },
5942 onSearchTermKeydown: function(e) {
5943 if (e.key == 'Escape') this.showingSearch = false;
5944 },
5945 showingSearchChanged_: function() {
5946 if (this.showingSearch) {
5947 this.focus_();
5948 return;
5949 }
5950 this.setValue('');
5951 this.getSearchInput().blur();
5952 }
5953 };
5954
5955 // Copyright 2016 The Chromium Authors. All rights reserved.
5956 // Use of this source code is governed by a BSD-style license that can be
5957 // found in the LICENSE file.
5958 Polymer({
5959 is: 'cr-toolbar-search-field',
5960 behaviors: [ CrSearchFieldBehavior ],
5961 properties: {
5962 narrow: {
5963 type: Boolean,
5964 reflectToAttribute: true
5965 },
5966 label: String,
5967 clearLabel: String,
5968 spinnerActive: {
5969 type: Boolean,
5970 reflectToAttribute: true
5971 },
5972 hasSearchText_: Boolean,
5973 isSpinnerShown_: {
5974 type: Boolean,
5975 computed: 'computeIsSpinnerShown_(spinnerActive, showingSearch)'
5976 }
5977 },
5978 listeners: {
5979 tap: 'showSearch_',
5980 'searchInput.bind-value-changed': 'onBindValueChanged_'
5981 },
5982 getSearchInput: function() {
5983 return this.$.searchInput;
5984 },
5985 isSearchFocused: function() {
5986 return this.$.searchTerm.focused;
5987 },
5988 computeIconTabIndex_: function(narrow) {
5989 return narrow ? 0 : -1;
5990 },
5991 computeIsSpinnerShown_: function() {
5992 return this.spinnerActive && this.showingSearch;
5993 },
5994 onInputBlur_: function() {
5995 if (!this.hasSearchText_) this.showingSearch = false;
5996 },
5997 onBindValueChanged_: function() {
5998 var newValue = this.$.searchInput.bindValue;
5999 this.hasSearchText_ = newValue != '';
6000 if (newValue != '') this.showingSearch = true;
6001 },
6002 showSearch_: function(e) {
6003 if (e.target != this.$.clearSearch) this.showingSearch = true;
6004 },
6005 hideSearch_: function(e) {
6006 this.showingSearch = false;
6007 e.stopPropagation();
6008 }
6009 });
6010
6011 // Copyright 2016 The Chromium Authors. All rights reserved.
6012 // Use of this source code is governed by a BSD-style license that can be
6013 // found in the LICENSE file.
6014 Polymer({
6015 is: 'cr-toolbar',
6016 properties: {
6017 pageName: String,
6018 searchPrompt: String,
6019 clearLabel: String,
6020 menuLabel: String,
6021 spinnerActive: Boolean,
6022 showMenu: {
6023 type: Boolean,
6024 value: false
6025 },
6026 narrow_: {
6027 type: Boolean,
6028 reflectToAttribute: true
6029 },
6030 showingSearch_: {
6031 type: Boolean,
6032 reflectToAttribute: true
6033 }
6034 },
6035 getSearchField: function() {
6036 return this.$.search;
6037 },
6038 onMenuTap_: function(e) {
6039 this.fire('cr-menu-tap');
6040 }
6041 });
6042
6043 // Copyright 2016 The Chromium Authors. All rights reserved.
6044 // Use of this source code is governed by a BSD-style license that can be
6045 // found in the LICENSE file.
6046 Polymer({
6047 is: 'history-lazy-render',
6048 "extends": 'template',
6049 behaviors: [ Polymer.Templatizer ],
6050 _renderPromise: null,
6051 _instance: null,
6052 get: function() {
6053 if (!this._renderPromise) {
6054 this._renderPromise = new Promise(function(resolve) {
6055 this._debounceTemplate(function() {
6056 this._render();
6057 this._renderPromise = null;
6058 resolve(this.getIfExists());
6059 }.bind(this));
6060 }.bind(this));
6061 }
6062 return this._renderPromise;
6063 },
6064 getIfExists: function() {
6065 if (this._instance) {
6066 var children = this._instance._children;
6067 for (var i = 0; i < children.length; i++) {
6068 if (children[i].nodeType == Node.ELEMENT_NODE) return children[i];
6069 }
6070 }
6071 return null;
6072 },
6073 _render: function() {
6074 if (!this.ctor) this.templatize(this);
6075 var parentNode = this.parentNode;
6076 if (parentNode && !this._instance) {
6077 this._instance = this.stamp({});
6078 var root = this._instance.root;
6079 parentNode.insertBefore(root, this);
6080 }
6081 },
6082 _forwardParentProp: function(prop, value) {
6083 if (this._instance) this._instance.__setProperty(prop, value, true);
6084 },
6085 _forwardParentPath: function(path, value) {
6086 if (this._instance) this._instance._notifyPath(path, value, true);
6087 }
6088 });
6089
6090 // Copyright 2015 The Chromium Authors. All rights reserved.
6091 // Use of this source code is governed by a BSD-style license that can be
6092 // found in the LICENSE file.
6093 Polymer({
6094 is: 'history-toolbar',
6095 properties: {
6096 count: {
6097 type: Number,
6098 value: 0,
6099 observer: 'changeToolbarView_'
6100 },
6101 itemsSelected_: {
6102 type: Boolean,
6103 value: false,
6104 reflectToAttribute: true
6105 },
6106 searchTerm: {
6107 type: String,
6108 notify: true
6109 },
6110 spinnerActive: {
6111 type: Boolean,
6112 value: false
6113 },
6114 hasDrawer: {
6115 type: Boolean,
6116 observer: 'hasDrawerChanged_',
6117 reflectToAttribute: true
6118 },
6119 showSyncNotice: Boolean,
6120 isGroupedMode: {
6121 type: Boolean,
6122 reflectToAttribute: true
6123 },
6124 groupedRange: {
6125 type: Number,
6126 value: 0,
6127 reflectToAttribute: true,
6128 notify: true
6129 },
6130 queryStartTime: String,
6131 queryEndTime: String
6132 },
6133 changeToolbarView_: function() {
6134 this.itemsSelected_ = this.count > 0;
6135 },
6136 setSearchTerm: function(search) {
6137 if (this.searchTerm == search) return;
6138 this.searchTerm = search;
6139 var searchField = this.$['main-toolbar'].getSearchField();
6140 searchField.showAndFocus();
6141 searchField.setValue(search);
6142 },
6143 onSearchChanged_: function(event) {
6144 this.searchTerm = event.detail;
6145 },
6146 onInfoButtonTap_: function() {
6147 this.$.syncNotice.get().then(function(dropdown) {
6148 dropdown.positionTarget = this.$$('#info-button-icon');
6149 if (dropdown.style.display == 'none') dropdown.open();
6150 }.bind(this));
6151 },
6152 onClearSelectionTap_: function() {
6153 this.fire('unselect-all');
6154 },
6155 onDeleteTap_: function() {
6156 this.fire('delete-selected');
6157 },
6158 get searchBar() {
6159 return this.$['main-toolbar'].getSearchField();
6160 },
6161 showSearchField: function() {
6162 this.$['main-toolbar'].getSearchField().showAndFocus();
6163 },
6164 deletingAllowed_: function() {
6165 return loadTimeData.getBoolean('allowDeletingHistory');
6166 },
6167 numberOfItemsSelected_: function(count) {
6168 return count > 0 ? loadTimeData.getStringF('itemsSelected', count) : '';
6169 },
6170 getHistoryInterval_: function(queryStartTime, queryEndTime) {
6171 return loadTimeData.getStringF('historyInterval', queryStartTime, queryEndTi me);
6172 },
6173 hasDrawerChanged_: function() {
6174 this.updateStyles();
6175 }
6176 });
6177
6178 // Copyright 2016 The Chromium Authors. All rights reserved.
6179 // Use of this source code is governed by a BSD-style license that can be
6180 // found in the LICENSE file.
6181 Polymer({
6182 is: 'cr-dialog',
6183 "extends": 'dialog',
6184 created: function() {
6185 window.addEventListener('popstate', function() {
6186 if (this.open) this.cancel();
6187 }.bind(this));
6188 },
6189 cancel: function() {
6190 this.fire('cancel');
6191 HTMLDialogElement.prototype.close.call(this, '');
6192 },
6193 close: function(opt_returnValue) {
6194 HTMLDialogElement.prototype.close.call(this, 'success');
6195 },
6196 getCloseButton: function() {
6197 return this.$.close;
6198 }
6199 });
6200
6201 Polymer({
6122 is: 'fade-in-animation', 6202 is: 'fade-in-animation',
6123 behaviors: [ Polymer.NeonAnimationBehavior ], 6203 behaviors: [ Polymer.NeonAnimationBehavior ],
6124 configure: function(config) { 6204 configure: function(config) {
6125 var node = config.node; 6205 var node = config.node;
6126 this._effect = new KeyframeEffect(node, [ { 6206 this._effect = new KeyframeEffect(node, [ {
6127 opacity: '0' 6207 opacity: '0'
6128 }, { 6208 }, {
6129 opacity: '1' 6209 opacity: '1'
6130 } ], this.timingFromConfig(config)); 6210 } ], this.timingFromConfig(config));
6131 return this._effect; 6211 return this._effect;
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
6529 for (var prop in rect) { 6609 for (var prop in rect) {
6530 if (rect[prop] !== 0) return true; 6610 if (rect[prop] !== 0) return true;
6531 } 6611 }
6532 return false; 6612 return false;
6533 }, 6613 },
6534 _calcSize: function() { 6614 _calcSize: function() {
6535 return this.getBoundingClientRect()[this.dimension] + 'px'; 6615 return this.getBoundingClientRect()[this.dimension] + 'px';
6536 } 6616 }
6537 }); 6617 });
6538 6618
6539 Polymer({
6540 is: 'paper-icon-button-light',
6541 "extends": 'button',
6542 behaviors: [ Polymer.PaperRippleBehavior ],
6543 listeners: {
6544 down: '_rippleDown',
6545 up: '_rippleUp',
6546 focus: '_rippleDown',
6547 blur: '_rippleUp'
6548 },
6549 _rippleDown: function() {
6550 this.getRipple().downAction();
6551 },
6552 _rippleUp: function() {
6553 this.getRipple().upAction();
6554 },
6555 ensureRipple: function(var_args) {
6556 var lastRipple = this._ripple;
6557 Polymer.PaperRippleBehavior.ensureRipple.apply(this, arguments);
6558 if (this._ripple && this._ripple !== lastRipple) {
6559 this._ripple.center = true;
6560 this._ripple.classList.add('circle');
6561 }
6562 }
6563 });
6564
6565 // Copyright 2016 The Chromium Authors. All rights reserved. 6619 // Copyright 2016 The Chromium Authors. All rights reserved.
6566 // Use of this source code is governed by a BSD-style license that can be 6620 // Use of this source code is governed by a BSD-style license that can be
6567 // found in the LICENSE file. 6621 // found in the LICENSE file.
6568 cr.define('cr.icon', function() { 6622 cr.define('cr.icon', function() {
6569 function getSupportedScaleFactors() { 6623 function getSupportedScaleFactors() {
6570 var supportedScaleFactors = []; 6624 var supportedScaleFactors = [];
6571 if (!cr.isIOS) { 6625 if (!cr.isIOS) {
6572 supportedScaleFactors.push(1); 6626 supportedScaleFactors.push(1);
6573 } 6627 }
6574 if (cr.isMac || cr.isChromeOS || cr.isWindows || cr.isLinux) { 6628 if (cr.isMac || cr.isChromeOS || cr.isWindows || cr.isLinux) {
(...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after
8012 }, 8066 },
8013 pathForItem_: function(index) { 8067 pathForItem_: function(index) {
8014 return 'historyData_.' + index; 8068 return 'historyData_.' + index;
8015 } 8069 }
8016 }); 8070 });
8017 8071
8018 // Copyright 2016 The Chromium Authors. All rights reserved. 8072 // Copyright 2016 The Chromium Authors. All rights reserved.
8019 // Use of this source code is governed by a BSD-style license that can be 8073 // Use of this source code is governed by a BSD-style license that can be
8020 // found in the LICENSE file. 8074 // found in the LICENSE file.
8021 Polymer({ 8075 Polymer({
8022 is: 'history-lazy-render',
8023 "extends": 'template',
8024 behaviors: [ Polymer.Templatizer ],
8025 _renderPromise: null,
8026 _instance: null,
8027 get: function() {
8028 if (!this._renderPromise) {
8029 this._renderPromise = new Promise(function(resolve) {
8030 this._debounceTemplate(function() {
8031 this._render();
8032 this._renderPromise = null;
8033 resolve(this.getIfExists());
8034 }.bind(this));
8035 }.bind(this));
8036 }
8037 return this._renderPromise;
8038 },
8039 getIfExists: function() {
8040 if (this._instance) {
8041 var children = this._instance._children;
8042 for (var i = 0; i < children.length; i++) {
8043 if (children[i].nodeType == Node.ELEMENT_NODE) return children[i];
8044 }
8045 }
8046 return null;
8047 },
8048 _render: function() {
8049 if (!this.ctor) this.templatize(this);
8050 var parentNode = this.parentNode;
8051 if (parentNode && !this._instance) {
8052 this._instance = this.stamp({});
8053 var root = this._instance.root;
8054 parentNode.insertBefore(root, this);
8055 }
8056 },
8057 _forwardParentProp: function(prop, value) {
8058 if (this._instance) this._instance.__setProperty(prop, value, true);
8059 },
8060 _forwardParentPath: function(path, value) {
8061 if (this._instance) this._instance._notifyPath(path, value, true);
8062 }
8063 });
8064
8065 // Copyright 2016 The Chromium Authors. All rights reserved.
8066 // Use of this source code is governed by a BSD-style license that can be
8067 // found in the LICENSE file.
8068 Polymer({
8069 is: 'history-list-container', 8076 is: 'history-list-container',
8070 properties: { 8077 properties: {
8071 selectedPage_: String, 8078 selectedPage_: String,
8072 grouped: Boolean, 8079 grouped: Boolean,
8073 groupedRange: { 8080 groupedRange: {
8074 type: Number, 8081 type: Number,
8075 observer: 'groupedRangeChanged_' 8082 observer: 'groupedRangeChanged_'
8076 }, 8083 },
8077 queryState: Object, 8084 queryState: Object,
8078 queryResult: Object 8085 queryResult: Object
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
8481 }); 8488 });
8482 8489
8483 // Copyright 2016 The Chromium Authors. All rights reserved. 8490 // Copyright 2016 The Chromium Authors. All rights reserved.
8484 // Use of this source code is governed by a BSD-style license that can be 8491 // Use of this source code is governed by a BSD-style license that can be
8485 // found in the LICENSE file. 8492 // found in the LICENSE file.
8486 Polymer({ 8493 Polymer({
8487 is: 'history-app', 8494 is: 'history-app',
8488 behaviors: [ Polymer.IronScrollTargetBehavior ], 8495 behaviors: [ Polymer.IronScrollTargetBehavior ],
8489 properties: { 8496 properties: {
8490 showSidebarFooter: Boolean, 8497 showSidebarFooter: Boolean,
8498 hasSyncedResults: Boolean,
8491 selectedPage_: { 8499 selectedPage_: {
8492 type: String, 8500 type: String,
8493 observer: 'unselectAll' 8501 observer: 'unselectAll'
8494 }, 8502 },
8495 grouped_: { 8503 grouped_: {
8496 type: Boolean, 8504 type: Boolean,
8497 reflectToAttribute: true 8505 reflectToAttribute: true
8498 }, 8506 },
8499 queryState_: { 8507 queryState_: {
8500 type: Object, 8508 type: Object,
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
8639 }, 8647 },
8640 updateSignInState: function(isUserSignedIn) { 8648 updateSignInState: function(isUserSignedIn) {
8641 this.isUserSignedIn_ = isUserSignedIn; 8649 this.isUserSignedIn_ = isUserSignedIn;
8642 }, 8650 },
8643 syncedTabsSelected_: function(selectedPage) { 8651 syncedTabsSelected_: function(selectedPage) {
8644 return selectedPage == 'syncedTabs'; 8652 return selectedPage == 'syncedTabs';
8645 }, 8653 },
8646 shouldShowSpinner_: function(querying, incremental, searchTerm) { 8654 shouldShowSpinner_: function(querying, incremental, searchTerm) {
8647 return querying && !incremental && searchTerm != ''; 8655 return querying && !incremental && searchTerm != '';
8648 }, 8656 },
8657 showSyncNotice_: function(hasSyncedResults, selectedPage) {
8658 return hasSyncedResults && selectedPage != 'syncedTabs';
8659 },
8649 routeDataChanged_: function(page) { 8660 routeDataChanged_: function(page) {
8650 this.selectedPage_ = page; 8661 this.selectedPage_ = page;
8651 }, 8662 },
8652 selectedPageChanged_: function(selectedPage) { 8663 selectedPageChanged_: function(selectedPage) {
8653 this.set('routeData_.page', selectedPage); 8664 this.set('routeData_.page', selectedPage);
8654 this.historyViewChanged_(); 8665 this.historyViewChanged_();
8655 }, 8666 },
8656 historyViewChanged_: function() { 8667 historyViewChanged_: function() {
8657 requestAnimationFrame(function() { 8668 requestAnimationFrame(function() {
8658 this.scrollTarget = this.$.content.selectedItem.getContentScrollTarget(); 8669 this.scrollTarget = this.$.content.selectedItem.getContentScrollTarget();
(...skipping 27 matching lines...) Expand all
8686 8697
8687 case HistoryRange.MONTH: 8698 case HistoryRange.MONTH:
8688 histogramValue = HistoryPageViewHistogram.GROUPED_MONTH; 8699 histogramValue = HistoryPageViewHistogram.GROUPED_MONTH;
8689 break; 8700 break;
8690 } 8701 }
8691 break; 8702 break;
8692 } 8703 }
8693 md_history.BrowserService.getInstance().recordHistogram('History.HistoryPage View', histogramValue, HistoryPageViewHistogram.END); 8704 md_history.BrowserService.getInstance().recordHistogram('History.HistoryPage View', histogramValue, HistoryPageViewHistogram.END);
8694 } 8705 }
8695 }); 8706 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/md_history/app.js ('k') | chrome/browser/resources/md_history/app.vulcanized.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698