lib/assets/javascripts/unpoly/flow.js.coffee in unpoly-rails-0.27.1 vs lib/assets/javascripts/unpoly/flow.js.coffee in unpoly-rails-0.27.2

- old
+ new

@@ -181,20 +181,29 @@ of all the viewports around or below the updated element. The position will be reset to the last known top position before a previous history change for the current URL. @param {Boolean} [options.cache] Whether to use a [cached response](/up.proxy) if available. - @param {Element|jQuery} [options.origin] - The element that triggered the replacement. The element's selector will - be substituted for the `&` shorthand in the target selector. @param {String} [options.historyMethod='push'] @param {Object} [options.headers={}] An object of additional header key/value pairs to send along with the request. @param {Boolean} [options.requireMatch=true] Whether to raise an error if the given selector is missing in either the current page or in the response. + @param {Element|jQuery} [options.origin] + The element that triggered the replacement. + + The element's selector will be substituted for the `&` shorthand in the target selector. + @param {String} [options.layer='auto'] + The name of the layer that ought to be updated. Valid values are + `auto`, `page`, `modal` and `popup`. + + If set to `auto` (default), Unpoly will try to find a match in the + same layer as the element that triggered the replacement (see `options.origin`). + If that element is not known, or no match was found in that layer, + Unpoly will search in other layers, starting from the topmost layer. @return {Promise} A promise that will be resolved when the page has been updated. @stable ### replace = (selectorOrElement, url, options) -> @@ -319,13 +328,14 @@ @experimental ### extract = (selectorOrElement, html, options) -> up.log.group 'Extracting %s from %d bytes of HTML', selectorOrElement, html?.length, -> options = u.options(options, - historyMethod: 'push', - requireMatch: true, + historyMethod: 'push' + requireMatch: true keep: true + layer: 'auto' ) selector = resolveSelector(selectorOrElement, options.origin) response = parseResponse(html, options) options.title ||= response.title() @@ -349,19 +359,17 @@ return $.when(swapPromises...) promise = promise.then(options.afterSwap) if options.afterSwap promise findOldFragment = (selector, options) -> - # Prefer to replace fragments in an open popup or modal - first(".up-popup #{selector}") || - first(".up-modal #{selector}") || - first(selector) || - oldFragmentNotFound(selector, options) + first(selector, options) || oldFragmentNotFound(selector, options) oldFragmentNotFound = (selector, options) -> if options.requireMatch - message = 'Could not find selector %s in current body HTML' + layerProse = options.layer + layerProse = 'page, modal or popup' if layerProse == 'auto' + message = "Could not find selector %s in the current #{layerProse}" if message[0] == '#' message += ' (avoid using IDs)' u.error(message, selector) filterScripts = ($element, options) -> @@ -704,27 +712,58 @@ Returns `undefined` if no element matches these conditions. @function up.first @param {String|Element|jQuery|Array<Element>} selectorOrElement - @return {jQuery} + @param {String} options.layer + The name of the layer in which to find the element. Valid values are + `auto`, `page`, `modal` and `popup`. + @param {} + @return {jQuery|Undefined} The first element that is neither a ghost or being destroyed, or `undefined` if no such element was given. @experimental ### - first = (selectorOrElement) -> - elements = undefined - if u.isString(selectorOrElement) - elements = $(selectorOrElement).get() + first = (selectorOrElement, options) -> + options = u.options(options, layer: 'auto') + if options.layer == 'auto' + firstInPriority(selectorOrElement, options.origin) else - elements = selectorOrElement + firstInLayer(selectorOrElement, options.layer) + + firstInPriority = (selectorOrElement, origin) -> + layers = ['popup', 'modal', 'page'] $match = undefined - for element in elements + if u.isPresent(origin) + originLayer = layerOf(origin) + u.remove(layers, originLayer) + layers.unshift(originLayer) + for layer in layers + if $match = firstInLayer(selectorOrElement, layer) + break + $match + + firstInLayer = (selectorOrElement, layer) -> + $elements = $(selectorOrElement) + $match = undefined + for element in $elements $element = $(element) - if isRealElement($element) + if isRealElement($element) && matchesLayer($element, layer) $match = $element break $match + + layerOf = (selectorOrElement) -> + $element = $(selectorOrElement) + if up.popup.contains($element) + 'popup' + else if up.modal.contains($element) + 'modal' + else + 'page' + + matchesLayer = (selectorOrElement, layer) -> + layerOf(selectorOrElement) == layer ###* Destroys the given element or selector. Takes care that all [`up.compiler`](/up.compiler) destructors, if any, are called.