| Index: pkg/polymer/lib/elements/polymer-anchor-point/polymer-anchor-point.html
|
| diff --git a/pkg/polymer/lib/elements/polymer-anchor-point/polymer-anchor-point.html b/pkg/polymer/lib/elements/polymer-anchor-point/polymer-anchor-point.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7df6e1d25c97e8ab5a799636599ef192f039cf5d
|
| --- /dev/null
|
| +++ b/pkg/polymer/lib/elements/polymer-anchor-point/polymer-anchor-point.html
|
| @@ -0,0 +1,196 @@
|
| +<!--
|
| +/**
|
| + * @module Polymer Elements
|
| + */
|
| +/**
|
| + * polymer-anchor-point can be used to align two nodes. The node to
|
| + * use as the reference position is the anchor node, and the node to
|
| + * be positioned is the target node.
|
| + *
|
| + * Both the anchor and target nodes should have an anchor-point
|
| + * attribute. The target node is positioned such that its anchor-point
|
| + * aligns with the anchor node's anchor-point.
|
| + *
|
| + * Note: The target node is positioned with position: fixed, and will not
|
| + * scroll with the page.
|
| + *
|
| + * Note: This is meant to polyfill the `<dialog>` positioning behavior when
|
| + * an anchor is provided. Spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#the-dialog-element
|
| + *
|
| + * Example:
|
| + *
|
| + * <div id="anchor" anchor-point="bottom left"></div>
|
| + * <div id="target" anchor-point="top left"></div>
|
| + * <polymer-anchor-point id="anchor-helper"></polymer-anchor-point>
|
| + * <script>
|
| + * var helper = document.querySelector('#anchor-helper');
|
| + * helper.anchor = document.querySelector('#anchor');
|
| + * helper.target = document.querySelector('#target');
|
| + * helper.apply();
|
| + * </script>
|
| + *
|
| + * @class polymer-anchor-point
|
| + */
|
| + -->
|
| +<link rel="import" href="../polymer/polymer.html">
|
| +
|
| +<polymer-element name="polymer-anchor-point" attributes="target anchor">
|
| + <script>
|
| + (function() {
|
| + var DEFAULT_ANCHOR_POINT = 'center center';
|
| +
|
| + function getAnchorPoint(node) {
|
| + var anchorPt = node.getAttribute('anchor-point');
|
| + if (!anchorPt || anchorPt === 'none') {
|
| + anchorPt = DEFAULT_ANCHOR_POINT;
|
| + }
|
| + return anchorPt;
|
| + };
|
| +
|
| + function lengthIsPx(length) {
|
| + return length.slice(-2) === 'px';
|
| + };
|
| +
|
| + function lengthIsPercent(length) {
|
| + return length.slice(-1) === '%';
|
| + };
|
| +
|
| + function computeLength(length, ref) {
|
| + var computed = 0;
|
| + if (lengthIsPx(length)) {
|
| + computed = length.slice(0, -2);
|
| + } else if (lengthIsPercent(length)) {
|
| + computed = ref * length.slice(0, -1) / 100;
|
| + }
|
| + return computed;
|
| + };
|
| +
|
| + function partIsX(part) {
|
| + return part === 'left' || part === 'right' || part === 'center';
|
| + };
|
| +
|
| + function partIsY(part) {
|
| + return part === 'top' || part === 'bottom' || part === 'center';
|
| + };
|
| +
|
| + function partIsKeyword(part) {
|
| + return part.slice(-1) !== '%' && part.slice(-2) !== 'px';
|
| + };
|
| +
|
| + function parsePosition(position) {
|
| + var parsed = {};
|
| + var parts = position.split(' ');
|
| + var i = 0;
|
| + var lastEdgeX = true;
|
| + do {
|
| + if (partIsX(parts[i])) {
|
| + parsed.x = parts[i];
|
| + lastEdgeX = parts[i] !== 'center';
|
| + } else if (partIsY(parts[i])) {
|
| + parsed.y = parts[i];
|
| + lastEdgeX = false;
|
| + } else if (lastEdgeX) {
|
| + parsed.xOffset = parts[i];
|
| + lastEdgeX = false;
|
| + } else {
|
| + parsed.yOffset = parts[i];
|
| + }
|
| + } while (++i < parts.length);
|
| + return parsed;
|
| + };
|
| +
|
| + function computeAnchorOffset(rect, anchorPt) {
|
| + var offset = {
|
| + left: 0,
|
| + top: 0
|
| + };
|
| + var parsed = parsePosition(anchorPt);
|
| + if (!parsed.x && !parsed.xOffset) {
|
| + offset.left = rect.width / 2;
|
| + } else if (parsed.x && !parsed.xOffset) {
|
| + switch (parsed.x) {
|
| + case 'left':
|
| + offset.left = 0;
|
| + break;
|
| + case 'right':
|
| + offset.left = rect.width;
|
| + break;
|
| + case 'center':
|
| + offset.left = rect.width / 2;
|
| + break;
|
| + }
|
| + } else {
|
| + var computed = computeLength(parsed.xOffset, rect.width);
|
| + if (parsed.x === 'right') {
|
| + offset.left = rect.width - computed;
|
| + } else if (!parsed.x || parsed.x === 'left') {
|
| + offset.left = computed;
|
| + }
|
| + }
|
| + if (!parsed.y && !parsed.yOffset) {
|
| + offset.top = rect.height / 2;
|
| + } else if (parsed.y && !parsed.yOffset) {
|
| + switch (parsed.y) {
|
| + case 'top':
|
| + offset.top = 0;
|
| + break;
|
| + case 'bottom':
|
| + offset.top = rect.height;
|
| + break;
|
| + case 'center':
|
| + offset.top = rect.height / 2;
|
| + break;
|
| + }
|
| + } else {
|
| + var computed = computeLength(parsed.yOffset, rect.height);
|
| + if (parsed.y === 'bottom') {
|
| + offset.top = rect.height - computed;
|
| + } else if (!parsed.y || parsed.y === 'top') {
|
| + offset.top = computed;
|
| + }
|
| + }
|
| + return offset;
|
| + };
|
| +
|
| + Polymer('polymer-anchor-point', {
|
| + /**
|
| + * The node to be positioned.
|
| + * @attribute target
|
| + * @type Node
|
| + */
|
| + target: null,
|
| + /**
|
| + * The node to align the target to.
|
| + * @attribute anchor
|
| + * @type node
|
| + */
|
| + anchor: null,
|
| + canPosition: function() {
|
| + return this.target && this.anchor;
|
| + },
|
| + apply: function() {
|
| + if (!this.canPosition()) {
|
| + return;
|
| + }
|
| + var pos = this.computePosition();
|
| + this.target.style.position = 'fixed';
|
| + this.target.style.top = pos.top + 'px';
|
| + this.target.style.left = pos.left + 'px';
|
| + },
|
| + computePosition: function() {
|
| + var rect = this.anchor.getBoundingClientRect();
|
| + var anchorPt = getAnchorPoint(this.anchor);
|
| + var anchorOffset = computeAnchorOffset(rect, anchorPt);
|
| + var targetRect = this.target.getBoundingClientRect();
|
| + var targetAnchorPt = getAnchorPoint(this.target);
|
| + var targetOffset = computeAnchorOffset(targetRect, targetAnchorPt);
|
| + var pos = {
|
| + left: rect.left + anchorOffset.left - targetOffset.left,
|
| + top: rect.top + anchorOffset.top - targetOffset.top
|
| + };
|
| + return pos;
|
| + }
|
| + });
|
| + })();
|
| + </script>
|
| +</polymer-element>
|
|
|