Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
core-popup -> core-dropdown, use position: absolute
Browse files Browse the repository at this point in the history
  • Loading branch information
Yvonne Yip committed Sep 3, 2014
1 parent 333230e commit 1ce8af8
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 185 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
core-popup
==========
core-dropdown
=============

owner: [@morethanreal](https://github.com/morethanreal)

See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-popup) for more information.
See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-dropdown) for more information.
98 changes: 56 additions & 42 deletions core-popup-overlay.html → core-dropdown-overlay.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,24 @@

<!--
`core-popup-overlay` is a helper class to position an overlay relative to another
element.
`core-dropdown-overlay` is a helper class to position an overlay relative to another
element within the same offsetParent.
@group Polymer Core Elements
@element core-popup-overlay
@element core-dropdown-overlay
@extends core-overlay
@homepage github.io
-->

<polymer-element name="core-popup-overlay" extends="core-overlay">
<polymer-element name="core-dropdown-overlay" extends="core-overlay">
<script>
Polymer({

publish: {

/**
* The `relatedTarget` is an element used to position the overlay.
* The `relatedTarget` is an element used to position the overlay. It should have
* the same offsetParent as the target.
*
* @attribute relatedTarget
* @type Node
Expand Down Expand Up @@ -57,8 +58,42 @@
*/
valign: 'top',

margin: 12
/**
* A pixel amount around the overlay that will be reserved. It's useful for
* ensuring that, for example, a shadow displayed outside the overlay will
* always be visible.
*
* @attribute margin
* @type number
* @default 0
*/
margin: 0

},

updateTargetDimensions: function() {
this.measureTarget();
this.super();
},

measureTarget: function() {
var sizer = this.sizingTarget || this.target;

/* position offscreen if we're auto-positioning to get the natural width and height of the dropdown */
sizer.style.position = 'absolute';
sizer.style.left = '-99999px';
sizer.style.top = '-99999px';

var rect = sizer.getBoundingClientRect();

this._naturalSize = {
width: rect.width,
height: rect.height
};

sizer.style.position = this.targetStyle.position;
sizer.style.left = null;
sizer.style.top = null;
},

positionTarget: function() {
Expand All @@ -67,61 +102,40 @@
return;
}

var top, left, bottom, right;
var ref = this.relatedTarget.getBoundingClientRect();
// Don't use CSS to handle halign/valign here so _shouldPosition still works.

if (this._shouldPosition.left) {
this.target.style.left = '-99999px';
}
if (this._shouldPosition.top) {
this.target.style.top = '-99999px';
}
var ref = this.relatedTarget.getBoundingClientRect();

if (this._shouldPosition.left) {
if (this.halign === 'left') {
left = ref.left;
} else if (this.halign === 'right') {
left = Math.max(ref.right - this.target.offsetWidth, this.margin);
var left;
if (this.halign === 'right') {
left = Math.max(-1 * ref.left + this.relatedTarget.offsetLeft + this.margin, this.relatedTarget.offsetLeft + ref.width - this._naturalSize.width);
} else {
left = this.relatedTarget.offsetLeft;
}
this.target.style.left = left + 'px';
}

if (this._shouldPosition.top) {
if (this.valign === 'top') {
top = ref.top;
var top;
if (this.valign === 'bottom') {
top = Math.max(-1 * ref.top + this.relatedTarget.offsetTop + this.margin, this.relatedTarget.offsetTop + ref.height - this._naturalSize.height);
} else {
top = Math.max(ref.bottom - this.target.offsetHeight, this.margin)
top = this.relatedTarget.offsetTop;
}
this.target.style.top = top + 'px';
}

},

sizeTarget: function() {
var sizer = this.sizingTarget || this.target;
var rect = sizer.getBoundingClientRect();
var ref = this.relatedTarget.getBoundingClientRect();

var minW = ref.width + 'px';

// at least as wide as the relatedTarget
sizer.style.minWidth = minW + 'px';
sizer.style.width = this._naturalSize.width + 'px';
sizer.style.height = this._naturalSize.height + 'px';

var maxW, maxH;
// XXX: if valign=bottom, maxHeight is too tall

if (this._shouldPosition.left) {
maxW = window.innerWidth - rect.left - this.margin;
sizer.style.maxWidth = maxW + 'px';
}

if (this._shouldPosition.top) {
maxH = window.innerHeight - rect.top - this.margin;
sizer.style.maxHeight = maxH + 'px';
}

if (!this._shouldPosition.left && !this._shouldPosition.top) {
this.super();
}
this.super();
}

});
Expand Down
5 changes: 2 additions & 3 deletions core-popup.css → core-dropdown.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*/

:host {
display: block;
border-radius: 3px;
color: #000;
position: absolute;
overflow: auto;
background-color: #fff;
}
84 changes: 42 additions & 42 deletions core-popup.html → core-dropdown.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,86 +9,75 @@

<!--
`core-popup` is an element that is positioned relatively to another element, usually the
element that triggers the popup. The popup and the triggering element should be children
of the same element that has a CSS `position`.
`core-dropdown` is an element that is initially hidden and is positioned relatively to another
element, usually the element that triggers the dropdown. The dropdown and the triggering element
should be children of the same offsetParent, e.g. the same `<div>` with `position: relative`.
It can be used to implement dropdown menus, menu buttons, etc..
Example:
<template is="auto-binding">
<div relative>
<div id="trigger">Your favorite pastry:</div>
<core-popup relatedTarget="{{$.trigger}}">
<core-icon-button id="trigger" icon="menu"></core-icon-button>
<core-dropdown relatedTarget="{{$.trigger}}">
<core-menu>
<core-item label="Churro"></core-item>
<core-item label="Donut"></core-item>
<core-item label="Macaron"></core-item>
<core-item>Cut</core-item>
<core-item>Copy</core-item>
<core-item>Paste</core-item>
</core-menu>
</core-popup>
</core-dropdown>
</div>
</template>
Positioning
-----------
By default, the popup is positioned on top of the `relatedTarget` with the top and left edges aligned.
The `halign` and `valign` properties controls the various alignments. The size of the popup is
automatically restrained such that it is entirely visible on the screen.
By default, the dropdown is absolutely positioned on top of the `relatedTarget` with the top and
left edges aligned. The `halign` and `valign` properties controls the various alignments. The size
of the dropdown is automatically restrained such that it is entirely visible on the screen. Use the
`margin`
If you need more control over the popup's position, use CSS. The `halign` and `valign` properties are
ignored if either `top` or `left` are set on the popup.
The popup is positioned with `position: absolute` by default.
If you need more control over the dropdown's position, use CSS. The `halign` and `valign` properties are
ignored if the dropdown is positioned with CSS.
Example:
<style>
/* manually position the popup with position: absolute in a container with position: relative so it scrolls with #control */
core-popup {
/* manually position the dropdown below the trigger */
core-dropdown {
position: absolute;
top: 0;
top: 38px;
left: 0;
}
</style>
<template is="auto-binding">
<div relative>
<div id="control">Your favorite pastry:</div>
<core-popup relatedTarget="{{$.control}}">
<core-icon-button id="trigger" icon="menu"></core-icon-button>
<core-dropdown relatedTarget="{{$.trigger}}">
<core-menu>
<core-item label="Churro"></core-item>
<core-item label="Donut"></core-item>
<core-item label="Macaron"></core-item>
<core-item>Cut</core-item>
<core-item>Copy</core-item>
<core-item>Paste</core-item>
</core-menu>
</core-popup>
</core-dropdown>
</div>
</template>
@group Polymer Core Elements
@element core-popup
@element core-dropdown
@homepage github.io
-->

<!--
Fired when an item's selection state is changed. This event is fired both
when an item is selected or deselected. The `isSelected` detail property
contains the selection state.
@event core-select
@param {Object} detail
@param {boolean} detail.isSelected true for selection and false for de-selection
@param {Object} detail.item the item element
-->
<link href="../polymer/polymer.html" rel="import">

<link href="core-popup-overlay.html" rel="import">
<link href="core-dropdown-overlay.html" rel="import">

<polymer-element name="core-popup">
<polymer-element name="core-dropdown">
<template>

<link href="core-popup.css" rel="stylesheet">
<link href="core-dropdown.css" rel="stylesheet">

<core-popup-overlay id="overlay" target="{{}}" sizingTarget="{{$.menu}}" relatedTarget="{{relatedTarget}}" opened="{{opened}}" halign="{{halign}}" valign="{{valign}}" transition="{{transition}}"></core-popup-overlay>
<core-dropdown-overlay id="overlay" target="{{}}" relatedTarget="{{relatedTarget}}" opened="{{opened}}" halign="{{halign}}" valign="{{valign}}" margin="{{margin}}" transition="{{transition}}"></core-dropdown-overlay>

<content></content>

Expand All @@ -100,7 +89,7 @@
publish: {

/**
* The element associated with this menu, usually the element that triggers
* The element associated with this dropdown, usually the element that triggers
* the menu.
*
* @attribute relatedTarget
Expand Down Expand Up @@ -139,6 +128,17 @@
*/
valign: 'top',

/**
* A pixel amount around the dropdown that will be reserved. It's useful for
* ensuring that, for example, a shadow displayed outside the dropdown will
* always be visible.
*
* @attribute margin
* @type number
* @default 0
*/
margin: 0,

/**
* The transition property specifies a string which identifies a
* <a href="../core-transition/">`core-transition`</a> element that
Expand Down
Loading

0 comments on commit 1ce8af8

Please sign in to comment.