lib/assets/javascripts/up/modal.js.coffee in upjs-rails-0.17.0 vs lib/assets/javascripts/up/modal.js.coffee in upjs-rails-0.18.0

- old
+ new

@@ -134,53 +134,48 @@ @function up.modal.coveredUrl @return {String} @experimental ### coveredUrl = -> - $modal = $('.up-modal') - $modal.attr('up-covered-url') + $('.up-modal').attr('up-covered-url') reset = -> - close() + close(animation: false) currentUrl = undefined config.reset() templateHtml = -> template = config.template if u.isFunction(template) template(config) else template - rememberHistory = -> - $modal = $('.up-modal') - $modal.attr('up-covered-url', up.browser.url()) - $modal.attr('up-covered-title', document.title) - discardHistory = -> $modal = $('.up-modal') $modal.removeAttr('up-covered-url') $modal.removeAttr('up-covered-title') - createHiddenModal = (options) -> + createFrame = (target, options) -> + shiftElements() $modal = $(templateHtml()) $modal.attr('up-sticky', '') if options.sticky $modal.attr('up-covered-url', up.browser.url()) $modal.attr('up-covered-title', document.title) $dialog = $modal.find('.up-modal-dialog') $dialog.css('width', options.width) if u.isPresent(options.width) $dialog.css('max-width', options.maxWidth) if u.isPresent(options.maxWidth) $dialog.css('height', options.height) if u.isPresent(options.height) $content = $modal.find('.up-modal-content') - $placeholder = u.$createElementFromSelector(options.selector) + # Create an empty element that will match the + # selector that is being replaced. + $placeholder = u.$createElementFromSelector(target) $placeholder.appendTo($content) $modal.appendTo(document.body) - rememberHistory() - $modal.hide() $modal - unshiftElements = [] + unshifters = [] # Gives `<body>` a right padding in the width of a scrollbar. # Also gives elements anchored to the right side of the screen # an increased `right`. # @@ -193,27 +188,32 @@ bodyRightShift = scrollbarWidth + bodyRightPadding unshiftBody = u.temporaryCss($('body'), 'padding-right': "#{bodyRightShift}px", 'overflow-y': 'hidden' ) - unshiftElements.push(unshiftBody) + unshifters.push(unshiftBody) up.layout.anchoredRight().each -> $element = $(this) elementRight = parseInt($element.css('right')) elementRightShift = scrollbarWidth + elementRight - unshiftElement = u.temporaryCss($element, 'right': elementRightShift) - unshiftElements.push(unshiftElement) + unshifter = u.temporaryCss($element, 'right': elementRightShift) + unshifters.push(unshifter) - updated = (animation, animateOptions) -> - $modal = $('.up-modal') - if $modal.is(':hidden') - shiftElements() - $modal.show() - deferred = up.animate($modal, animation, animateOptions) - deferred.then -> up.emit('up:modal:opened') + # Reverts the effects of `shiftElements`. + unshiftElements = -> + unshifter() while unshifter = unshifters.pop() ###* + Returns whether a modal is currently open. + + @function up.modal.isOpen + @stable + ### + isOpen = -> + $('.up-modal').length > 0 + + ###* Opens the given link's destination in a modal overlay: var $link = $('...'); up.modal.follow($link); @@ -233,10 +233,13 @@ The width of the dialog in pixels. By [default](/up.modal.config) the dialog will grow to fit its contents. @param {Boolean} [options.sticky=false] If set to `true`, the modal remains open even if the page changes in the background. + @param {String} [options.confirm] + A message that will be displayed in a cancelable confirmation dialog + before the modal is being opened. @param {Object} [options.history=true] Whether to add a browser history entry for the modal's source URL. @param {String} [options.animation] The animation to use when opening the modal. @param {Number} [options.duration] @@ -244,11 +247,12 @@ @param {Number} [options.delay] The delay before the animation starts. See [`up.animate`](/up.animate). @param {String} [options.easing] The timing function that controls the animation's acceleration. [`up.animate`](/up.animate). @return {Promise} - A promise that will be resolved when the popup has been loaded and rendered. + A promise that will be resolved when the modal has been loaded and + the opening animation has completed. @stable ### follow = (linkOrSelector, options) -> options = u.options(options) options.$link = $(linkOrSelector) @@ -273,11 +277,12 @@ The CSS selector to extract from the response. The extracted content will be placed into the dialog window. @param {Object} options See options for [`up.modal.follow`](/up.modal.follow). @return {Promise} - A promise that will be resolved when the popup has been loaded and rendered. + A promise that will be resolved when the modal has been loaded and the opening + animation has completed. @stable ### visit = (url, options) -> options = u.options(options) options.url = url @@ -289,39 +294,40 @@ ### open = (options) -> options = u.options(options) $link = u.option(options.$link, u.nullJQuery()) url = u.option(options.url, $link.attr('up-href'), $link.attr('href')) - selector = u.option(options.target, $link.attr('up-modal'), 'body') - width = u.option(options.width, $link.attr('up-width'), config.width) - maxWidth = u.option(options.maxWidth, $link.attr('up-max-width'), config.maxWidth) - height = u.option(options.height, $link.attr('up-height'), config.height) - animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation) - sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky')) + target = u.option(options.target, $link.attr('up-modal'), 'body') + options.width = u.option(options.width, $link.attr('up-width'), config.width) + options.maxWidth = u.option(options.maxWidth, $link.attr('up-max-width'), config.maxWidth) + options.height = u.option(options.height, $link.attr('up-height'), config.height) + options.animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation) + options.sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky')) # Although we usually fall back to full page loads if a browser doesn't support pushState, # in the case of modals we assume that the developer would rather see a dialog # without an URL update. - history = if up.browser.canPushState() then u.option(options.history, u.castedAttr($link, 'up-history'), config.history) else false + options.history = if up.browser.canPushState() then u.option(options.history, u.castedAttr($link, 'up-history'), config.history) else false + options.confirm = u.option(options.confirm, $link.attr('up-confirm')) animateOptions = up.motion.animateOptions(options, $link) - close() + up.browser.confirm(options.confirm).then -> + if up.bus.nobodyPrevents('up:modal:open', url: url) + wasOpen = isOpen() + close(animation: false) if wasOpen + options.beforeSwap = -> createFrame(target, options) + promise = up.replace(target, url, u.merge(options, animation: false)) + unless wasOpen + promise = promise.then -> + up.animate($('.up-modal'), options.animation, animateOptions) + promise = promise.then -> + up.emit('up:modal:opened') + promise + else + # Although someone prevented opening the modal, keep a uniform API for + # callers by returning a Deferred that will never be resolved. + u.unresolvablePromise() - if up.bus.nobodyPrevents('up:modal:open', url: url) - createHiddenModal - selector: selector - width: width - maxWidth: maxWidth - height: height - sticky: sticky - promise = up.replace(selector, url, history: history, requireMatch: false) - promise.then -> updated(animation, animateOptions) - promise - else - # Although someone prevented the destruction, keep a uniform API for - # callers by returning a Deferred that will never be resolved. - u.unresolvableDeferred() - ###* This event is [emitted](/up.emit) when a modal dialog is starting to open. @event up:modal:open @param event.preventDefault() @@ -359,15 +365,15 @@ animation: config.closeAnimation, url: $modal.attr('up-covered-url') title: $modal.attr('up-covered-title') ) currentUrl = undefined - deferred = up.destroy($modal, options) - deferred.then -> - unshifter() while unshifter = unshiftElements.pop() + promise = up.destroy($modal, options) + promise = promise.then -> + unshiftElements() up.emit('up:modal:closed') - deferred + promise else # Although someone prevented the destruction, # keep a uniform API for callers by returning # a Deferred that will never be resolved. u.unresolvableDeferred() @@ -421,23 +427,30 @@ the HTML response. Up.js will dim the page with an overlay and place the matching `.blog-list` tag will be placed in a modal dialog. @selector a[up-modal] - @param [up-sticky] - @param [up-animation] - @param [up-height] + @param {String} [up-confirm] + A message that will be displayed in a cancelable confirmation dialog + before the modal is opened. + @param {String} [up-sticky] + If set to `"true"`, the modal remains + open even if the page changes in the background. + @param {String} [up-animation] + The animation to use when opening the modal. + @param {String} [up-height] + The width of the dialog in pixels. + By [default](/up.modal.config) the dialog will grow to fit its contents. @param [up-width] - @param [up-history] + The width of the dialog in pixels. + By [default](/up.modal.config) the dialog will grow to fit its contents. + @param [up-history="true"] + Whether to add a browser history entry for the modal's source URL. @stable ### - up.link.registerFollowVariant '[up-modal]', ($link) -> - event.preventDefault() - if $link.is('.up-current') - close() - else - follow($link) + up.link.onAction '[up-modal]', ($link) -> + follow($link) # Close the modal when someone clicks outside the dialog # (but not on a modal opener). up.on('click', 'body', (event, $body) -> $target = $(event.target) @@ -489,8 +502,9 @@ url: -> currentUrl coveredUrl: coveredUrl config: config defaults: -> u.error('up.modal.defaults(...) no longer exists. Set values on he up.modal.config property instead.') contains: contains - source: -> up.error('up.popup.source no longer exists. Please use up.popup.url instead.') + source: -> up.error('up.modal.source no longer exists. Please use up.popup.url instead.') + isOpen: isOpen )(jQuery)