UNPKG

amazeui

Version:

Sleek, intuitive, and powerful front-end framework for faster and easier web development.

301 lines (248 loc) 7.76 kB
'use strict'; var $ = require('jquery'); var UI = require('./core'); var dimmer = require('./ui.dimmer'); var $doc = $(document); var supportTransition = UI.support.transition; /** * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE */ var Modal = function(element, options) { this.options = $.extend({}, Modal.DEFAULTS, options || {}); this.$element = $(element); this.$dialog = this.$element.find('.am-modal-dialog'); if (!this.$element.attr('id')) { this.$element.attr('id', UI.utils.generateGUID('am-modal')); } this.isPopup = this.$element.hasClass('am-popup'); this.isActions = this.$element.hasClass('am-modal-actions'); this.isPrompt = this.$element.hasClass('am-modal-prompt'); this.isLoading = this.$element.hasClass('am-modal-loading'); this.active = this.transitioning = this.relatedTarget = null; this.dimmer = this.options.dimmer ? dimmer : { open: function() { }, close: function() { } }; this.events(); }; Modal.DEFAULTS = { className: { active: 'am-modal-active', out: 'am-modal-out' }, selector: { modal: '.am-modal', active: '.am-modal-active' }, closeViaDimmer: true, cancelable: true, onConfirm: function() { }, onCancel: function() { }, closeOnCancel: true, closeOnConfirm: true, dimmer: true, height: undefined, width: undefined, duration: 300, // must equal the CSS transition duration transitionEnd: supportTransition && supportTransition.end + '.modal.amui' }; Modal.prototype.toggle = function(relatedTarget) { return this.active ? this.close() : this.open(relatedTarget); }; Modal.prototype.open = function(relatedTarget) { var $element = this.$element; var options = this.options; var isPopup = this.isPopup; var width = options.width; var height = options.height; var style = {}; if (this.active) { return; } if (!this.$element.length) { return; } // callback hook relatedTarget && (this.relatedTarget = relatedTarget); // 判断如果还在动画,就先触发之前的closed事件 if (this.transitioning) { clearTimeout($element.transitionEndTimmer); $element.transitionEndTimmer = null; $element.trigger(options.transitionEnd) .off(options.transitionEnd); } isPopup && this.$element.show(); this.active = true; $element.trigger($.Event('open.modal.amui', {relatedTarget: relatedTarget})); this.dimmer.open($element); $element.show().redraw(); // apply Modal width/height if set if (!isPopup && !this.isActions) { if (width) { style.width = parseInt(width, 10) + 'px'; } if (height) { style.height = parseInt(height, 10) + 'px'; } this.$dialog.css(style); } $element .removeClass(options.className.out) .addClass(options.className.active); this.transitioning = 1; var complete = function() { $element.trigger($.Event('opened.modal.amui', { relatedTarget: relatedTarget })); this.transitioning = 0; // Prompt auto focus if (this.isPrompt) { this.$dialog.find('input').eq(0).focus(); } }; if (!supportTransition) { return complete.call(this); } $element .one(options.transitionEnd, $.proxy(complete, this)) .emulateTransitionEnd(options.duration); }; Modal.prototype.close = function(relatedTarget) { if (!this.active) { return; } var $element = this.$element; var options = this.options; var isPopup = this.isPopup; // 判断如果还在动画,就先触发之前的opened事件 if (this.transitioning) { clearTimeout($element.transitionEndTimmer); $element.transitionEndTimmer = null; $element.trigger(options.transitionEnd).off(options.transitionEnd); this.dimmer.close($element, true); } this.$element.trigger($.Event('close.modal.amui', { relatedTarget: relatedTarget })); this.transitioning = 1; var complete = function() { $element.trigger('closed.modal.amui'); isPopup && $element.removeClass(options.className.out); $element.hide(); this.transitioning = 0; // 不强制关闭 Dimmer,以便多个 Modal 可以共享 Dimmer this.dimmer.close($element, false); this.active = false; }; $element.removeClass(options.className.active) .addClass(options.className.out); if (!supportTransition) { return complete.call(this); } $element.one(options.transitionEnd, $.proxy(complete, this)) .emulateTransitionEnd(options.duration); }; Modal.prototype.events = function() { var _this = this; var options = this.options; var $element = this.$element; var $dimmer = this.dimmer.$element; var $ipt = $element.find('.am-modal-prompt-input'); var $confirm = $element.find('[data-am-modal-confirm]'); var $cancel = $element.find('[data-am-modal-cancel]'); var getData = function() { var data = []; $ipt.each(function() { data.push($(this).val()); }); return (data.length === 0) ? undefined : ((data.length === 1) ? data[0] : data); }; // close via Esc key if (this.options.cancelable) { $element.on('keyup.modal.amui', function(e) { if (_this.active && e.which === 27) { $element.trigger('cancel.modal.amui'); _this.close(); } }); } // Close Modal when dimmer clicked if (this.options.dimmer && this.options.closeViaDimmer && !this.isLoading) { $dimmer.on('click.dimmer.modal.amui', function() { _this.close(); }); } // Close Modal when button clicked $element.on( 'click.close.modal.amui', '[data-am-modal-close], .am-modal-btn', function(e) { e.preventDefault(); var $this = $(this); if ($this.is($confirm)) { options.closeOnConfirm && _this.close(); } else if ($this.is($cancel)) { options.closeOnCancel && _this.close(); } else { _this.close(); } } ) // trigger dimmer click event if non-dialog area clicked // fixes #882 caused by https://github.com/amazeui/amazeui/commit/b6be7719681193f1c4cb04af89cb9fd9f4422163 .on('click', function(e) { // fixes #900 // e.stopPropagation(); $(e.target).is($element) && $dimmer.trigger('click.dimmer.modal.amui'); }); $confirm.on('click.confirm.modal.amui', function() { $element.trigger($.Event('confirm.modal.amui', { trigger: this })); }); $cancel.on('click.cancel.modal.amui', function() { $element.trigger($.Event('cancel.modal.amui', { trigger: this })); }); $element.on('confirm.modal.amui', function(e) { e.data = getData(); _this.options.onConfirm.call(_this, e); }).on('cancel.modal.amui', function(e) { e.data = getData(); _this.options.onCancel.call(_this, e); }); }; function Plugin(option, relatedTarget) { return this.each(function() { var $this = $(this); var data = $this.data('amui.modal'); var options = typeof option == 'object' && option; if (!data) { $this.data('amui.modal', (data = new Modal(this, options))); } if (typeof option == 'string') { data[option] && data[option](relatedTarget); } else { data.toggle(option && option.relatedTarget || undefined); } }); } $.fn.modal = Plugin; // Init $doc.on('click.modal.amui.data-api', '[data-am-modal]', function() { var $this = $(this); var options = UI.utils.parseOptions($this.attr('data-am-modal')); var $target = $(options.target || (this.href && this.href.replace(/.*(?=#[^\s]+$)/, ''))); var option = $target.data('amui.modal') ? 'toggle' : options; Plugin.call($target, option, this); }); module.exports = UI.modal = Modal;