├── .gitignore ├── .hsdoc ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bower.json ├── dist ├── css │ ├── tooltip-theme-arrows.css │ └── tooltip-theme-twipsy.css └── js │ ├── tooltip.js │ └── tooltip.min.js ├── docs ├── intro.md └── welcome │ ├── coffee │ └── welcome.coffee │ ├── css │ ├── prism.css │ └── welcome.css │ ├── index.html │ ├── js │ ├── jquery.js │ ├── log.js │ └── welcome.js │ └── sass │ └── welcome.sass ├── examples └── tooltip │ └── index.html ├── gulpfile.js ├── package.json └── src ├── css ├── tooltip-theme-arrows.sass └── tooltip-theme-twipsy.sass └── js └── tooltip.js /.gitignore: -------------------------------------------------------------------------------- 1 | .sass-cache 2 | node_modules/ 3 | deps/ 4 | bower_components/ -------------------------------------------------------------------------------- /.hsdoc: -------------------------------------------------------------------------------- 1 | title: "tooltip" 2 | description: "Styleable tooltips built on Tether" 3 | examples: "docs/**/*.md" 4 | assets: "{bower_components/*,dist/js/*.js,dist/css/*.css,docs/css/*.css,docs/js/*,js,docs/welcome/*}" 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v1.2.0 2 | - Update to `Drop` version v1.4.0 3 | - Add role=tooltip, aria-describedby attributes ([#51](https://github.com/HubSpot/tooltip/pull/51)) 4 | 5 | ## v1.1.0 6 | - Update to `Tether` version v1.0.0 7 | - Update to `Drop` version v1.1.0 8 | - Add badges to readme 9 | 10 | ## v1.0.5 11 | - Remove `bower install` post-install script 12 | 13 | ## v1.0.4 14 | - Use correct `require` name for `drop` 15 | 16 | ## v1.0.3 17 | - Remove Compass and Ruby dependencies 18 | 19 | ## v1.0.0 20 | - Add proper UMD to `Tooltip` 21 | - Convert from `Coffeescript` to `ES6 (Babel)` 22 | - Fix `*.json` files to include `main` 23 | - Remove bundled `tooltip.js` 24 | - Restructure directory layout 25 | - Update `gulp` builds 26 | - Update `drop` dependency to `v1.0.0` 27 | - Update `tether` dependency to `v0.7.1` 28 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | You will need: 4 | 5 | - Node.js/io.js & npm 6 | - Bower 7 | - Gulp 8 | 9 | 10 | ## Getting started 11 | 12 | 1. Fork the project 13 | 2. Clone your forked project by running `git clone git@github.com:{ 14 | YOUR_USERNAME }/drop.git` 15 | 3. Run `npm install` to install both node modules and bower components 16 | 4. Test that you can build the source by moving/renaming the existing `dist` 17 | directory and running `npm run build` 18 | 5. Assuming everything went well, you should now have a `dist` directory that 19 | matches the one you moved in step 4. 20 | 21 | 22 | ## Writing code! 23 | 24 | We use `gulp` to facilitate things like transpilation, minification, etc. so 25 | can focus on writing relevant code. If there is a fix or feature you would like 26 | to contribute, we ask that you take the following steps: 27 | 28 | 1. Most of the _editable_ code lives in the `src` directory while built code 29 | will end up in the `dist` directory upon running `npm run build`. 30 | 31 | 2. Depending on how big your changes are, bump the version numbers appropriately 32 | in `bower.json` and `package.json`. We try to follow semver, so a good rule 33 | of thumb for how to bump the version is: 34 | - A fix to existing code, perform a patch bump e.g. x.x.0 -> x.x.1 35 | - New feature, perform a minor bump e.g. x.0.x -> x.1.x 36 | - Breaking changes such a rewrite, perform a major bump e.g. 37 | 1.x.x -> 2.x.x 38 | 39 | Versioning is hard, so just use good judgement and we'll be more than happy 40 | to help out. 41 | 42 | __NOTE__: There is a `gulp` task that will automate some of the versioning. 43 | You can run `gulp version:{type}` where type is `patch|minor|major` to 44 | update both `bower.json` and `package.json` as well as add the appropriate 45 | git tag. 46 | 47 | 3. Provide a thoughtful commit message and push your changes to your fork using 48 | `git push origin master` (assuming your forked project is using `origin` for 49 | the remote name and you are on the `master` branch). 50 | 51 | 4. Open a Pull Request on GitHub with a description of your changes. 52 | 53 | 54 | ## Testing 55 | 56 | Work in progress. We are hoping to add some tests, so if you would like to help 57 | us get started, feel free to contact us through the Issues or open a Pull 58 | Request. 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 HubSpot, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Tooltip 2 | 3 | [![GitHub 4 | version](https://badge.fury.io/gh/HubSpot%2Ftooltip.svg)](http://badge.fury.io/gh/HubSpot%2Ftooltip) 5 | 6 | Tooltip.js is a Javascript and CSS library for creating styleable tooltips. 7 | 8 | 9 | ## Install 10 | 11 | __Dependencies__ 12 | 13 | * __[Tether](https://github.com/HubSpot/tether)__ 14 | * __[Drop](https://github.com/HubSpot/drop)__ 15 | 16 | Installing via `npm` and `bower` will bring in the above dependencies as well. 17 | 18 | 19 | __npm__ 20 | ```sh 21 | $ npm install tether-tooltip 22 | ``` 23 | 24 | __bower__ 25 | ```sh 26 | $ bower install tether-tooltip 27 | ``` 28 | 29 | ## Usage 30 | 31 | ```javascript 32 | let tooltipInstance = new Tooltip({ 33 | target: document.querySelector('.tooltip-target'), 34 | content: "My awesome content.", 35 | classes: 'tooltip-tether-arrows', 36 | position: 'top left' 37 | }) 38 | ``` 39 | 40 | [API Documentation](http://github.hubspot.com/tooltip) 41 | 42 | [Demo](http://github.hubspot.com/tooltip/docs/welcome) 43 | 44 | 45 | ## Contributing 46 | 47 | We encourage contributions of all kinds. If you would like to contribute in some way, please review our [guidelines for contributing](CONTRIBUTING.md). 48 | 49 | 50 | ## License 51 | Copyright © 2015 HubSpot - [MIT License](LICENSE) 52 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tether-tooltip", 3 | "version": "1.2.0", 4 | "homepage": "https://github.hubspot.com/tooltip", 5 | "authors": [ 6 | "Zack Bloom ", 7 | "Adam Schwartz " 8 | ], 9 | "maintainers": [ 10 | "Nicholas Hwang " 11 | ], 12 | "description": "Tooltips built on Tether", 13 | "keywords": [ 14 | "tooltip", 15 | "overlay", 16 | "tether" 17 | ], 18 | "license": "MIT", 19 | "main": "dist/js/tooltip.js", 20 | "ignore": [ 21 | "**/.*", 22 | "node_modules", 23 | "bower_components", 24 | "test", 25 | "tests" 26 | ], 27 | "dependencies": { 28 | "tether": "^1.1.0", 29 | "tether-drop": "^1.4.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dist/css/tooltip-theme-arrows.css: -------------------------------------------------------------------------------- 1 | .tooltip-element, .tooltip-element:after, .tooltip-element:before, .tooltip-element *, .tooltip-element *:after, .tooltip-element *:before { 2 | box-sizing: border-box; } 3 | 4 | .tooltip-element { 5 | position: absolute; 6 | display: none; } 7 | .tooltip-element.tooltip-open { 8 | display: block; } 9 | 10 | .tooltip-element.tooltip-theme-arrows { 11 | max-width: 100%; 12 | max-height: 100%; } 13 | .tooltip-element.tooltip-theme-arrows .tooltip-content { 14 | border-radius: 5px; 15 | position: relative; 16 | font-family: inherit; 17 | background: #000; 18 | color: #eee; 19 | padding: 1em; 20 | font-size: 1.1em; 21 | line-height: 1.5em; } 22 | .tooltip-element.tooltip-theme-arrows .tooltip-content:before { 23 | content: ""; 24 | display: block; 25 | position: absolute; 26 | width: 0; 27 | height: 0; 28 | border-color: transparent; 29 | border-width: 8px; 30 | border-style: solid; } 31 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-center .tooltip-content { 32 | margin-bottom: 8px; } 33 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-center .tooltip-content:before { 34 | top: 100%; 35 | left: 50%; 36 | margin-left: -8px; 37 | border-top-color: #000; } 38 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-center .tooltip-content { 39 | margin-top: 8px; } 40 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-center .tooltip-content:before { 41 | bottom: 100%; 42 | left: 50%; 43 | margin-left: -8px; 44 | border-bottom-color: #000; } 45 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-right.tooltip-element-attached-middle .tooltip-content { 46 | margin-right: 8px; } 47 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-right.tooltip-element-attached-middle .tooltip-content:before { 48 | left: 100%; 49 | top: 50%; 50 | margin-top: -8px; 51 | border-left-color: #000; } 52 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-left.tooltip-element-attached-middle .tooltip-content { 53 | margin-left: 8px; } 54 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-left.tooltip-element-attached-middle .tooltip-content:before { 55 | right: 100%; 56 | top: 50%; 57 | margin-top: -8px; 58 | border-right-color: #000; } 59 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-left.tooltip-target-attached-bottom .tooltip-content { 60 | margin-top: 8px; } 61 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-left.tooltip-target-attached-bottom .tooltip-content:before { 62 | bottom: 100%; 63 | left: 8px; 64 | border-bottom-color: #000; } 65 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-right.tooltip-target-attached-bottom .tooltip-content { 66 | margin-top: 8px; } 67 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-right.tooltip-target-attached-bottom .tooltip-content:before { 68 | bottom: 100%; 69 | right: 8px; 70 | border-bottom-color: #000; } 71 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-left.tooltip-target-attached-top .tooltip-content { 72 | margin-bottom: 8px; } 73 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-left.tooltip-target-attached-top .tooltip-content:before { 74 | top: 100%; 75 | left: 8px; 76 | border-top-color: #000; } 77 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-right.tooltip-target-attached-top .tooltip-content { 78 | margin-bottom: 8px; } 79 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-right.tooltip-target-attached-top .tooltip-content:before { 80 | top: 100%; 81 | right: 8px; 82 | border-top-color: #000; } 83 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-right.tooltip-target-attached-left .tooltip-content { 84 | margin-right: 8px; } 85 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-right.tooltip-target-attached-left .tooltip-content:before { 86 | top: 8px; 87 | left: 100%; 88 | border-left-color: #000; } 89 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-left.tooltip-target-attached-right .tooltip-content { 90 | margin-left: 8px; } 91 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-top.tooltip-element-attached-left.tooltip-target-attached-right .tooltip-content:before { 92 | top: 8px; 93 | right: 100%; 94 | border-right-color: #000; } 95 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-right.tooltip-target-attached-left .tooltip-content { 96 | margin-right: 8px; } 97 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-right.tooltip-target-attached-left .tooltip-content:before { 98 | bottom: 8px; 99 | left: 100%; 100 | border-left-color: #000; } 101 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-left.tooltip-target-attached-right .tooltip-content { 102 | margin-left: 8px; } 103 | .tooltip-element.tooltip-theme-arrows.tooltip-element-attached-bottom.tooltip-element-attached-left.tooltip-target-attached-right .tooltip-content:before { 104 | bottom: 8px; 105 | right: 100%; 106 | border-right-color: #000; } 107 | 108 | .tooltip-element.tooltip-theme-arrows { 109 | pointer-events: none; } 110 | .tooltip-element.tooltip-theme-arrows .tooltip-content { 111 | padding: 0.5em 1em; } 112 | -------------------------------------------------------------------------------- /dist/css/tooltip-theme-twipsy.css: -------------------------------------------------------------------------------- 1 | .tooltip-element, .tooltip-element:after, .tooltip-element:before, .tooltip-element *, .tooltip-element *:after, .tooltip-element *:before { 2 | box-sizing: border-box; } 3 | 4 | .tooltip-element { 5 | position: absolute; 6 | display: none; } 7 | .tooltip-element.tooltip-open { 8 | display: block; } 9 | 10 | .tooltip-element.tooltip-theme-twipsy { 11 | max-width: 100%; 12 | max-height: 100%; } 13 | .tooltip-element.tooltip-theme-twipsy .tooltip-content { 14 | border-radius: 5px; 15 | position: relative; 16 | font-family: inherit; 17 | background: #414141; 18 | color: #fff; 19 | padding: 1em; 20 | font-size: 1.1em; 21 | line-height: 1.5em; } 22 | .tooltip-element.tooltip-theme-twipsy .tooltip-content:before { 23 | content: ""; 24 | display: block; 25 | position: absolute; 26 | width: 0; 27 | height: 0; 28 | border-color: transparent; 29 | border-width: 10px; 30 | border-style: solid; } 31 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-center .tooltip-content { 32 | margin-bottom: 10px; } 33 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-center .tooltip-content:before { 34 | top: 100%; 35 | left: 50%; 36 | margin-left: -10px; 37 | border-top-color: #414141; } 38 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-center .tooltip-content { 39 | margin-top: 10px; } 40 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-center .tooltip-content:before { 41 | bottom: 100%; 42 | left: 50%; 43 | margin-left: -10px; 44 | border-bottom-color: #414141; } 45 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-right.tooltip-element-attached-middle .tooltip-content { 46 | margin-right: 10px; } 47 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-right.tooltip-element-attached-middle .tooltip-content:before { 48 | left: 100%; 49 | top: 50%; 50 | margin-top: -10px; 51 | border-left-color: #414141; } 52 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-left.tooltip-element-attached-middle .tooltip-content { 53 | margin-left: 10px; } 54 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-left.tooltip-element-attached-middle .tooltip-content:before { 55 | right: 100%; 56 | top: 50%; 57 | margin-top: -10px; 58 | border-right-color: #414141; } 59 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-left.tooltip-target-attached-bottom .tooltip-content { 60 | margin-top: 10px; } 61 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-left.tooltip-target-attached-bottom .tooltip-content:before { 62 | bottom: 100%; 63 | left: 10px; 64 | border-bottom-color: #414141; } 65 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-right.tooltip-target-attached-bottom .tooltip-content { 66 | margin-top: 10px; } 67 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-right.tooltip-target-attached-bottom .tooltip-content:before { 68 | bottom: 100%; 69 | right: 10px; 70 | border-bottom-color: #414141; } 71 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-left.tooltip-target-attached-top .tooltip-content { 72 | margin-bottom: 10px; } 73 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-left.tooltip-target-attached-top .tooltip-content:before { 74 | top: 100%; 75 | left: 10px; 76 | border-top-color: #414141; } 77 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-right.tooltip-target-attached-top .tooltip-content { 78 | margin-bottom: 10px; } 79 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-right.tooltip-target-attached-top .tooltip-content:before { 80 | top: 100%; 81 | right: 10px; 82 | border-top-color: #414141; } 83 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-right.tooltip-target-attached-left .tooltip-content { 84 | margin-right: 10px; } 85 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-right.tooltip-target-attached-left .tooltip-content:before { 86 | top: 10px; 87 | left: 100%; 88 | border-left-color: #414141; } 89 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-left.tooltip-target-attached-right .tooltip-content { 90 | margin-left: 10px; } 91 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-top.tooltip-element-attached-left.tooltip-target-attached-right .tooltip-content:before { 92 | top: 10px; 93 | right: 100%; 94 | border-right-color: #414141; } 95 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-right.tooltip-target-attached-left .tooltip-content { 96 | margin-right: 10px; } 97 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-right.tooltip-target-attached-left .tooltip-content:before { 98 | bottom: 10px; 99 | left: 100%; 100 | border-left-color: #414141; } 101 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-left.tooltip-target-attached-right .tooltip-content { 102 | margin-left: 10px; } 103 | .tooltip-element.tooltip-theme-twipsy.tooltip-element-attached-bottom.tooltip-element-attached-left.tooltip-target-attached-right .tooltip-content:before { 104 | bottom: 10px; 105 | right: 100%; 106 | border-right-color: #414141; } 107 | 108 | .tooltip-element.tooltip-theme-twipsy { 109 | opacity: 0; 110 | -webkit-transition: opacity 150ms; 111 | transition: opacity 150ms; 112 | pointer-events: none; } 113 | .tooltip-element.tooltip-theme-twipsy .tooltip-content { 114 | padding: 0.5em 1em; } 115 | .tooltip-element.tooltip-theme-twipsy .tooltip-content { 116 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.2); 117 | border-radius: 2px; 118 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 119 | padding: 3px 8px; 120 | line-height: 18px; 121 | font-size: 11px; } 122 | .tooltip-element.tooltip-theme-twipsy.tooltip-open-transitionend { 123 | display: block; } 124 | .tooltip-element.tooltip-theme-twipsy.tooltip-after-open { 125 | opacity: 1; } 126 | -------------------------------------------------------------------------------- /dist/js/tooltip.js: -------------------------------------------------------------------------------- 1 | /*! tether-tooltip 1.1.0 */ 2 | 3 | (function(root, factory) { 4 | if (typeof define === 'function' && define.amd) { 5 | define(["tether-drop","tether"], factory); 6 | } else if (typeof exports === 'object') { 7 | module.exports = factory(require('tether-drop'), require('tether')); 8 | } else { 9 | root.Tooltip = factory(root.Drop, root.Tether); 10 | } 11 | }(this, function(Drop, Tether) { 12 | 13 | /* global Tether Drop */ 14 | 15 | 'use strict'; 16 | 17 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 18 | 19 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 20 | 21 | var extend = Tether.Utils.extend; 22 | 23 | var _Drop = Drop.createContext({ 24 | classPrefix: 'tooltip' 25 | }); 26 | 27 | var defaults = { 28 | position: 'top center', 29 | openOn: 'hover', 30 | classes: 'tooltip-theme-arrows', 31 | constrainToWindow: true, 32 | constrainToScrollParent: false 33 | }; 34 | 35 | var tooltipCount = 0; 36 | 37 | var Tooltip = (function () { 38 | function Tooltip(options) { 39 | _classCallCheck(this, Tooltip); 40 | 41 | this.options = options; 42 | 43 | if (!this.options.target) { 44 | throw new Error('Tooltip Error: You must provide a target for Tooltip to attach to'); 45 | } 46 | 47 | var position = this.options.target.getAttribute('data-tooltip-position'); 48 | if (position) { 49 | if (typeof this.options.position === 'undefined') { 50 | this.options.position = position; 51 | } 52 | } 53 | 54 | var content = this.options.target.getAttribute('data-tooltip'); 55 | 56 | if (content) { 57 | if (typeof this.options.content === 'undefined') { 58 | var contentEl = document.createElement('div'); 59 | contentEl.innerHTML = content; 60 | 61 | // Add ARIA attributes (see #50) 62 | contentEl.setAttribute('role', 'tooltip'); 63 | contentEl.id = 'drop-tooltip-' + tooltipCount; 64 | this.options.target.setAttribute('aria-describedby', contentEl.id); 65 | tooltipCount += 1; 66 | 67 | this.options.content = contentEl; 68 | } 69 | } 70 | 71 | if (!this.options.content) { 72 | throw new Error('Tooltip Error: You must provide content for Tooltip to display'); 73 | } 74 | 75 | this.options = extend({}, defaults, this.options); 76 | 77 | this.drop = new _Drop(this.options); 78 | } 79 | 80 | _createClass(Tooltip, [{ 81 | key: 'close', 82 | value: function close() { 83 | this.drop.close(); 84 | } 85 | }, { 86 | key: 'open', 87 | value: function open() { 88 | this.drop.open(); 89 | } 90 | }, { 91 | key: 'toggle', 92 | value: function toggle() { 93 | this.drop.toggle(); 94 | } 95 | }, { 96 | key: 'remove', 97 | value: function remove() { 98 | this.drop.remove(); 99 | } 100 | }, { 101 | key: 'destroy', 102 | value: function destroy() { 103 | this.drop.destroy(); 104 | } 105 | }, { 106 | key: 'position', 107 | value: function position() { 108 | this.drop.position(); 109 | } 110 | }]); 111 | 112 | return Tooltip; 113 | })(); 114 | 115 | var initialized = []; 116 | 117 | Tooltip.init = function () { 118 | var tooltipElements = document.querySelectorAll('[data-tooltip]'); 119 | var len = tooltipElements.length; 120 | for (var i = 0; i < len; ++i) { 121 | var el = tooltipElements[i]; 122 | if (initialized.indexOf(el) === -1) { 123 | new Tooltip({ 124 | target: el 125 | }); 126 | initialized.push(el); 127 | } 128 | } 129 | }; 130 | 131 | document.addEventListener('DOMContentLoaded', function () { 132 | if (Tooltip.autoinit !== false) { 133 | Tooltip.init(); 134 | } 135 | }); 136 | return Tooltip; 137 | 138 | })); 139 | -------------------------------------------------------------------------------- /dist/js/tooltip.min.js: -------------------------------------------------------------------------------- 1 | !function(t,o){"function"==typeof define&&define.amd?define(["tether-drop","tether"],o):"object"==typeof exports?module.exports=o(require("tether-drop"),require("tether")):t.Tooltip=o(t.Drop,t.Tether)}(this,function(t,o){"use strict";function e(t,o){if(!(t instanceof o))throw new TypeError("Cannot call a class as a function")}var i=function(){function t(t,o){for(var e=0;ee;++e){var i=t[e];-1===u.indexOf(i)&&(new a({target:i}),u.push(i))}},document.addEventListener("DOMContentLoaded",function(){a.autoinit!==!1&&a.init()}),a}); -------------------------------------------------------------------------------- /docs/intro.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ## Tooltip 7 | 8 | Tooltip is a javascript and CSS library for creating styleable tooltip elements. 9 | 10 | Tooltip uses [Tether](http://github.hubspot.com/tether) and [Drop](http://github.hubspot.com/drop) for reliable and efficient positioning. 11 | 12 | ### Dependencies 13 | 14 | Tether 15 | 16 | Drop 17 | 18 | ### Browser Support 19 | 20 | IE9+ and everything modern 21 | 22 | ### Usage 23 | 24 | - Include the js and theme: 25 | 26 | ```html 27 | 28 | 29 | 30 | 31 | ``` 32 | 33 | - Add `data-tooltip`, and optionally `data-tooltip-position` to any element. 34 | 35 | ```html 36 | I'm a link! 37 | ``` 38 | 39 | #### Manual Initialization 40 | 41 | To manually create a tooltip, create a `new Tooltip` object: 42 | 43 | ```coffeescript 44 | new Tooltip 45 | target: targetElement 46 | position: 'top left' 47 | content: "My awesome content." 48 | classes: 'my-tether-theme' 49 | ``` 50 | 51 | You can also pass a DOM node as `content`. 52 | 53 | #### Changing the positioning 54 | 55 | Tooltips can be attached to 12 locations around the target. When initializing, you may set the `position` property to any of the following: 56 | 57 | ```coffeescript 58 | 'top left' 59 | 'left top' 60 | 'left middle' 61 | 'left bottom' 62 | 'bottom left' 63 | 'bottom center' 64 | 'bottom right' 65 | 'right bottom' 66 | 'right middle' 67 | 'right top' 68 | 'top right' 69 | 'top center' 70 | ``` 71 | 72 | ### Themes 73 | 74 | Currently there are two themes. If you would like to contribute your own themes, feel free to open pull requests and we'll be happy to include them in our library. 75 | -------------------------------------------------------------------------------- /docs/welcome/coffee/welcome.coffee: -------------------------------------------------------------------------------- 1 | isMobile = $(window).width() < 567 2 | 3 | init = -> 4 | setupHero() 5 | 6 | setupHero = -> 7 | $target = $('.tooltip-target-demo') 8 | 9 | positions = [ 10 | 'top left' 11 | 'left top' 12 | 'left middle' 13 | 'left bottom' 14 | 'bottom left' 15 | 'bottom center' 16 | 'bottom right' 17 | 'right bottom' 18 | 'right middle' 19 | 'right top' 20 | 'top right' 21 | 'top center' 22 | ] 23 | 24 | if isMobile 25 | positions = [ 26 | 'top left' 27 | 'bottom left' 28 | 'bottom right' 29 | 'top right' 30 | ] 31 | 32 | window.drops = {} 33 | 34 | for position in positions 35 | drops[position] = new Tooltip 36 | target: $target[0] 37 | position: position 38 | openOn: '' 39 | content: $.map(position.split(' '), (word) -> word.substr(0, 1).toUpperCase() + word.substr(1)).join(' ') 40 | constrainToWindow: false 41 | 42 | openIndex = 0 43 | frames = 0 44 | frameLengthMS = 10 45 | 46 | openAllDrops = -> 47 | for position, drop of drops 48 | drop.open() 49 | 50 | openNextDrop = -> 51 | for position, drop of drops 52 | drop.close() 53 | 54 | drops[positions[openIndex]].open() 55 | 56 | openIndex = (openIndex + 1) % positions.length 57 | 58 | if frames > 20 59 | return openAllDrops() 60 | 61 | frames += 1 62 | 63 | setTimeout openNextDrop, frameLengthMS * frames 64 | 65 | if isMobile 66 | drops['top left'].open() 67 | drops['bottom right'].open() 68 | 69 | else 70 | openNextDrop() 71 | 72 | init() 73 | -------------------------------------------------------------------------------- /docs/welcome/css/prism.css: -------------------------------------------------------------------------------- 1 | /* Prism.js */ 2 | code[class*="language-"], pre[class*="language-"] {color: black; font-family: Consolas, Monaco, 'Andale Mono', monospace; direction: ltr; text-align: left; white-space: pre; word-spacing: normal; -moz-tab-size: 4; -o-tab-size: 4; tab-size: 4; -webkit-hyphens: none; -moz-hyphens: none; -ms-hyphens: none; hyphens: none; } /* Code blocks */ pre[class*="language-"] {padding: 1em; margin: .5em 0; overflow: auto; font-size: 14px; } :not(pre) > code[class*="language-"], pre[class*="language-"] {background: rgba(0, 0, 0, .05); } /* Inline code */ :not(pre) > code[class*="language-"] {padding: .1em; border-radius: .3em; } .token.comment, .token.prolog, .token.doctype, .token.cdata {color: slategray; } .token.punctuation {color: #999; } .namespace {opacity: .7; } .token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol {color: #905; } .token.selector, .token.attr-name, .token.string, .token.builtin {color: #690; } .token.operator, .token.entity, .token.url, .language-css .token.string, .style .token.string, .token.variable {color: #a67f59; } .token.atrule, .token.attr-value, .token.keyword {color: #07a; } .token.regex, .token.important {color: #e90; } .token.important {font-weight: bold; } .token.entity {cursor: help; } -------------------------------------------------------------------------------- /docs/welcome/css/welcome.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; } 3 | 4 | body { 5 | margin: 0; 6 | font-family: "proxima-nova", "Helvetica Neue", sans-serif; } 7 | 8 | .button { 9 | display: inline-block; 10 | border: 2px solid #333333; 11 | color: #333333; 12 | padding: 1em 1.25em; 13 | font-weight: 500; 14 | text-transform: uppercase; 15 | letter-spacing: 3px; 16 | text-decoration: none; 17 | cursor: pointer; 18 | width: 140px; 19 | font-size: 0.8em; 20 | line-height: 1.3em; } 21 | 22 | .button.dark { 23 | background: #333333; 24 | color: white; } 25 | 26 | .hero-wrap { 27 | height: 100%; 28 | overflow: hidden; } 29 | 30 | table.showcase { 31 | height: 100%; 32 | width: 100%; 33 | position: relative; } 34 | table.showcase:after { 35 | content: ""; 36 | display: block; 37 | position: absolute; 38 | left: 0; 39 | right: 0; 40 | bottom: 20px; 41 | margin: auto; 42 | height: 0; 43 | width: 0; 44 | border-width: 18px; 45 | border-style: solid; 46 | border-color: transparent; 47 | border-top-color: rgba(0, 0, 0, 0.2); } 48 | table.showcase.no-next-arrow:after { 49 | display: none; } 50 | table.showcase .showcase-inner { 51 | margin: 40px auto 60px; 52 | padding: 10px; } 53 | table.showcase .showcase-inner h1 { 54 | font-size: 50px; 55 | text-align: center; 56 | font-weight: 300; } 57 | @media (max-width: 567px) { 58 | table.showcase .showcase-inner h1 { 59 | font-size: 40px; } } 60 | table.showcase .showcase-inner h2 { 61 | font-size: 24px; 62 | text-align: center; 63 | font-weight: 300; 64 | margin: 1em 0 1em; } 65 | @media (max-width: 567px) { 66 | table.showcase .showcase-inner h2 { 67 | font-size: 14px; } } 68 | table.showcase .showcase-inner p { 69 | text-align: center; } 70 | table.showcase.about { 71 | text-align: left; 72 | background: #fff1dd; } 73 | table.showcase.about a { 74 | color: #c96c24; } 75 | table.showcase.about p { 76 | -webkit-box-sizing: border-box; 77 | -moz-box-sizing: border-box; 78 | box-sizing: border-box; 79 | text-align: left; 80 | width: 500px; 81 | max-width: 100%; 82 | margin-left: auto; 83 | margin-right: auto; } 84 | table.showcase.about p > code { 85 | background: rgba(0, 0, 0, 0.05); } 86 | table.showcase.about pre { 87 | -webkit-box-sizing: border-box; 88 | -moz-box-sizing: border-box; 89 | box-sizing: border-box; 90 | text-align: left; 91 | width: 500px; 92 | max-width: 100%; 93 | margin-left: auto; 94 | margin-right: auto; } 95 | table.showcase.hero { 96 | text-align: center; } 97 | table.showcase.hero .tooltip-target-demo { 98 | display: -moz-inline-stack; 99 | display: inline-block; 100 | vertical-align: middle; 101 | *vertical-align: auto; 102 | zoom: 1; 103 | *display: inline; 104 | border: 2px dotted black; 105 | margin: 5rem auto; 106 | padding: 3rem; } 107 | @media (max-width: 567px) { 108 | table.showcase.hero .tooltip-target-demo { 109 | padding: 1rem; } } 110 | -------------------------------------------------------------------------------- /docs/welcome/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tooltip — CSS tooltips built on tooltip 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 |
26 |
27 |

Tooltip

28 |

Styleable tooltips built on Tether

29 |

30 | ★ On Github 31 |

32 |
33 |
34 |
35 |
36 | 37 |
38 |
39 |

How to Use

40 |

Tooltip is an open-source javascript and CSS library for creating styleable tooltips.

41 |

To use, first download the latest tether, drop, and tooltip releases. 42 |

Then simply add this javascript to your page:

43 |
<link rel="stylesheet" href="tooltip-theme-default.css" />
 44 | <script src="tether.min.js"></script>
 45 | <script src="drop.min.js"></script>
 46 | <script src="tooltip.min.js"></script>
47 |

And that's it! Learn more by visiting the documentation. 48 |

49 |
50 | 51 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 121 | 122 | 123 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /docs/welcome/js/log.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var ffSupport, formats, getOrderedMatches, hasMatches, isFF, isIE, isOpera, isSafari, log, makeArray, operaSupport, safariSupport, stringToArgs, _log; 3 | if (!(window.console && window.console.log)) { 4 | return; 5 | } 6 | log = function() { 7 | var args; 8 | args = []; 9 | makeArray(arguments).forEach(function(arg) { 10 | if (typeof arg === 'string') { 11 | return args = args.concat(stringToArgs(arg)); 12 | } else { 13 | return args.push(arg); 14 | } 15 | }); 16 | return _log.apply(window, args); 17 | }; 18 | _log = function() { 19 | return console.log.apply(console, makeArray(arguments)); 20 | }; 21 | makeArray = function(arrayLikeThing) { 22 | return Array.prototype.slice.call(arrayLikeThing); 23 | }; 24 | formats = [ 25 | { 26 | regex: /\*([^\*]+)\*/, 27 | replacer: function(m, p1) { 28 | return "%c" + p1 + "%c"; 29 | }, 30 | styles: function() { 31 | return ['font-style: italic', '']; 32 | } 33 | }, { 34 | regex: /\_([^\_]+)\_/, 35 | replacer: function(m, p1) { 36 | return "%c" + p1 + "%c"; 37 | }, 38 | styles: function() { 39 | return ['font-weight: bold', '']; 40 | } 41 | }, { 42 | regex: /\`([^\`]+)\`/, 43 | replacer: function(m, p1) { 44 | return "%c" + p1 + "%c"; 45 | }, 46 | styles: function() { 47 | return ['background: rgb(255, 255, 219); padding: 1px 5px; border: 1px solid rgba(0, 0, 0, 0.1)', '']; 48 | } 49 | }, { 50 | regex: /\[c\=(?:\"|\')?((?:(?!(?:\"|\')\]).)*)(?:\"|\')?\]((?:(?!\[c\]).)*)\[c\]/, 51 | replacer: function(m, p1, p2) { 52 | return "%c" + p2 + "%c"; 53 | }, 54 | styles: function(match) { 55 | return [match[1], '']; 56 | } 57 | } 58 | ]; 59 | hasMatches = function(str) { 60 | var _hasMatches; 61 | _hasMatches = false; 62 | formats.forEach(function(format) { 63 | if (format.regex.test(str)) { 64 | return _hasMatches = true; 65 | } 66 | }); 67 | return _hasMatches; 68 | }; 69 | getOrderedMatches = function(str) { 70 | var matches; 71 | matches = []; 72 | formats.forEach(function(format) { 73 | var match; 74 | match = str.match(format.regex); 75 | if (match) { 76 | return matches.push({ 77 | format: format, 78 | match: match 79 | }); 80 | } 81 | }); 82 | return matches.sort(function(a, b) { 83 | return a.match.index - b.match.index; 84 | }); 85 | }; 86 | stringToArgs = function(str) { 87 | var firstMatch, matches, styles; 88 | styles = []; 89 | while (hasMatches(str)) { 90 | matches = getOrderedMatches(str); 91 | firstMatch = matches[0]; 92 | str = str.replace(firstMatch.format.regex, firstMatch.format.replacer); 93 | styles = styles.concat(firstMatch.format.styles(firstMatch.match)); 94 | } 95 | return [str].concat(styles); 96 | }; 97 | isSafari = function() { 98 | return /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor); 99 | }; 100 | isOpera = function() { 101 | return /OPR/.test(navigator.userAgent) && /Opera/.test(navigator.vendor); 102 | }; 103 | isFF = function() { 104 | return /Firefox/.test(navigator.userAgent); 105 | }; 106 | isIE = function() { 107 | return /MSIE/.test(navigator.userAgent); 108 | }; 109 | safariSupport = function() { 110 | var m; 111 | m = navigator.userAgent.match(/AppleWebKit\/(\d+)\.(\d+)(\.|\+|\s)/); 112 | if (!m) { 113 | return false; 114 | } 115 | return 537.38 <= parseInt(m[1], 10) + (parseInt(m[2], 10) / 100); 116 | }; 117 | operaSupport = function() { 118 | var m; 119 | m = navigator.userAgent.match(/OPR\/(\d+)\./); 120 | if (!m) { 121 | return false; 122 | } 123 | return 15 <= parseInt(m[1], 10); 124 | }; 125 | ffSupport = function() { 126 | return window.console.firebug || window.console.exception; 127 | }; 128 | if (isIE() || (isFF() && !ffSupport()) || (isOpera() && !operaSupport()) || (isSafari() && !safariSupport())) { 129 | window.log = _log; 130 | } else { 131 | window.log = log; 132 | } 133 | window.log.l = _log; 134 | }).call(this); -------------------------------------------------------------------------------- /docs/welcome/js/welcome.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var init, isMobile, setupHero; 3 | 4 | isMobile = $(window).width() < 567; 5 | 6 | init = function() { 7 | return setupHero(); 8 | }; 9 | 10 | setupHero = function() { 11 | var $target, frameLengthMS, frames, openAllDrops, openIndex, openNextDrop, position, positions, _i, _len; 12 | $target = $('.tooltip-target-demo'); 13 | positions = ['top left', 'left top', 'left middle', 'left bottom', 'bottom left', 'bottom center', 'bottom right', 'right bottom', 'right middle', 'right top', 'top right', 'top center']; 14 | if (isMobile) { 15 | positions = ['top left', 'bottom left', 'bottom right', 'top right']; 16 | } 17 | window.drops = {}; 18 | for (_i = 0, _len = positions.length; _i < _len; _i++) { 19 | position = positions[_i]; 20 | drops[position] = new Tooltip({ 21 | target: $target[0], 22 | position: position, 23 | openOn: '', 24 | content: $.map(position.split(' '), function(word) { 25 | return word.substr(0, 1).toUpperCase() + word.substr(1); 26 | }).join(' '), 27 | constrainToWindow: false 28 | }); 29 | } 30 | openIndex = 0; 31 | frames = 0; 32 | frameLengthMS = 10; 33 | openAllDrops = function() { 34 | var drop, _results; 35 | _results = []; 36 | for (position in drops) { 37 | drop = drops[position]; 38 | _results.push(drop.open()); 39 | } 40 | return _results; 41 | }; 42 | openNextDrop = function() { 43 | var drop; 44 | for (position in drops) { 45 | drop = drops[position]; 46 | drop.close(); 47 | } 48 | drops[positions[openIndex]].open(); 49 | openIndex = (openIndex + 1) % positions.length; 50 | if (frames > 20) { 51 | return openAllDrops(); 52 | } 53 | frames += 1; 54 | return setTimeout(openNextDrop, frameLengthMS * frames); 55 | }; 56 | if (isMobile) { 57 | drops['top left'].open(); 58 | return drops['bottom right'].open(); 59 | } else { 60 | return openNextDrop(); 61 | } 62 | }; 63 | 64 | init(); 65 | 66 | }).call(this); 67 | -------------------------------------------------------------------------------- /docs/welcome/sass/welcome.sass: -------------------------------------------------------------------------------- 1 | @import compass/css3 2 | 3 | html, body 4 | height: 100% 5 | 6 | body 7 | margin: 0 8 | font-family: "proxima-nova", "Helvetica Neue", sans-serif 9 | 10 | .button 11 | display: inline-block 12 | border: 2px solid #333 13 | color: #333 14 | padding: 1em 1.25em 15 | font-weight: 500 16 | text-transform: uppercase 17 | letter-spacing: 3px 18 | text-decoration: none 19 | cursor: pointer 20 | width: 140px 21 | font-size: .8em 22 | line-height: 1.3em 23 | 24 | .button.dark 25 | background: #333 26 | color: #fff 27 | 28 | .hero-wrap 29 | height: 100% 30 | overflow: hidden 31 | 32 | table.showcase 33 | height: 100% 34 | width: 100% 35 | position: relative 36 | 37 | &:after 38 | content: "" 39 | display: block 40 | position: absolute 41 | left: 0 42 | right: 0 43 | bottom: 20px 44 | margin: auto 45 | height: 0 46 | width: 0 47 | border-width: 18px 48 | border-style: solid 49 | border-color: transparent 50 | border-top-color: rgba(0, 0, 0, 0.2) 51 | 52 | &.no-next-arrow:after 53 | display: none 54 | 55 | .showcase-inner 56 | margin: 40px auto 60px 57 | padding: 10px 58 | 59 | h1 60 | font-size: 50px 61 | text-align: center 62 | font-weight: 300 63 | 64 | @media (max-width: 567px) 65 | font-size: 40px 66 | 67 | h2 68 | font-size: 24px 69 | text-align: center 70 | font-weight: 300 71 | margin: 1em 0 1em 72 | 73 | @media (max-width: 567px) 74 | font-size: 14px 75 | 76 | p 77 | text-align: center 78 | 79 | &.about 80 | text-align: left 81 | background: #fff1dd 82 | 83 | a 84 | color: #c96c24 85 | 86 | p 87 | +box-sizing(border-box) 88 | text-align: left 89 | width: 500px 90 | max-width: 100% 91 | margin-left: auto 92 | margin-right: auto 93 | 94 | > code 95 | background: rgba(0, 0, 0, 0.05) 96 | 97 | pre 98 | +box-sizing(border-box) 99 | text-align: left 100 | width: 500px 101 | max-width: 100% 102 | margin-left: auto 103 | margin-right: auto 104 | 105 | &.hero 106 | text-align: center 107 | 108 | .tooltip-target-demo 109 | +inline-block 110 | border: 2px dotted #000 111 | margin: 5rem auto 112 | padding: 3rem 113 | 114 | @media (max-width: 567px) 115 | padding: 1rem -------------------------------------------------------------------------------- /examples/tooltip/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 26 | 27 | 28 |
29 |

This is a paragraph of text

30 |

This is a paragraph of text

31 |

Tooltip on Top

32 |

This is a paragraph of text

33 |

This is a paragraph of text

34 |

Tooltip on Bottom

35 |

This is a paragraph of text

36 |

This is a paragraph of text

37 |

Tooltip on Left

38 |

This is a paragraph of text

39 |

This is a paragraph of text

40 |

Tooltip on Right

41 |

This is a paragraph of text

42 |

This is a paragraph of text

43 |

Tooltip on Bottom Left

44 |

This is a paragraph of text

45 |

This is a paragraph of text

46 |

Tooltip on Bottom Right

47 |

This is a paragraph of text

48 |

This is a paragraph of text

49 |

Tooltip on Top Left

50 |

This is a paragraph of text

51 |

This is a paragraph of text

52 |

Tooltip on Top Right

53 |

This is a paragraph of text

54 |

This is a paragraph of text

55 |

Tooltip on Left Bottom

56 |

This is a paragraph of text

57 |

This is a paragraph of text

58 |

Tooltip on Left Top

59 |

This is a paragraph of text

60 |

This is a paragraph of text

61 |

Tooltip on Right Bottom

62 |

This is a paragraph of text

63 |

This is a paragraph of text

64 |

Tooltip on Right Top

65 |

This is a paragraph of text

66 |

This is a paragraph of text

67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var del = require('del'); 2 | var gulp = require('gulp'); 3 | var babel = require('gulp-babel'); 4 | var bump = require('gulp-bump'); 5 | var header = require('gulp-header'); 6 | var prefixer = require('gulp-autoprefixer'); 7 | var rename = require('gulp-rename'); 8 | var sass = require('gulp-sass'); 9 | var uglify = require('gulp-uglify'); 10 | var umd = require('gulp-wrap-umd'); 11 | 12 | 13 | // Variables 14 | var distDir = './dist'; 15 | var pkg = require('./package.json'); 16 | var banner = ['/*!', pkg.name, pkg.version, '*/\n'].join(' '); 17 | var umdOptions = { 18 | exports: 'Tooltip', 19 | namespace: 'Tooltip', 20 | deps: [{ 21 | name: 'Drop', 22 | globalName: 'Drop', 23 | paramName: 'Drop', 24 | amdName: 'tether-drop', 25 | cjsName: 'tether-drop' 26 | }, 27 | { 28 | name: 'Tether', 29 | globalName: 'Tether', 30 | paramName: 'Tether', 31 | amdName: 'tether', 32 | cjsName: 'tether' 33 | }] 34 | }; 35 | 36 | 37 | // Clean 38 | gulp.task('clean', function() { 39 | del.sync([distDir]); 40 | }); 41 | 42 | 43 | // Javascript 44 | gulp.task('js', function() { 45 | gulp.src('./src/js/**/*.js') 46 | .pipe(babel()) 47 | .pipe(umd(umdOptions)) 48 | .pipe(header(banner)) 49 | 50 | // Original 51 | .pipe(gulp.dest(distDir + '/js')) 52 | 53 | // Minified 54 | .pipe(uglify()) 55 | .pipe(rename({suffix: '.min'})) 56 | .pipe(gulp.dest(distDir + '/js')); 57 | }); 58 | 59 | 60 | // CSS 61 | gulp.task('css', function() { 62 | gulp.src('./src/css/**/*.sass') 63 | .pipe(sass({ 64 | includePaths: ['./bower_components'] 65 | })) 66 | .pipe(prefixer()) 67 | .pipe(gulp.dest(distDir + '/css')); 68 | }); 69 | 70 | 71 | // Version bump 72 | var VERSIONS = ['patch', 'minor', 'major']; 73 | for (var i = 0; i < VERSIONS.length; ++i){ 74 | (function(version) { 75 | gulp.task('version:' + version, function() { 76 | gulp.src(['package.json', 'bower.json']) 77 | .pipe(bump({type: version})) 78 | .pipe(gulp.dest('.')); 79 | }); 80 | })(VERSIONS[i]); 81 | } 82 | 83 | 84 | // Watch 85 | gulp.task('watch', ['js', 'css'], function() { 86 | gulp.watch('./src/js/**/*', ['js']); 87 | gulp.watch('./src/css/**/*', ['css']); 88 | }); 89 | 90 | 91 | // Defaults 92 | gulp.task('build', ['js', 'css']); 93 | gulp.task('default', ['build']); 94 | 95 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tether-tooltip", 3 | "version": "1.2.0", 4 | "description": "CSS tooltips built on Tether", 5 | "authors": [ 6 | "Adam Schwartz ", 7 | "Zack Bloom " 8 | ], 9 | "maintainers": [ 10 | "Nicholas Hwang " 11 | ], 12 | "scripts": { 13 | "build": "gulp build" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/HubSpot/tooltip.git" 18 | }, 19 | "license": "MIT", 20 | "main": "dist/js/tooltip.js", 21 | "devDependencies": { 22 | "bower": "^1.4.1", 23 | "del": "^1.2.0", 24 | "gulp": "^3.9.0", 25 | "gulp-autoprefixer": "^2.3.1", 26 | "gulp-babel": "^5.1.0", 27 | "gulp-bump": "^0.3.0", 28 | "gulp-header": "^1.2.2", 29 | "gulp-rename": "^1.2.2", 30 | "gulp-sass": "^2.0.1", 31 | "gulp-uglify": "^1.2.0", 32 | "gulp-wrap-umd": "^0.2.1" 33 | }, 34 | "dependencies": { 35 | "tether": "^1.1.0", 36 | "tether-drop": "^1.4.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/css/tooltip-theme-arrows.sass: -------------------------------------------------------------------------------- 1 | // The majority of the tooltip styles come from a tether helper 2 | 3 | @import ../bower_components/tether/src/css/helpers/tether 4 | @import ../bower_components/tether/src/css/helpers/tether-theme-arrows 5 | 6 | $themePrefix: "tooltip" 7 | $arrowSize: 8px 8 | $backgroundColor: #000 9 | $color: #eee 10 | $useDropShadow: false 11 | 12 | +tether($themePrefix: $themePrefix) 13 | +tether-theme-arrows($themePrefix: $themePrefix, $arrowSize: $arrowSize, $backgroundColor: $backgroundColor, $color: $color, $useDropShadow: $useDropShadow) 14 | 15 | // Just a few additions 16 | 17 | .#{ $themePrefix }-element.#{ $themePrefix }-theme-arrows 18 | pointer-events: none 19 | 20 | .#{ $themePrefix }-content 21 | padding: .5em 1em 22 | -------------------------------------------------------------------------------- /src/css/tooltip-theme-twipsy.sass: -------------------------------------------------------------------------------- 1 | @import ../bower_components/tether/src/css/helpers/tether 2 | @import ../bower_components/tether/src/css/helpers/tether-theme-arrows 3 | 4 | $themePrefix: "tooltip" 5 | $themeName: "twipsy" 6 | $arrowSize: 10px 7 | $backgroundColor: #414141 8 | $color: #fff 9 | $useDropShadow: false 10 | 11 | +tether($themePrefix: $themePrefix) 12 | +tether-theme-arrows($themePrefix: $themePrefix, $themeName: $themeName, $arrowSize: $arrowSize, $backgroundColor: $backgroundColor, $color: $color, $useDropShadow: $useDropShadow) 13 | 14 | .#{ $themePrefix }-element.#{ $themePrefix }-theme-#{ $themeName } 15 | opacity: 0 16 | transition: opacity 150ms 17 | pointer-events: none 18 | 19 | .#{ $themePrefix }-content 20 | padding: .5em 1em 21 | 22 | .#{ $themePrefix }-content 23 | box-shadow: 0 3px 7px rgba(0, 0, 0, .2) 24 | border-radius: 2px 25 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif 26 | padding: 3px 8px 27 | line-height: 18px 28 | font-size: 11px 29 | 30 | &.#{ $themePrefix }-open-transitionend 31 | display: block 32 | 33 | &.#{ $themePrefix }-after-open 34 | opacity: 1 35 | -------------------------------------------------------------------------------- /src/js/tooltip.js: -------------------------------------------------------------------------------- 1 | /* global Tether Drop */ 2 | 3 | const { extend } = Tether.Utils; 4 | 5 | const _Drop = Drop.createContext({ 6 | classPrefix: 'tooltip' 7 | }); 8 | 9 | const defaults = { 10 | position: 'top center', 11 | openOn: 'hover', 12 | classes: 'tooltip-theme-arrows', 13 | constrainToWindow: true, 14 | constrainToScrollParent: false 15 | }; 16 | 17 | let tooltipCount = 0; 18 | 19 | class Tooltip { 20 | constructor(options) { 21 | this.options = options; 22 | 23 | if (!this.options.target) { 24 | throw new Error('Tooltip Error: You must provide a target for Tooltip to attach to'); 25 | } 26 | 27 | const position = this.options.target.getAttribute('data-tooltip-position'); 28 | if (position) { 29 | if (typeof this.options.position === 'undefined') { 30 | this.options.position = position; 31 | } 32 | } 33 | 34 | const content = this.options.target.getAttribute('data-tooltip'); 35 | 36 | if (content) { 37 | if (typeof this.options.content === 'undefined') { 38 | const contentEl = document.createElement('div'); 39 | contentEl.innerHTML = content; 40 | 41 | // Add ARIA attributes (see #50) 42 | contentEl.setAttribute('role', 'tooltip'); 43 | contentEl.id = `drop-tooltip-${ tooltipCount }`; 44 | this.options.target.setAttribute('aria-describedby', contentEl.id); 45 | tooltipCount += 1; 46 | 47 | this.options.content = contentEl; 48 | } 49 | } 50 | 51 | if (!this.options.content) { 52 | throw new Error('Tooltip Error: You must provide content for Tooltip to display'); 53 | } 54 | 55 | this.options = extend({}, defaults, this.options); 56 | 57 | this.drop = new _Drop(this.options); 58 | 59 | 60 | } 61 | 62 | close() { 63 | this.drop.close(); 64 | } 65 | 66 | open() { 67 | this.drop.open(); 68 | } 69 | 70 | toggle() { 71 | this.drop.toggle(); 72 | } 73 | 74 | remove() { 75 | this.drop.remove(); 76 | } 77 | 78 | destroy() { 79 | this.drop.destroy(); 80 | } 81 | 82 | position() { 83 | this.drop.position(); 84 | } 85 | } 86 | 87 | let initialized = []; 88 | 89 | Tooltip.init = () => { 90 | const tooltipElements = document.querySelectorAll('[data-tooltip]'); 91 | const len = tooltipElements.length; 92 | for (let i = 0; i < len; ++i) { 93 | const el = tooltipElements[i]; 94 | if (initialized.indexOf(el) === -1) { 95 | new Tooltip({ 96 | target: el 97 | }); 98 | initialized.push(el); 99 | } 100 | } 101 | }; 102 | 103 | document.addEventListener('DOMContentLoaded', () => { 104 | if (Tooltip.autoinit !== false) { 105 | Tooltip.init(); 106 | } 107 | }); 108 | --------------------------------------------------------------------------------