Git Product home page Git Product logo

ember-modal-dialog's Introduction

Ember Modal Dialog Build Status Ember Observer Score

The ember-modal-dialog addon provides components to implement modal dialogs throughout an Ember application using a simple, consistent pattern.

Unlike some other modal libraries for Ember, ember-modal-dialog uses solutions like ember-wormhole to render a modal structure as a top-level DOM element for layout purposes while retaining its logical position in the Ember view hierarchy. This difference introduces a certain elegance and, dare we say, joy, into the experience of using modals in your app. For more info on this, see the "Wormhole" section below.

Table of Contents

Live Demo and Test Examples

View a live demo here: http://yapplabs.github.io/ember-modal-dialog/

Test examples are located in tests/dummy/app/templates/application.hbs and can be run locally by following the instructions in the "Installation" and "Running" sections below.

Video image

Including In An Ember Application

Here is the simplest way to get started with ember-modal-dialog:

ember install ember-modal-dialog

Then import the CSS files

app.css

@import "ember-modal-dialog/ember-modal-structure.css";
@import "ember-modal-dialog/ember-modal-appearance.css";

If you’re using SASS then just import the CSS slightly differently

app.scss

@import "ember-modal-dialog/ember-modal-structure";
@import "ember-modal-dialog/ember-modal-appearance";

application.hbs

{{#modal-dialog}}
  Oh hai there!
{{/modal-dialog}}

Upgrading

Earlier versions of ember-modal-dialog required ember-cli-sass and an app.scss file to import styling.

Please be aware this is no longer the case.

Existing applications should continue to work correctly but if you were using ember-cli-sass solely due to ember-modal-dialog it might be worthwhile removing ember-cli-sass completely and just importing the styles directly into app.css instead, as shown above.

Controller-bound Usage

Here is a more useful example of how to conditionally display a modal based on a user interaction.

Template

<button {{action (action "toggleModal")}}>Toggle Modal</button>

{{#if isShowingModal}}
  {{#modal-dialog
      onClose=(action "toggleModal")
      targetAttachment="center"
      translucentOverlay=true
  }}
    Oh hai there!
  {{/modal-dialog}}
{{/if}}

Controller

import Controller from '@ember/controller';

export default Controller.extend({
  isShowingModal: false,
  actions: {
    toggleModal() {
      this.toggleProperty('isShowingModal');
    }
  }
});

Routable Usage

To have a modal open for a specific route, just drop the {{modal-dialog}} into that route's template. Don't forget to have an {{outlet}} on the parent route.

Configurable Properties

modal-dialog

The modal-dialog component supports the following properties:

Property Purpose
hasOverlay Toggles presence of overlay div in DOM
translucentOverlay Indicates translucence of overlay, toggles presence of translucent CSS selector
onClose The action handler for the dialog's onClose action. This action triggers when the user clicks the modal overlay.
onClickOverlay An action to be called when the overlay is clicked. If this action is specified, clicking the overlay will invoke it instead of onClose.
clickOutsideToClose Indicates whether clicking outside a modal without an overlay should close the modal. Useful if your modal isn't the focus of interaction, and you want hover effects to still work outside the modal.
renderInPlace A boolean, when true renders the modal without wormholing or tethering, useful for including a modal in a style guide
overlayPosition either 'parent' or 'sibling', to control whether the overlay div is rendered as a parent element of the container div or as a sibling to it (default: 'parent')
containerClass CSS class name(s) to append to container divs. Set this from template.
containerClassNames CSS class names to append to container divs. If you subclass this component, you may define this in your subclass.)
overlayClass CSS class name(s) to append to overlay divs. Set this from template.
overlayClassNames CSS class names to append to overlay divs. If you subclass this component, you may define this in your subclass.)
wrapperClass CSS class name(s) to append to wrapper divs. Set this from template.
wrapperClassNames CSS class names to append to wrapper divs. If you subclass this component, you may define this in your subclass.)
animatable A boolean, when true makes modal animatable using liquid-fire (requires liquid-wormhole to be installed, and for tethering situations liquid-tether. Having these optional dependencies installed and not specifying animatable will make animatable=true be the default.)

Tethering

If you specify a tetherTarget, you are opting into "tethering" behavior, and you must have either ember-tether or liquid-tether installed.

Property Purpose
tetherTarget Element selector or element reference for that serves as the reference for modal position

We use the amazing Tether.js library (via ember-tether) to let you position your dialog relative to other elements in the DOM.

* Please see Hubspot Tether for usage documentation.

When in a tethering scenario, you may also pass the following properties, which are passed through to Tether:

Property Purpose
attachment Delegates to Hubspot Tether*
targetAttachment Delegates to Hubspot Tether*
tetherClassPrefix Delegates to Hubspot Tether*
offset Delegates to Hubspot Tether*
targetOffset Delegates to Hubspot Tether*
constraints Delegates to Hubspot Tether*

Animation

This component supports animation when certain addons are present (liquid-wormhole, liquid-tether).

Detection is be automatic. To opt out of using animatable features when you have these liquid-* addons installed, pass animatable=false.

When in an animatable scenario, you may also pass the following properties, which are passed through to liquid-wormhole or liquid-tether:

Property Purpose
stack Delegates to liquid-wormhole/liquid-tether

Optional Dependencies

Dependency Documentation
ember install ember-tether Docs
ember install liquid-wormhole Docs
ember install liquid-tether Docs
ember install liquid-fire Docs

Which Component Should I Use?

Various modal use cases are best supported by different DOM structures. Ember Modal Dialog's modal-dialog component provides the following capabilities:

  • modal-dialog without passing a tetherTarget: Uses ember-wormhole to append the following parent divs to the destination element: wrapper div > overlay div > container div

This can be customized (see overlayPosition).

  • modal-dialog, with a tetherTarget provided: Uses ember-tether to display modal container div. Uses ember-wormhole to append optional overlay div to the destination element. Requires separate installation of ember-tether dependency.

Positioning

With the default CSS provided, your modal will be centered in the viewport. By adjusting the CSS, you can adjust this logic.

Pass a tetherTarget in order to position our modal in relation to the target and enable your modal remain positioned near their targets when users scroll or resize the window.

Use attachment and targetAttachment properties to configure positioning of the modal dialog near its target. Ember Modal Dialog uses the syntax from Hubspot Tether for these properties: "top|middle|bottom left|center|right|elementCenter"... e.g. 'middle left'

To enable this behavior, install ember-tether as a dependency of your ember app.

ember install ember-tether

Then pass a selector as tetherTarget for the modal you wish to position this way:

{{#modal-dialog
    tetherTarget='#target-element-id'
    targetAttachment='middle right'
    attachment='middle left'
}}
  I am a modal that will remain tethered to the right of the element with id 'target-element-id'
{{/modal-dialog}}

Caveats

Event delegation originating from content inside ember-tether blocks will only work for Ember apps that use Ember's default root element of the body tag. This is because, generally speaking, the Hubspot Tether library appends its positioned elements to the body element.

If you are not overriding the default root element, then don't worry and carry on. ember-tether will work just fine for you.

Wormholes

Display of a modal dialog is typically triggered by a user interaction. While the content in the dialog is related to the content in the user interaction, the underlying display mechanism for the dialogs can be shared across the entire application.

The add-modals-container initializer appends a container element to the application.rootElement. It injects a reference to this container element id as a property of the modal-dialog service, which is then used in the modal-dialog component. The property is injected into a service instead of directly into the modal-dialog component to make it easier to extend the component and make custom modals.

ember-modal-dialog uses ember-wormhole to append modal overlays and contents to a dedicated element in the DOM. This decouples the DOM location of a modal from the DOM location of whatever triggered its display... hence wormholes!

Configuring the Modal Root Element Id

This default id of the modal root element is modal-overlays and can be overridden in environment application options as follows:

environment.js

module.exports = function(environment) {
  var ENV = {
    // ...
    APP: {
      // ...
      emberModalDialog: {
        modalRootElementId: 'custom-modal-root-element'
      }
    }
  };
  // ...

  return ENV;
};

Configuring Styles

You can import the CSS files directly

app.css

@import "ember-modal-dialog/ember-modal-structure.css";
@import "ember-modal-dialog/ember-modal-appearance.css";

If you’re using SASS then just import the CSS slightly differently

app.scss

@import "ember-modal-dialog/ember-modal-structure";
@import "ember-modal-dialog/ember-modal-appearance";

Keyboard shortcuts

A quick-and-dirty way to implement keyboard shortcuts (e.g. to dismiss your modals with escape) is to subclass the dialog and attach keyboard events:

// app/components/modal-dialog.js
import ModalDialog from 'ember-modal-dialog/components/modal-dialog';

const ESC_KEY = 27;

export default ModalDialog.extend({
  didInsertElement() {
    this._super(...arguments);
    this._initEscListener();
  },

  willDestroyElement(){
    this._super(...arguments);
    Ember.$('body').off('keyup.modal-dialog');
  },

  _initEscListener() {
    const closeOnEscapeKey = (ev) => {
      if (ev.keyCode === ESC_KEY) { get(this, 'onClose')(); }
    };

    Ember.$('body').on('keyup.modal-dialog', closeOnEscapeKey);
  },
});

This can work, but some apps require a more sophisticated approach. One approach takes advantage of the ember-keyboard library. Here's an example:

// app/components/modal-dialog.js
import { on } from '@ember/object/evented';
import ModalDialog from 'ember-modal-dialog/components/modal-dialog';
import { EKMixin as EmberKeyboardMixin, keyDown } from 'ember-keyboard';

export default ModalDialog.extend(EmberKeyboardMixin, {
  init() {
    this._super(...arguments);

    set(this, 'keyboardActivated', true);
  },

  closeOnEsc: on(keyDown('Escape'), function() {
    get(this, 'onClose')();
  })
});

View the library for more information.

iOS

In order for taps on the overlay to be functional on iOS, a cursor: pointer style is added to the div when on iOS. If you need to change this behavior, subclass modal-dialog and override makeOverlayClickableOnIOS.

Custom Modals

If you have various different styles of modal dialog in your app, it can be useful to subclass the dialog as a new component:

// app/components/full-screen-modal.js

import ModalDialog from 'ember-modal-dialog/components/modal-dialog';

export default ModalDialog.extend({
  containerClassNames: "full-screen-modal",
  targetAttachment: "none"
});

By subclassing modal-dialog your component will use the default modal dialog template. Therefore, you do not need to create a app/templates/components/full-screen-modal.hbs file. Your component can then be used like so:

{{#full-screen-modal}}
  Custom modal contents
{{/full-screen-modal}}

Using as a nested addon

If you create an addon that you want to depend on ember-modal-dialog, you need to provide for ember-modal-dialog's config hook to run. You do this in the config hook of your addon. Example:

// index.js

module.exports = {
  name: 'my-addon',
  config(environment, appConfig) {
    let initialConfig = _.merge({}, appConfig);
    let updatedConfig = this.addons.reduce((config, addon) => {
      if (addon.config) {
        _.merge(config, addon.config(environment, config));
      }
      return config;
    }, initialConfig);
    return updatedConfig;
  }
};

Dependencies

  • For Ember versions >= 3.20, use the latest published version
  • For Ember versions >= 2.8 and < 3.20, use the latest 3.x version (Note that ember-cli >= 2.13 is required, though your ember version may be >= 2.8)
  • For Ember versions >= 2.4 and < 2.8, use the latest 2.x version
  • For Ember versions >= 1.10 and < 2.4, use ember-modal-dialog 1.0.0 (Due to a bug in these versions of Ember, you may have trouble with Ember 1.13.7, 1.13.8 and 1.13.9 -- See #71)

Additional Resources

Contributing

See the Contributing guide for details.

Credits

Contributions from @stefanpenner, @krisselden, @chrislopresto, @lukemelia, @raycohen, @andrewhavens, @samselikoff and others. Yapp Labs was an Ember.js consultancy based in NYC, that has since been folded into Yapp.

ember-modal-dialog's People

Contributors

andrewhavens avatar balinterdi avatar benkiefer avatar bjornharrtell avatar blimmer avatar buschtoens avatar chrislopresto avatar chrism avatar christophermlne avatar cyril-sf avatar dan-ste avatar dependabot[bot] avatar dhaulagiri avatar ef4 avatar hakilebara avatar hmcq6 avatar lukemelia avatar mattmcmanus avatar mcfiredrill avatar mdentremont avatar mike-north avatar mum-never-proud avatar olivia avatar oscarni avatar ratierd avatar raycohen avatar robbiethewagner avatar rwjblue avatar samselikoff avatar turbo87 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  avatar  avatar  avatar  avatar  avatar

ember-modal-dialog's Issues

About integration tests

Hey there!

I found a dead link in the README file, section Unit Tests: "See this example for how to set this up in a unit test."

I found the deleted file by browsing older versions of this repo, but I was wondering whether there is a new (simpler?) way of writing an integration test for a component that subclasses (or contains) a modal-dialog.

My current issue concerns the destinationElementId. Since I am only rendering the component I'm testing, the destination element does not exist. Changing the value of modalRootElementId in environment.js does not seem to work either.

The deleted test suggested to appendChild on #ember-testing. Is it still the right thing to do?

Thanks!

click in acceptance tests stopped working for tether-dialog

Earlier with version 0.7.7, in testing, having { tethered: false } in modal options that is passed to https://github.com/yapplabs/ember-modal-dialog/blob/master/tests/helpers/modal-asserts.js#L24 did work fine with click inside an opened modal.

example

let modalSelector = '#testModal';
test('example test', function(assert) {
  visit('/');

  andThen(function() {
    modalOptions.whileOpen = function() {
      click(`${modalSelector}`);
      andThen(function() {
        assert.equal(Ember.$('.check-element').length, 1, 'has the element');
      });
    };

    assert.dialogOpensAndCloses(modalOptions);
  });
});

But with the newest version: 0.8.2
This would return an Element not found error saying that it can't find the element (which is #testModal here)

This is a very critical issue we're facing in testing since we are following the TDD approach.

Deprecation warning on Ember CLI master

Using Ember CLI 1.13.8-master-ae5e72614e, I get the following deprecation warning:

[Deprecated] new this.Funnel(..) is deprecated, please use broccoli-funnel directly instead [addon: ember-modal-dialog]

Pass-thru tether args

Currently it looks like there's a number of tether args such as contraints which are not exposed to the embedded ember-tether component. It would be useful to enable passing-thru these args.

Acceptance testing the tether-dialog when input is in the block?

I have a simple tether-dialog that inside the block contains an input bound to a model like you'd expect

    {{#if toggleFilter}}
      {{#tether-dialog}}
        {{input-dynamic-filter obj=filterModel prop=filterField}}
      {{/tether-dialog}}
    {{/if}}

The input is dynamic ... in that I can pass it a model but switch the bound prop on the fly (something that works great btw -awesome work ember). This helps me "share" a single tether dialog across the UI as you could imagine.

export default Ember.TextField.extend({
  value: Ember.computed('obj', {
    get(key){
      var prop = this.get('prop');
      return this.get('obj.' + prop);
    },
    set(key, value){
      var prop = this.get('prop');
      this.set('obj.' + prop, value);
      return this.get('obj.' + prop, value);
    }
  })
});

In the browser all is good - when I flip between properties this input just shows the "now bound" value and away I go. In acceptance testing however the event above (my setter) never fires when I type into it. I did notice the init will fire for this TextField (in a test) but beyond that I assume it may be destoryed/or removed for some reason.

I'm curious if this has an obvious "oh yeah don't do that because..." or if this is all new/crazy :)

I'm starting to source dive/debug through the tether/modal source while I acceptance test to see if and when this gets removed /destoryed/ who knows what.

Any tips on where to look as I run it down? Thanks again for such a great OSS project! If I get to the root cause I'll report back for others who might run up against this issue like I did

edit

the input is present during the test /when I pause I can see it, query for it, update it's val property no problem ... it's the event (setter) that must be disconnected at some point (my pain point today).

Alignment 'none' issue in positioned container

After an upgrade I'm getting an error inside of positioned container: https://github.com/yapplabs/ember-modal-dialog/blob/v0.7.7/addon/components/positioned-container.js#L56

I'm using the renderInPlace: true option when testing which sets alignment to the string 'none'. However there is no alignNone method for positioned-container.

My current workaround is this:

import EmberModalDialogPositionedContainerComponent from 'ember-modal-dialog/components/positioned-container';
import Ember from 'ember';
const { computed } = Ember;

export default EmberModalDialogPositionedContainerComponent.extend({
  isPositioned: computed('alignment', 'alignmentTarget', function() {
    if (this.get('alignment') === 'none') {
      return false;
    }

    return this._super(...arguments);
  }),
});

I must say it is so great to be able to override these components, so thanks for that!

Make composable with liquid-fire

liquid-fire has its own modals API, but I'd like to take that out in favor of something like this addon, since "how to do modals" is really a separate concern from animation. Instead, it would be great if people could just use the liquid-fire animation helpers with ember-modal-dialog if they want to make their modals animate in & out.

Conceptually, to make this happen we would need to expose both

  • the active modal state
  • and the ability to render it into DOM

into user's templates. For example, the default implementation of the top-level container could look like this in application.hbs:

{{#with-active-modal as |modal|}}
  {{show-modal modal}}
{{/with-active-modal}}

(with-active-modal and show-modal would be components that are part of ember-modal-dialog. Better name suggestions welcome.)

Inserting the above snippet under the application root can still be done automatically for users who don't care about customizing. But users who do care can override by doing it themselves like this:

{{#with-active-modal as |modal|}}
  {{#liquid-with modal as |modalVersion|}}
    {{show-modal modalVersion}}
  {{/liquid-with}}
{{/with-active-modal}}

(The above can actually get packaged up as a {{liquid-modal-target}} component in liquid-fire, so users aren't typing it. But the point is that with-active-modal and show-modal would become an extensible API offered by ember-modal-dialog.)

liquid-with controls versioning of the modal as it changes, and lets the liquid-fire transition rules govern how it will animate. Two common examples would be:

  • when a modal is dismissed, the modal variable goes to undefined. But if liquid-with finds a matching animation rule, it will still render with the old modalVersion until that modal has a chance to animate away.
  • if you switch directly from modal A to modal B, liquid-with can actually render its block twice, so that both modals can be on screen simultaneously, displaying a graceful transition between them.

If people like this idea I can work on it.

Deprecation warning with Ember CLI 1.13.12

When loading an app with the latest version of ember-modal-dialog Ember CLI gives the warning:

[Deprecated] new this.Funnel(..) is deprecated, please use broccoli-funnel directly instead [addon: ember-modal-dialog].

Modal inside a modal doesn't close on clickOutsideToClose

Our app uses tether-dialog and we need to have the functionality to open dialogs inside dialogs (e.g: Trello). But when tether-dialog is used it doesn't close with outside click even having the following property set:

{{#tether-dialog
  attachment='top left'
  clickOutsideToClose=true
  close=toggleModal
  containerClassNames=containerClassNames
  hasOverlay=false
  target=toggleButton
  targetAttachment='top right'}}
  <div>content</div>
{{/tether-dialog}}

Thanks.

Opening modal fails in Ember 1.13.7+

I was using ember-modal-dialog 0.7.7 and ember 1.13.6 and all was well. I just updated to Ember 1.13.8 and when I try to open a popover I get a Uncaught TypeError: this.get(...).join is not a function error from the modal-dialog component.

I created a fresh project to test and can confirm that I see this error when using Ember 1.13.7 and 1.13.8.

image

image

How to pass along close action from inner component?

If I've got an inner component that wants to sendAction('close') at some point how can I modify the modal to fire the actual "close" event set on the modal itself (using a sub class driven approach for now)?

Right now I have something like this but the event is never picked up by my parent

export default Ember.TextField.extend({
    keyDown: function (event) {
        Ember.run.later(() => {
            this.send('close');
        }, 100);
    },
    actions: {
        close: function() {
            //I do see this but after the sendAction below nothing happens :(
            this.sendAction('close');
        }
    }
});

update

my hbs looks like this and the close action does work as-is (just not using sendAction as shown above from inner component)

    {{#tether-dialog close='toggleTheModal' clickOutsideToClose=true}}
      {{my-text-input placeholder=filterPlaceholder}}
    {{/tether-dialog}}

Acceptance tests with ember-tether

I would like to clarify what the best practices are around acceptance tests with ember-tether.

When I write a basic ember-modal-dialog acceptance test that launches a modal, makes an assertion and closes it works fine and as expected. When I switch over to using ember-tether the same test fails because it can't find the content inside the modal. Is there a recommended way support ember-tether based modals in acceptance tests?

I tried switching the modalRootElementId in the test environment but that does not seem to work.

Container class name bindings

Would be great to be able to bind props to the container-class names:

{{#ted-modal small=true}}
  ...
{{/ted-modal}}
// components/ted-modal/component.js
import ModalDialog from 'ember-modal-dialog/components/modal-dialog';
import Ember from 'ember';

export default ModalDialog.extend({

  overlayClassNames: ['Ted-modal-overlay'],
  containerClassNames: ['Ted-modal'],
  containerClassNameBindings: ['small:Ted-modal--small'],
  translucentOverlay: true,

});

This is not possible today, correct?

ember-modal-dialog doesn't work with IE8

Thanks for making this library. It's been working well for me during my development but it's not working on Win 7 / IE8 which is unfortunately a requirement for the project I'm currently working on.

When I try to load the demo page with IE8, I get a blank page with this error message in the console:

Object doesn't support this property or method

The error directs me to this line of the compiled app:

Ember.keys(requirejs._eak_seen).map(function(e){return{moduleName:e,matches:r.exec(e)}}).filter( <snip>

When I try to load my application that uses ember-modal-dialog (in dev mode) with IE8, I get a blank app with these console messages:

DEPRECATION: Ember.keys is deprecated in favor of Object.keys
Expected identifier
DEPRECATION: Ember.keys is deprecated in favor of Object.keys
Expected identifier

The Expected identifier error directs me to the exports.default = line of this block:

define('content-app/components/ember-wormhole', ['exports', 'ember-wormhole/components/ember-wormhole'], function (exports, ember_wormhole) {
    'use strict';
    exports.default = ember_wormhole.default;
});

I'm using these versions of Ember and related libraries in my application:

DEBUG: Ember      : 1.13.3
DEBUG: Ember Data : 1.13.5
DEBUG: jQuery     : 1.11.3

I'm curious to know if supporting IE8 is something that you are interested in doing (if it's even possible). Obviously this would only be for a version that's compatible with Ember 1.13 as IE8 will go away in Ember 2.0. For me it's ok if the solution is that I need to add a polyfill for some functionality that's missing in IE8. If this is the way to go, could you point me in the right direction for which polyfills I'd need to use? Thanks.

modal-dialog template disjunction in >0.7.3 breaks dependency setup

Uncaught Error: Could not find module `ember-modal-dialog/templates/components/modal-dialog` imported from `ember-modal-dialog/components/modal-dialog`

Obviously the problem is we now have two separate subdirs to get an Ember version-specific template from, and the workaround is to move/copy the appropriate .hbs file to parent directory. However, from the install-dependencies-and-run standpoint, this breaks the build.

Add Proper ARIA Roles

This addon should really use the role="alertdialog" assertive role for screen readers.

All we have to do is add corresponding attributeBindings and role: 'alertdialog' on the component.

Also, as the document specifies, we should also add:

  • aria-labelledby
  • aria-describedby

As top-level attributes on the modal.

Finally, I might advise adding a role="button" for non-button close elements... but I digress that that might be something left up to the user.

Routable modal without losing existing routes template

Great addon guys, thanks for sharing.

I was wondering if there is anyway to have a routable modal which pops up over the currently existing routes template.

Say if i'm at /user and I click a link or action which requires me to be logged in, I automatically redirect to /login and the login modal dialog pops up, but I want the template for the previous route to be still present underneath the modal. Right now it just gets wiped out and the modal is shown over a blank page, which kind of defeats the point of having the content in a modal to some degree?!

Template Deprecations (due to `bind-attr` and `classNameBindings`) with 1.13+.

The addon/templates/components/modal-dialog.hbs is triggering the following deprecations on Canary builds:

DEPRECATION: The `bind-attr` helper ('modules/ember-modal-dialog/templates/components/modal-dialog.hbs' @ L3:C11) is deprecated in favor of HTMLBars-style bound attributes.
        at isBindAttrModifier (/Users/rwjblue/src/work/cardstack/takeoff/bower_components/ember/ember-template-compiler.js:9692:24)
        at /Users/rwjblue/src/work/cardstack/takeoff/bower_components/ember/ember-template-compiler.js:9568:15
        at Walker.visit (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15489:7)
        at visitors.Program (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15499:16)
        at Walker.children (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15522:7)
        at Walker.visit (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15490:12)
        at visitors.BlockStatement (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15510:14)
        at Walker.children (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15522:7)
        at Walker.visit (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15490:12)
DEPRECATION: You're using legacy class binding syntax: classBinding="containerClassNamesString alignmentClass renderInPlaceClass container-class" @ 5:45 in (inline). Please replace with class=""
        at /Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:10241:26
        at each (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:10308:7)
        at /Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:10226:7
        at Walker.visit (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15489:7)
        at visitors.Program (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15499:16)
        at Walker.children (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15522:7)
        at Walker.visit (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15490:12)
        at visitors.BlockStatement (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15510:14)
        at Walker.children (/Users/rwjblue/src/work/foo-bar/bower_components/ember/ember-template-compiler.js:15522:7)

scrolling behavior for large modals

I'm having a hard time getting the styling just the way I want it for large modals. Essentially I want want Trello has:

modal-scroll

Scrollbar on right, modal scrolls up and down.

I used flexbox to style the modal and overlay, but the problem is on scroll. Since the overlay is a sibling of the modal, calculating its height is the problem. If it's just fullscreen (something like 100vh), when your mouse cursor is over the overlay, the modal won't scroll:

modal-scroll-1

This is because the overlay is 100% height so, there's no overflow to scroll. Without using JavaScript I don't see a way to get its height to adjust - and even when I set it manually, I saw some strange visual quirks.

I'm wondering if it'd be possible to opt-out of the .ember-modal-overlay element, and to have the click event fire close from the #modal-overlays element? Or possibly even drop the .ember-modal-overlay altogether, and #modal-overlays would essentially also act as the overlay. That way it would wrap the content, making styling with flexbox (and other strategies) easier. Thoughts?

close on 'escape'

What's the suggested way to add close-on-escape functionality? I tried using keyPress

import ModalDialog from 'ember-modal-dialog/components/modal-dialog';

export default ModalDialog.extend({

  keyPress() {
    console.log('pressed!');
  }
});

but it didn't work. Here's what I have now:

import ModalDialog from 'ember-modal-dialog/components/modal-dialog';

export default ModalDialog.extend({

  setup: function() {
    Ember.$('body').on('keyup', (e) => {
      if (e.keyCode == 27) {
        this.sendAction('close');
      }
    });
  }.on('didInsertElement'),

  teardown: function() {
    Ember.$('body').off('keyup');
  }.on('willDestroyElement'),

});

Simple install doesn't work

ember new testModal
cd testModal
ember install ember-modal-dialog
ember install ember-cli-sass
ember serve

results in the error shown below

File not found: /app/styles/app.scss
in any of the following include paths:
/home/pm/Projects/ember/testModal/tmp/sass_compiler-input_base_path-g9lZr7BL.tmp/0
Error: File not found: /app/styles/app.scss
in any of the following include paths:

Modal positioning fails after browser resizing

I have a modal with the following positioning (using Ember Tether):

alignmentTarget='body'
attachment='top right'
targetAttachment='top right'

This renders the modal, as expected, in the top right corner of the screen. However, as soon as I resize the browser, the modal jumps to the top left of the screen and stays there.

Thoughts?

Extending breaks wormhole to modal-overlays on 2.1.x and 2.2.x

Doing a simple extend of modal-dialog as shown below, does not wormhole to the correct #modal-overlays in Ember 2.1.x and 2.2.x but is fine on 1.13.x and 2.0.x.

import ModalDialog from 'ember-modal-dialog/components/modal-dialog';

export default ModalDialog.extend({});

Custom modals don't have destinationElementId injected

In our app we have some modals which are "full screen" and have some custom behaviour/settings (no overlay, different CSS etc…).

To accomplish this I made a new component which extends from ModalDialogComponent add adds in the custom behaviour so in my templates I can now do:

<full-screen-modal>
    modal contents here
</full-screen-modal>

This breaks because the wormhole's destination element ID is only injected into the 'modal-dialog' component.

This is easily worked around by adding another injection:

export default {
  after: 'add-modals-container',
  name: 'custom-modals',
  initialize(_, application) {
    application.inject('component:full-screen-modal',
                       'destinationElementId',
                       'config:modals-container-id');
  }
};

However, ideally we wouldn't have to do this.

Loading styles results in build error

When I follow the documentation and do @import "ember-modal-dialog/ember-modal-sturcture"; I get the following build error:
file to import not found or unreadable: ember-modal-dialog/ember-modal-structure

Loading the CSS files with relative paths was working until I tried to add the ember-tether gem which obviously isn't ideal.

@import "../../node_modules/ember-modal-dialog/app/styles/ember-modal-dialog/ember-modal-structure";

Any recommendations would be appreciated.

basic modal test modal container incorrect

I'm working on a PR, but the modals aren't going where I expect. I'm looking at the basic modal test with tether. Here is what the DOM looks like after the open click and before the close click.
capture
The test has destinationElementId: 'modal-overlays' in the setup, but I don't understand why it didn't attach there.

Hide on click out with hasOverlay=false

The use case is a modal that is off to the side, not inhibiting your use of the page. You can still get hover effects and link cursor changes, but your first click hides the modal. I have accomplished this with:

const teamMembersClickEvent = 'click.team-members';
//...
  didInsertElement() {
    this.set('clickOutElement', Ember.$('#modal-overlays + .ember-view'));
  },

  toggleTeamMembers() {
    var clickOutElement = this.get('clickOutElement');
    if (this.toggleProperty('shouldShowTeam')) {
      clickOutElement.on(teamMembersClickEvent, () => this.send('toggleTeamMembers'));
    } else {
      clickOutElement.off(teamMembersClickEvent);
    }
  },

  actions: {
    toggleTeamMembers() {
      // debounce because click event and action can both trigger at once
      Ember.run.debounce(this, this.toggleTeamMembers, 0);
    }
  }

Is this something you would want to add, or leave it up to the consumer?

Modal is measured pre-wormhole?

I was having some issues with modals gettting the wrong padding, and not being centered correctly.
So I put a breakpoint in positioned-container.js#alignCenter. I noticed that at this point, when dimension measurements are being made, the element is located in the DOM where the {{#modal-dialog}} component is used (i.e. it has not yet been pulled out into the modal container).

In our case we had a stray rule on divs. But basically, it's being measured in one place in the document, then those measurements are assumed to be accurate when it's placed in a different location in the document.

Is there a technical reason why this is?

crossdomain.xml and robots.txt

This plugin seems to spawn crossdomain.xml and robots.txt in a folder named ember-modal-dialog, inside dist.

Is it possible to have them removed? [not spawned]

How to test in a component unit test

I'm using modal-dialog in a component test and it's currently bombing on

Cannot read property 'appendChild' of null
at DOMHelper.prototype.appendMorph (http://localhost:4200/assets/vendor.js:13401:14)
at render (http://localhost:4200/assets/vendor.js:118128:32)
at superWrapper as render
at EmberRenderer_createElement as createElement
at EmberRenderer.Renderer_renderTree as renderTree
at http://localhost:4200/assets/vendor.js:51886:24
at Queue.invoke (http://localhost:4200/assets/vendor.js:11420:18)
at Object.Queue.flush (http://localhost:4200/assets/vendor.js:11485:13)
at Object.DeferredActionQueues.flush (http://localhost:4200/assets/vendor.js:11290:19)
at Object.Backburner.end (http://localhost:4200/assets/vendor.js:10715:27)

I'm wondering if it's because the wormhole target doesn't exist in a unit test. Any thoughts on how one may go about working around this issue?

alignment properties don't seem to make a difference

The code below always positions the modal in the middle/center of the screen. I'm using v0.8.2

{{#modal-dialog
    target='body'
    attachment='top center'
    targetAttachment='top center'}}
  {{yield}}
{{/modal-dialog}}

allow click outside to close with overlay

Would be nice have the clickOutsideToClose option available when there's an overlay. i.e. when true and translucentOverlay is also true, clicking on the overlay would close the modal.

Sass mandatory?

is sass mandatory for the use of this library?. If not, i think the README is not clear.
If yes, the README should be more clear.
TY.

Doesn't work with custom fonts

If you update the fonts, it calculates the size incorrectly, thus making the positioning off. Probably need to wrap in some sort of font loader.

Enter KeyboardEvent

Pressing the enter key causes the close action to send. What is the suggested way to send an alternate action for this keyboard event?

Doesn't respect deferReadiness, advanceReadiness

My ember application in initialized in certain pages only so I use deferReadiness to halt ember app if required. ember-modal-dialog throws up a error when no ember root-element is found

   // The initializer I use to check for ember root-element
   var Initializer = {

     name: 'check-root-element',

     initialize: function(container, app) {
       app.deferReadiness();
       jQuery(function() {
         if ( jQuery( "#admin-ember-app" ).length ) {
           app.advanceReadiness();
         }
       });
     }

   };

   export default Initializer;

Here's the error from console

Uncaught TypeError: Cannot read property 'appendChild' of null
appendContainerElement @ add-modals-container.js:17
exports.default @ add-modals-container.js:33

Any idea how I can solve this?

Deprecated in ember-cli 0.2.6

I just installed ember-cli 0.2.6 and it threw me a deprecated waring:

[Deprecated] this.pickFiles is deprecated, please use broccoli-funnel directly instead  [addon: ember-modal-dialog]

Feature Request? Trigger Modal Resize

Obsessed w/ this add-on and am interested if you have any suggestions on how to handle a common scenario we have where the modal content changes as you interact w/ it and we want to reposition the dialogue, either automatically (ideally) or somehow trigger it.

And suggestions on how to pull this off? I'm happy to put out a pull if you think it's reasonable!

Dealing with Dynamic Height

How would you go about keeping a modal centered when its height is determined by content that is loaded after rendering? Is there any way to do that?

Addon doesn't work with ember-cli < 0.2.6

Ember-cli 0.2.6 introduced new addon hook treeForAddonTemplates which is used in index.js, I think this hook is not getting executed in previous versions. So addon fails with the error:

Error: Could not find module `ember-modal-dialog/templates/components/modal-dialog` imported from `ingenio-web/templates/components/modal-dialog`
    at requireFrom (loader.js:110)
    at reify (loader.js:97)
    at mod.state (loader.js:140)
    at tryFinally (loader.js:21)
    at requireModule (loader.js:139)
    at Ember.DefaultResolver.extend._extractDefaultExport (ember-resolver.js:367)
    at resolveOther (ember-resolver.js:109)
    at superWrapper [as resolveTemplate] (ember.debug.js:17428)
    at exports.default.EmberObject.default.extend.resolve (ember.debug.js:4594)
    at Object.resolve [as resolver] (ember.debug.js:4437)

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.