unpoly-rails 0.27.1 → 0.27.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of unpoly-rails might be problematic. Click here for more details.

@@ -126,6 +126,7 @@ up.form = (($) ->
126
126
  options.cache = u.option(options.cache, u.castedAttr($form, 'up-cache'))
127
127
  options.restoreScroll = u.option(options.restoreScroll, u.castedAttr($form, 'up-restore-scroll'))
128
128
  options.origin = u.option(options.origin, $form)
129
+ options.layer = u.option(options.layer, $form.attr('up-layer'), 'auto')
129
130
  options.data = up.util.requestDataFromForm($form)
130
131
  options = u.merge(options, up.motion.animateOptions(options, $form))
131
132
 
@@ -158,6 +158,13 @@ up.link = (($) ->
158
158
  @param {Object} [options.headers={}]
159
159
  An object of additional header key/value pairs to send along
160
160
  with the request.
161
+ @param {String} [options.layer='auto']
162
+ The name of the layer that ought to be updated. Valid values are
163
+ `auto`, `page`, `modal` and `popup`.
164
+
165
+ If set to `auto` (default), Unpoly will try to find a match in the
166
+ same layer as the given link. If no match was found in that layer,
167
+ Unpoly will search in other layers, starting from the topmost layer.
161
168
  @return {Promise}
162
169
  A promise that will be resolved when the link destination
163
170
  has been loaded and rendered.
@@ -179,6 +186,7 @@ up.link = (($) ->
179
186
  options.restoreScroll = u.option(options.restoreScroll, u.castedAttr($link, 'up-restore-scroll'))
180
187
  options.method = followMethod($link, options)
181
188
  options.origin = u.option(options.origin, $link)
189
+ options.layer = u.option(options.layer, $link.attr('up-layer'), 'auto')
182
190
  options.confirm = u.option(options.confirm, $link.attr('up-confirm'))
183
191
  options = u.merge(options, up.motion.animateOptions(options, $link))
184
192
 
@@ -330,7 +338,14 @@ up.link = (($) ->
330
338
  @param {String} [up-cache]
331
339
  Whether to force the use of a cached response (`true`)
332
340
  or never use the cache (`false`)
333
- or make an educated guess (`undefined`).
341
+ or make an educated guess (default).
342
+ @param {String} [up-layer='auto']
343
+ The name of the layer that ought to be updated. Valid values are
344
+ `auto`, `page`, `modal` and `popup`.
345
+
346
+ If set to `auto` (default), Unpoly will try to find a match in the
347
+ same layer as the given link. If no match was found in that layer,
348
+ Unpoly will search in other layers, starting from the topmost layer.
334
349
  @param [up-history]
335
350
  Whether to push an entry to the browser history when following the link.
336
351
 
@@ -189,6 +189,10 @@ up.modal = (($) ->
189
189
  else
190
190
  template
191
191
 
192
+ discardHistory = ->
193
+ state.coveredTitle = null
194
+ state.coveredUrl = null
195
+
192
196
  createFrame = (target, options) ->
193
197
  $modal = $(templateHtml())
194
198
  $modal.attr('up-flavor', state.flavor)
@@ -380,6 +384,7 @@ up.modal = (($) ->
380
384
  options.sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'), flavorDefault('sticky', options.flavor))
381
385
  options.confirm = u.option(options.confirm, $link.attr('up-confirm'))
382
386
  options.method = up.link.followMethod($link, options)
387
+ options.layer = 'modal'
383
388
  animateOptions = up.motion.animateOptions(options, $link, duration: flavorDefault('openDuration', options.flavor), easing: flavorDefault('openEasing', options.flavor))
384
389
 
385
390
  # Although we usually fall back to full page loads if a browser doesn't support pushState,
@@ -518,7 +523,9 @@ up.modal = (($) ->
518
523
  ###
519
524
 
520
525
  autoclose = ->
521
- closeAsap() unless state.sticky
526
+ unless state.sticky
527
+ discardHistory()
528
+ closeAsap()
522
529
 
523
530
  ###*
524
531
  Returns whether the given element or selector is contained
@@ -149,6 +149,10 @@ up.popup = (($) ->
149
149
  state.$popup.attr('up-position', state.position)
150
150
  state.$popup.css(css)
151
151
 
152
+ discardHistory = ->
153
+ state.coveredTitle = null
154
+ state.coveredUrl = null
155
+
152
156
  createFrame = (target) ->
153
157
  $popup = u.$createElementFromSelector('.up-popup')
154
158
  # Create an empty element that will match the
@@ -224,6 +228,7 @@ up.popup = (($) ->
224
228
  options.history = if up.browser.canPushState() then u.option(options.history, u.castedAttr($anchor, 'up-history'), config.history) else false
225
229
  options.confirm = u.option(options.confirm, $anchor.attr('up-confirm'))
226
230
  options.method = up.link.followMethod($anchor, options)
231
+ options.layer = 'popup'
227
232
  animateOptions = up.motion.animateOptions(options, $anchor, duration: config.openDuration, easing: config.openEasing)
228
233
 
229
234
  up.browser.whenConfirmed(options).then ->
@@ -328,7 +333,9 @@ up.popup = (($) ->
328
333
  ###
329
334
 
330
335
  autoclose = ->
331
- closeAsap() unless state.sticky
336
+ unless state.sticky
337
+ discardHistory()
338
+ closeAsap()
332
339
 
333
340
  ###*
334
341
  Returns whether the given element or selector is contained
@@ -199,7 +199,7 @@ up.util = (($) ->
199
199
 
200
200
  openTag = (tag) -> "<#{tag}(?: [^>]*)?>"
201
201
  closeTag = (tag) -> "</#{tag}>"
202
- anything = '(?:.|\\n)*?'
202
+ anything = '(?:.|\\s)*?'
203
203
  capture = (pattern) -> "(#{pattern})"
204
204
 
205
205
  titlePattern = new RegExp(
@@ -618,7 +618,7 @@ up.util = (($) ->
618
618
  merged
619
619
 
620
620
  ###*
621
- Returns the first argument that is considered present.
621
+ Returns the first argument that is considered [given](/up.util.isGiven).
622
622
 
623
623
  This function is useful when you have multiple option sources and the value can be boolean.
624
624
  In that case you cannot change the sources with a `||` operator
@@ -4,6 +4,6 @@ module Unpoly
4
4
  # The current version of the unpoly-rails gem.
5
5
  # This version number is also used for releases of the Unpoly
6
6
  # frontend code.
7
- VERSION = '0.27.1'
7
+ VERSION = '0.27.2'
8
8
  end
9
9
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- unpoly-rails (0.27.0)
4
+ unpoly-rails (0.27.1)
5
5
  rails (>= 3)
6
6
 
7
7
  GEM
@@ -0,0 +1,5 @@
1
+ beforeEach ->
2
+ jasmine.addMatchers
3
+ toBeJQuery: (util, customEqualityTesters) ->
4
+ compare: (actual) ->
5
+ pass: up.util.isJQuery(actual)
@@ -566,7 +566,7 @@ describe 'up.flow', ->
566
566
  it "throws an error if the selector can't be found on the current page", ->
567
567
  html = '<div class="foo-bar">text</div>'
568
568
  extract = -> up.extract('.foo-bar', html)
569
- expect(extract).toThrowError(/Could not find selector ".foo-bar" in current body/i)
569
+ expect(extract).toThrowError(/Could not find selector ".foo-bar"/i)
570
570
 
571
571
  it "throws an error if the selector can't be found in the given HTML string", ->
572
572
  affix('.foo-bar')
@@ -365,6 +365,30 @@ describe 'up.link', ->
365
365
  expect($('.target')).toHaveText('new text')
366
366
  expect(location.pathname).toEqual('/other/path')
367
367
 
368
+ it 'prefers to update a container in the same layer as the clicked link', ->
369
+ up.motion.config.enabled = false
370
+
371
+ $popupOpener = affix('a[href="/popup"]')
372
+ up.popup.attach($popupOpener, html: "<div class='target'>old popup text</div>", target: '.target')
373
+
374
+ affix('.document').affix('.target').text('old document text')
375
+ $linkInDocument = affix('a[href="/foo"][up-target=".target"]')
376
+ $linkInDocument.click()
377
+
378
+ @respondWith '<div class="target">new text from document link</div>'
379
+
380
+ expect($('.document .target')).toHaveText('new text from document link')
381
+ expect($('.up-popup .target')).toHaveText('old popup text')
382
+
383
+ $linkInPopup = $('.up-popup').affix('a[href="/bar"][up-target=".target"]')
384
+ $linkInPopup.click()
385
+
386
+ @respondWith '<div class="target">new text from popup link</div>'
387
+
388
+ expect($('.document .target')).toHaveText('new text from document link')
389
+ expect($('.up-popup .target')).toHaveText('new text from popup link')
390
+
391
+
368
392
  describe 'with [up-transition] modifier', ->
369
393
 
370
394
  describeCapability 'canCssTransition', ->
@@ -463,6 +463,23 @@ describe 'up.modal', ->
463
463
  expect($('.outside')).toHaveText('new outside')
464
464
  expect($('.up-modal')).not.toExist()
465
465
 
466
+ it 'does not restore the covered URL when auto-closing', (done) ->
467
+ up.motion.config.enabled = true
468
+ up.modal.config.openDuration = 0
469
+ up.modal.config.closeDuration = 20
470
+
471
+ affix('.outside').text('old outside')
472
+ whenModalOpen = up.modal.visit('/path', target: '.inside')
473
+ @respondWith("<div class='inside'>old inside</div>") # Populate modal
474
+
475
+ whenModalOpen.then ->
476
+ up.extract('.outside', "<div class='outside'>new outside</div>",
477
+ origin: $('.inside'), history: '/new-location') # Provoke auto-close
478
+
479
+ u.setTimer 50, ->
480
+ expect(location.href).toEndWith '/new-location'
481
+ done()
482
+
466
483
  it 'does not auto-close the modal when a replacement from inside the modal affects a selector inside the modal', ->
467
484
  affix('.outside').text('old outside')
468
485
  up.modal.visit('/path', target: '.inside')
@@ -300,7 +300,7 @@ describe 'up.popup', ->
300
300
  it 'prefers to replace a selector within the popup', ->
301
301
  $outside = affix('.foo').text('old outside')
302
302
  $link = affix('.link')
303
- up.popup.attach($link, href: '/path', target: '.foo')
303
+ up.popup.attach($link, target: '.foo')
304
304
  @respondWith("<div class='foo'>old inside</div>")
305
305
  up.extract('.foo', "<div class='foo'>new text</div>")
306
306
  expect($outside).toBeInDOM()
@@ -310,16 +310,35 @@ describe 'up.popup', ->
310
310
  it 'auto-closes the popup when a replacement from inside the popup affects a selector behind the popup', ->
311
311
  affix('.outside').text('old outside')
312
312
  $link = affix('.link')
313
- up.popup.attach($link, href: '/path', target: '.inside')
313
+ up.popup.attach($link, target: '.inside')
314
314
  @respondWith("<div class='inside'>old inside</div>")
315
315
  up.extract('.outside', "<div class='outside'>new outside</div>", origin: $('.inside'))
316
316
  expect($('.outside')).toHaveText('new outside')
317
317
  expect($('.up-popup')).not.toExist()
318
318
 
319
+ it 'does not restore the covered URL when auto-closing', (done) ->
320
+ up.motion.config.enabled = true
321
+ up.popup.config.openDuration = 0
322
+ up.popup.config.closeDuration = 20
323
+ up.popup.config.history = true
324
+
325
+ affix('.outside').text('old outside')
326
+ $link = affix('.link')
327
+ whenPopupOpen = up.popup.attach($link, url: '/path', target: '.inside')
328
+ @respondWith("<div class='inside'>old inside</div>") # Populate popup
329
+
330
+ whenPopupOpen.then ->
331
+ up.extract('.outside', "<div class='outside'>new outside</div>",
332
+ origin: $('.inside'), history: '/new-location') # Provoke auto-close
333
+
334
+ u.setTimer 50, ->
335
+ expect(location.href).toEndWith '/new-location'
336
+ done()
337
+
319
338
  it 'does not auto-close the popup when a replacement from inside the popup affects a selector inside the popup', ->
320
339
  affix('.outside').text('old outside')
321
340
  $link = affix('.link')
322
- up.popup.attach($link, href: '/path', target: '.inside')
341
+ up.popup.attach($link, target: '.inside')
323
342
  @respondWith("<div class='inside'>old inside</div>")
324
343
  up.extract('.inside', "<div class='inside'>new inside</div>", origin: $('.inside'))
325
344
  expect($('.inside')).toHaveText('new inside')
@@ -328,7 +347,7 @@ describe 'up.popup', ->
328
347
  it 'does not auto-close the popup when a replacement from outside the popup affects a selector outside the popup', ->
329
348
  affix('.outside').text('old outside')
330
349
  $link = affix('.link')
331
- up.popup.attach($link, href: '/path', target: '.inside')
350
+ up.popup.attach($link, target: '.inside')
332
351
  @respondWith("<div class='inside'>old inside</div>")
333
352
  up.extract('.outside', "<div class='outside'>new outside</div>", origin: $('.outside'))
334
353
  expect($('.outside')).toHaveText('new outside')
@@ -337,7 +356,7 @@ describe 'up.popup', ->
337
356
  it 'does not auto-close the popup when a replacement from outside the popup affects a selector inside the popup', ->
338
357
  affix('.outside').text('old outside')
339
358
  $link = affix('.link')
340
- up.popup.attach($link, href: '/path', target: '.inside')
359
+ up.popup.attach($link, target: '.inside')
341
360
  @respondWith("<div class='inside'>old inside</div>")
342
361
  up.extract('.inside', "<div class='inside'>new inside</div>", origin: $('.outside'))
343
362
  expect($('.inside')).toHaveText('new inside')
@@ -351,7 +370,7 @@ describe 'up.popup', ->
351
370
  it 'closes a popup on mousedown (in case an [up-instant] link removes its parent and thus a click event never fires)', ->
352
371
  affix('.outside').text('old outside')
353
372
  $link = affix('.link')
354
- up.popup.attach($link, href: '/path', target: '.inside')
373
+ up.popup.attach($link, target: '.inside')
355
374
  @respondWith("<div class='inside'>inside</div>")
356
375
  Trigger.mousedown($('body'))
357
376
  expect($('.up-popup')).not.toExist()
@@ -2,6 +2,42 @@ describe 'up.util', ->
2
2
 
3
3
  describe 'Javascript functions', ->
4
4
 
5
+ describe 'up.util.createElementFromHtml', ->
6
+
7
+ it 'parses a string that contains a serialized HTML document', ->
8
+ string = """
9
+ <html lang="foo">
10
+ <head>
11
+ <title>document title</title>
12
+ </head>
13
+ <body data-env='production'>
14
+ <div>line 1</div>
15
+ <div>line 2</div>
16
+ </body>
17
+ </html>
18
+ """
19
+
20
+ element = up.util.createElementFromHtml(string)
21
+
22
+ expect(element.querySelector('head title').textContent).toEqual('document title')
23
+ expect(element.querySelectorAll('body div').length).toBe(2)
24
+ expect(element.querySelectorAll('body div')[0].textContent).toEqual('line 1')
25
+ expect(element.querySelectorAll('body div')[1].textContent).toEqual('line 2')
26
+
27
+ it 'parses a string that contains carriage returns (bugfix)', ->
28
+ string = """
29
+ <html>\r
30
+ <body>\r
31
+ <div>line</div>\r
32
+ </body>\r
33
+ </html>\r
34
+ """
35
+
36
+ $element = up.util.createElementFromHtml(string)
37
+ expect($element.querySelector('body')).toBeGiven()
38
+ expect($element.querySelector('body div').textContent).toEqual('line')
39
+
40
+
5
41
  describe 'up.util.cssAnimate', ->
6
42
 
7
43
  it 'returns a deferred that eventually resolves if called with a duration of 0 (bugfix)', (done) ->
@@ -197,6 +233,12 @@ describe 'up.util', ->
197
233
  it 'returns false for an array with at least one element', ->
198
234
  expect(up.util.isBlank(['element'])).toBe(false)
199
235
 
236
+ it 'returns true for an empty jQuery collection', ->
237
+ expect(up.util.isBlank($([]))).toBe(true)
238
+
239
+ it 'returns false for a jQuery collection with at least one element', ->
240
+ expect(up.util.isBlank($('body'))).toBe(false)
241
+
200
242
  it 'returns true for an empty object', ->
201
243
  expect(up.util.isBlank({})).toBe(true)
202
244
 
@@ -254,6 +296,22 @@ describe 'up.util', ->
254
296
  object.reset()
255
297
  expect(object.reset).toBeDefined()
256
298
 
299
+ describe 'up.util.remove', ->
300
+
301
+ it 'removes the given string from the given array', ->
302
+ array = ['a', 'b', 'c']
303
+ up.util.remove(array, 'b')
304
+ expect(array).toEqual ['a', 'c']
305
+
306
+ it 'removes the given object from the given array', ->
307
+ obj1 = { 'key': 1 }
308
+ obj2 = { 'key': 2 }
309
+ obj3 = { 'key': 3 }
310
+ array = [obj1, obj2, obj3]
311
+ up.util.remove(array, obj2)
312
+ expect(array).toEqual [obj1, obj3]
313
+
314
+
257
315
  describe 'up.util.requestDataAsQuery', ->
258
316
 
259
317
  encodedOpeningBracket = '%5B'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unpoly-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.1
4
+ version: 0.27.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-15 00:00:00.000000000 Z
11
+ date: 2016-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -216,6 +216,7 @@ files:
216
216
  - spec_app/spec/javascripts/helpers/to_be_around.js.coffee
217
217
  - spec_app/spec/javascripts/helpers/to_be_blank.js.coffee
218
218
  - spec_app/spec/javascripts/helpers/to_be_given.js.coffee
219
+ - spec_app/spec/javascripts/helpers/to_be_jquery.js.coffee
219
220
  - spec_app/spec/javascripts/helpers/to_be_missing.js.coffee
220
221
  - spec_app/spec/javascripts/helpers/to_be_present.js.coffee
221
222
  - spec_app/spec/javascripts/helpers/to_contain.js.coffee