Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
ember-modal-dialog
Advanced tools
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.
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.
Here is the simplest way to get started with ember-modal-dialog:
ember install ember-modal-dialog
ember install ember-cli-sass
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}}
Here is a more useful example of how to conditionally display a modal based on a user interaction.
Template
<button {{action "toggleModal"}}>Toggle Modal</button>
{{#if isShowingModal}}
{{#modal-dialog onClose="toggleModal"
targetAttachment="center"
translucentOverlay=true}}
Oh hai there!
{{/modal-dialog}}
{{/if}}
Controller
import Ember from 'ember';
export default Ember.Controller.extend({
isShowingModal: false,
actions: {
toggleModal: function() {
this.toggleProperty('isShowingModal');
}
}
});
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.
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. This is a concatenated property, so it does not replace the default container class (default: 'ember-modal-dialog' . 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. This is a concatenated property, so it does not replace the default overlay class (default: 'ember-modal-overlay' . 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. This is a concatenated property, so it does not replace the default container class (default: 'ember-modal-wrapper' . 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 explicitly specifying animatable is deprecated in 2.x and is equivalent to animatable=false for backwards compatibility. As of 3.x, the implicit default will be animatable=true when the optional liquid-wormhole /liquid-tether dependency is present. |
The above properties of the modal-dialog
component can be used without any additional dependencies.
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* |
This component supports animation when certain addons are present (liquid-wormhole, liquid-tether).
Current 2.x behavior: Having these optional dependencies installed and NOT explicitly specifying animatable
is deprecated in 2.x and is equivalent to animatable=false
for backwards compatibility. To get animation, pass animatable=true
and install liquid-wormhole
for non-tethering usage and liquid-tether
for tethering usage.
Upcoming 3.x behavior: Detection will be automatic. To opt out of using animatable features when you have these liquid-*
addons installed, pass animatable=false
.
ember install ember-tether
Docs
ember install liquid-wormhole
Docs
ember install liquid-tether
Docs
ember install liquid-fire
Docs
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.
With the default SCSS 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}}
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.
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!
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;
};
The addon packages default styles for modal structure and appearance. To use these styles, install ember-cli-sass and import the relevant SCSS file(s) in app.scss
.
> ember install ember-cli-sass
app.scss
@import "ember-modal-dialog/ember-modal-structure";
@import "ember-modal-dialog/ember-modal-appearance";
If you would prefer not to use Sass, just grab the contents of these files and adapt them for your needs -- there is not much there.
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';
export default ModalDialog.extend({
setup: function() {
Ember.$('body').on('keyup.modal-dialog', (e) => {
if (e.keyCode === 27) {
this.sendAction('close');
}
});
}.on('didInsertElement'),
teardown: function() {
Ember.$('body').off('keyup.modal-dialog');
}.on('willDestroyElement')
});
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 Ember from 'ember';
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);
this.set('keyboardActivated', true);
}
closeOnEsc: Ember.on(keyDown('Escape'), function() {
this.sendAction('close');
})
});
View the library for more information.
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
.
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"
});
This can then be used like so:
{{#full-screen-modal}}
Custom modal contents
{{/full-screen-modal}}
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: function(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;
}
};
ember install ember-modal-dialog
ember server
ember try:each
ember test
ember test --server
When running unit tests on components that use ember-modal-dialog, modals will be
attached to the #ember-testing
div.
ember build
For more information on using ember-cli, visit http://www.ember-cli.com/.
This project uses https://github.com/skywinder/github-changelog-generator to generate its changelog.
github_changelog_generator --future-release=x.y.z
Contributions from @stefanpenner, @krisselden, @chrislopresto, @lukemelia, @raycohen, @andrewhavens, @samselikoff and others. Yapp Labs is an Ember.js consultancy based in NYC.
v2.2.0 (2017-05-15)
Merged pull requests:
overlayPosition
property which supports values of 'parent'
or 'sibling'
#192 (lukemelia)hasOverlay=false
to suppress output of the overlay div. #191 (lukemelia)FAQs
An ember-cli addon for implementing modal dialogs
The npm package ember-modal-dialog receives a total of 15,988 weekly downloads. As such, ember-modal-dialog popularity was classified as popular.
We found that ember-modal-dialog demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.