<!-- @license Copyright (c) 2015 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 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 --> <link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> <link rel="import" href="../iron-resizable-behavior/iron-resizable-behavior.html"> <link rel="import" href="../paper-styles/default-theme.html"> <!-- `<paper-badge>` is a circular text badge that is displayed on the top right corner of an element, representing a status or a notification. It will badge the anchor element specified in the `for` attribute, or, if that doesn't exist, centered to the parent node containing it. Example: <div style="display:inline-block"> <span>Inbox</span> <paper-badge label="3"></paper-badge> </div> <div> <paper-button id="btn">Status</paper-button> <paper-badge for="btn" label="♥︎"></paper-badge> </div> ### Styling The following custom properties and mixins are available for styling: Custom property | Description | Default ----------------|-------------|---------- `--paper-badge-background` | The background color of the badge | `--accent-color` `--paper-badge-opacity` | The opacity of the badge | `1.0` `--paper-badge-text-color` | The color of the badge text | `white` `--paper-badge-width` | The width of the badge circle | `22px` `--paper-badge-height` | The height of the badge circle | `22px` `--paper-badge-margin-left` | Optional spacing added to the left of the badge. | `0px` `--paper-badge-margin-bottom` | TOptional spacing added to the bottom of the badge. | `0px` `--paper-badge` | Mixin applied to the badge | `{}` @group Paper Elements @element paper-badge @demo demo/index.html --> <dom-module id="paper-badge"> <template> <style> :host { display: block; position: absolute; outline: none; } #badge { @apply(--paper-font-common-base); font-weight: 600; font-size: 12px; border-radius: 50%; margin-left: var(--paper-badge-margin-left, 0px); margin-bottom: var(--paper-badge-margin-bottom, 0px); width: var(--paper-badge-width, 22px); height: var(--paper-badge-height, 22px); background-color: var(--paper-badge-background, --accent-color); opacity: var(--paper-badge-opacity, 1.0); color: var(--paper-badge-text-color, white); @apply(--layout); @apply(--layout-center-center); @apply(--paper-badge); } </style> <div id="badge">{{label}}</div> </template> <script> Polymer({ is: 'paper-badge', hostAttributes: { tabindex: '0', role: 'status' }, behaviors: [ Polymer.IronResizableBehavior ], listeners: { 'iron-resize': 'updatePosition' }, properties: { /** * The id of the element that the badge is anchored to. This element * must be a sibling of the badge. */ for: { type: String, observer: '_forChanged' }, /** * The label displayed in the badge. The label is centered, and ideally * should have very few characters. */ label: { type: String, observer: '_labelChanged' } }, attached: function() { this._updateTarget(); }, _forChanged: function() { // The first time the property is set is before the badge is attached, // which means we're not ready to position it yet. if (!this.isAttached) { return; } this._updateTarget(); }, _labelChanged: function() { this.setAttribute('aria-label', this.label); }, _updateTarget: function() { this._target = this.target; this.async(this.notifyResize, 1); }, /** * Returns the target element that this badge is anchored to. It is * either the element given by the `for` attribute, or the immediate parent * of the badge. */ get target () { var parentNode = Polymer.dom(this).parentNode; // If the parentNode is a document fragment, then we need to use the host. var ownerRoot = Polymer.dom(this).getOwnerRoot(); var target; if (this.for) { target = Polymer.dom(ownerRoot).querySelector('#' + this.for); } else { target = parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? ownerRoot.host : parentNode; } return target; }, /** * Repositions the badge relative to its anchor element. This is called * automatically when the badge is attached or an `iron-resize` event is * fired (for exmaple if the window has resized, or your target is a * custom element that implements IronResizableBehavior). * * You should call this in all other cases when the achor's position * might have changed (for example, if it's visibility has changed, or * you've manually done a page re-layout). */ updatePosition: function() { if (!this._target) return; if (!this.offsetParent) return; var parentRect = this.offsetParent.getBoundingClientRect(); var targetRect = this._target.getBoundingClientRect(); var thisRect = this.getBoundingClientRect(); this.style.left = targetRect.left - parentRect.left + (targetRect.width - thisRect.width / 2) + 'px'; this.style.top = targetRect.top - parentRect.top - (thisRect.height / 2) + 'px'; } }) </script> </dom-module>