Code Monkey home page Code Monkey logo

ember-tooltips's Introduction

Ember-tooltips (and popovers) Build Status npm Ember Observer Score

Render tooltips and popovers on components and other HTML elements using HTMLBars.

Installation

ember install ember-tooltips

Upgrading from 2.x

See UPGRADING-3.x.md

Documentation

Documentation for usage is below:

Usage

This documentation is for the 3.x version of ember-tooltips. For 2.x documentation, please refer to the 2.x branch README.

Note: The documentation below is up-to-date for Ember Octane Edition conventions. However, it is still valid to use earlier curly-bracket syntax too, e.g. {{ember-tooltip text="Hello!" onShow=(action 'someAction')}}

Ember Tooltip

The easiest way to add a tooltip to any element is with the <EmberTooltip /> component:

<MyComponent>
  Hover for more info

  <EmberTooltip @text="Here is more info!" />
</MyComponent>

Or in block form:

<MyComponent>
  Hover for more info

  <EmberTooltip>
    Here is the info in a tooltip!
  </EmberTooltip>
</MyComponent>

The tooltip will always be rendered on its parent element unless you specify the targetId attribute:

<input id="has-info-tooltip" value="" placeholder="Enter first name..." />

<EmberTooltip @targetId="has-info-tooltip">
  Here is some more info
</EmberTooltip>

or the targetElement attribute:

<EmberTooltip @targetElement={{this.tooltipTargetElement}}>
  Here is some more info
</EmberTooltip>

Tooltips and popovers are lazy rendered. That means the are only rendered in the DOM once the user interacts with the target element.

Options can be set on the <EmberTooltip> as attributes:

<MyComponent>
  Click for more info

  <EmberTooltip @event="click">
    This info will show on click!
  </EmberTooltip>
</MyComponent>

Documentation for supported options is located here.

Ember popover

Popovers can be created with the <EmberPopover /> component, which is added to apps just like <EmberTooltip />.

Popovers support the same target behavior as tooltips; popovers will render on their parent element unless a targetId or targetElement is supplied.

All the options passed to tooltip components can be passed to popover components:

<MyComponent>
  Click for more info

  <EmberPopover @event="click">
    This info will show in a popover on click!
  </EmberPopover>
</MyComponent>

Popovers also benefit from a hide API made publically acessible:

<EmberPopover as |popover|>
  <button onClick={{action "hide" target=popover}} type="button">Click here</button> to hide the popover
</EmberPopover>

In addition, a popoverHideDelay option is made available for popovers only.

Options

Options are set as attributes on the tooltip/popover components. Current tooltip/popover properties this addon supports are:

animationDuration

Type Default
Number 200

Defines the duration of tooltip animation in milliseconds. In testing, animation duration is always 0.

<EmberTooltip @animationDuration={{0}} />

arrowClass

Type Default
String 'tooltip-arrow'

Adds extra classes to tooltip arrows.

Usually used along with tooltipClass.

<EmberTooltip @arrowClass="hoverhelp__arrow" />

This will create html similar to:

<div class="tooltip">
  <div class="hoverhelp__arrow"></div>
  <div class="tooltip-inner"><!-- content --></div>
</div>

class

Type Default
String none

Adds a class to any tooltip wrapper:

<EmberTooltip class="tooltip-wrapper" />

Note: This is usually not what you want, as the wrapper itself is hidden by default. You are probably looking for tooltipClass.

delay

Type Default
Number 0

Delays showing the tooltip by the given number of milliseconds.

{{!--Delays the show animation by 500ms--}}

<EmberTooltip @delay={{500}} />

This does not affect the hiding of the tooltip. See also, delayOnChange.

delayOnChange

Type Default
Boolean true

Whether or not to enforce the delay even when the user transitions their cursor between multiple target elements with tooltips.

See this animation for a visual explanation:

{{!--Forces delay to be enforced when the user skips
between elements with tooltips--}}

<EmberTooltip @delayOnChange={{true}} />

duration

Type Default
Number 0

Sets the duration for which the tooltip will be open, in milliseconds. When the tooltip has been opened for the duration set it will hide itself.

The user will still hide the tooltip if the hide event occurs before the duration expires.

{{!-- Closes the tooltip after 1000ms--}}

<EmberTooltip @duration={{1000}} />

Leave as 0 if you wish for the tooltip to remain open indefinitely.

effect

Type Default
String 'slide'

Sets the animation used to show and hide the tooltip. Possible options are:

  • 'fade'
  • 'slide'
  • 'none'
<EmberTooltip @effect="slide" />

event

Type Default
String 'hover'

The event that the tooltip will hide and show for. Possible options are:

  • 'hover'
  • 'click'
  • 'focus' (hides on blur)
  • 'none'
<EmberTooltip @event="click" />

This event is overwritten by the individual hideOn and showOn properties. In effect, setting event sets hideOn and shownOn for you.

The tooltip can also be shown programatically by passing in the isShown property, documented here.

hideOn

Type Default
String 'none'

Sets the event that the tooltip will hide on. This overwrites any event set with the event option.

This can be any javascript-emitted event.

{{!--This tooltip will hide on mouseleave, NOT click--}}

<EmberTooltip
  @event="click"
  @hideOn="mouseleave"
/>

Usually, you'll use the event option, which sets showOn and hideOn automatically, instead of this option.

This option does not affect the event the tooltip shows on. That is set by the showOn option. This will override the event property in deciding when the tooltip is hidden.

innerClass

Type Default
String 'tooltip-inner'

Adds extra classes to inner tooltips.

Usually used along with tooltipClass.

<EmberTooltip @innerClass="hoverhelp__inner" />

This will create html similar to:

<div class="tooltip">
  <div class="tooltip-arrow"></div>
  <div class="hoverhelp__inner"><!-- content --></div>
</div>

isShown

Type Default
Boolean false

Gives you a programatic way to hide and show a tooltip. Set this value to true to manually show the tooltip.

This can be useful alongside event='none' when you only want to toolip to show when you specific and not based on an user action.

{{!--Binds the tooltip visibility to the showTooltip property--}}
<EmberTooltip @isShown={{this.showTooltip}} @event="none" />

popoverHideDelay

Type Default
Number 250

POPOVER ONLY: The number of milliseconds before the popover will hide after the user hovers away from the popover and the popover target. This is only applicable when event='hover'.

<EmberPopover @event="hover" @popoverHideDelay={{300}} />

popover-hover

popperContainer

Type Default
HTMLElement | String | false false

Appends the tooltip to a specific element. By default, the tooltip will be rendered as a sibling of its target. This attribute can be set to render the tooltip elsewhere in the DOM. See the tooltip.js container option.

{{!--Renders the tooltip as a child of the body element--}}

<EmberTooltip @popperContainer="body" />

popperOptions

Type Default
Object null

Sets the popperOptions on the underlying tooltip.js instance. Currently, only overriding modifiers is supported. See popper.js documentation for more information on available modifiers.

This can be used to customize various aspects of tooltip rendering and override certain popper.js defaults set by ember-tooltips. For example, using a tooltip inside of an absolutely or relatively positioned container with overflow constraints, you may want to disable preventOverflow.escapeWithReference.

/* app/components/some-component.js */
import Component from '@ember/component';

export default Component.extend({
  popperOptions: {
    modifiers: {
      preventOverflow: {
        escapeWithReference: false
      }
    }
  },
  /* ... other stuff */
});
{{!-- app/templates/components/some-component.hbs` --}}

<div class="my-scrollable-container">
  {{#each items as |item|}}
    <div class="row">
      {{item.text}}
      <EmberTooltip @text={{item.tooltip}} @popperOptions={{this.popperOptions}} />
    </div>
  {{/each}}
</div>

Note that popperOptions is only applied during tooltip creation and that it is not reapplied if the value changes after the tooltip is rendered.

side

Type Default
String 'top'

Sets the side the tooltip will render on.

Possible options are:

  • 'top'
  • 'right'
  • 'bottom'
  • 'left'

In addition, you may also specify -start and -end variants supported by Popper.js. e.g. top-start to position the tooltip from the top-left or right-end to position from the bottom right.

{{!--The tooltip will render on the right of the target element--}}

<EmberTooltip @side="right" />

showOn

Type Default
String 'none'

Sets the event that the tooltip will show on. This overwrites any event set with the event option.

This can be any javascript-emitted event.

{{!--This tooltip will show on click, NOT hover--}}

<EmberTooltip @showOn="click" />

Usually, you'll use the event option, which sets showOn and hideOn automatically, instead of this option.

This option does not affect the event the tooltip hides on. That is set by the [hideOn](#hide on) option. This will override the event property in deciding when the tooltip is shown.

spacing

Type Default
Number 10

Sets the number of pixels the tooltip will render from the target element. A higher number will move the tooltip further from the target. This can be any number.

{{!--Render the tooltip 20px from the target element--}}
<EmberTooltip @spacing={{20}} />

targetId

Type Default
String null (parent element of the tooltip)

The concept of a 'target' is used through this addon. A target is the element that the tooltip or popover is attached to. Each tooltip or popvers has its own target. Interacting with this target will render and/or show the tooltip or popover. By default, the tooltip's target is the parent element. However, with targetId, you can specify another element's ID to attach the tooltip to another element on the page.

For example, if you want to show a tooltip over a button when the user hovers over the button, the button is the target. If you want to show a popover over an input when the user focuses on the input, the input is the target.

<input id="has-info-tooltip" value="" placeholder="Enter first name..." />

<EmberTooltip @targetId="has-info-tooltip">
  Here is some more info
</EmberTooltip>

targetElement

Type Default
Element null (parent element of the tooltip)

This behaves the same as the target attribute, except is used to specify the target element itself, rather than a selector for finding the target element. If both targetElement and targetId are specified, targetId will take precedence.

<EmberTooltip @targetElement={{this.tooltipTargetElement}}>
  Here is some more info
</EmberTooltip>

text

Type Default
String null

Sets the text of any tooltip without needing the tooltip to be written in block form.

<MyComponent>
  Hover for more info

  <EmberTooltip @text="Here is more info!" />
</MyComponent>

tooltipClass

Type Default
String 'tooltip'

Adds extra classes to tooltips.

Useful to avoid conflicts with other libraries.

<EmberTooltip @tooltipClass="hoverhelp" />

This will create html similar to:

<div class="hoverhelp">
  <div class="tooltip-arrow"></div>
  <div class="tooltip-inner"><!-- content --></div>
</div>

Setting Defaults

You can set the default for any option by extending the <EmberTooltip /> or <EmberPopover /> component:

/* your-app/components/ember-tooltip.js */

import EmberTooltipComponent from 'ember-tooltips/components/ember-tooltip';

export default EmberTooltipComponent.extend({
  effect: 'fade',
  side: 'bottom',
});

Note: Do not provide a template hbs file, when overriding/extending ember-tooltips or ember-popover, as this will override the template provided by the addon and prevent tooltip or popover content from appearing.

Actions

Four actions are available for you to hook onto through the tooltip/popover lifecycle:

<EmberTooltip
  @onDestroy={{action 'onDestroy'}}
  @onHide={{action 'onHide'}}
  @onRender={{action 'onRender'}}
  @onShow={{action 'onShow'}}
/>

Testing

Test helpers

This addon exposes testing helpers which can be used inside of the consuming app's acceptance and integration tests. We use a tooltip-centric naming convention but these can also be used to test popovers.

Publically available test helpers are:

All assert helpers require assert to be passed as the first param and some accept a second, optional param for additional test options. All assert helpers work with both QUnit's assert and chai's assert.

For detailed usage instructions and examples, see the documentation for each test helper below.

There are currently two supported flavors of test helpers: one implementation uses jQuery and one uses the browser's DOM APIs (querySelector, etc.). The two share the same APIs, with exception for the types of selectors they support.

The jQuery assertion test helpers support jQuery-specific pseudoselectors like :contains. However, as jQuery is now optional in Ember 3.4+ and the use-cases for jQuery-specific selectors and the use of the library are small, these helpers will likely be removed in the next major release of ember-tooltips.

All test helpers live under the following modules:

// (Recommended) Auto-selection of either jQuery or DOM-based APIs, based
// on @ember/optional-features and whether jquery-integration is enabled.
import { assertTooltipContent } from 'ember-tooltips/test-support';

// Explicit path for DOM-based APIs
import { assertTooltipContent } from 'ember-tooltips/test-support/dom';

// Explicit path for jQuery-based APIs (deprecated)
import { assertTooltipContent } from 'ember-tooltips/test-support/jquery';

Example

/* appname/tests/integration/components/some-component.js */

import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, triggerEvent } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

import { assertTooltipRendered } from 'ember-tooltips/test-support';
// Or, on ember-tooltips 3.3.0+ and not using jQuery:
// import { assertTooltipRendered } from 'ember-tooltips/test-support/dom/assertions';

module('Integration | Component | Some component', function(hooks) {
  setupRenderingTest(hooks);

  test('ember-tooltip renders', async function(assert) {

    await render(hbs`<EmberTooltip isShown={{true}} />`);

    assertTooltipRendered(assert);
  });
});

assertTooltipContent()

Asserts that a tooltip or popover has content that matches a given string.

import { assertTooltipContent } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip @text="More info" @isShown={{true}} />`);

  assertTooltipContent(assert, {
    contentString: 'More info',
  });
});

The options hash accepts:

assertTooltipRendered()

Asserts that a tooltip or popover has been rendered in the DOM.

import { render, triggerEvent } from '@ember/test-helpers';
import { assertTooltipRendered } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip />`);

  await triggerEvent(this.element, 'mouseenter');

  assertTooltipRendered(assert);
});

Please note, assertTooltipRendered() does not assert that the tooltip or popover is visible to the user - use assertTooltipVisible() for that.

Given this addon's lazy rendering capabilities (explained in targetId), tooltips will not be rendered until the target is interacted with.

The options hash accepts:

assertTooltipNotRendered()

Asserts that a tooltip or popover has not been rendered in the DOM.

Why is this test helper useful? Well, given this addon's lazy rendering capabilities (explained in targetId), tooltips may not be rendered until the target is interacted with.

import { render, triggerEvent } from '@ember/test-helpers';
import { assertTooltipNotRendered } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip />`);

  assertTooltipNotRendered(assert);
});

This helper does not assert that the tooltip or popover is not visible to the user. The assertion will fail if the tooltip or popover is not visible to the user but is still rendered in the DOM. If you want to assert that a tooltip or popover is not visible once it's rendered in the DOM, use assertTooltipNotVisible().

The options hash accepts:

assertTooltipVisible()

Asserts that a tooltip or popover is visible.

For example:

import { render, triggerEvent } from '@ember/test-helpers';
import { assertTooltipVisible } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip />`);

  await triggerEvent(this.element, 'mouseenter');

  assertTooltipVisible(assert);
});

You may use this helper with a variety of different user interactions. Here's an example that asserts that a tooltip is shown when the user focusses on an input:

import { render, triggerEvent } from '@ember/test-helpers';
import { assertTooltipVisible } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`
    <input id="url-input">
    <EmberTooltip @targetId="url-input" />
  `);

  await triggerEvent('#url-input', 'focus');

  /* Asserts that the tooltip is made visible when the user focuses on the input */

  assertTooltipVisible(assert);
});

The options hash accepts:

assertTooltipNotVisible()

Asserts that a tooltip or popover is not visible.

This helper is usually used in conjunction with triggerTooltipTargetEvent() to assert that a particular user interaction hides a tooltip to the user.

For example:

import { render, triggerEvent } from '@ember/test-helpers';
import {
  assertTooltipNotVisible,
  assertTooltipVisible,
} from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip />`);

  const { element } = this;

  /* Hover over the target to show the tooltip... */

  await triggerEvent(element, 'mouseenter');

  assertTooltipVisible(assert);

  /* Stop hovering over the target in order to hide the tooltip... */

  await triggerEvent(element, 'mouseleave');

  assertTooltipNotVisible(assert);
});

The options hash accepts:

assertTooltipSide()

Asserts that a tooltip or popover is rendered on the correct side of the target.

This helper tests the side option that can be passed to tooltips and popovers.

An options hash is required and it must contain a side property. For example:

import { assertTooltipSide } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip @side="right" @isShown={{true}} />`);

  /* Asserts that the tooltip is rendered but not shown when the user hovers over the target, which is this test's element */

  assertTooltipSide(assert, {
    side: 'right',
  });
});

The options hash accepts:

assertTooltipSpacing()

Asserts that a tooltip or popover is rendered a given number of pixels from the target.

This helper tests the spacing option that can be passed to tooltips and popovers.

An options hash is required and it must contain spacing and side properties. For example:

import { assertTooltipSpacing } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip @spacing={{35}} @isShown={{true}} />`);

  /* Asserts that the tooltip is rendered but not shown when the user hovers over the target, which is this test's element */

  assertTooltipSpacing(assert, {
    side: 'right', /* Side is required */
    spacing: 35,
  });
});

The options hash accepts:

Test helper options

Most test helpers accept a second, optional param called options. This is an object you can pass that customizes various options in a test. The properties you can pass via options for each test helper is listed above. Below you will find more information for each property.

Test helper option: contentString

The content string you expect the tooltip or popover to have.

Type Default
String null

Usage example:

import { assertTooltipContent } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip @text="More info" @isShown={{true}} />`);

  assertTooltipContent(assert, {
    contentString: 'More info',
  });
});

Test helper option: selector

The selector of the tooltip or popover you are testing.

If more than one tooltip or popover is found in the DOM when you run an assertion, you will be asked to specify this.

Type Default
String '.ember-tooltip, .ember-popover'

Usage example:

import { render, triggerEvent } from '@ember/test-helpers';
import { assertTooltipVisible } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`
    <EmberTooltip />
    <EmberTooltip class="differentiator" />
  `);

  await triggerEvent(this.element, 'mouseenter');

  assertTooltipVisible(assert, {
    selector: '.differentiator', /* Or whatever class you added to the desired tooltip */
  });
});

Test helper option: side

The value for the tooltip or popover's side option that you are asserting.

Type Default
String null

For example, if you specify for the tooltip or popover be shown on the right of the target using side='right', you will pass side: 'right' in assertions that test side. Here is the code for this example:

import { assertTooltipSide } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip @side="right" @isShown={{true}} />`);

  /* Asserts that the tooltip is rendered but not shown when the user hovers over the target, which is this test's element */

  assertTooltipSide(assert, {
    side: 'right',
  });
});

Test helper option: spacing

The value for the tooltip or popover's spacing option that you are asserting. Specify as a number of pixels expected (without a px unit).

Type Default
Number null

For example, if you specify for the tooltip or popover be shown on the right of the target using side='right', you will pass side: 'right' in assertions that test side. Here is the code for this example:

import { assertTooltipSide } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`<EmberTooltip @spacing={{35}} @isShown={{true}} />`);

  /* Asserts that the tooltip is rendered but not shown when the user hovers over the target, which is this test's element */

  assertTooltipSide(assert, {
    side: 'right', /* Side is required */
    spacing: 35,
  });
});

Test helper option: targetSelector

The selector of the target element of the tooltip or popover you are testing.

If more than one tooltip or popover is found in the DOM with a particular selector when you run an assertion, you will be asked to specify this.

Type Default
String '.ember-tooltip-target, .ember-popover-target'

Usage example:

import { render, triggerEvent } from '@ember/test-helpers';
import { assertTooltipVisible } from 'ember-tooltips/test-support';

test('Example test', async function(assert) {

  await render(hbs`
    <div class="target-a">
      <EmberTooltip class="common-tooltip" @side="top" @isShown={{true}} @text="Hi" @effect="none" />
    </div>
    <div class="target-b">
      <EmberTooltip class="common-tooltip" @side="left" @isShown={{true}} @text="Bye" @effect="none" />
    </div>
  `);

  assertTooltipVisible(assert, {
    targetSelector: '.target-b', /* Or whatever class you added to the target element */
  });
});

Accessibility

This addon aims to meet 508 compliance.

Elements with tooltips are given a tabindex attribute and when the element receives focus, the tooltip will show.

Additionally, the aria-describedby, title, id, and role attributes are managed by this addon.

There is always room for improvement and PRs to improve accessibility are welcome.

Development

This project is maintained by:

Duncan Walker Max Fierke
Duncan Walker Max Fierke

All PRs and issues are welcome to the following branches:

  • master for 3.x improvements and bug fixes
  • 2.x for 2.x improvements and bug fixes

Before starting work on a PR, please read the quick guide, CONTRIBUTING, to save you time and energy!

Maintainer information

To release an update to the demo app (for maintainers only):

git checkout master # make sure you're on master branch
ember github-pages:commit --message "Some commit message" # Builds the app
git push origin gh-pages:gh-pages # Deploys the app

ember-tooltips's People

Contributors

a15n avatar andrew-zenefits avatar bekzod avatar brookjordan avatar camerondubas avatar chrism avatar cooperjbrandon avatar davidgovea avatar dependabot[bot] avatar elwayman02 avatar josemarluedke avatar jrowlingson avatar jurgenwerk avatar kmiyashiro avatar lepolt avatar lukes avatar luxzeitlos avatar maxfierke avatar maxhungry avatar miguelmadero avatar ndemonner avatar pauc avatar pgengler avatar raido avatar rob-long avatar ryanlabouve avatar sir-dunxalot avatar techn1x avatar timmorey avatar yankeeinlondon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ember-tooltips's Issues

More options for the "side" parameter

Hi,

as the "keepInWindow" paramete doesn't work very reliable, how about implementing some more options for the "side" parameter? Something like "bottomleft", "bottomright" etc.
This way it would be possible to position the tooltip inside the window so that it should be completely visible in most cases.

CSP reports

Hi there,

After installing this plugin I'm getting a lot of CSP reports on the console saying:
Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive. tooltip.js:210..

Is there any way to supress these messages without adding unsafe-eval to my CSP configuration?

image

Hide / show tooltip is reversed sometimes when hovering over multiple tooltips

When hovering immediately from one to another tooltip the show / hide functionality is not working properly. Sometimes the hide / show is reversed, so hovering over a tooltip hides the tooltip and when I'm not hovering it shows the tooltip.

Our application runs on Ember 1.13.10 and I tried ember-tooltips 0.5.2 and 0.4.0 but I'm seeing this behaviour in both versions. It doesn't matter if I use the tooltips as data-* attributes or as components / tooltip-on-parent component.

Looks like the addon is hiding the new tooltip when hovering immediately from one tooltip to another and the hide() method is triggered after the show() method.

Ember-tooltips.css.map is missing

Has anyone else came across this issue where something is requesting for /assets/ember-tooltips.css.map? I am using Ember-cli-rails by the way.

Started GET "/assets/ember-tooltips.css.map" for 127.0.0.1 at 2016-06-08 02:14:41 -0500
02:14:41 web.1  | 
02:14:41 web.1  | ActionController::RoutingError (No route matches [GET] "/assets/ember-tooltips.css.map"):
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/show_exceptions.rb:30:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rails/rack/logger.rb:38:in `call_app'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rails/rack/logger.rb:20:in `block in call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/active_support/tagged_logging.rb:68:in `block in tagged'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/active_support/tagged_logging.rb:26:in `tagged'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/active_support/tagged_logging.rb:68:in `tagged'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rails/rack/logger.rb:20:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/request_id.rb:21:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rack/methodoverride.rb:22:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rack/runtime.rb:18:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rack/lock.rb:17:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/static.rb:120:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rack/sendfile.rb:113:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rails/engine.rb:518:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rails/application.rb:165:in `call'
02:14:41 web.1  |   /usr/lib/ruby/vendor_ruby/rack/content_length.rb:15:in `call'
02:14:41 web.1  |   puma (3.4.0) lib/puma/configuration.rb:224:in `call'
02:14:41 web.1  |   puma (3.4.0) lib/puma/server.rb:569:in `handle_request'
02:14:41 web.1  |   puma (3.4.0) lib/puma/server.rb:406:in `process_client'
02:14:41 web.1  |   puma (3.4.0) lib/puma/server.rb:271:in `block in run'
02:14:41 web.1  |   puma (3.4.0) lib/puma/thread_pool.rb:114:in `block in spawn_thread'
02:14:41 web.1  | 
02:14:41 web.1  | 
02:14:41 web.1  |   Rendered /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/templates/rescues/_trace.html.erb (0.9ms)
02:14:41 web.1  |   Rendered /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/templates/routes/_route.html.erb (4.2ms)
02:14:41 web.1  |   Rendered /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/templates/routes/_table.html.erb (6.1ms)
02:14:41 web.1  |   Rendered /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.9ms)
02:14:41 web.1  |   Rendered /usr/lib/ruby/vendor_ruby/action_dispatch/middleware/templates/rescues/routing_error.html.erb within rescues/layout (40.1ms)

Let me know if there is any other information I can provide! Also, the Source Code is open source, and accessible at Deovandski/Fakktion

typeClass not applying styles

I am doing the following:

renderTooltip(element, {
      content,
      effectClass: 'grow',
      hideOn: 'click',
      place: 'top',
      showOn: 'click',
      typeClass: 'light'
    });

However, the tooltip remains the dark 'none' style. Am I doing something wrong? I noticed that the darsain library seems to use classes like light and success but it appears this addon is adding tooltip- in front of the classes maybe?

I can't actually look at the markup for the tooltip because I can't figure out how to keep them open with dev tools open.

Wrong positioning when attaching tooltips to elements inside table cells

Hi guys,

First of all, thanks for this cool addon. Really easy to use unlike other addons I tried before.
I don't know if this really is an issue or a feature request, but I hope it's okay anyway.

My problem:
I'm rendering a table (100% width) with a varying amount of cells inside. Let's assume I have 5 cells and in each cell there is a {{#tooltip-on-element ...}} attached to an element.
As each row starts to render the cells one by one, the cells are growing after the tooltip inside was already rendered, so they are slightly moved to the side. If a resize the window, repositioning is taking effect and everything is fine.

Does anybody has a solution for this problem that comes out of the box?

Thanks in advance for having a look at my message! =)

Merge error: file app.scss exists

After installing it gives the following build error when ember s is run:

Merge error: file app.scss exists in /mnt/EmberCliRamdisk/ember-client/broccoli_merge_trees-input_base_path-RxstezkD.tmp/39 and /mnt/EmberCliRamdisk/ember-client/broccoli_merge_trees-input_base_path-RxstezkD.tmp/42
Pass option { overwrite: true } to mergeTrees in order to have the latter file win.

Removing the addon resolves it. So it's obvious that the above error happens due to this addon.

Ember-cli: 1.13.8
Ember: 1.13.10

Deprecated sourcemap comments

It looks like the files concatenated together into vendor/tooltip/tooltip.js contain a deprecated sigil for sourcemap comments (@ vs #) which is producing the following warnings Chrome and similar ones in Firefox:

image

Having read through darsain/tooltip#28, it looks like the upstream author's stance amounts to:

"I'm not going to work on this until someone magically fixes package management, and I'm also not going accept PRs either because everyone else should also refuse to do work until that happens."

😒

Given that, would you consider just swapping in #s for the @s in the vendored file in this repo (or removing the comments entirely, since they don't actually point anywhere)?

tooltipContent can't be a SafeString

tooltip.content(this.get('tooltipContent'));
passes tooltipContent directly to tooltip.content(...). This must be a plain string; the underlying library doesn't coerce it. If I do the following

someProperty: Ember.computed(function() {
  return Ember.String.htmlSafe('some text');
})
{{link-to .... tooltipContent=someProperty}}

Then I get

Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.

This is notable because ember-i18n returns all translated strings as SafeStrings.

I have two ideas:

  1. just stringify anything that comes in: tooltip.content('' + tooltipContent)
  2. try to understand HTML safety and HTML-escape tooltipContent unless it's a SafeString

I think (2) is more correct than (1), but it may break some apps.

Do not add title

Hey, guys! Is it possible to ember-tooltips does not add the title attr? Or at least, do not show two tooltips. One styled and the default one.

Positional options lost in 1.0

As I was up upgrading this (fantastic!) addon, it looks like we have lost some granularity in positioning the tooltip (ie top-left, top-right, bottom-left, bottom-right). I think ember-tether can support these, and I'm happy to take a crack at implementing it in ember-tooltips but I wanted to check in first on your thoughts @sir-dunxalot. Thanks!

Use Mixins and allow option for no Initializers

Hi

I like this library but would prefer that it didn't load code on every single one of my components and views. The code in the 'didInsertElement' is run for every element inserted in my app - all the time. This shouldn't be the default behaviour - or it should at least be able to be turned off.

Also - I see that you've actually got the code that is inserted on every view/component in the initializer - it would be better if this was a Mixin that could be imported separately.. Allowing the initializer to be turned off and providing a mixin would allow people to put the tooltip only on components they want..

If you are open to these suggestions I may spend time implementing them and doing a PR - let me know your thoughts.

Can I use addon with handlebars?

Hi

I try to use addon with ember 1.9.1 ( ember-cli 0.2.7 )
I try both

  "tooltips": {
    "setupInInitializer": true
  },
//and
  "tooltips": {
    "addTo": ["View", "Component"]
  },

do nothing. I even can't find addon's code at developing tools ( and that's strange - cause it means that files are not included ) ( Of course I restart my app on config changes )

Can you help?

Thx

Add Section 508 compliance

We need section 508 compliance for the tooltips (keyboard navigation to focusable elements in the tooltip). This requires support for:

  1. clicks/hover
  2. touchscreen taps
  3. screen reader / keyboard navigation

Proposed solution:

The tooltip itself becomes a property on the ember component as well as an element in the DOM page. So we just need an event listener on focus [or above event] of the original element and then call this.get('tooltip').show() and focus on the tooltip element that was just shown

Tooltip inconsistent inside Bootstrap Modal

Hey There,

Trying to use tooltips inside a Modal however they're not showing up consistently. If I open the modal and then hover over a tooltip, the tooltip isn't getting attached to the target element. However, when I open the inspector and then 'click' on the tooltip it gets activated next to the element. Do you know how I can get this to activate within the modal correctly every time?

      <div class='col-xs-12'>
        <label>Title</label>
          <span id='event_title' class='icon icon-question-mark'>
            {{#tooltip-on-element target='#event_title' side='right' spacing=20}}Enter a short, descriptive event title.{{/tooltip-on-element}}
          </span>
        {{focused-input value=model.title type="text" placeholder="Trip to the Mountains!" required=true}}
      </div>

And a couple images showing the two tooltips getting initialized:
screenshot 2016-05-23 13 57 52
screenshot 2016-05-23 14 01 24

render-tooltip.js::setTooltipVisibility() Method Has Incorrect Logic

The first if statement has backwards logic. Currently it is...

if (tooltip.hidden === shouldShow) { return; }

...when it should be...

if (tooltip.hidden !== shouldShow) { return; }

This is not causing issues because the ember-tooltips mixin is setting hidden to an integer (i.e. 1) in the vendor/tooltip.js file, so the if statement is never true. However, if it were using the updated tooltip JS file from https://github.com/darsain/tooltip (where it is set to true), this logic will break because of the triple equals.

Tooltip for input remains after action

I use ember liquid-fire which allows smooth transitions between routes. I have an action attached to input fields so that when a user presses the enter key within an input field, it takes them to a new route.

Unfortunately, the old tooltip for the input field (that no longer is present) remains on the screen and requires a hard refresh to remove.

If there could be a way to trigger a tooltip clear on transition change, that would solve this issue.

Make ember-tether a peer dependency

At the moment the remove-vendor-css branch breaks on render because ember-tether doesn't get installed. I believe that by making it a peer dependency that npm will warn the user to install it.
I could be wrong, who knows with npm sometimes ;P

Tooltip text doesn't change when tooltipContent changes

I have the following element inside a component:

<a class="btn btn--grade has-tooltip"
    {{action "grade"}}
    data-tooltip-content={{gradeTooltipText}}>
  {{!-- button content... --}}
</a>

The component, on didInsertElement, calls this.renderChildTooltips();, which works great. However, when the data-tooltip-content attribute changes, the content of the tooltip itself doesn't change.

Subsequent calls to this.renderChildTooltips() doesn't re-render the existing tooltip - it just creates another tooltip with the new content, the old one still existing.

Is there a method I can call to destroy and re-render (or update) all tooltips? Or is this just a case that isn't covered yet?

How to prevent tooltips from being created on mobile

Hi there,

I'm just upgrading from version 0.7. Really enjoying what you've done with version 2! Feels so much more ember-y :)

We're using a number of tooltips that show on hover. Previously in v0.7, I was using the mixin and just wouldn't render the tooltips on mobile, but I was just wondering how I could set all of the tooltips not to show on mobile?

Is there something I could do to stop all tooltips from being created in mobile (my app knows when it is mobile) other than wrapping all of the {{#tooltip-on-element}} in {{#if}} blocks?

Maybe by extending the tooltip component?

tooltipContent can't handle safeString

I'm setting tooltipContent from the translation object (ember-i18n) which returns an SafeString object with the string property, which contains the actual message.

As a result from the tooltip I get an error message: Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'. tooltip/index.js:225

Deprecation and fail on Addon => Addon

I have an addon ui-button which I'd really like to use your addon for tooltips rather than Bootstrap's. I have added it to my template like this:

<button type="button" class="ui-button btn btn-{{mood}} {{_size}}">
  {{#if hasBlock}}
    {{yield}}
  {{else}}
    <span class="content">
      {{#if tooltip}}
        {{#tooltip-on-parent}}{{tooltip}}{{/tooltip-on-parent}}
      {{/if}}
      {{#if icon}}
      <span class="icon">
        {{ui-icon icon=icon spin=iconSpin pulse=iconPulse}}
      </span>
      {{/if}}
      {{#if title}}
      <span class="title">
        {{title}}
      </span>
      {{/if}}
    </span>
  {{/if}}
</button> 

However when add a tooltip I suddenly get two DEPRECATIONS (with rubbish debugging info):

2016-02-08_14-52-43

If I take it out of the conditional {{#if}} block then I get 15 deprecations of the same variety. Furthermore my tooltip does not display though I did check and the parent element and it does indeed have the Tooltip object attached and with a config that looks good to me:

2016-02-08_15-25-01

I think I can help with the DEPRECATIONS part, i'll send you a PR which I've already tested and it does indeed remove the deps. WRT, to the lack of a popup, however, I defer to your wisdom. Am I missing something?

No failing test for tooltip persisting on transition

#36 fixed a bug causing tooltips to remain in the DOM after transitions.

We were unable to produce a consistently failing test for the bug before the PR was merged. Instead, we had to rely on manual testing. Whilst some test coverage for transitions was added, the tests passed before and after the PR.

We should have at least one test that fails at 0a8842e and passes at 31ab114.

rename tooltip class to ember-tooltip

We have a massive codebase and are migrating to ember-tooltips for all our tooltip needs. In the past people have created tooltip classes for their one-off tooltip components. This means that a plain inclusion of this library will introduce many style conflicts to existing tooltips, and vice-versa. Right now our options are...

  1. Fork our own PR with a temporary fix (extended the components, additional className for specificity, and add this in the library's styles .ember-tooltip.tooltip). We would need to keep this fork until we've deprecated all of our existing .tooltip class reliant components and instance.
  2. Upgrade this library to use .ember-tooltip classes everywhere instead of .tooltip.

It seems that more specificity in naming conventions is better and that if this library were to use .ember-tooltip there would be less chance of similar roadblocks for large companies hoping to use it.

If this is an acceptable solution I can address it.

@MiguelMadero ^

Expand documentation

Documentation could be expanded to include the renderTooltip util and other such parts that operate under the hood.

Feature request: add to arbitrary element

addon/utils/render-tooltip takes an element as its first argument.

addon/mixins/components/tooltips#renderTooltip always passes this.get('element') as that argument.

I'd like to have a tooltip appear on something like this.$().closest('.tooltip-target') to have it appear on a parent element that isn't itself an Ember.Component that mixes in the TooltipsMixin:

<div class='tooltip-target'>
  {{my-component tooltip-content="Hello"}}
</div>
MyComponent = Ember.Component.extend({
  tooltipTarget: Ember.computed(function() {
    return this.$().closest('.tooltip-target');
  });
});

Namespace for CSS classNames

Just a quick suggestion: CSS classNames like 'right', 'left', 'in', and even 'tooltip' are pretty broad and can easily conflict with an existing codebase. Fwiw, in our case, many of these classNames are already widely used utility classes in our app. It would be great to have a simple namespace prefixed to all of them, so they become 'ember-tooltips-right', 'ember-tooltips-left', etc., or something similar. Thanks for sharing this cool lib.

Canary support

Hello,
The current build fails on canary. As the ember team is working towards the final 2.0.0 release, it would be good if we had support for canary.

Thanks,
Michael

0.x maintenance releases?

Hi! First off, thanks for your work maintaining this addon.

Currently we're stuck on 0.7 until some of the parity loss from the old tooltips plugin (like #82) is regained. Hopefully we'll have a chance to help out with that stuff when time permits, but in the meantime we're having to monkey patch our way around deprecations and incompatibilities in Ember 2.8.

Would you be open to maintaining an 0.x branch for a while for folks stuck in the same boat as us? No new features or anything, just avoiding errors/deprecations as new Ember releases come out. If you're not opposed to the idea, I'd be happy to open up a PR to kick if off.

Tooltip made visible on focus even when event set to "manual"

Hey, was a little perplexed as to why clicking on my target element was causing my tooltip visibility to toggle, given that I had set the visibility of the tooltip to manual.

After a combing through the code (very well written btw, great documentation) I found that ember-tooltips toggles visibility on focus for any event not set to "focus"; a little counter-intuitive, but the comment above made it clear that this was specifically for accessibility.

if (event !== 'focus') {

While I think the intent is clear and fair, the primary use case for "manual" is to have explicit control for when a tooltip needs to be present and I think this undermines the use case.

Might I suggest we change that line to:

if (event !== 'focus' && event !=='manual' && event!=='none') {

Blocker bug - plugin explodes if you already have a tooltip property anywhere in your app or any of your apps components

This plugin adds a destroyTooltip: on('willDestroyElement', function () { method that is in the mixin that gets injected everywhere.

Inside there it says:

var tooltip = this.get('tooltip');

if (tooltip) {
  .... DO SOME CRAY STUFF THAT ONLY MY TOOLTIP RESPONDS TO
}

So, if you have a tooltip property, or worse yet, you are using someone else's add-on who has a tooltip property, your app will come to a screeching halt when you navigate away from that view.

The fix should be that this plugin uses a more specific name for that property that is less likely to conflict AND checks to see if the tooltip it gets back is, in fact, the type of tooltip you are expecting.

v1.0 How to add tooltips to HTML

In 0.6 I used ember-tooltips/utils/render-tooltip for my own custom component. It would parse text and render HTML which was injected through a computed property. I then used your renderTooltip using a jQuery .each().

With 1.0 this concept was completely removed. How can we attach a tool tip to elements that were injected directly into the DOM?

Use case: Server sends text, Ember wishes to decorate the text so I compiles the text into HTML with span tags in it. Component then attaches the tooltip to each span tag after it being rendered into the template with {{{compiledHtml}}}:

export default Ember.Component.extend({
  compiledHtml: Ember.computed('text', function() {
    return myCustomCompiler(this.get('text')).htmlSafe();
  }),
  didInsertElement() {
    this._super();
    this.$('span').each((index, el) => {
      renderTooltip(el, {});
    });
  }
});

Adding a link inside the tooltip

Hi,

I didn't see any demo examples of a clickable link in the content of a tooltip - is this currently possible? I tried adding an anchor tag to the content but it's not clickable, presumably because the focus is not on the tooltip?

Thanks, and great addon!

CHANGELOG.md

Hey, sorry for the drive-by issue opening! Thanks a lot for taking the time to build this addon and put in all the hard work of maintaining it.

I was wondering if you wouldn't mind adding a CHANGELOG.md and document some of the changes? It took me a little time to work through where to find the 2.0.0 release (not in a PR, a separate commit) and the changes associated with it. 2.0.0 is a big bump so some documentation around it would be good.

You can then suggest that new changes to the code base require a corresponding change to the CHANGELOG, and then you can accumulate and reorganize those when you publish releases.

I wish I had time to help more on this issue, so apologies again for making a request for more of your time without helping personally. Feel free to reject this request, but thought it might help!

renderTooltip equivalent in 2.x?

Hi,

We were using 0.5.9 and just upgraded and found that renderTooltip is no longer available. Is there an equivalent in 2.x? We're using the tooltips for event in FullCalendar, so there is no handlebars template for us to work with; we need an the option to use it programmatically.

Thanks for your hard work!

Tooltip is not working with 'ember-infinity'

Tooltip content is not showing on infinite scrolled content.
it's working on first-page content but when infinite scrolling content comes it's not working on it.

View

import Ember from 'ember';
import TooltipsMixin from 'ember-tooltips/mixins/components/tooltips';

export default Ember.Component.extend(TooltipsMixin, {
    didInsertElement: function() {
        this.renderChildTooltips();
    }
});

and tooltip content structure,

<div class="has-tooltip" data-tooltip-content='test'>Test</div>

peerDependencies warning

npm WARN peerDependencies The peer dependency [email protected] included from ember-tooltips will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.

Does this mean we should start depending on the dependency explicitly ourselves?

Tooltip is not working under conditional statements

<div>
{{------This is working well---}}
 <span class="fa fa-check text-green cursor-pointer has-tooltip form-code-validation absolute" data-tooltip-content={{tooltipData}}></span>

{{---This is not working---}}
{{#if isValidCode}}
            <span class="fa fa-check text-green cursor-pointer has-tooltip form-code-validation absolute" data-tooltip-content={{tooltipData}}></span>
          {{else}}
            <span class="fa fa-times text-red cursor-pointer has-tooltip form-code-validation absolute" data-tooltip-content={{tooltipData}}></span>
          {{/if}}
</div>

Tooltip reappears after route transition

If I add a tooltip to a link:

{{link-to "Somewhere" "some.where" tooltipContent="Go Somehwere"}}

then the tooltip shows up when I hover over the link (yay!). When I click the link, the tooltip disappears (yay!). But when I then move the mouse, it reappears (boo!).

I've set a debugger on Tooltip.prototype.show. It turns out that the mouseover event is getting fired on the <a> when it no longer is in the DOM. I think the simple solution is to guard in either Tooltip.prototype.show (an upstream library unfortunately) or in renderTooltip:

var willShow = tooltip.hidden && jQuery.contains(document, tooltip.element);

Visual issues with tooltips

First off, this addon looks very promising and is much easier to use with ember than something like bootstrap tooltips. Secondly...I ran into a bunch of visual issues that I was hoping I could get some help with. I hope it's okay that I list several issues here.

1.) keepInWindow doesn't actually try to keep the tooltip inside the window...or maybe it just doesn't try as hard as the bootstrap tooltip addon?
An example: When I resize the window, the tooltip doesn't get resized to try to fit in.
If you look at the bootstrap example ( http://getbootstrap.com/javascript/#tooltips ) while resizing the page, you'll notice that the tooltip overflows to multiple lines and it does a pretty good job, to a certain extent, to stay inside the window.

2.) ember-tooltips don't get re-rendered between model changes
I've noticed that ember-tooltips always display well after I transition between different routes. However, in the case that I stay on the same route and substitute in different models, the tooltips stop showing up all together.
^ I hope this was descriptive enough. I think what I'm looking for is a functionality to force the ember-tooltips to re-init themselves.

3.) ember-tooltips don't always get displayed under the correct element even when setting a target
Consider the block like
{{#if yelpData.haveReviews}} <a id="yelp-anchor" href="{{yelpData.url}}" target="_blank" rel="noopener noreferrer"> <img src="{{yelpData.rating_img_url_large}}" id="yelp-rating" /> </a> {{#tooltip-on-element class="ember-tooltip" target="#yelp-anchor"}}{{yelpData.rating}} based on {{yelpData.review_count}} reviews{{/tooltip-on-element}} {{/if}}

where the tooltip is attached to #yelp-anchor. When I hover over the element the tooltip correctly comes up, but its position is way off.


Any help debugging this would be appreciated

Tooltip crashes when binding to a property that could return different SafeStrings

In our app, we have a template that is binding to a component property that returns variable string values using Ember i18n. ember-tooltips works correctly with SafeStrings the first time the string is rendered, but if the property updates and returns a different value, the tooltip crashes. The first half of this issue was fixed in #30. I have a PR forthcoming...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.