@Mercury.modal = (url, options = {}) -> Mercury.modal.show(url, options) return Mercury.modal jQuery.extend Mercury.modal, minWidth: 400 show: (@url, @options = {}) -> Mercury.trigger('focus:window') @initialize() if @visible then @update() else @appear() if @options.content setTimeout 500, => @loadContent(@options.content) initialize: -> return if @initialized @build() @bindEvents() @initialized = true build: -> @element = jQuery('
', {class: 'mercury-modal loading'}) @element.html('

×

') @element.append('
') @overlay = jQuery('
', {class: 'mercury-modal-overlay'}) @titleElement = @element.find('.mercury-modal-title') @contentContainerElement = @element.find('.mercury-modal-content-container') @contentElement = @element.find('.mercury-modal-content') @element.appendTo(jQuery(@options.appendTo).get(0) ? 'body') @overlay.appendTo(jQuery(@options.appendTo).get(0) ? 'body') bindEvents: -> Mercury.on 'refresh', => @resize(true) Mercury.on 'resize', => @position() @overlay.on 'click', => @hide() if @options.allowHideUsingOverlay @titleElement.find('a').on 'click', => @hide() @element.on 'ajax:beforeSend', (event, xhr, options) => options.success = (content) => @loadContent(content) jQuery(document).on 'keydown', (event) => @hide() if event.keyCode == 27 && @visible appear: -> @showing = true @position() @overlay.show() @overlay.animate {opacity: 1}, 200, 'easeInOutSine', => @element.css({top: -@element.height()}) @setTitle() @element.show() @element.animate {top: 0}, 200, 'easeInOutSine', => @visible = true @showing = false @load() resize: (keepVisible) -> visibility = if keepVisible then 'visible' else 'hidden' titleHeight = @titleElement.outerHeight() width = @contentElement.outerWidth() @contentPane.css({height: 'auto'}) if @contentPane @contentElement.css({height: 'auto', visibility: visibility, display: 'block'}) height = @contentElement.outerHeight() + titleHeight width = @minWidth if width < @minWidth height = Mercury.displayRect.fullHeight - 20 if height > Mercury.displayRect.fullHeight - 20 || @options.fullHeight @element.stop().animate {left: (Mercury.displayRect.width - width) / 2, width: width, height: height}, 200, 'easeInOutSine', => @contentElement.css({visibility: 'visible', display: 'block'}) if @contentPane.length @contentElement.css({height: height - titleHeight, overflow: 'visible'}) controlHeight = if @contentControl.length then @contentControl.outerHeight() else 0 @contentPane.css({height: height - titleHeight - controlHeight - 40}) @contentPane.find('.mercury-display-pane').css({width: width - 40}) else @contentElement.css({height: height - titleHeight, overflow: 'auto'}) position: -> viewportWidth = Mercury.displayRect.width @contentPane.css({height: 'auto'}) if @contentPane @contentElement.css({height: 'auto'}) @element.css({width: 'auto', height: 'auto', display: 'block', visibility: 'hidden'}) width = @element.width() height = @element.height() width = @minWidth if width < @minWidth height = Mercury.displayRect.fullHeight - 20 if height > Mercury.displayRect.fullHeight - 20 || @options.fullHeight titleHeight = @titleElement.outerHeight() if @contentPane && @contentPane.length @contentElement.css({height: height - titleHeight, overflow: 'visible'}) controlHeight = if @contentControl.length then @contentControl.outerHeight() else 0 @contentPane.css({height: height - titleHeight - controlHeight - 40}) @contentPane.find('.mercury-display-pane').css({width: width - 40}) else @contentElement.css({height: height - titleHeight, overflow: 'auto'}) @element.css { left: (viewportWidth - width) / 2 width: width height: height display: if @visible then 'block' else 'none' visibility: 'visible' } update: -> @reset() @resize() @load() load: -> @setTitle() return unless @url @element.addClass('loading') if Mercury.preloadedViews[@url] setTimeout(10, => @loadContent(Mercury.preloadedViews[@url])) else jQuery.ajax @url, { headers: Mercury.ajaxHeaders() type: @options.loadType || 'GET' data: @options.loadData success: (data) => @loadContent(data) error: => @hide() Mercury.notify("Mercury was unable to load %s for the modal.", @url) } loadContent: (data, options = null) -> @initialize() @options = options || @options @setTitle() @loaded = true @element.removeClass('loading') @contentElement.html(data) @contentElement.css({display: 'none', visibility: 'hidden'}) # for complex modal content, we provide panes and controls @contentPane = @element.find('.mercury-display-pane-container') @contentControl = @element.find('.mercury-display-controls') @options.afterLoad.call(@) if @options.afterLoad if @options.handler if Mercury.modalHandlers[@options.handler] Mercury.modalHandlers[@options.handler].call(@) else if Mercury.lightviewHandlers[@options.handler] Mercury.lightviewHandlers[@options.handler].call(@) @element.localize(Mercury.locale()) if Mercury.config.localization.enabled @resize() setTitle: -> @titleElement.find('span').html(Mercury.I18n(@options.title)) closeButton = @titleElement.find('a') if @options.closeButton == false then closeButton.hide() else closeButton.show() reset: -> @titleElement.find('span').html('') @contentElement.html('') hide: -> return if @showing @options = {} @initialized = false Mercury.trigger('focus:frame') @element.hide() @overlay.hide() @reset() @visible = false