update components

This commit is contained in:
Luke Pulverenti 2016-03-11 22:29:37 -05:00
parent 1f41a29864
commit ba749de15d
18 changed files with 482 additions and 369 deletions

View file

@ -16,12 +16,12 @@
}, },
"devDependencies": {}, "devDependencies": {},
"ignore": [], "ignore": [],
"version": "1.1.33", "version": "1.1.37",
"_release": "1.1.33", "_release": "1.1.37",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "1.1.33", "tag": "1.1.37",
"commit": "9933aefe464ffcf5a3a29851ec0f34ff088d0ff5" "commit": "7235838b8cff53a9bb2aea7d6c6418160728cd3a"
}, },
"_source": "git://github.com/MediaBrowser/emby-webcomponents.git", "_source": "git://github.com/MediaBrowser/emby-webcomponents.git",
"_target": "~1.1.5", "_target": "~1.1.5",

View file

@ -99,6 +99,7 @@
browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) != -1; browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) != -1;
browser.tv = isTv(); browser.tv = isTv();
browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') != -1;
return browser; return browser;
}); });

View file

@ -88,6 +88,12 @@ define(['browser'], function (browser) {
// Unfortunately there's no real way to detect mkv support // Unfortunately there's no real way to detect mkv support
if (browser.chrome) { if (browser.chrome) {
// Not supported on opera tv
if (browser.operaTv) {
return false;
}
return true; return true;
} }
@ -125,6 +131,15 @@ define(['browser'], function (browser) {
case 'wmv': case 'wmv':
supported = browser.tizen || browser.web0s; supported = browser.tizen || browser.web0s;
break; break;
case 'ts':
supported = browser.tizen || browser.web0s;
if (supported) {
return {
Container: 'ts,mpegts',
Type: 'Video'
};
}
break;
default: default:
break; break;
} }
@ -231,17 +246,8 @@ define(['browser'], function (browser) {
}); });
} }
if (canPlayTs) {
profile.DirectPlayProfiles.push({
Container: 'ts,mpegts',
Type: 'Video',
VideoCodec: 'h264',
AudioCodec: videoAudioCodecs.join(',')
});
}
// These are formats we can't test for but some devices will support // These are formats we can't test for but some devices will support
['m2ts', 'wmv'].map(getDirectPlayProfileForVideoContainer).filter(function (i) { ['m2ts', 'wmv', 'ts'].map(getDirectPlayProfileForVideoContainer).filter(function (i) {
return i != null; return i != null;
}).forEach(function (i) { }).forEach(function (i) {

View file

@ -5,8 +5,8 @@ define(['visibleinviewport', 'imageFetcher'], function (visibleinviewport, image
var wheelEvent = (document.implementation.hasFeature('Event.wheel', '3.0') ? 'wheel' : 'mousewheel'); var wheelEvent = (document.implementation.hasFeature('Event.wheel', '3.0') ? 'wheel' : 'mousewheel');
function isVisible(elem) { function isVisible(elem, windowSize) {
return visibleinviewport(elem, true, thresholdX, thresholdY); return visibleinviewport(elem, true, thresholdX, thresholdY, windowSize);
} }
var self = {}; var self = {};
@ -56,6 +56,11 @@ define(['visibleinviewport', 'imageFetcher'], function (visibleinviewport, image
var anyFound = false; var anyFound = false;
var out = false; var out = false;
var windowSize = {
innerHeight: window.innerHeight,
innerWidth: window.innerWidth
};
// TODO: This out construct assumes left to right, top to bottom // TODO: This out construct assumes left to right, top to bottom
for (var i = 0, length = images.length; i < length; i++) { for (var i = 0, length = images.length; i < length; i++) {
@ -64,7 +69,7 @@ define(['visibleinviewport', 'imageFetcher'], function (visibleinviewport, image
return; return;
} }
var img = images[i]; var img = images[i];
if (!out && isVisible(img)) { if (!out && isVisible(img, windowSize)) {
anyFound = true; anyFound = true;
fillImage(img); fillImage(img);
} else { } else {

View file

@ -1,31 +1,54 @@
define(['focusManager'], function (focusManager) { define(['focusManager'], function (focusManager) {
function getOffset(elem) { function getOffsets(elems) {
var doc = document; var doc = document;
var box = { top: 0, left: 0 }; var results = [];
if (!doc) { if (!doc) {
return box; return results;
} }
var docElem = doc.documentElement; var docElem = doc.documentElement;
var docElemValues = {
// Support: BlackBerry 5, iOS 3 (original iPhone) clientTop: docElem.clientTop,
// If we don't have gBCR, just use 0,0 rather than error clientLeft: docElem.clientLeft
if (elem.getBoundingClientRect) {
box = elem.getBoundingClientRect();
}
var win = doc.defaultView;
return {
top: box.top + win.pageYOffset - docElem.clientTop,
left: box.left + win.pageXOffset - docElem.clientLeft
}; };
var win = doc.defaultView;
var winValues = {
pageXOffset: win.pageXOffset,
pageYOffset: win.pageYOffset
};
var box;
var elem;
for (var i = 0, length = elems.length; i < length; i++) {
elem = elems[i];
// Support: BlackBerry 5, iOS 3 (original iPhone)
// If we don't have gBCR, just use 0,0 rather than error
if (elem.getBoundingClientRect) {
box = elem.getBoundingClientRect();
} else {
box = { top: 0, left: 0 };
}
results[i] = {
top: box.top + winValues.pageYOffset - docElemValues.clientTop,
left: box.left + winValues.pageXOffset - docElemValues.clientLeft
};
}
return results;
} }
function getPosition(scrollContainer, item, horizontal) { function getPosition(scrollContainer, item, horizontal) {
var slideeOffset = getOffset(scrollContainer);
var itemOffset = getOffset(item); var offsets = getOffsets([scrollContainer, item]);
var slideeOffset = offsets[0];
var itemOffset = offsets[1];
var offset = horizontal ? itemOffset.left - slideeOffset.left : itemOffset.top - slideeOffset.top; var offset = horizontal ? itemOffset.left - slideeOffset.left : itemOffset.top - slideeOffset.top;
var size = item[horizontal ? 'offsetWidth' : 'offsetHeight']; var size = item[horizontal ? 'offsetWidth' : 'offsetHeight'];

View file

@ -10,17 +10,22 @@
* the user visible viewport of a web browser. * the user visible viewport of a web browser.
* only accounts for vertical position, not horizontal. * only accounts for vertical position, not horizontal.
*/ */
function visibleInViewport(elem, partial, thresholdX, thresholdY) { function visibleInViewport(elem, partial, thresholdX, thresholdY, windowSize) {
thresholdX = thresholdX || 0; thresholdX = thresholdX || 0;
thresholdY = thresholdY || 0; thresholdY = thresholdY || 0;
var vpWidth = window.innerWidth, if (!elem.getBoundingClientRect) {
vpHeight = window.innerHeight; return true;
}
if (!elem.getBoundingClientRect){
return true; windowSize = windowSize || {
} innerHeight: window.innerHeight,
innerWidth: window.innerWidth
};
var vpWidth = windowSize.innerWidth,
vpHeight = windowSize.innerHeight;
// Use this native browser method, if available. // Use this native browser method, if available.
var rec = elem.getBoundingClientRect(), var rec = elem.getBoundingClientRect(),

View file

@ -1,6 +1,6 @@
{ {
"name": "iron-dropdown", "name": "iron-dropdown",
"version": "1.2.0", "version": "1.3.0",
"description": "An unstyled element that works similarly to a native browser select", "description": "An unstyled element that works similarly to a native browser select",
"authors": [ "authors": [
"The Polymer Authors" "The Polymer Authors"
@ -36,11 +36,11 @@
"iron-image": "polymerelements/iron-image#^1.0.0" "iron-image": "polymerelements/iron-image#^1.0.0"
}, },
"ignore": [], "ignore": [],
"_release": "1.2.0", "_release": "1.3.0",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v1.2.0", "tag": "v1.3.0",
"commit": "f864191c6ffbd3aaddea8102102ab40137046327" "commit": "9d6bb9e7a8150430e61559f5a0827526d2eefaa4"
}, },
"_source": "git://github.com/polymerelements/iron-dropdown.git", "_source": "git://github.com/polymerelements/iron-dropdown.git",
"_target": "^1.0.0", "_target": "^1.0.0",

View file

@ -1,6 +1,6 @@
{ {
"name": "iron-dropdown", "name": "iron-dropdown",
"version": "1.2.0", "version": "1.3.0",
"description": "An unstyled element that works similarly to a native browser select", "description": "An unstyled element that works similarly to a native browser select",
"authors": [ "authors": [
"The Polymer Authors" "The Polymer Authors"

View file

@ -175,9 +175,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
_scrollInteractionHandler: function(event) { _scrollInteractionHandler: function(event) {
var scrolledElement =
/** @type {HTMLElement} */(Polymer.dom(event).rootTarget);
if (Polymer if (Polymer
.IronDropdownScrollManager .IronDropdownScrollManager
.elementIsScrollLocked(Polymer.dom(event).rootTarget)) { .elementIsScrollLocked(scrolledElement)) {
if (event.type === 'keydown' && if (event.type === 'keydown' &&
!Polymer.IronDropdownScrollManager._isScrollingKeypress(event)) { !Polymer.IronDropdownScrollManager._isScrollingKeypress(event)) {
return; return;

View file

@ -143,8 +143,7 @@ method is called on the element.
* it is opened. * it is opened.
*/ */
positionTarget: { positionTarget: {
type: Object, type: Object
observer: '_positionTargetChanged'
}, },
/** /**
@ -189,15 +188,6 @@ method is called on the element.
allowOutsideScroll: { allowOutsideScroll: {
type: Boolean, type: Boolean,
value: false value: false
},
/**
* We memoize the positionTarget bounding rectangle so that we can
* limit the number of times it is queried per resize / relayout.
* @type {?Object}
*/
_positionRectMemo: {
type: Object
} }
}, },
@ -206,13 +196,13 @@ method is called on the element.
}, },
observers: [ observers: [
'_updateOverlayPosition(verticalAlign, horizontalAlign, verticalOffset, horizontalOffset)' '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign, verticalOffset, horizontalOffset)'
], ],
attached: function() { attached: function() {
if (this.positionTarget === undefined) { this.positionTarget = this.positionTarget || this._defaultPositionTarget;
this.positionTarget = this._defaultPositionTarget; // Memoize this to avoid expensive calculations & relayouts.
} this._isRTL = window.getComputedStyle(this).direction == 'rtl';
}, },
/** /**
@ -230,13 +220,6 @@ method is called on the element.
return this.focusTarget || this.containedElement; return this.focusTarget || this.containedElement;
}, },
/**
* Whether the text direction is RTL
*/
_isRTL: function() {
return window.getComputedStyle(this).direction == 'rtl';
},
/** /**
* The element that should be used to position the dropdown when * The element that should be used to position the dropdown when
* it opens, if no position target is configured. * it opens, if no position target is configured.
@ -252,31 +235,32 @@ method is called on the element.
}, },
/** /**
* The bounding rect of the position target. * The horizontal align value, accounting for the RTL/LTR text direction.
*/ */
get _positionRect() { get _localeHorizontalAlign() {
if (!this._positionRectMemo && this.positionTarget) { // In RTL, "left" becomes "right".
this._positionRectMemo = this.positionTarget.getBoundingClientRect(); if (this._isRTL) {
return this.horizontalAlign === 'right' ? 'left' : 'right';
} else {
return this.horizontalAlign;
} }
return this._positionRectMemo;
}, },
/** /**
* The horizontal offset value used to position the dropdown. * The horizontal offset value used to position the dropdown.
* @param {ClientRect} dropdownRect
* @param {ClientRect} positionRect
* @param {boolean=false} fromRight
* @return {number} pixels
* @private
*/ */
get _horizontalAlignTargetValue() { _horizontalAlignTargetValue: function(dropdownRect, positionRect, fromRight) {
var target; var target;
if (fromRight) {
// In RTL, the direction flips, so what is "right" in LTR becomes "left". target = document.documentElement.clientWidth - positionRect.right - (this._fitWidth - dropdownRect.right);
var isRTL = this._isRTL();
if ((!isRTL && this.horizontalAlign === 'right') ||
(isRTL && this.horizontalAlign === 'left')) {
target = document.documentElement.clientWidth - this._positionRect.right;
} else { } else {
target = this._positionRect.left; target = positionRect.left - dropdownRect.left;
} }
target += this.horizontalOffset; target += this.horizontalOffset;
return Math.max(target, 0); return Math.max(target, 0);
@ -284,33 +268,24 @@ method is called on the element.
/** /**
* The vertical offset value used to position the dropdown. * The vertical offset value used to position the dropdown.
* @param {ClientRect} dropdownRect
* @param {ClientRect} positionRect
* @param {boolean=false} fromBottom
* @return {number} pixels
* @private
*/ */
get _verticalAlignTargetValue() { _verticalAlignTargetValue: function(dropdownRect, positionRect, fromBottom) {
var target; var target;
if (fromBottom) {
if (this.verticalAlign === 'bottom') { target = document.documentElement.clientHeight - positionRect.bottom - (this._fitHeight - dropdownRect.bottom);
target = document.documentElement.clientHeight - this._positionRect.bottom;
} else { } else {
target = this._positionRect.top; target = positionRect.top - dropdownRect.top;
} }
target += this.verticalOffset; target += this.verticalOffset;
return Math.max(target, 0); return Math.max(target, 0);
}, },
/**
* The horizontal align value, accounting for the RTL/LTR text direction.
*/
get _localeHorizontalAlign() {
// In RTL, "left" becomes "right".
if (this._isRTL()) {
return this.horizontalAlign === 'right' ? 'left' : 'right';
} else {
return this.horizontalAlign;
}
},
/** /**
* Called when the value of `opened` changes. * Called when the value of `opened` changes.
* *
@ -321,7 +296,8 @@ method is called on the element.
this.cancel(); this.cancel();
} else { } else {
this.cancelAnimation(); this.cancelAnimation();
this._prepareDropdown(); this.sizingTarget = this.containedElement || this.sizingTarget;
this._updateAnimationConfig();
Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments); Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments);
} }
}, },
@ -335,6 +311,9 @@ method is called on the element.
} }
if (!this.noAnimations && this.animationConfig && this.animationConfig.open) { if (!this.noAnimations && this.animationConfig && this.animationConfig.open) {
if (this.withBackdrop) {
this.backdropElement.open();
}
this.$.contentWrapper.classList.add('animating'); this.$.contentWrapper.classList.add('animating');
this.playAnimation('open'); this.playAnimation('open');
} else { } else {
@ -348,6 +327,9 @@ method is called on the element.
_renderClosed: function() { _renderClosed: function() {
Polymer.IronDropdownScrollManager.removeScrollLock(this); Polymer.IronDropdownScrollManager.removeScrollLock(this);
if (!this.noAnimations && this.animationConfig && this.animationConfig.close) { if (!this.noAnimations && this.animationConfig && this.animationConfig.close) {
if (this.withBackdrop) {
this.backdropElement.close();
}
this.$.contentWrapper.classList.add('animating'); this.$.contentWrapper.classList.add('animating');
this.playAnimation('close'); this.playAnimation('close');
} else { } else {
@ -364,44 +346,12 @@ method is called on the element.
_onNeonAnimationFinish: function() { _onNeonAnimationFinish: function() {
this.$.contentWrapper.classList.remove('animating'); this.$.contentWrapper.classList.remove('animating');
if (this.opened) { if (this.opened) {
Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this); Polymer.IronOverlayBehaviorImpl._finishRenderOpened.apply(this);
} else { } else {
Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this); Polymer.IronOverlayBehaviorImpl._finishRenderClosed.apply(this);
} }
}, },
/**
* Called when an `iron-resize` event fires.
*/
_onIronResize: function() {
var containedElement = this.containedElement;
var scrollTop;
var scrollLeft;
if (this.opened && containedElement) {
scrollTop = containedElement.scrollTop;
scrollLeft = containedElement.scrollLeft;
}
if (this.opened) {
this._updateOverlayPosition();
}
Polymer.IronOverlayBehaviorImpl._onIronResize.apply(this, arguments);
if (this.opened && containedElement) {
containedElement.scrollTop = scrollTop;
containedElement.scrollLeft = scrollLeft;
}
},
/**
* Called when the `positionTarget` property changes.
*/
_positionTargetChanged: function() {
this._updateOverlayPosition();
},
/** /**
* Constructs the final animation config from different properties used * Constructs the final animation config from different properties used
* to configure specific parts of the opening and closing animations. * to configure specific parts of the opening and closing animations.
@ -434,43 +384,73 @@ method is called on the element.
}, },
/** /**
* Prepares the dropdown for opening by updating measured layout * Updates the overlay position based on configured horizontal
* values. * and vertical alignment.
*/ */
_prepareDropdown: function() { _updateOverlayPosition: function() {
this.sizingTarget = this.containedElement || this.sizingTarget; if (this.isAttached) {
this._updateAnimationConfig(); // This triggers iron-resize, and iron-overlay-behavior will call refit if needed.
this._updateOverlayPosition(); this.notifyResize();
}
}, },
/** /**
* Updates the overlay position based on configured horizontal * Useful to call this after the element, the window, or the `fitInfo`
* and vertical alignment, and re-memoizes these values for the sake * element has been resized. Will maintain the scroll position.
* of behavior in `IronFitBehavior`.
*/ */
_updateOverlayPosition: function() { refit: function () {
this._positionRectMemo = null; if (!this.opened) {
return
if (!this.positionTarget) {
return;
} }
var containedElement = this.containedElement;
var scrollTop;
var scrollLeft;
this.style[this._localeHorizontalAlign] = if (containedElement) {
this._horizontalAlignTargetValue + 'px'; scrollTop = containedElement.scrollTop;
scrollLeft = containedElement.scrollLeft;
this.style[this.verticalAlign] =
this._verticalAlignTargetValue + 'px';
// NOTE(cdata): We re-memoize inline styles here, otherwise
// calling `refit` from `IronFitBehavior` will reset inline styles
// to whatever they were when the dropdown first opened.
if (this._fitInfo) {
this._fitInfo.inlineStyle[this.horizontalAlign] =
this.style[this.horizontalAlign];
this._fitInfo.inlineStyle[this.verticalAlign] =
this.style[this.verticalAlign];
} }
Polymer.IronFitBehavior.refit.apply(this, arguments);
if (containedElement) {
containedElement.scrollTop = scrollTop;
containedElement.scrollLeft = scrollLeft;
}
},
/**
* Resets the target element's position and size constraints, and clear
* the memoized data.
*/
resetFit: function() {
Polymer.IronFitBehavior.resetFit.apply(this, arguments);
var hAlign = this._localeHorizontalAlign;
var vAlign = this.verticalAlign;
// Set to 0, 0 in order to discover any offset caused by parent stacking contexts.
this.style[hAlign] = this.style[vAlign] = '0px';
var dropdownRect = this.getBoundingClientRect();
var positionRect = this.positionTarget.getBoundingClientRect();
var horizontalValue = this._horizontalAlignTargetValue(dropdownRect, positionRect, hAlign === 'right');
var verticalValue = this._verticalAlignTargetValue(dropdownRect, positionRect, vAlign === 'bottom');
this.style[hAlign] = horizontalValue + 'px';
this.style[vAlign] = verticalValue + 'px';
},
/**
* Overridden from `IronFitBehavior`.
* Ensure positionedBy has correct values for horizontally & vertically.
*/
_discoverInfo: function() {
Polymer.IronFitBehavior._discoverInfo.apply(this, arguments);
// Note(valdrin): in Firefox, an element with style `position: fixed; bottom: 90vh; height: 20vh`
// would have `getComputedStyle(element).top < 0` (instead of being `auto`) http://jsbin.com/cofired/3/edit?html,output
// This would cause IronFitBehavior's `constrain` to wrongly calculate sizes
// (it would use `top` instead of `bottom`), so we ensure we give the correct values.
this._fitInfo.positionedBy.horizontally = this._localeHorizontalAlign;
this._fitInfo.positionedBy.vertically = this.verticalAlign;
}, },
/** /**

View file

@ -28,13 +28,38 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.container {
display: block;
position: relative;
width: 100px;
height: 100px;
background-color: yellow;
}
.positioned {
position: absolute;
top: 40px;
left: 40px;
}
.dropdown-content {
width: 50px;
height: 50px;
background-color: orange;
}
.full-screen {
width: 100vw;
height: 100vh;
}
</style> </style>
<body> <body>
<test-fixture id="TrivialDropdown"> <test-fixture id="TrivialDropdown">
<template> <template>
<iron-dropdown> <iron-dropdown>
<div class="dropdown-content">Hello!</div> <div class="dropdown-content"></div>
</iron-dropdown> </iron-dropdown>
</template> </template>
</test-fixture> </test-fixture>
@ -49,9 +74,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<test-fixture id="AlignedDropdown"> <test-fixture id="AlignedDropdown">
<template> <template>
<div style="display: block; position: relative; width: 100px; height: 100px;"> <div class="container">
<iron-dropdown horizontal-align="right" vertical-align="top"> <iron-dropdown horizontal-align="right" vertical-align="top">
<div class="dropdown-content">Hello!</div> <div class="dropdown-content full-screen"></div>
</iron-dropdown> </iron-dropdown>
</div> </div>
</template> </template>
@ -60,9 +85,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<!-- Absolutely position the dropdown so that it has enough space to move around --> <!-- Absolutely position the dropdown so that it has enough space to move around -->
<test-fixture id="OffsetDropdownTopLeft"> <test-fixture id="OffsetDropdownTopLeft">
<template> <template>
<div style="display: block; position: absolute; top: 40px; left: 40px; width: 100px; height: 100px;"> <div class="container positioned">
<iron-dropdown> <iron-dropdown>
<div class="dropdown-content">Hello!</div> <div class="dropdown-content"></div>
</iron-dropdown> </iron-dropdown>
</div> </div>
</template> </template>
@ -70,9 +95,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<test-fixture id="OffsetDropdownBottomRight"> <test-fixture id="OffsetDropdownBottomRight">
<template> <template>
<div style="display: block; position: absolute; top: 40px; left: 40px; width: 100px; height: 100px;"> <div class="container positioned">
<iron-dropdown horizontal-align="right" vertical-align="bottom"> <iron-dropdown horizontal-align="right" vertical-align="bottom">
<div class="dropdown-content">Hello!</div> <div class="dropdown-content"></div>
</iron-dropdown> </iron-dropdown>
</div> </div>
</template> </template>
@ -90,9 +115,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<test-fixture id="RTLDropdownLeft"> <test-fixture id="RTLDropdownLeft">
<template> <template>
<div dir="rtl" style="display: block; position: relative; width: 100px; height: 100px;"> <div dir="rtl" class="container">
<iron-dropdown> <iron-dropdown>
<div class="dropdown-content">Hello!</div> <div class="dropdown-content"></div>
</iron-dropdown> </iron-dropdown>
</div> </div>
</template> </template>
@ -100,9 +125,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<test-fixture id="RTLDropdownRight"> <test-fixture id="RTLDropdownRight">
<template> <template>
<div dir="rtl" style="display: block; position: relative; width: 100px; height: 100px;"> <div dir="rtl" class="container">
<iron-dropdown horizontal-align="right"> <iron-dropdown horizontal-align="right">
<div class="dropdown-content">Hello!</div> <div class="dropdown-content"></div>
</iron-dropdown> </iron-dropdown>
</div> </div>
</template> </template>
@ -196,7 +221,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
.to.be.equal(1); .to.be.equal(1);
expect(Polymer.IronDropdownScrollManager.elementIsScrollLocked(document.body)) expect(Polymer.IronDropdownScrollManager.elementIsScrollLocked(document.body))
.to.be.equal(true); .to.be.equal(true);
if(openCount === 0) { if(openCount === 0) {
// This triggers a second `pushScrollLock` with the same element, however // This triggers a second `pushScrollLock` with the same element, however
// that should not add the element to the `_lockingElements` stack twice // that should not add the element to the `_lockingElements` stack twice
@ -240,11 +265,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
runAfterOpen(dropdown, function () { runAfterOpen(dropdown, function () {
dropdownRect = dropdown.getBoundingClientRect(); dropdownRect = dropdown.getBoundingClientRect();
parentRect = parent.getBoundingClientRect(); parentRect = parent.getBoundingClientRect();
assert.equal(dropdownRect.top, parentRect.top, 'top ok');
// NOTE(cdata): IE10 / 11 have minor rounding errors in this case, assert.equal(dropdownRect.left, 0, 'left ok');
// so we assert with `closeTo` and a tight threshold: assert.equal(dropdownRect.bottom, document.documentElement.clientHeight, 'bottom ok');
expect(dropdownRect.top).to.be.closeTo(parentRect.top, 0.1); assert.equal(dropdownRect.right, parentRect.right, 'right ok');
expect(dropdownRect.right).to.be.closeTo(parentRect.right, 0.1);
done(); done();
}); });
}); });
@ -257,11 +281,26 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
runAfterOpen(dropdown, function () { runAfterOpen(dropdown, function () {
parentRect = parent.getBoundingClientRect(); parentRect = parent.getBoundingClientRect();
dropdownRect = dropdown.getBoundingClientRect(); dropdownRect = dropdown.getBoundingClientRect();
assert.equal(dropdownRect.top, 0, 'top ok');
assert.equal(dropdownRect.left, 0, 'left ok');
assert.equal(dropdownRect.bottom, parentRect.bottom, 'bottom ok');
assert.equal(dropdownRect.right, parentRect.right, 'right ok');
done();
});
});
// NOTE(cdata): IE10 / 11 have minor rounding errors in this case, test('handles parent\'s stacking context', function(done) {
// so we assert with `closeTo` and a tight threshold: var parentRect;
expect(dropdownRect.bottom).to.be.closeTo(parentRect.bottom, 0.1); var dropdownRect;
expect(dropdownRect.right).to.be.closeTo(parentRect.right, 0.1); // This will create a new stacking context.
parent.style.transform = 'translateZ(0)';
runAfterOpen(dropdown, function () {
dropdownRect = dropdown.getBoundingClientRect();
parentRect = parent.getBoundingClientRect();
assert.equal(dropdownRect.top, parentRect.top, 'top ok');
assert.equal(dropdownRect.left, 0, 'left ok');
assert.equal(dropdownRect.bottom, document.documentElement.clientHeight, 'bottom ok');
assert.equal(dropdownRect.right, parentRect.right, 'right ok');
done(); done();
}); });
}); });
@ -285,9 +324,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
offsetDropdownRect = dropdown.getBoundingClientRect(); offsetDropdownRect = dropdown.getBoundingClientRect();
// verticalAlign is top, so a positive offset moves down. // verticalAlign is top, so a positive offset moves down.
expect(dropdownRect.top + 10).to.be.closeTo(offsetDropdownRect.top, 0.1); assert.equal(dropdownRect.top + 10, offsetDropdownRect.top, 'top ok');
// horizontalAlign is left, so a positive offset moves to the right. // horizontalAlign is left, so a positive offset moves to the right.
expect(dropdownRect.left + 10).to.be.closeTo(offsetDropdownRect.left, 0.1); assert.equal(dropdownRect.left + 10, offsetDropdownRect.left, 'left ok');
done(); done();
}); });
}); });
@ -301,9 +340,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
offsetDropdownRect = dropdown.getBoundingClientRect(); offsetDropdownRect = dropdown.getBoundingClientRect();
// verticalAlign is top, so a negative offset moves up. // verticalAlign is top, so a negative offset moves up.
expect(dropdownRect.top - 10).to.be.closeTo(offsetDropdownRect.top, 0.1); assert.equal(dropdownRect.top - 10, offsetDropdownRect.top, 'top ok');
// horizontalAlign is left, so a negative offset moves to the left. // horizontalAlign is left, so a negative offset moves to the left.
expect(dropdownRect.left - 10).to.be.closeTo(offsetDropdownRect.left, 0.1); assert.equal(dropdownRect.left - 10, offsetDropdownRect.left, 'left ok');
done(); done();
}); });
}); });
@ -327,9 +366,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
offsetDropdownRect = dropdown.getBoundingClientRect(); offsetDropdownRect = dropdown.getBoundingClientRect();
// verticalAlign is bottom, so a positive offset moves up. // verticalAlign is bottom, so a positive offset moves up.
expect(dropdownRect.bottom - 10).to.be.closeTo(offsetDropdownRect.bottom, 0.1); assert.equal(dropdownRect.bottom - 10, offsetDropdownRect.bottom, 'bottom ok');
// horizontalAlign is right, so a positive offset moves to the left. // horizontalAlign is right, so a positive offset moves to the left.
expect(dropdownRect.right - 10).to.be.closeTo(offsetDropdownRect.right, 0.1); assert.equal(dropdownRect.right - 10, offsetDropdownRect.right, 'right ok');
done(); done();
}); });
}); });
@ -343,9 +382,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
offsetDropdownRect = dropdown.getBoundingClientRect(); offsetDropdownRect = dropdown.getBoundingClientRect();
// verticalAlign is bottom, so a negative offset moves down. // verticalAlign is bottom, so a negative offset moves down.
expect(dropdownRect.bottom + 10).to.be.closeTo(offsetDropdownRect.bottom, 0.1); assert.equal(dropdownRect.bottom + 10, offsetDropdownRect.bottom, 'bottom ok');
// horizontalAlign is right, so a positive offset moves to the right. // horizontalAlign is right, so a positive offset moves to the right.
expect(dropdownRect.right + 10).to.be.closeTo(offsetDropdownRect.right, 0.1); assert.equal(dropdownRect.right + 10, offsetDropdownRect.right, 'right ok');
done(); done();
}); });
}); });

View file

@ -32,14 +32,14 @@
"web-component-tester": "^4.0.0", "web-component-tester": "^4.0.0",
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
}, },
"homepage": "https://github.com/PolymerElements/iron-icon", "homepage": "https://github.com/polymerelements/iron-icon",
"_release": "1.0.8", "_release": "1.0.8",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v1.0.8", "tag": "v1.0.8",
"commit": "f36b38928849ef3853db727faa8c9ef104d611eb" "commit": "f36b38928849ef3853db727faa8c9ef104d611eb"
}, },
"_source": "git://github.com/PolymerElements/iron-icon.git", "_source": "git://github.com/polymerelements/iron-icon.git",
"_target": "^1.0.0", "_target": "^1.0.0",
"_originalSource": "PolymerElements/iron-icon" "_originalSource": "polymerelements/iron-icon"
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "iron-overlay-behavior", "name": "iron-overlay-behavior",
"version": "1.4.2", "version": "1.4.3",
"license": "http://polymer.github.io/LICENSE.txt", "license": "http://polymer.github.io/LICENSE.txt",
"description": "Provides a behavior for making an element an overlay", "description": "Provides a behavior for making an element an overlay",
"private": true, "private": true,
@ -35,11 +35,11 @@
}, },
"ignore": [], "ignore": [],
"homepage": "https://github.com/polymerelements/iron-overlay-behavior", "homepage": "https://github.com/polymerelements/iron-overlay-behavior",
"_release": "1.4.2", "_release": "1.4.3",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v1.4.2", "tag": "v1.4.3",
"commit": "565869d04433fb1065210ca30d81e7b7c4af73f8" "commit": "6b8662619fbd4e82c2cebce6a846425ff9fc610d"
}, },
"_source": "git://github.com/polymerelements/iron-overlay-behavior.git", "_source": "git://github.com/polymerelements/iron-overlay-behavior.git",
"_target": "^1.0.0", "_target": "^1.0.0",

View file

@ -1,6 +1,6 @@
{ {
"name": "iron-overlay-behavior", "name": "iron-overlay-behavior",
"version": "1.4.2", "version": "1.4.3",
"license": "http://polymer.github.io/LICENSE.txt", "license": "http://polymer.github.io/LICENSE.txt",
"description": "Provides a behavior for making an element an overlay", "description": "Provides a behavior for making an element an overlay",
"private": true, "private": true,

View file

@ -136,6 +136,11 @@ context. You should place this element as a child of `<body>` whenever possible.
value: false value: false
}, },
/**
* Shortcut to access to the overlay manager.
* @private
* @type {Polymer.IronOverlayManagerClass}
*/
_manager: { _manager: {
type: Object, type: Object,
value: Polymer.IronOverlayManager value: Polymer.IronOverlayManager
@ -176,7 +181,7 @@ context. You should place this element as a child of `<body>` whenever possible.
/** /**
* The backdrop element. * The backdrop element.
* @type {Node} * @type {Element}
*/ */
get backdropElement() { get backdropElement() {
return this._manager.backdropElement; return this._manager.backdropElement;
@ -197,7 +202,7 @@ context. You should place this element as a child of `<body>` whenever possible.
* *
* If you know what is your content (specifically the first and last focusable children), * If you know what is your content (specifically the first and last focusable children),
* you can override this method to return only `[firstFocusable, lastFocusable];` * you can override this method to return only `[firstFocusable, lastFocusable];`
* @type {[Node]} * @type {Array<Node>}
* @protected * @protected
*/ */
get _focusableNodes() { get _focusableNodes() {
@ -295,7 +300,7 @@ context. You should place this element as a child of `<body>` whenever possible.
/** /**
* Cancels the overlay. * Cancels the overlay.
* @param {?Event} event The original event * @param {Event=} event The original event
*/ */
cancel: function(event) { cancel: function(event) {
var cancelEvent = this.fire('iron-overlay-canceled', event, {cancelable: true}); var cancelEvent = this.fire('iron-overlay-canceled', event, {cancelable: true});

View file

@ -15,197 +15,244 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/** /**
* @struct * @struct
* @constructor * @constructor
* @private
*/ */
Polymer.IronOverlayManagerClass = function() { Polymer.IronOverlayManagerClass = function() {
/**
* Used to keep track of the opened overlays.
* @private {Array<Element>}
*/
this._overlays = []; this._overlays = [];
// Used to keep track of the last focused node before an overlay gets opened.
/**
* Used to keep track of the last focused node before an overlay gets opened.
* @private {Array<Element>}
*/
this._lastFocusedNodes = []; this._lastFocusedNodes = [];
/** /**
* iframes have a default z-index of 100, so this default should be at least * iframes have a default z-index of 100,
* that. * so this default should be at least that.
* @private {number} * @private {number}
*/ */
this._minimumZ = 101; this._minimumZ = 101;
/**
* Used to keep track of the opened overlays with backdrop.
* @private {Array<Element>}
*/
this._backdrops = []; this._backdrops = [];
/**
* Memoized backdrop element.
* @private {Element|null}
*/
this._backdropElement = null; this._backdropElement = null;
Object.defineProperty(this, 'backdropElement', { };
get: function() {
if (!this._backdropElement) { Polymer.IronOverlayManagerClass.prototype = {
this._backdropElement = document.createElement('iron-overlay-backdrop');
} constructor: Polymer.IronOverlayManagerClass,
return this._backdropElement;
}.bind(this) /**
}); * The shared backdrop element.
* @type {Element} backdropElement
*/
get backdropElement() {
if (!this._backdropElement) {
this._backdropElement = document.createElement('iron-overlay-backdrop');
}
return this._backdropElement;
},
/** /**
* The deepest active element. * The deepest active element.
* returns {?Node} element the active element * @type {Element|undefined} activeElement the active element
*/ */
this.deepActiveElement = null; get deepActiveElement() {
Object.defineProperty(this, 'deepActiveElement', { var active = document.activeElement;
get: function() { // document.activeElement can be null
var active = document.activeElement; // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
// document.activeElement can be null while (active && active.root && Polymer.dom(active.root).activeElement) {
// https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement active = Polymer.dom(active.root).activeElement;
while (active && active.root && Polymer.dom(active.root).activeElement) { }
active = Polymer.dom(active.root).activeElement; return active;
},
/**
* If a node is contained in an overlay.
* @param {Element=} node
* @return {boolean}
* @private
*/
_isChildOfOverlay: function(node) {
while (node && node !== document.body) {
// Use logical parentNode, or native ShadowRoot host.
node = Polymer.dom(node).parentNode || node.host;
// Check if it is an overlay.
if (node && node.behaviors && node.behaviors.indexOf(Polymer.IronOverlayBehaviorImpl) !== -1) {
return true;
} }
return active;
}.bind(this)
});
};
/**
* If a node is contained in an overlay.
* @private
* @param {Node} node
* @returns {Boolean}
*/
Polymer.IronOverlayManagerClass.prototype._isChildOfOverlay = function(node) {
while (node && node !== document.body) {
// Use logical parentNode, or native ShadowRoot host.
node = Polymer.dom(node).parentNode || node.host;
// Check if it is an overlay.
if (node && node.behaviors && node.behaviors.indexOf(Polymer.IronOverlayBehaviorImpl) !== -1) {
return true;
} }
} return false;
return false; },
};
Polymer.IronOverlayManagerClass.prototype._applyOverlayZ = function(overlay, aboveZ) { /**
this._setZ(overlay, aboveZ + 2); * @param {Element} overlay
}; * @param {number} aboveZ
* @private
*/
_applyOverlayZ: function(overlay, aboveZ) {
this._setZ(overlay, aboveZ + 2);
},
Polymer.IronOverlayManagerClass.prototype._setZ = function(element, z) { /**
element.style.zIndex = z; * @param {Element} element
}; * @param {number|string} z
* @private
*/
_setZ: function(element, z) {
element.style.zIndex = z;
},
/** /**
* track overlays for z-index and focus managemant * Tracks overlays for z-index and focus management.
*/ * @param {Element} overlay
Polymer.IronOverlayManagerClass.prototype.addOverlay = function(overlay) { */
var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ); addOverlay: function(overlay) {
this._overlays.push(overlay); var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
var newZ = this.currentOverlayZ(); this._overlays.push(overlay);
if (newZ <= minimumZ) { var newZ = this.currentOverlayZ();
this._applyOverlayZ(overlay, minimumZ); if (newZ <= minimumZ) {
} this._applyOverlayZ(overlay, minimumZ);
var element = this.deepActiveElement;
// If already in other overlay, don't reset focus there.
if (this._isChildOfOverlay(element)) {
element = null;
}
this._lastFocusedNodes.push(element);
};
Polymer.IronOverlayManagerClass.prototype.removeOverlay = function(overlay) {
var i = this._overlays.indexOf(overlay);
if (i >= 0) {
this._overlays.splice(i, 1);
this._setZ(overlay, '');
var node = this._lastFocusedNodes[i];
// Focus only if still contained in document.body
if (overlay.restoreFocusOnClose && node && Polymer.dom(document.body).deepContains(node)) {
node.focus();
} }
this._lastFocusedNodes.splice(i, 1); var element = this.deepActiveElement;
} // If already in other overlay, don't reset focus there.
}; if (this._isChildOfOverlay(element)) {
element = null;
Polymer.IronOverlayManagerClass.prototype.currentOverlay = function() {
var i = this._overlays.length - 1;
while (this._overlays[i] && !this._overlays[i].opened) {
--i;
}
return this._overlays[i];
};
Polymer.IronOverlayManagerClass.prototype.currentOverlayZ = function() {
return this._getOverlayZ(this.currentOverlay());
};
/**
* Ensures that the minimum z-index of new overlays is at least `minimumZ`.
* This does not effect the z-index of any existing overlays.
*
* @param {number} minimumZ
*/
Polymer.IronOverlayManagerClass.prototype.ensureMinimumZ = function(minimumZ) {
this._minimumZ = Math.max(this._minimumZ, minimumZ);
};
Polymer.IronOverlayManagerClass.prototype.focusOverlay = function() {
var current = this.currentOverlay();
// We have to be careful to focus the next overlay _after_ any current
// transitions are complete (due to the state being toggled prior to the
// transition). Otherwise, we risk infinite recursion when a transitioning
// (closed) overlay becomes the current overlay.
//
// NOTE: We make the assumption that any overlay that completes a transition
// will call into focusOverlay to kick the process back off. Currently:
// transitionend -> _applyFocus -> focusOverlay.
if (current && !current.transitioning) {
current._applyFocus();
}
};
Polymer.IronOverlayManagerClass.prototype.trackBackdrop = function(element) {
// backdrops contains the overlays with a backdrop that are currently
// visible
var index = this._backdrops.indexOf(element);
if (element.opened && element.withBackdrop) {
// no duplicates
if (index === -1) {
this._backdrops.push(element);
} }
} else if (index >= 0) { this._lastFocusedNodes.push(element);
this._backdrops.splice(index, 1); },
}
};
Polymer.IronOverlayManagerClass.prototype.getBackdrops = function() { /**
return this._backdrops; * @param {Element} overlay
}; */
removeOverlay: function(overlay) {
var i = this._overlays.indexOf(overlay);
if (i >= 0) {
this._overlays.splice(i, 1);
this._setZ(overlay, '');
/** var node = this._lastFocusedNodes[i];
* Returns the z-index for the backdrop. // Focus only if still contained in document.body
*/ if (overlay.restoreFocusOnClose && node && Polymer.dom(document.body).deepContains(node)) {
Polymer.IronOverlayManagerClass.prototype.backdropZ = function() { node.focus();
return this._getOverlayZ(this._overlayWithBackdrop()) - 1; }
}; this._lastFocusedNodes.splice(i, 1);
/**
* Returns the first opened overlay that has a backdrop.
*/
Polymer.IronOverlayManagerClass.prototype._overlayWithBackdrop = function() {
for (var i = 0; i < this._overlays.length; i++) {
if (this._overlays[i].opened && this._overlays[i].withBackdrop) {
return this._overlays[i];
} }
} },
};
/** /**
* Calculates the minimum z-index for the overlay. * @return {Element|undefined} overlay The current overlay.
*/ */
Polymer.IronOverlayManagerClass.prototype._getOverlayZ = function(overlay) { currentOverlay: function() {
var z = this._minimumZ; var i = this._overlays.length - 1;
if (overlay) { while (this._overlays[i] && !this._overlays[i].opened) {
var z1 = Number(window.getComputedStyle(overlay).zIndex); --i;
// Check if is a number
// Number.isNaN not supported in IE 10+
if (z1 === z1) {
z = z1;
} }
return this._overlays[i];
},
/**
* @return {number} zIndex the current overlay z-index.
*/
currentOverlayZ: function() {
return this._getOverlayZ(this.currentOverlay());
},
/**
* Ensures that the minimum z-index of new overlays is at least `minimumZ`.
* This does not effect the z-index of any existing overlays.
* @param {number} minimumZ
*/
ensureMinimumZ: function(minimumZ) {
this._minimumZ = Math.max(this._minimumZ, minimumZ);
},
focusOverlay: function() {
var current = /** @type {?} */ (this.currentOverlay());
// We have to be careful to focus the next overlay _after_ any current
// transitions are complete (due to the state being toggled prior to the
// transition). Otherwise, we risk infinite recursion when a transitioning
// (closed) overlay becomes the current overlay.
//
// NOTE: We make the assumption that any overlay that completes a transition
// will call into focusOverlay to kick the process back off. Currently:
// transitionend -> _applyFocus -> focusOverlay.
if (current && !current.transitioning) {
current._applyFocus();
}
},
/**
* @param {Element} overlay The overlay that updated its withBackdrop.
*/
trackBackdrop: function(overlay) {
var index = this._backdrops.indexOf(overlay);
if (overlay.opened && overlay.withBackdrop) {
// no duplicates
if (index === -1) {
this._backdrops.push(overlay);
}
} else if (index >= 0) {
this._backdrops.splice(index, 1);
}
},
/**
* @return {Array<Element>} backdrops
*/
getBackdrops: function() {
return this._backdrops;
},
/**
* @return {number} index The z-index for the backdrop.
*/
backdropZ: function() {
return this._getOverlayZ(this._overlayWithBackdrop()) - 1;
},
/**
* @return {Element|undefined} overlay The first opened overlay that has a backdrop.
* @private
*/
_overlayWithBackdrop: function() {
for (var i = 0; i < this._overlays.length; i++) {
if (this._overlays[i].opened && this._overlays[i].withBackdrop) {
return this._overlays[i];
}
}
},
/**
* Calculates the minimum z-index for the overlay.
* @param {Element=} overlay
* @private
*/
_getOverlayZ: function(overlay) {
var z = this._minimumZ;
if (overlay) {
var z1 = Number(window.getComputedStyle(overlay).zIndex);
// Check if is a number
// Number.isNaN not supported in IE 10+
if (z1 === z1) {
z = z1;
}
}
return z;
} }
return z;
}; };
Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();
</script> </script>

View file

@ -45,7 +45,7 @@
"tag": "v1.0.11", "tag": "v1.0.11",
"commit": "e3c1ab0c72905b58fb4d9adc2921ea73b5c085a5" "commit": "e3c1ab0c72905b58fb4d9adc2921ea73b5c085a5"
}, },
"_source": "git://github.com/polymerelements/paper-behaviors.git", "_source": "git://github.com/PolymerElements/paper-behaviors.git",
"_target": "^1.0.0", "_target": "^1.0.0",
"_originalSource": "polymerelements/paper-behaviors" "_originalSource": "PolymerElements/paper-behaviors"
} }

View file

@ -32,14 +32,14 @@
"iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0" "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0"
}, },
"ignore": [], "ignore": [],
"homepage": "https://github.com/polymerelements/paper-ripple", "homepage": "https://github.com/PolymerElements/paper-ripple",
"_release": "1.0.5", "_release": "1.0.5",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v1.0.5", "tag": "v1.0.5",
"commit": "d72e7a9a8ab518b901ed18dde492df3b87a93be5" "commit": "d72e7a9a8ab518b901ed18dde492df3b87a93be5"
}, },
"_source": "git://github.com/polymerelements/paper-ripple.git", "_source": "git://github.com/PolymerElements/paper-ripple.git",
"_target": "^1.0.0", "_target": "^1.0.0",
"_originalSource": "polymerelements/paper-ripple" "_originalSource": "PolymerElements/paper-ripple"
} }