lib/assets/javascripts/unpoly/popup.js.coffee in unpoly-rails-0.24.1 vs lib/assets/javascripts/unpoly/popup.js.coffee in unpoly-rails-0.25.0
- old
+ new
@@ -3,11 +3,11 @@
===============
Instead of [linking to a page fragment](/up.link), you can choose
to show a fragment in a popup overlay that rolls down from an anchoring element.
-To open a popup, add an [`up-popup` attribute](/a-up-popup) to a link,
+To open a popup, add an [`up-popup` attribute](/up-popup) to a link,
or call the Javascript function [`up.popup.attach`](/up.popup.attach).
For modal dialogs see [up.modal](/up.modal) instead.
\#\#\#\# Customizing the popup design
@@ -29,11 +29,11 @@
\#\#\#\# Closing behavior
The popup closes when the user clicks anywhere outside the popup area.
By default the popup also closes
-*whenever a page fragment behind the popup is updated*.
+*when a link within the popup changes a fragment behind the popup*.
This is useful to have the popup interact with the page that
opened it, e.g. by updating parts of a larger form or by signing in a user
and revealing additional information.
To disable this behavior, give the opening link an `up-sticky` attribute:
@@ -69,25 +69,40 @@
###*
Sets default options for future popups.
@property up.popup.config
- @param {String} [config.openAnimation='fade-in']
- The animation used to open a popup.
- @param {String} [config.closeAnimation='fade-out']
- The animation used to close a popup.
@param {String} [config.position='bottom-right']
Defines where the popup is attached to the opening element.
Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
@param {String} [config.history=false]
Whether opening a popup will add a browser history entry.
+ @param {String} [config.openAnimation='fade-in']
+ The animation used to open a popup.
+ @param {String} [config.closeAnimation='fade-out']
+ The animation used to close a popup.
+ @param {String} [config.openDuration]
+ The duration of the open animation (in milliseconds).
+ @param {String} [config.closeDuration]
+ The duration of the close animation (in milliseconds).
+ @param {String} [config.openEasing]
+ The timing function controlling the acceleration of the opening animation.
+ @param {String} [config.closeEasing]
+ The timing function controlling the acceleration of the closing animation.
+ @param {Boolean} [options.sticky=false]
+ If set to `true`, the popup remains
+ open even it changes the page in the background.
@stable
###
config = u.config
openAnimation: 'fade-in'
closeAnimation: 'fade-out'
+ openDuration: null
+ closeDuration: null
+ openEasing: null
+ closeEasing: null
position: 'bottom-right'
history: false
reset = ->
close(animation: false)
@@ -145,19 +160,24 @@
$popup = $('.up-popup')
$popup.removeAttr('up-covered-url')
$popup.removeAttr('up-covered-title')
createFrame = (target, options) ->
- $popup = u.$createElementFromSelector('.up-popup')
- $popup.attr('up-sticky', '') if options.sticky
- $popup.attr('up-covered-url', up.browser.url())
- $popup.attr('up-covered-title', document.title)
- # Create an empty element that will match the
- # selector that is being replaced.
- u.$createPlaceholder(target, $popup)
- $popup.appendTo(document.body)
- $popup
+ promise = u.resolvedPromise()
+ if isOpen()
+ promise = promise.then -> close()
+ promise = promise.then ->
+ $popup = u.$createElementFromSelector('.up-popup')
+ $popup.attr('up-sticky', '') if options.sticky
+ $popup.attr('up-covered-url', up.browser.url())
+ $popup.attr('up-covered-title', document.title)
+ # Create an empty element that will match the
+ # selector that is being replaced.
+ u.$createPlaceholder(target, $popup)
+ $popup.appendTo(document.body)
+ $popup
+ return promise
###*
Returns whether popup modal is currently open.
@function up.popup.isOpen
@@ -172,10 +192,12 @@
Emits events [`up:popup:open`](/up:popup:open) and [`up:popup:opened`](/up:popup:opened).
@function up.popup.attach
@param {Element|jQuery|String} elementOrSelector
@param {String} [options.url]
+ @param {String} [options.target]
+ A CSS selector that will be extracted from the response and placed into the popup.
@param {String} [options.position='bottom-right']
Defines where the popup is attached to the opening element.
Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
@param {String} [options.confirm]
@@ -201,37 +223,39 @@
attach = (linkOrSelector, options) ->
$link = $(linkOrSelector)
$link.length or u.error('Cannot attach popup to non-existing element %o', linkOrSelector)
options = u.options(options)
- url = u.option(options.url, $link.attr('href'))
- target = u.option(options.target, $link.attr('up-popup'), 'body')
+ url = u.option(u.pluckKey(options, 'url'), $link.attr('up-href'), $link.attr('href'))
+ html = u.option(u.pluckKey(options, 'html'))
+ target = u.option(u.pluckKey(options, 'target'), $link.attr('up-popup'), 'body')
options.position = u.option(options.position, $link.attr('up-position'), config.position)
options.animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation)
- options.sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'))
+ options.sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'), config.sticky)
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)
+ animateOptions = up.motion.animateOptions(options, $link, duration: config.openDuration, easing: config.openEasing)
up.browser.confirm(options).then ->
if up.bus.nobodyPrevents('up:popup:open', url: url, message: 'Opening popup')
- wasOpen = isOpen()
- close(animation: false) if wasOpen
options.beforeSwap = -> createFrame(target, options)
- promise = up.replace(target, url, u.merge(options, animation: false))
+ extractOptions = u.merge(options, animation: false)
+ if html
+ promise = up.extract(target, html, extractOptions)
+ else
+ promise = up.replace(target, url, extractOptions)
promise = promise.then ->
setPosition($link, options.position)
- unless wasOpen
- promise = promise.then ->
- up.animate($('.up-popup'), options.animation, animateOptions)
promise = promise.then ->
+ up.animate($('.up-popup'), options.animation, animateOptions)
+ promise = promise.then ->
up.emit('up:popup:opened', message: 'Popup opened')
promise
else
# Although someone prevented the destruction, keep a uniform API for
- # callers by returning a Deferred that will never be resolved.
- u.unresolvableDeferred()
+ # callers by returning a promise that will never be resolved.
+ u.unresolvablePromise()
###*
This event is [emitted](/up.emit) when a popup is starting to open.
@event up:popup:open
@@ -255,11 +279,11 @@
Emits events [`up:popup:close`](/up:popup:close) and [`up:popup:closed`](/up:popup:closed).
@function up.popup.close
@param {Object} options
See options for [`up.animate`](/up.animate).
- @return {Deferred}
+ @return {Promise}
A promise that will be resolved once the modal's close
animation has finished.
@stable
###
close = (options) ->
@@ -269,21 +293,22 @@
options = u.options(options,
animation: config.closeAnimation,
url: $popup.attr('up-covered-url'),
title: $popup.attr('up-covered-title')
)
+ animateOptions = up.motion.animateOptions(options, duration: config.closeDuration, easing: config.closeEasing)
+ u.extend(options, animateOptions)
currentUrl = undefined
- deferred = up.destroy($popup, options)
- deferred.then -> up.emit('up:popup:closed', message: 'Popup closed')
- deferred
+ promise = up.destroy($popup, options)
+ promise = promise.then -> up.emit('up:popup:closed', message: 'Popup closed')
+ promise
else
- # Although someone prevented the destruction,
- # keep a uniform API for callers by returning
- # a Deferred that will never be resolved.
- u.unresolvableDeferred()
+ # Although someone prevented the destruction, keep a uniform API
+ # for callers by returning a promise that will never be resolved.
+ u.unresolvablePromise()
else
- u.resolvedDeferred()
+ u.resolvedPromise()
###*
This event is [emitted](/up.emit) when a popup dialog
is starting to [close](/up.popup.close).
@@ -327,10 +352,10 @@
if a page fragment behind the popup overlay updates:
<a href="/decks" up-popup=".deck_list">Switch deck</a>
<a href="/settings" up-popup=".options" up-sticky>Settings</a>
- @selector a[up-popup]
+ @selector [up-popup]
@param [up-position]
Defines where the popup is attached to the opening element.
Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
@param {String} [up-confirm]