mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
1654a2681f
Summary: This moves all client code to core, and makes minimal fix-ups to get grist and grist-core to compile correctly. The client works in core, but I'm leaving clean-up around the build and bundles to follow-up. Test Plan: existing tests pass; server-dev bundle looks sane Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2627
126 lines
4.5 KiB
JavaScript
126 lines
4.5 KiB
JavaScript
/* global $, document, window */
|
||
|
||
var _ = require('underscore');
|
||
var ko = require('knockout');
|
||
var BackboneEvents = require('backbone').Events;
|
||
var dom = require('../lib/dom');
|
||
var kd = require('../lib/koDom');
|
||
var Base = require('./Base');
|
||
|
||
/**
|
||
* ModalDialog constructor creates a new ModalDialog element. The dialog accepts a bunch of
|
||
* options, and the content can be overridde when calling .show(), so that a single ModalDialog
|
||
* component can be used for different purposes. It triggers a 'close' event (using
|
||
* Backbone.Events) when hidden.
|
||
*
|
||
* The DOM of the dialog is always attached to document.body.
|
||
*
|
||
* @param {Boolean} [options.fade] Include `fade` css class to fade the modal in/out.
|
||
* @param {Boolean} [options.close] Include a close icon in the corner (default true).
|
||
* @param {Boolean} [options.backdrop] Include a modal-backdrop element (default true).
|
||
* @param {Boolean} [options.keyboard] Close the modal on Escape key (default true).
|
||
* @param {Boolean} [options.show] Shows the modal when initialized (default true).
|
||
* @param {CSS String} [options.width] Optional css width to override default.
|
||
* @param {DOM|String} [options.title] The content to place in the title.
|
||
* @param {DOM|String} [options.body] The content to place in the body.
|
||
* @param {DOM|String} [options.footer] The content to place in the footer.
|
||
*/
|
||
function ModalDialog(options) {
|
||
Base.call(this, options);
|
||
options = options || {};
|
||
this.options = _.defaults(options, {
|
||
fade: false, // Controls whether the model pops or fades into view
|
||
close: true, // Determines whether the "x" dismiss icon appears in the modal
|
||
backdrop: true,
|
||
keyboard: true,
|
||
show: false,
|
||
});
|
||
|
||
// If the width option is set, the margins must be set to auto to keep the dialog centered.
|
||
this.style = options.width ?
|
||
`width: ${this.options.width}; margin-left: auto; margin-right: auto;` : '';
|
||
this.title = ko.observable(options.title || null);
|
||
this.body = ko.observable(options.body || null);
|
||
this.footer = ko.observable(options.footer || null);
|
||
|
||
this.modal = this.autoDispose(this._buildDom());
|
||
document.body.appendChild(this.modal);
|
||
$(this.modal).modal(_.pick(this.options, 'backdrop', 'keyboard', 'show'));
|
||
|
||
// On applyState event, close the modal.
|
||
this.onEvent(window, 'applyState', () => this.hide());
|
||
|
||
// If disposed, let the underlying JQuery Modal run its hiding logic, and trigger 'close' event.
|
||
this.autoDisposeCallback(this.hide);
|
||
}
|
||
Base.setBaseFor(ModalDialog);
|
||
_.extend(ModalDialog.prototype, BackboneEvents);
|
||
|
||
/**
|
||
* Shows the ModalDialog. It accepts the same `title`, `body`, and `footer` options as the
|
||
* constructor, which will replace previous content of those sections.
|
||
*/
|
||
ModalDialog.prototype.show = function(options) {
|
||
options = options || {};
|
||
// Allow options to specify new title, body, and footer content.
|
||
['title', 'body', 'footer'].forEach(function(prop) {
|
||
if (options.hasOwnProperty(prop)) {
|
||
this[prop](options[prop]);
|
||
}
|
||
}, this);
|
||
|
||
$(this.modal).modal('show');
|
||
};
|
||
|
||
/**
|
||
* Hides the ModalDialog. This triggers the `close` to be triggered using Backbone.Events.
|
||
*/
|
||
ModalDialog.prototype.hide = function() {
|
||
$(this.modal).modal('hide');
|
||
};
|
||
|
||
/**
|
||
* Internal helper to build the DOM of the dialog.
|
||
*/
|
||
ModalDialog.prototype._buildDom = function() {
|
||
var self = this;
|
||
// The .clipboard_focus class tells Clipboard.js to let this component have focus. Otherwise
|
||
// it's impossible to select text.
|
||
return dom('div.modal.clipboard_focus',
|
||
{ "role": "dialog", "tabIndex": -1 },
|
||
|
||
// Emit a 'close' Backbone.Event whenever the dialog is hidden.
|
||
dom.on('hidden.bs.modal', function() {
|
||
self.trigger('close');
|
||
}),
|
||
|
||
dom('div.modal-dialog', { style: this.style },
|
||
dom('div.modal-content',
|
||
kd.toggleClass('fade', self.options.fade),
|
||
|
||
kd.maybe(this.title, function(title) {
|
||
return dom('div.modal-header',
|
||
kd.maybe(self.options.close, function () {
|
||
return dom('button.close',
|
||
{"data-dismiss": "modal", "aria-label": "Close"},
|
||
dom('span', {"aria-hidden": true}, '×')
|
||
);
|
||
}),
|
||
dom('h4.modal-title', title)
|
||
);
|
||
}),
|
||
|
||
kd.maybe(this.body, function(body) {
|
||
return dom('div.modal-body', body);
|
||
}),
|
||
|
||
kd.maybe(this.footer, function(footer) {
|
||
return dom('div.modal-footer', footer);
|
||
})
|
||
)
|
||
)
|
||
);
|
||
};
|
||
|
||
module.exports = ModalDialog;
|