mirror of
https://github.com/jellyfin/jellyfin-web.git
synced 2024-11-18 03:18:19 -07:00
commit
6aa15be23f
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iron-fit-behavior",
|
||||
"version": "1.0.6",
|
||||
"version": "1.1.0",
|
||||
"license": "http://polymer.github.io/LICENSE.txt",
|
||||
"description": "Fits an element inside another element",
|
||||
"private": true,
|
||||
@ -21,19 +21,19 @@
|
||||
"polymer": "Polymer/polymer#^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"paper-styles": "polymerelements/paper-styles#^1.0.2",
|
||||
"iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
|
||||
"iron-demo-helpers": "PolymerElements/iron-demo-helpers#^1.0.0",
|
||||
"test-fixture": "PolymerElements/test-fixture#^1.0.0",
|
||||
"web-component-tester": "^4.0.0",
|
||||
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
|
||||
},
|
||||
"ignore": [],
|
||||
"homepage": "https://github.com/PolymerElements/iron-fit-behavior",
|
||||
"_release": "1.0.6",
|
||||
"_release": "1.1.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.0.6",
|
||||
"commit": "f2e868af4fad643ffb7fea3501e1429acc4ec0f0"
|
||||
"tag": "v1.1.0",
|
||||
"commit": "6602a102f425f5ccc9e05e9cc15139a3ad259081"
|
||||
},
|
||||
"_source": "git://github.com/PolymerElements/iron-fit-behavior.git",
|
||||
"_target": "^1.0.0",
|
||||
|
33
dashboard-ui/bower_components/iron-fit-behavior/.github/ISSUE_TEMPLATE.md
vendored
Normal file
33
dashboard-ui/bower_components/iron-fit-behavior/.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<!-- Instructions: https://github.com/PolymerElements/iron-fit-behavior/CONTRIBUTING.md#filing-issues -->
|
||||
### Description
|
||||
<!-- Example: The `paper-foo` element causes the page to turn pink when clicked. -->
|
||||
|
||||
### Expected outcome
|
||||
|
||||
<!-- Example: The page stays the same color. -->
|
||||
|
||||
### Actual outcome
|
||||
|
||||
<!-- Example: The page turns pink. -->
|
||||
|
||||
### Live Demo
|
||||
<!-- Example: https://jsbin.com/cagaye/edit?html,output -->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!-- Example
|
||||
1. Put a `paper-foo` element in the page.
|
||||
2. Open the page in a web browser.
|
||||
3. Click the `paper-foo` element.
|
||||
-->
|
||||
|
||||
### Browsers Affected
|
||||
<!-- Check all that apply -->
|
||||
- [ ] Chrome
|
||||
- [ ] Firefox
|
||||
- [ ] Safari 9
|
||||
- [ ] Safari 8
|
||||
- [ ] Safari 7
|
||||
- [ ] Edge
|
||||
- [ ] IE 11
|
||||
- [ ] IE 10
|
@ -1,5 +1,5 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
sudo: required
|
||||
before_script:
|
||||
- npm install -g bower polylint web-component-tester
|
||||
- bower install
|
||||
@ -8,18 +8,16 @@ env:
|
||||
global:
|
||||
- secure: QL2j7nfSA/40iIPMKLMosv9hj8q7eGBbPQXVQmCL3uXD5qoMPTqo1qronKKX+bi3Rh7W104ufV4CzzbWvBwQh8gipx+4REGijzc77Fro2y3v3/wUp9H/UEWnbhAWPDsqEoAD8xQXFHkVv7874/VwOlubQyXDGlvqh0fzYbUNUQo=
|
||||
- secure: ajBo8YcSzi4kNuCHcmajCirWQKf5Mj4OZ3tQjNAcJJAy0UtyrAgTenayWN2ijKqD5V8wfTK66jUXGYMZkoJV4EpknrUliqRgRqKHHfULXYWRSC7lDGxf835ReFxstkPun4HmNtxraAWJgmgFz7mylntTVKm46Ce4INj3n8reWaY=
|
||||
- CXX=g++-4.8
|
||||
node_js: stable
|
||||
addons:
|
||||
firefox: latest
|
||||
apt:
|
||||
sources:
|
||||
- google-chrome
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- google-chrome-stable
|
||||
- g++-4.8
|
||||
sauce_connect: true
|
||||
script:
|
||||
- xvfb-run wct
|
||||
- "if [ \"${TRAVIS_PULL_REQUEST}\" = \"false\" ]; then wct -s 'default'; fi"
|
||||
dist: trusty
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iron-fit-behavior",
|
||||
"version": "1.0.6",
|
||||
"version": "1.1.0",
|
||||
"license": "http://polymer.github.io/LICENSE.txt",
|
||||
"description": "Fits an element inside another element",
|
||||
"private": true,
|
||||
@ -21,8 +21,8 @@
|
||||
"polymer": "Polymer/polymer#^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"paper-styles": "polymerelements/paper-styles#^1.0.2",
|
||||
"iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
|
||||
"iron-demo-helpers": "PolymerElements/iron-demo-helpers#^1.0.0",
|
||||
"test-fixture": "PolymerElements/test-fixture#^1.0.0",
|
||||
"web-component-tester": "^4.0.0",
|
||||
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
|
||||
|
@ -9,35 +9,124 @@ Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<title>iron-fit-behavior demo</title>
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
|
||||
<title>iron-fit-behavior demo</title>
|
||||
|
||||
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<link href="../../paper-styles/demo-pages.html" rel="import">
|
||||
<link rel="import" href="simple-fit.html">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
|
||||
|
||||
<style>
|
||||
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<link rel="import" href="simple-fit.html">
|
||||
<link rel="import" href="../../iron-demo-helpers/demo-snippet.html">
|
||||
<link rel="import" href="../../iron-demo-helpers/demo-pages-shared-styles.html">
|
||||
|
||||
.sized {
|
||||
max-width: 50%;
|
||||
max-height: 50%;
|
||||
padding: 20px;
|
||||
<style is="custom-style" include="demo-pages-shared-styles">
|
||||
demo-snippet {
|
||||
--demo-snippet-code: {
|
||||
max-height: 250px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
</head>
|
||||
<body unresolved>
|
||||
<body unresolved class="centered">
|
||||
<h3>
|
||||
An element with <code>IronFitBehavior</code> can be centered in
|
||||
<code>fitInto</code> or positioned around a <code>positionTarget</code>
|
||||
</h3>
|
||||
<demo-snippet>
|
||||
<template>
|
||||
<style>
|
||||
.target {
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid;
|
||||
width: 100px;
|
||||
padding: 20px 0;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
<simple-fit id="myFit" auto-fit-on-attach class="sized" onclick="myFit.refit()">
|
||||
Centered in window.<br><br>
|
||||
Resize the window and click here to refit.
|
||||
</simple-fit>
|
||||
#myFit {
|
||||
z-index: 10;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
width: 220px;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-bind">
|
||||
<template is="dom-repeat" items="[[containers]]">
|
||||
<div class="target" on-tap="updatePositionTarget">Target</div>
|
||||
</template>
|
||||
<simple-fit id="myFit" auto-fit-on-attach>
|
||||
<h2>Align</h2>
|
||||
<p>
|
||||
<button on-tap="updateAlign" vertical-align="top">top</button>
|
||||
<button on-tap="updateAlign" vertical-align="bottom">bottom</button>
|
||||
<button on-tap="updateAlign" vertical-align="auto">auto</button>
|
||||
<button on-tap="updateAlign" vertical-align>null</button>
|
||||
</p>
|
||||
<p>
|
||||
<button on-tap="updateAlign" horizontal-align="left">left</button>
|
||||
<button on-tap="updateAlign" horizontal-align="right">right</button>
|
||||
<button on-tap="updateAlign" horizontal-align="auto">auto</button>
|
||||
<button on-tap="updateAlign" horizontal-align>null</button>
|
||||
</p>
|
||||
<button on-tap="toggleNoOverlap">Toggle overlap</button>
|
||||
</simple-fit>
|
||||
<script>
|
||||
var defaultTarget = Polymer.dom(myFit).parentNode;
|
||||
var template = document.querySelector('template[is="dom-bind"]');
|
||||
|
||||
template.containers = new Array(30);
|
||||
|
||||
template.updatePositionTarget = function(e) {
|
||||
var target = Polymer.dom(e).rootTarget;
|
||||
target = myFit.positionTarget === target ? defaultTarget : target;
|
||||
myFit.positionTarget.style.backgroundColor = '';
|
||||
target.style.backgroundColor = 'orange';
|
||||
myFit.positionTarget = target;
|
||||
template.refit();
|
||||
};
|
||||
|
||||
template._raf = null;
|
||||
template.refit = function() {
|
||||
template._raf && window.cancelAnimationFrame(template._raf);
|
||||
template._raf = window.requestAnimationFrame(function() {
|
||||
template._raf = null;
|
||||
myFit.refit();
|
||||
});
|
||||
};
|
||||
|
||||
template.updateAlign = function(e) {
|
||||
var target = Polymer.dom(e).rootTarget;
|
||||
if (target.hasAttribute('horizontal-align')) {
|
||||
myFit.horizontalAlign = target.getAttribute('horizontal-align');
|
||||
}
|
||||
if (target.hasAttribute('vertical-align')) {
|
||||
myFit.verticalAlign = target.getAttribute('vertical-align');
|
||||
}
|
||||
template.refit();
|
||||
};
|
||||
|
||||
template.toggleNoOverlap = function() {
|
||||
myFit.noOverlap = !myFit.noOverlap;
|
||||
template.refit();
|
||||
};
|
||||
|
||||
// Listen for resize and scroll on window.
|
||||
window.addEventListener('resize', template.refit);
|
||||
window.addEventListener('scroll', template.refit);
|
||||
</script>
|
||||
</template>
|
||||
</template>
|
||||
</demo-snippet>
|
||||
|
||||
</body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -10,23 +10,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
<link rel="import" href="../../polymer/polymer.html">
|
||||
<link rel="import" href="../iron-fit-behavior.html">
|
||||
<link rel="import" href="../../paper-styles/color.html">
|
||||
<link rel="import" href="../../iron-flex-layout/iron-flex-layout.html">
|
||||
|
||||
<dom-module id="simple-fit">
|
||||
|
||||
<style>
|
||||
:host {
|
||||
@apply(--layout);
|
||||
|
||||
background-color: var(--paper-light-blue-500);
|
||||
color: white;
|
||||
text-align: center;
|
||||
|
||||
align-items:center;
|
||||
-webkit-align-items: center;
|
||||
|
||||
justify-content:center;
|
||||
-webkit-justify-content:center;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -11,9 +11,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
<link rel="import" href="../polymer/polymer.html">
|
||||
|
||||
<script>
|
||||
|
||||
/**
|
||||
Polymer.IronFitBehavior fits an element in another element using `max-height` and `max-width`, and
|
||||
`Polymer.IronFitBehavior` fits an element in another element using `max-height` and `max-width`, and
|
||||
optionally centers it in the window or another element.
|
||||
|
||||
The element will only be sized and/or positioned if it has not already been sized and/or positioned
|
||||
@ -24,8 +23,25 @@ CSS properties | Action
|
||||
`position` set | Element is not centered horizontally or vertically
|
||||
`top` or `bottom` set | Element is not vertically centered
|
||||
`left` or `right` set | Element is not horizontally centered
|
||||
`max-height` or `height` set | Element respects `max-height` or `height`
|
||||
`max-width` or `width` set | Element respects `max-width` or `width`
|
||||
`max-height` set | Element respects `max-height`
|
||||
`max-width` set | Element respects `max-width`
|
||||
|
||||
`Polymer.IronFitBehavior` can position an element into another element using
|
||||
`verticalAlign` and `horizontalAlign`. This will override the element's css position.
|
||||
|
||||
<div class="container">
|
||||
<iron-fit-impl vertical-align="top" horizontal-align="auto">
|
||||
Positioned into the container
|
||||
</iron-fit-impl>
|
||||
</div>
|
||||
|
||||
Use `noOverlap` to position the element around another element without overlapping it.
|
||||
|
||||
<div class="container">
|
||||
<iron-fit-impl no-overlap vertical-align="auto" horizontal-align="auto">
|
||||
Positioned around the container
|
||||
</iron-fit-impl>
|
||||
</div>
|
||||
|
||||
@demo demo/index.html
|
||||
@polymerBehavior
|
||||
@ -56,6 +72,78 @@ CSS properties | Action
|
||||
value: window
|
||||
},
|
||||
|
||||
/**
|
||||
* Will position the element around the positionTarget without overlapping it.
|
||||
*/
|
||||
noOverlap: {
|
||||
type: Boolean
|
||||
},
|
||||
|
||||
/**
|
||||
* The element that should be used to position the element. If not set, it will
|
||||
* default to the parent node.
|
||||
* @type {!Element}
|
||||
*/
|
||||
positionTarget: {
|
||||
type: Element
|
||||
},
|
||||
|
||||
/**
|
||||
* The orientation against which to align the element horizontally
|
||||
* relative to the `positionTarget`. Possible values are "left", "right", "auto".
|
||||
*/
|
||||
horizontalAlign: {
|
||||
type: String
|
||||
},
|
||||
|
||||
/**
|
||||
* The orientation against which to align the element vertically
|
||||
* relative to the `positionTarget`. Possible values are "top", "bottom", "auto".
|
||||
*/
|
||||
verticalAlign: {
|
||||
type: String
|
||||
},
|
||||
|
||||
/**
|
||||
* A pixel value that will be added to the position calculated for the
|
||||
* given `horizontalAlign`, in the direction of alignment. You can think
|
||||
* of it as increasing or decreasing the distance to the side of the
|
||||
* screen given by `horizontalAlign`.
|
||||
*
|
||||
* If `horizontalAlign` is "left", this offset will increase or decrease
|
||||
* the distance to the left side of the screen: a negative offset will
|
||||
* move the element to the left; a positive one, to the right.
|
||||
*
|
||||
* Conversely if `horizontalAlign` is "right", this offset will increase
|
||||
* or decrease the distance to the right side of the screen: a negative
|
||||
* offset will move the element to the right; a positive one, to the left.
|
||||
*/
|
||||
horizontalOffset: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
notify: true
|
||||
},
|
||||
|
||||
/**
|
||||
* A pixel value that will be added to the position calculated for the
|
||||
* given `verticalAlign`, in the direction of alignment. You can think
|
||||
* of it as increasing or decreasing the distance to the side of the
|
||||
* screen given by `verticalAlign`.
|
||||
*
|
||||
* If `verticalAlign` is "top", this offset will increase or decrease
|
||||
* the distance to the top side of the screen: a negative offset will
|
||||
* move the element upwards; a positive one, downwards.
|
||||
*
|
||||
* Conversely if `verticalAlign` is "bottom", this offset will increase
|
||||
* or decrease the distance to the bottom side of the screen: a negative
|
||||
* offset will move the element downwards; a positive one, upwards.
|
||||
*/
|
||||
verticalOffset: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
notify: true
|
||||
},
|
||||
|
||||
/**
|
||||
* Set to true to auto-fit on attach.
|
||||
*/
|
||||
@ -68,7 +156,6 @@ CSS properties | Action
|
||||
_fitInfo: {
|
||||
type: Object
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
get _fitWidth() {
|
||||
@ -111,7 +198,40 @@ CSS properties | Action
|
||||
return fitTop;
|
||||
},
|
||||
|
||||
/**
|
||||
* The element that should be used to position the element,
|
||||
* if no position target is configured.
|
||||
*/
|
||||
get _defaultPositionTarget() {
|
||||
var parent = Polymer.dom(this).parentNode;
|
||||
|
||||
if (parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
||||
parent = parent.host;
|
||||
}
|
||||
|
||||
return parent;
|
||||
},
|
||||
|
||||
/**
|
||||
* The horizontal align value, accounting for the RTL/LTR text direction.
|
||||
*/
|
||||
get _localeHorizontalAlign() {
|
||||
if (this._isRTL) {
|
||||
// In RTL, "left" becomes "right".
|
||||
if (this.horizontalAlign === 'right') {
|
||||
return 'left';
|
||||
}
|
||||
if (this.horizontalAlign === 'left') {
|
||||
return 'right';
|
||||
}
|
||||
}
|
||||
return this.horizontalAlign;
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
// Memoize this to avoid expensive calculations & relayouts.
|
||||
this._isRTL = window.getComputedStyle(this).direction == 'rtl';
|
||||
this.positionTarget = this.positionTarget || this._defaultPositionTarget;
|
||||
if (this.autoFitOnAttach) {
|
||||
if (window.getComputedStyle(this).display === 'none') {
|
||||
setTimeout(function() {
|
||||
@ -124,10 +244,11 @@ CSS properties | Action
|
||||
},
|
||||
|
||||
/**
|
||||
* Fits and optionally centers the element into the window, or `fitInfo` if specified.
|
||||
* Positions and fits the element into the `fitInto` element.
|
||||
*/
|
||||
fit: function() {
|
||||
this._discoverInfo();
|
||||
this.position();
|
||||
this.constrain();
|
||||
this.center();
|
||||
},
|
||||
@ -144,18 +265,25 @@ CSS properties | Action
|
||||
this._fitInfo = {
|
||||
inlineStyle: {
|
||||
top: this.style.top || '',
|
||||
left: this.style.left || ''
|
||||
left: this.style.left || '',
|
||||
position: this.style.position || ''
|
||||
},
|
||||
sizerInlineStyle: {
|
||||
maxWidth: this.sizingTarget.style.maxWidth || '',
|
||||
maxHeight: this.sizingTarget.style.maxHeight || '',
|
||||
boxSizing: this.sizingTarget.style.boxSizing || ''
|
||||
},
|
||||
positionedBy: {
|
||||
vertically: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ?
|
||||
'bottom' : null),
|
||||
horizontally: target.left !== 'auto' ? 'left' : (target.right !== 'auto' ?
|
||||
'right' : null),
|
||||
css: target.position
|
||||
'right' : null)
|
||||
},
|
||||
sizedBy: {
|
||||
height: sizer.maxHeight !== 'none',
|
||||
width: sizer.maxWidth !== 'none'
|
||||
width: sizer.maxWidth !== 'none',
|
||||
minWidth: parseInt(sizer.minWidth, 10) || 0,
|
||||
minHeight: parseInt(sizer.minHeight, 10) || 0
|
||||
},
|
||||
margin: {
|
||||
top: parseInt(target.marginTop, 10) || 0,
|
||||
@ -171,23 +299,21 @@ CSS properties | Action
|
||||
* the memoized data.
|
||||
*/
|
||||
resetFit: function() {
|
||||
if (!this._fitInfo || !this._fitInfo.sizedBy.width) {
|
||||
this.sizingTarget.style.maxWidth = '';
|
||||
var info = this._fitInfo || {};
|
||||
for (var property in info.sizerInlineStyle) {
|
||||
this.sizingTarget.style[property] = info.sizerInlineStyle[property];
|
||||
}
|
||||
if (!this._fitInfo || !this._fitInfo.sizedBy.height) {
|
||||
this.sizingTarget.style.maxHeight = '';
|
||||
}
|
||||
this.style.top = this._fitInfo ? this._fitInfo.inlineStyle.top : '';
|
||||
this.style.left = this._fitInfo ? this._fitInfo.inlineStyle.left : '';
|
||||
if (this._fitInfo) {
|
||||
this.style.position = this._fitInfo.positionedBy.css;
|
||||
for (var property in info.inlineStyle) {
|
||||
this.style[property] = info.inlineStyle[property];
|
||||
}
|
||||
|
||||
this._fitInfo = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Equivalent to calling `resetFit()` and `fit()`. Useful to call this after the element,
|
||||
* the window, or the `fitInfo` element has been resized.
|
||||
* Equivalent to calling `resetFit()` and `fit()`. Useful to call this after
|
||||
* the element or the `fitInto` element has been resized, or if any of the
|
||||
* positioning properties (e.g. `horizontalAlign, verticalAlign`) is updated.
|
||||
*/
|
||||
refit: function() {
|
||||
this.resetFit();
|
||||
@ -195,37 +321,129 @@ CSS properties | Action
|
||||
},
|
||||
|
||||
/**
|
||||
* Constrains the size of the element to the window or `fitInfo` by setting `max-height`
|
||||
* Positions the element according to `horizontalAlign, verticalAlign`.
|
||||
*/
|
||||
position: function() {
|
||||
if (!this.horizontalAlign && !this.verticalAlign) {
|
||||
// needs to be centered, and it is done after constrain.
|
||||
return;
|
||||
}
|
||||
|
||||
this.style.position = 'fixed';
|
||||
// Need border-box for margin/padding.
|
||||
this.sizingTarget.style.boxSizing = 'border-box';
|
||||
// Set to 0, 0 in order to discover any offset caused by parent stacking contexts.
|
||||
this.style.left = '0px';
|
||||
this.style.top = '0px';
|
||||
|
||||
var rect = this.getBoundingClientRect();
|
||||
var positionRect = this.__getNormalizedRect(this.positionTarget);
|
||||
var fitRect = this.__getNormalizedRect(this.fitInto);
|
||||
|
||||
var alignRight = this.__isAlignRight(this._localeHorizontalAlign, rect, positionRect, fitRect);
|
||||
var alignBottom = this.__isAlignBottom(this.verticalAlign, rect, positionRect, fitRect);
|
||||
|
||||
var top = alignBottom ? positionRect.bottom - rect.height - this.verticalOffset : positionRect.top + this.verticalOffset;
|
||||
var left = alignRight ? positionRect.right - rect.width - this.horizontalOffset : positionRect.left + this.horizontalOffset;
|
||||
|
||||
if (this.noOverlap) {
|
||||
// We can overlap one of the dimensions, choose the one that minimizes the cropped area.
|
||||
var noOverlapLeft = left + positionRect.width * (alignRight ? -1 : 1);
|
||||
var noOverlapTop = top + positionRect.height * (alignBottom ? -1 : 1);
|
||||
var areaOverlapLeft = this.__getCroppedArea({
|
||||
top: noOverlapTop,
|
||||
left: left,
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
}, fitRect);
|
||||
var areaOverlapTop = this.__getCroppedArea({
|
||||
top: top,
|
||||
left: noOverlapLeft,
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
}, fitRect);
|
||||
if (areaOverlapLeft < areaOverlapTop) {
|
||||
left = noOverlapLeft;
|
||||
} else {
|
||||
top = noOverlapTop;
|
||||
}
|
||||
}
|
||||
|
||||
var right = left + rect.width;
|
||||
var bottom = top + rect.height;
|
||||
|
||||
left = Math.max(left, 0);
|
||||
top = Math.max(top, 0);
|
||||
|
||||
var maxWidth = Math.min(fitRect.right, right) - left;
|
||||
var maxHeight = Math.min(fitRect.bottom, bottom) - top;
|
||||
|
||||
var minWidth = this._fitInfo.sizedBy.minWidth;
|
||||
var minHeight = this._fitInfo.sizedBy.minHeight;
|
||||
|
||||
if (maxWidth < minWidth || right < minWidth) {
|
||||
left = -9999;
|
||||
maxWidth = 0;
|
||||
}
|
||||
if (maxHeight < minHeight || bottom < minHeight) {
|
||||
top = -9999;
|
||||
maxHeight = 0;
|
||||
}
|
||||
|
||||
this.sizingTarget.style.maxWidth = maxWidth + 'px';
|
||||
this.sizingTarget.style.maxHeight = maxHeight + 'px';
|
||||
|
||||
// Remove the offset caused by any stacking context.
|
||||
this.style.left = (left - rect.left) + 'px';
|
||||
this.style.top = (top - rect.top) + 'px';
|
||||
},
|
||||
|
||||
/**
|
||||
* Constrains the size of the element to `fitInto` by setting `max-height`
|
||||
* and/or `max-width`.
|
||||
*/
|
||||
constrain: function() {
|
||||
if (this.horizontalAlign || this.verticalAlign) {
|
||||
return;
|
||||
}
|
||||
var info = this._fitInfo;
|
||||
// position at (0px, 0px) if not already positioned, so we can measure the natural size.
|
||||
if (!this._fitInfo.positionedBy.vertically) {
|
||||
if (!info.positionedBy.vertically) {
|
||||
this.style.position = 'fixed';
|
||||
this.style.top = '0px';
|
||||
}
|
||||
if (!this._fitInfo.positionedBy.horizontally) {
|
||||
if (!info.positionedBy.horizontally) {
|
||||
this.style.position = 'fixed';
|
||||
this.style.left = '0px';
|
||||
}
|
||||
if (!this._fitInfo.positionedBy.vertically || !this._fitInfo.positionedBy.horizontally) {
|
||||
// need position:fixed to properly size the element
|
||||
this.style.position = 'fixed';
|
||||
}
|
||||
|
||||
// need border-box for margin/padding
|
||||
this.sizingTarget.style.boxSizing = 'border-box';
|
||||
// constrain the width and height if not already set
|
||||
var rect = this.getBoundingClientRect();
|
||||
if (!info.sizedBy.height) {
|
||||
this._sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
|
||||
this.__sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
|
||||
}
|
||||
if (!info.sizedBy.width) {
|
||||
this._sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right', 'Width');
|
||||
this.__sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right', 'Width');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @deprecated
|
||||
*/
|
||||
_sizeDimension: function(rect, positionedBy, start, end, extent) {
|
||||
this.__sizeDimension(rect, positionedBy, start, end, extent);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
__sizeDimension: function(rect, positionedBy, start, end, extent) {
|
||||
var info = this._fitInfo;
|
||||
var max = extent === 'Width' ? this._fitWidth : this._fitHeight;
|
||||
var fitRect = this.__getNormalizedRect(this.fitInto);
|
||||
var max = extent === 'Width' ? fitRect.width : fitRect.height;
|
||||
var flip = (positionedBy === end);
|
||||
var offset = flip ? max - rect[end] : rect[start];
|
||||
var margin = info.margin[flip ? start : end];
|
||||
@ -239,6 +457,9 @@ CSS properties | Action
|
||||
* `position:fixed`.
|
||||
*/
|
||||
center: function() {
|
||||
if (this.horizontalAlign || this.verticalAlign) {
|
||||
return;
|
||||
}
|
||||
var positionedBy = this._fitInfo.positionedBy;
|
||||
if (positionedBy.vertically && positionedBy.horizontally) {
|
||||
// Already positioned.
|
||||
@ -257,16 +478,58 @@ CSS properties | Action
|
||||
}
|
||||
// It will take in consideration margins and transforms
|
||||
var rect = this.getBoundingClientRect();
|
||||
var fitRect = this.__getNormalizedRect(this.fitInto);
|
||||
if (!positionedBy.vertically) {
|
||||
var top = this._fitTop - rect.top + (this._fitHeight - rect.height) / 2;
|
||||
var top = fitRect.top - rect.top + (fitRect.height - rect.height) / 2;
|
||||
this.style.top = top + 'px';
|
||||
}
|
||||
if (!positionedBy.horizontally) {
|
||||
var left = this._fitLeft - rect.left + (this._fitWidth - rect.width) / 2;
|
||||
var left = fitRect.left - rect.left + (fitRect.width - rect.width) / 2;
|
||||
this.style.left = left + 'px';
|
||||
}
|
||||
},
|
||||
|
||||
__getNormalizedRect: function(target) {
|
||||
if (target === document.documentElement || target === window) {
|
||||
return {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
right: window.innerWidth,
|
||||
bottom: window.innerHeight
|
||||
};
|
||||
}
|
||||
return target.getBoundingClientRect();
|
||||
},
|
||||
|
||||
__isAlignRight: function(hAlign, rect, positionRect, fitRect) {
|
||||
if (hAlign === 'right') {
|
||||
return true;
|
||||
}
|
||||
if (hAlign === 'auto') {
|
||||
return positionRect.left + positionRect.width/2 > fitRect.left + fitRect.width/2 ||
|
||||
(!this.noOverlap && positionRect.left < 0 && positionRect.right - rect.width > positionRect.left);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
__isAlignBottom: function(vAlign, rect, positionRect, fitRect) {
|
||||
if (vAlign === 'bottom') {
|
||||
return true;
|
||||
}
|
||||
if (vAlign === 'auto') {
|
||||
return positionRect.top + positionRect.height/2 > fitRect.top + fitRect.height/2 ||
|
||||
(!this.noOverlap && positionRect.top < 0 && positionRect.bottom - rect.height > positionRect.top);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
__getCroppedArea: function(rect, fitRect) {
|
||||
var verticalCrop = Math.min(0, rect.top) + Math.min(0, fitRect.bottom - (rect.top + rect.height));
|
||||
var horizontalCrop = Math.min(0, rect.left) + Math.min(0, fitRect.right - (rect.left + rect.width));
|
||||
return verticalCrop * rect.width + horizontalCrop * rect.height;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
|
@ -39,16 +39,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
|
||||
.sized-x {
|
||||
width: 200px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.sized-y {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.sized-xy {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.positioned-left {
|
||||
@ -83,11 +78,22 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.constrain {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border: 1px solid black;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="constrain"></div>
|
||||
|
||||
<test-fixture id="absolute">
|
||||
<template>
|
||||
@ -113,16 +119,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="with-max-width">
|
||||
<template>
|
||||
<div class="constrain" style="position: fixed; top: 20px; left: 100px; width: 50vw; height: 50vh; border: 1px solid black;">
|
||||
<test-fit auto-fit-on-attach class="with-max-width el">
|
||||
with-max-width, auto center/center
|
||||
</test-fit>
|
||||
</div>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="positioned-xy">
|
||||
<template>
|
||||
<test-fit auto-fit-on-attach class="sized-x positioned-left positioned-top">
|
||||
@ -152,8 +148,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
<test-fixture id="constrain-target">
|
||||
<template>
|
||||
<div class="constrain" style="position: fixed; top: 20px; left: 100px; width: 50vw; height: 50vh; border: 1px solid black;">
|
||||
<test-fit auto-fit-on-attach class="el sized-xy">
|
||||
<div class="constrain">
|
||||
<test-fit auto-fit-on-attach class="el sized-x sized-y">
|
||||
<div>
|
||||
Auto center/center to parent element
|
||||
</div>
|
||||
@ -188,6 +184,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
}
|
||||
|
||||
function intersects(r1, r2) {
|
||||
return !(r2.left >= r1.right || r2.right <= r1.left || r2.top >= r1.bottom || r2.bottom <= r1.top);
|
||||
}
|
||||
|
||||
suite('manual positioning', function() {
|
||||
|
||||
test('css positioned element is not re-positioned', function() {
|
||||
@ -380,7 +380,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
test('element centers in another element', function() {
|
||||
var constrain = fixture('constrain-target');
|
||||
var el = Polymer.dom(constrain).querySelector('.el')
|
||||
var el = Polymer.dom(constrain).querySelector('.el');
|
||||
makeScrolling(el);
|
||||
el.fitInto = constrain;
|
||||
el.refit();
|
||||
@ -391,8 +391,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
});
|
||||
|
||||
test('element with max-width centers in another element', function() {
|
||||
var constrain = fixture('with-max-width');
|
||||
var el = Polymer.dom(constrain).querySelector('.el');
|
||||
var constrain = document.querySelector('.constrain');
|
||||
var el = fixture('sized-xy');
|
||||
el.classList.add('with-max-width');
|
||||
el.fitInto = constrain;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
@ -403,6 +404,324 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
});
|
||||
|
||||
suite('horizontal/vertical align', function() {
|
||||
var parent, parentRect;
|
||||
var el, elRect;
|
||||
var fitRect = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: window.innerWidth,
|
||||
bottom: window.innerHeight,
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight
|
||||
};
|
||||
|
||||
setup(function() {
|
||||
parent = fixture('constrain-target');
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el = Polymer.dom(parent).querySelector('.el');
|
||||
elRect = el.getBoundingClientRect();
|
||||
});
|
||||
|
||||
test('intersects works', function() {
|
||||
var base = {top: 0, bottom: 1, left:0, right: 1};
|
||||
assert.isTrue(intersects(base, base), 'intersects itself');
|
||||
assert.isFalse(intersects(base, {top:1, bottom: 2, left: 0, right: 1}), 'no intersect on edge');
|
||||
assert.isFalse(intersects(base, {top:-2, bottom: -1, left: 0, right: 1}), 'no intersect on edge (negative values)');
|
||||
assert.isFalse(intersects(base, {top:2, bottom: 3, left: 0, right: 1}), 'no intersect');
|
||||
});
|
||||
|
||||
suite('when verticalAlign is top', function() {
|
||||
test('element is aligned to the positionTarget top', function() {
|
||||
el.verticalAlign = 'top';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.top, parentRect.top, 'top ok');
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
});
|
||||
|
||||
test('element is aligned to the positionTarget top without overlapping it', function() {
|
||||
// Allow enough space on the parent's bottom & right.
|
||||
parent.style.width = '10px';
|
||||
parent.style.height = '10px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.verticalAlign = 'top';
|
||||
el.noOverlap = true;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.isFalse(intersects(rect, parentRect), 'no overlap');
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
});
|
||||
|
||||
test('verticalOffset is applied', function() {
|
||||
el.verticalAlign = 'top';
|
||||
el.verticalOffset = 10;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.top, parentRect.top + 10, 'top ok');
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
});
|
||||
|
||||
test('max-height is updated', function() {
|
||||
parent.style.top = '-10px';
|
||||
el.verticalAlign = 'top';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.top, 0, 'top ok');
|
||||
assert.isBelow(rect.height, elRect.height, 'height ok');
|
||||
});
|
||||
|
||||
test('min-height is respected: element is hidden if does not have enough height', function() {
|
||||
parent.style.top = '-10px';
|
||||
el.verticalAlign = 'top';
|
||||
el.style.minHeight = elRect.height + 'px';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.isFalse(intersects(rect, fitRect), 'not visible');
|
||||
});
|
||||
});
|
||||
|
||||
suite('when verticalAlign is bottom', function() {
|
||||
test('element is aligned to the positionTarget bottom', function() {
|
||||
el.verticalAlign = 'bottom';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.bottom, parentRect.bottom, 'bottom ok');
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
});
|
||||
|
||||
test('element is aligned to the positionTarget bottom without overlapping it', function() {
|
||||
el.verticalAlign = 'bottom';
|
||||
el.noOverlap = true;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.isFalse(intersects(rect, parentRect), 'no overlap');
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
});
|
||||
|
||||
test('verticalOffset is applied', function() {
|
||||
el.verticalAlign = 'bottom';
|
||||
el.verticalOffset = 10;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.bottom, parentRect.bottom - 10, 'bottom ok');
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
});
|
||||
|
||||
test('element max-height is updated', function() {
|
||||
parent.style.top = (100 - parentRect.height) + 'px';
|
||||
el.verticalAlign = 'bottom';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.bottom, 100, 'bottom ok');
|
||||
assert.equal(rect.height, 100, 'height ok');
|
||||
});
|
||||
|
||||
test('min-height is respected: element is hidden if does not have enough height', function() {
|
||||
parent.style.top = (elRect.height - 10 - parentRect.height) + 'px';
|
||||
el.verticalAlign = 'bottom';
|
||||
el.style.minHeight = elRect.height + 'px';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.isFalse(intersects(rect, fitRect), 'not visible');
|
||||
});
|
||||
});
|
||||
|
||||
suite('when verticalAlign is auto', function() {
|
||||
test('element is aligned to the positionTarget top', function() {
|
||||
el.verticalAlign = 'auto';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.top, parentRect.top, 'auto aligned to top');
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
});
|
||||
|
||||
test('element is aligned to the positionTarget top without overlapping it', function() {
|
||||
// Allow enough space on the parent's bottom & right.
|
||||
parent.style.width = '10px';
|
||||
parent.style.height = '10px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.verticalAlign = 'auto';
|
||||
el.noOverlap = true;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
assert.isFalse(intersects(rect, parentRect), 'no overlap');
|
||||
});
|
||||
|
||||
test('bottom is preferred to top if it diminishes the cropped area', function() {
|
||||
// This would cause a cropping of the element, so it should automatically
|
||||
// align to the bottom to avoid it.
|
||||
parent.style.top = '-10px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.verticalAlign = 'auto';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.bottom, parentRect.bottom, 'auto aligned to bottom');
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
});
|
||||
|
||||
test('bottom is preferred to top if it diminishes the cropped area, without overlapping positionTarget', function() {
|
||||
// This would cause a cropping of the element, so it should automatically
|
||||
// align to the bottom to avoid it.
|
||||
parent.style.top = '-10px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.verticalAlign = 'auto';
|
||||
el.noOverlap = true;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.height, elRect.height, 'no cropping');
|
||||
assert.isFalse(intersects(rect, parentRect), 'no overlap');
|
||||
});
|
||||
});
|
||||
|
||||
suite('when horizontalAlign is left', function() {
|
||||
test('element is aligned to the positionTarget left', function() {
|
||||
el.horizontalAlign = 'left';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.left, parentRect.left, 'left ok');
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
});
|
||||
|
||||
test('element is aligned to the positionTarget left without overlapping it', function() {
|
||||
// Make space at the parent's right.
|
||||
parent.style.width = '10px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.horizontalAlign = 'left';
|
||||
el.noOverlap = true;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.isFalse(intersects(rect, parentRect), 'no overlap');
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
});
|
||||
|
||||
test('horizontalOffset is applied', function() {
|
||||
el.horizontalAlign = 'left';
|
||||
el.horizontalOffset = 10;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.left, parentRect.left + 10, 'left ok');
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
});
|
||||
|
||||
test('element max-width is updated', function() {
|
||||
parent.style.left = '-10px';
|
||||
el.horizontalAlign = 'left';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.left, 0, 'left ok');
|
||||
assert.isBelow(rect.width, elRect.width, 'width ok');
|
||||
});
|
||||
|
||||
test('min-width is respected: element is hidden if does not have enough width', function() {
|
||||
parent.style.left = '-10px';
|
||||
el.style.minWidth = elRect.width + 'px';
|
||||
el.horizontalAlign = 'left';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.isFalse(intersects(rect, fitRect), 'not visible');
|
||||
});
|
||||
});
|
||||
|
||||
suite('when horizontalAlign is right', function() {
|
||||
test('element is aligned to the positionTarget right', function() {
|
||||
el.horizontalAlign = 'right';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.right, parentRect.right, 'right ok');
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
});
|
||||
|
||||
test('element is aligned to the positionTarget right without overlapping it', function() {
|
||||
// Make space at the parent's left.
|
||||
parent.style.left = elRect.width + 'px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.horizontalAlign = 'right';
|
||||
el.noOverlap = true;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.isFalse(intersects(rect, parentRect), 'no overlap');
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
});
|
||||
|
||||
test('horizontalOffset is applied', function() {
|
||||
el.horizontalAlign = 'right';
|
||||
el.horizontalOffset = 10;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.right, parentRect.right - 10, 'right ok');
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
});
|
||||
|
||||
test('element max-width is updated', function() {
|
||||
parent.style.left = (100 - parentRect.width) + 'px';
|
||||
el.horizontalAlign = 'right';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.right, 100, 'right ok');
|
||||
assert.equal(rect.width, 100, 'width ok');
|
||||
});
|
||||
|
||||
test('min-width is respected: element is hidden if does not have enough width', function() {
|
||||
parent.style.left = (elRect.width - 10 - parentRect.width) + 'px';
|
||||
el.horizontalAlign = 'right';
|
||||
el.style.minWidth = elRect.width + 'px';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.isFalse(intersects(rect, fitRect), 'not visible');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('when horizontalAlign is auto', function() {
|
||||
test('element is aligned to the positionTarget left', function() {
|
||||
el.horizontalAlign = 'auto';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.left, parentRect.left, 'auto aligned to left');
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
});
|
||||
|
||||
test('element is aligned to the positionTarget left without overlapping positionTarget', function() {
|
||||
// Make space at the parent's left.
|
||||
parent.style.left = elRect.width + 'px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.horizontalAlign = 'auto';
|
||||
el.noOverlap = true;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
assert.isFalse(intersects(rect, parentRect), 'no overlap');
|
||||
});
|
||||
|
||||
test('right is preferred to left if it diminishes the cropped area', function() {
|
||||
// This would cause a cropping of the element, so it should automatically
|
||||
// align to the right to avoid it.
|
||||
parent.style.left = '-10px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.horizontalAlign = 'auto';
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.right, parentRect.right, 'auto aligned to right');
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
});
|
||||
|
||||
test('right is preferred to left if it diminishes the cropped area, without overlapping positionTarget', function() {
|
||||
// Make space at the parent's right.
|
||||
parent.style.width = '10px';
|
||||
parentRect = parent.getBoundingClientRect();
|
||||
el.horizontalAlign = 'auto';
|
||||
el.noOverlap = true;
|
||||
el.refit();
|
||||
var rect = el.getBoundingClientRect();
|
||||
assert.equal(rect.width, elRect.width, 'no cropping');
|
||||
assert.isFalse(intersects(rect, parentRect), 'no overlap');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
@ -32,14 +32,14 @@
|
||||
"web-component-tester": "^4.0.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",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.0.8",
|
||||
"commit": "f36b38928849ef3853db727faa8c9ef104d611eb"
|
||||
},
|
||||
"_source": "git://github.com/PolymerElements/iron-icon.git",
|
||||
"_source": "git://github.com/polymerelements/iron-icon.git",
|
||||
"_target": "^1.0.0",
|
||||
"_originalSource": "PolymerElements/iron-icon"
|
||||
"_originalSource": "polymerelements/iron-icon"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iron-overlay-behavior",
|
||||
"version": "1.6.5",
|
||||
"version": "1.7.0",
|
||||
"license": "http://polymer.github.io/LICENSE.txt",
|
||||
"description": "Provides a behavior for making an element an overlay",
|
||||
"private": true,
|
||||
@ -35,11 +35,11 @@
|
||||
},
|
||||
"ignore": [],
|
||||
"homepage": "https://github.com/polymerelements/iron-overlay-behavior",
|
||||
"_release": "1.6.5",
|
||||
"_release": "1.7.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.6.5",
|
||||
"commit": "19311400fe42fe3992fb8925dfd2582c63c67d82"
|
||||
"tag": "v1.7.0",
|
||||
"commit": "d61575162a40904914fa3528ba20bb531d098001"
|
||||
},
|
||||
"_source": "git://github.com/polymerelements/iron-overlay-behavior.git",
|
||||
"_target": "^1.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iron-overlay-behavior",
|
||||
"version": "1.6.5",
|
||||
"version": "1.7.0",
|
||||
"license": "http://polymer.github.io/LICENSE.txt",
|
||||
"description": "Provides a behavior for making an element an overlay",
|
||||
"private": true,
|
||||
|
@ -9,7 +9,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
-->
|
||||
|
||||
<link rel="import" href="../polymer/polymer.html">
|
||||
<link rel="import" href="iron-overlay-manager.html">
|
||||
|
||||
<!--
|
||||
`iron-overlay-backdrop` is a backdrop used by `Polymer.IronOverlayBehavior`. It should be a
|
||||
@ -30,7 +29,6 @@ Custom property | Description | Default
|
||||
<dom-module id="iron-overlay-backdrop">
|
||||
|
||||
<style>
|
||||
|
||||
:host {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@ -41,17 +39,14 @@ Custom property | Description | Default
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
pointer-events: none;
|
||||
|
||||
@apply(--iron-overlay-backdrop);
|
||||
}
|
||||
|
||||
:host([opened]) {
|
||||
:host(.opened) {
|
||||
opacity: var(--iron-overlay-backdrop-opacity, 0.6);
|
||||
pointer-events: auto;
|
||||
|
||||
@apply(--iron-overlay-backdrop-opened);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<template>
|
||||
@ -61,8 +56,8 @@ Custom property | Description | Default
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Polymer({
|
||||
|
||||
@ -74,75 +69,94 @@ Custom property | Description | Default
|
||||
* Returns true if the backdrop is opened.
|
||||
*/
|
||||
opened: {
|
||||
readOnly: true,
|
||||
reflectToAttribute: true,
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
|
||||
_manager: {
|
||||
type: Object,
|
||||
value: Polymer.IronOverlayManager
|
||||
value: false,
|
||||
observer: '_openedChanged'
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
listeners: {
|
||||
'transitionend' : '_onTransitionend'
|
||||
'transitionend': '_onTransitionend'
|
||||
},
|
||||
|
||||
created: function() {
|
||||
// Used to cancel previous requestAnimationFrame calls when opened changes.
|
||||
this.__openedRaf = null;
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
this.opened && this._openedChanged(this.opened);
|
||||
},
|
||||
|
||||
/**
|
||||
* Appends the backdrop to document body and sets its `z-index` to be below the latest overlay.
|
||||
* Appends the backdrop to document body if needed.
|
||||
*/
|
||||
prepare: function() {
|
||||
if (!this.parentNode) {
|
||||
if (this.opened && !this.parentNode) {
|
||||
Polymer.dom(document.body).appendChild(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the backdrop if needed.
|
||||
* Shows the backdrop.
|
||||
*/
|
||||
open: function() {
|
||||
// only need to make the backdrop visible if this is called by the first overlay with a backdrop
|
||||
if (this._manager.getBackdrops().length < 2) {
|
||||
this._setOpened(true);
|
||||
}
|
||||
this.opened = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides the backdrop if needed.
|
||||
* Hides the backdrop.
|
||||
*/
|
||||
close: function() {
|
||||
// close only if no element with backdrop is left
|
||||
if (this._manager.getBackdrops().length === 0) {
|
||||
// Read style before setting opened.
|
||||
var cs = getComputedStyle(this);
|
||||
var noAnimation = (cs.transitionDuration === '0s' || cs.opacity == 0);
|
||||
this._setOpened(false);
|
||||
// In case of no animations, complete
|
||||
if (noAnimation) {
|
||||
this.complete();
|
||||
}
|
||||
}
|
||||
this.opened = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the backdrop from document body if needed.
|
||||
*/
|
||||
complete: function() {
|
||||
// only remove the backdrop if there are no more overlays with backdrops
|
||||
if (this._manager.getBackdrops().length === 0 && this.parentNode) {
|
||||
if (!this.opened && this.parentNode === document.body) {
|
||||
Polymer.dom(this.parentNode).removeChild(this);
|
||||
}
|
||||
},
|
||||
|
||||
_onTransitionend: function (event) {
|
||||
_onTransitionend: function(event) {
|
||||
if (event && event.target === this) {
|
||||
this.complete();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_openedChanged: function() {
|
||||
if (this.opened) {
|
||||
// Auto-attach.
|
||||
this.prepare();
|
||||
} else {
|
||||
// Animation might be disabled via the mixin or opacity custom property.
|
||||
// If it is disabled in other ways, it's up to the user to call complete.
|
||||
var cs = window.getComputedStyle(this);
|
||||
if (cs.transitionDuration === '0s' || cs.opacity == 0) {
|
||||
this.complete();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.isAttached) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always cancel previous requestAnimationFrame.
|
||||
if (this.__openedRaf) {
|
||||
window.cancelAnimationFrame(this.__openedRaf);
|
||||
this.__openedRaf = null;
|
||||
}
|
||||
// Force relayout to ensure proper transitions.
|
||||
this.scrollTop = this.scrollTop;
|
||||
this.__openedRaf = window.requestAnimationFrame(function() {
|
||||
this.__openedRaf = null;
|
||||
this.toggleClass('opened', this.opened);
|
||||
}.bind(this));
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -11,11 +11,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
<link rel="import" href="../polymer/polymer.html">
|
||||
<link rel="import" href="../iron-fit-behavior/iron-fit-behavior.html">
|
||||
<link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html">
|
||||
<link rel="import" href="iron-overlay-backdrop.html">
|
||||
<link rel="import" href="iron-overlay-manager.html">
|
||||
|
||||
<script>
|
||||
// IIFE to help scripts concatenation.
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
@ -257,10 +255,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
||||
Polymer.dom(this).unobserveNodes(this._observer);
|
||||
this._observer = null;
|
||||
this.opened = false;
|
||||
if (this.withBackdrop) {
|
||||
// Allow user interactions right away.
|
||||
this.backdropElement.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -337,9 +331,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
||||
this.__isAnimating = true;
|
||||
|
||||
if (this.opened) {
|
||||
if (this.withBackdrop) {
|
||||
this.backdropElement.prepare();
|
||||
}
|
||||
// requestAnimationFrame for non-blocking rendering
|
||||
this.__openChangedAsync = window.requestAnimationFrame(function() {
|
||||
this.__openChangedAsync = null;
|
||||
@ -367,15 +358,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
||||
}
|
||||
if (this.opened) {
|
||||
this._manager.trackBackdrop();
|
||||
if (this.withBackdrop) {
|
||||
this.backdropElement.prepare();
|
||||
// Give time to be added to document.
|
||||
this.async(function(){
|
||||
this.backdropElement.open();
|
||||
}, 1);
|
||||
} else {
|
||||
this.backdropElement.close();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -403,9 +385,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
||||
* @protected
|
||||
*/
|
||||
_renderOpened: function() {
|
||||
if (this.withBackdrop) {
|
||||
this.backdropElement.open();
|
||||
}
|
||||
this._finishRenderOpened();
|
||||
},
|
||||
|
||||
@ -414,9 +393,6 @@ context. You should place this element as a child of `<body>` whenever possible.
|
||||
* @protected
|
||||
*/
|
||||
_renderClosed: function() {
|
||||
if (this.withBackdrop) {
|
||||
this.backdropElement.close();
|
||||
}
|
||||
this._finishRenderClosed();
|
||||
},
|
||||
|
||||
|
@ -10,6 +10,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
<link rel="import" href="../polymer/polymer.html">
|
||||
<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
|
||||
<link rel="import" href="iron-overlay-backdrop.html">
|
||||
|
||||
<script>
|
||||
|
||||
@ -224,7 +225,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
* Updates the backdrop z-index.
|
||||
*/
|
||||
trackBackdrop: function() {
|
||||
this.backdropElement.style.zIndex = this.backdropZ();
|
||||
var overlay = this._overlayWithBackdrop();
|
||||
// Avoid creating the backdrop if there is no overlay with backdrop.
|
||||
if (!overlay && !this._backdropElement) {
|
||||
return;
|
||||
}
|
||||
this.backdropElement.style.zIndex = this._getZ(overlay) - 1;
|
||||
this.backdropElement.opened = !!overlay;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -700,10 +700,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
});
|
||||
|
||||
test('backdrop is opened when overlay is opened', function(done) {
|
||||
assert.isDefined(overlay.backdropElement, 'backdrop is defined');
|
||||
assert.isOk(overlay.backdropElement, 'backdrop is defined');
|
||||
runAfterOpen(overlay, function() {
|
||||
assert.isTrue(overlay.backdropElement.opened, 'backdrop is opened');
|
||||
assert.isDefined(overlay.backdropElement.parentNode, 'backdrop is inserted in the DOM');
|
||||
assert.isOk(overlay.backdropElement.parentNode, 'backdrop is inserted in the DOM');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -54,7 +54,7 @@
|
||||
"tag": "v1.1.11",
|
||||
"commit": "8cfe5c5bf8c2e40d243443d046a94b6fe371983c"
|
||||
},
|
||||
"_source": "git://github.com/PolymerElements/paper-input.git",
|
||||
"_target": "^1.0.0",
|
||||
"_originalSource": "PolymerElements/paper-input"
|
||||
"_source": "git://github.com/polymerelements/paper-input.git",
|
||||
"_target": "^1.0.9",
|
||||
"_originalSource": "polymerelements/paper-input"
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
define(['dialogHelper', 'jQuery', 'paper-fab', 'paper-input', 'paper-checkbox'], function (dialogHelper, $) {
|
||||
define(['dialogHelper', 'loading', 'jQuery', 'paper-fab', 'paper-input', 'paper-checkbox'], function (dialogHelper, loading, $) {
|
||||
|
||||
var currentItem;
|
||||
var currentItemType;
|
||||
@ -56,7 +56,7 @@
|
||||
IncludeDisabledProviders: true
|
||||
};
|
||||
|
||||
Dashboard.showLoadingMsg();
|
||||
loading.show();
|
||||
|
||||
ApiClient.ajax({
|
||||
type: "POST",
|
||||
@ -67,7 +67,7 @@
|
||||
|
||||
}).then(function (results) {
|
||||
|
||||
Dashboard.hideLoadingMsg();
|
||||
loading.hide();
|
||||
showIdentificationSearchResults(page, results);
|
||||
});
|
||||
}
|
||||
@ -108,7 +108,7 @@
|
||||
function finishFindNewDialog(dlg, identifyResult) {
|
||||
currentSearchResult = identifyResult;
|
||||
hasChanges = true;
|
||||
Dashboard.hideLoadingMsg();
|
||||
loading.hide();
|
||||
|
||||
dialogHelper.close(dlg);
|
||||
}
|
||||
@ -202,7 +202,7 @@
|
||||
|
||||
function submitIdentficationResult(page) {
|
||||
|
||||
Dashboard.showLoadingMsg();
|
||||
loading.show();
|
||||
|
||||
var options = {
|
||||
ReplaceAllImages: $('#chkIdentifyReplaceImages', page).checked()
|
||||
@ -217,13 +217,13 @@
|
||||
}).then(function () {
|
||||
|
||||
hasChanges = true;
|
||||
Dashboard.hideLoadingMsg();
|
||||
loading.hide();
|
||||
|
||||
dialogHelper.close(page);
|
||||
|
||||
}, function () {
|
||||
|
||||
Dashboard.hideLoadingMsg();
|
||||
loading.hide();
|
||||
|
||||
dialogHelper.close(page);
|
||||
});
|
||||
@ -249,12 +249,12 @@
|
||||
|
||||
var value = providerIds[idInfo.Key] || '';
|
||||
|
||||
html += '<paper-input class="txtLookupId" value="' + value + '" data-providerkey="' + idInfo.Key + '" id="' + id + '" label="' + idLabel + '"></paper-input>';
|
||||
html += '<paper-input class="txtLookupId" data-providerkey="' + idInfo.Key + '" id="' + id + '" label="' + idLabel + '"></paper-input>';
|
||||
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
$('#txtLookupName', page).val(item.Name);
|
||||
$('#txtLookupName', page).val('');
|
||||
|
||||
if (item.Type == "Person" || item.Type == "BoxSet") {
|
||||
|
||||
@ -263,7 +263,7 @@
|
||||
} else {
|
||||
|
||||
$('.fldLookupYear', page).show();
|
||||
$('#txtLookupYear', page).val(item.ProductionYear);
|
||||
$('#txtLookupYear', page).val('');
|
||||
}
|
||||
|
||||
$('.identifyProviderIds', page).html(html);
|
||||
@ -274,7 +274,7 @@
|
||||
|
||||
function showEditor(itemId) {
|
||||
|
||||
Dashboard.showLoadingMsg();
|
||||
loading.show();
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'components/itemidentifier/itemidentifier.template.html', true);
|
||||
@ -282,7 +282,7 @@
|
||||
xhr.onload = function (e) {
|
||||
|
||||
var template = this.response;
|
||||
ApiClient.getItem(Dashboard.getCurrentUserId(), itemId).then(function (item) {
|
||||
ApiClient.getItem(ApiClient.getCurrentUserId(), itemId).then(function (item) {
|
||||
|
||||
currentItem = item;
|
||||
currentItemType = currentItem.Type;
|
||||
@ -327,7 +327,7 @@
|
||||
dlg.classList.add('identifyDialog');
|
||||
|
||||
showIdentificationForm(dlg, item);
|
||||
Dashboard.hideLoadingMsg();
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
@ -337,7 +337,7 @@
|
||||
function onDialogClosed() {
|
||||
|
||||
$(this).remove();
|
||||
Dashboard.hideLoadingMsg();
|
||||
loading.hide();
|
||||
currentDeferred.resolveWith(null, [hasChanges]);
|
||||
}
|
||||
|
||||
@ -382,7 +382,7 @@
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
Dashboard.hideLoadingMsg();
|
||||
loading.hide();
|
||||
var foundItem = hasChanges ? currentSearchResult : null;
|
||||
|
||||
resolveFunc(foundItem);
|
||||
|
@ -509,14 +509,6 @@
|
||||
guideView.url = 'livetv.html?tab=1';
|
||||
guideView.onclick = "LibraryBrowser.showTab('livetv.html', 1);";
|
||||
list.push(guideView);
|
||||
|
||||
var recordedTvView = Object.assign({}, view);
|
||||
recordedTvView.Name = Globalize.translate('ButtonRecordedTv');
|
||||
recordedTvView.ImageTags = {};
|
||||
recordedTvView.icon = 'video-library';
|
||||
recordedTvView.url = 'livetv.html?tab=3';
|
||||
recordedTvView.onclick = "LibraryBrowser.showTab('livetv.html', 3);";
|
||||
list.push(recordedTvView);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,25 +17,6 @@
|
||||
}
|
||||
|
||||
list.push(view);
|
||||
|
||||
if (view.CollectionType == 'livetv') {
|
||||
|
||||
var guideView = $.extend({}, view);
|
||||
guideView.Name = Globalize.translate('ButtonGuide');
|
||||
guideView.ImageTags = {};
|
||||
guideView.icon = 'dvr';
|
||||
guideView.url = 'livetv.html?tab=1';
|
||||
guideView.onclick = "LibraryBrowser.showTab('livetv.html', 1);event.preventDefault();event.stopPropagation();return false;";
|
||||
list.push(guideView);
|
||||
|
||||
var recordedTvView = $.extend({}, view);
|
||||
recordedTvView.Name = Globalize.translate('ButtonRecordedTv');
|
||||
recordedTvView.ImageTags = {};
|
||||
recordedTvView.icon = 'video-library';
|
||||
recordedTvView.url = 'livetv.html?tab=3';
|
||||
recordedTvView.onclick = "LibraryBrowser.showTab('livetv.html', 3);event.preventDefault();event.stopPropagation();return false;";
|
||||
list.push(recordedTvView);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
|
Loading…
Reference in New Issue
Block a user