unpoly-rails 0.22.0 → 0.22.1

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.

@@ -5,7 +5,7 @@ Caching and preloading
5
5
  All HTTP requests go through the Unpoly proxy.
6
6
  It caches a [limited](/up.proxy.config) number of server responses
7
7
  for a [limited](/up.proxy.config) amount of time,
8
- making requests to these URLs return insantly.
8
+ making requests to these URLs return instantly.
9
9
 
10
10
  The cache is cleared whenever the user makes a non-`GET` request
11
11
  (like `POST`, `PUT` or `DELETE`).
@@ -15,42 +15,6 @@ links when the user hovers over the click area](/up-preload) (or puts the mouse/
15
15
  down before releasing). This way the response will already be cached when
16
16
  the user performs the click.
17
17
 
18
- Spinners
19
- --------
20
-
21
- You can [listen](/up.on) to the [`up:proxy:slow`](/up:proxy:slow)
22
- and [`up:proxy:recover`](/up:proxy:recover) events to implement a spinner
23
- that appears during a long-running request,
24
- and disappears once the response has been received:
25
-
26
- <div class="spinner">Please wait!</div>
27
-
28
- Here is the Javascript to make it alive:
29
-
30
- up.compiler('.spinner', function($element) {
31
-
32
- show = function() { $element.show() };
33
- hide = function() { $element.hide() };
34
-
35
- showOff = up.on('up:proxy:slow', show);
36
- hideOff = up.on('up:proxy:recover', hide);
37
-
38
- hide();
39
-
40
- // Clean up when the element is removed from the DOM
41
- return function() {
42
- showOff();
43
- hideOff();
44
- };
45
-
46
- });
47
-
48
- The `up:proxy:slow` event will be emitted after a delay of 300 ms
49
- to prevent the spinner from flickering on and off.
50
- You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.config) like this:
51
-
52
- up.proxy.config.slowDelay = 150;
53
-
54
18
  @class up.proxy
55
19
  ###
56
20
  up.proxy = (($) ->
@@ -349,6 +313,43 @@ up.proxy = (($) ->
349
313
  Note that if additional requests are made while Unpoly is already busy
350
314
  waiting, **no** additional `up:proxy:slow` events will be triggered.
351
315
 
316
+
317
+ \#\#\#\# Spinners
318
+
319
+ You can [listen](/up.on) to the `up:proxy:slow`
320
+ and [`up:proxy:recover`](/up:proxy:recover) events to implement a spinner
321
+ that appears during a long-running request,
322
+ and disappears once the response has been received:
323
+
324
+ <div class="spinner">Please wait!</div>
325
+
326
+ Here is the Javascript to make it alive:
327
+
328
+ up.compiler('.spinner', function($element) {
329
+
330
+ show = function() { $element.show() };
331
+ hide = function() { $element.hide() };
332
+
333
+ showOff = up.on('up:proxy:slow', show);
334
+ hideOff = up.on('up:proxy:recover', hide);
335
+
336
+ hide();
337
+
338
+ // Clean up when the element is removed from the DOM
339
+ return function() {
340
+ showOff();
341
+ hideOff();
342
+ };
343
+
344
+ });
345
+
346
+ The `up:proxy:slow` event will be emitted after a delay of 300 ms
347
+ to prevent the spinner from flickering on and off.
348
+ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.config) like this:
349
+
350
+ up.proxy.config.slowDelay = 150;
351
+
352
+
352
353
  @event up:proxy:slow
353
354
  @stable
354
355
  ###
@@ -363,6 +364,10 @@ up.proxy = (($) ->
363
364
  This event is [emitted]/(up.emit) when [AJAX requests](/up.ajax)
364
365
  have [taken long to finish](/up:proxy:slow), but have finished now.
365
366
 
367
+ See [`up:proxy:slow`](/up:proxy:slow) for more documentation on
368
+ how to use this event for implementing a spinner that shows during
369
+ long-running requests.
370
+
366
371
  @event up:proxy:recover
367
372
  @stable
368
373
  ###
@@ -46,11 +46,11 @@ up.syntax = (($) ->
46
46
  Registers a function to be called whenever an element with
47
47
  the given selector is inserted into the DOM.
48
48
 
49
- $('.action').compiler(function($element) {
49
+ up.compiler('.action', function($element) {
50
50
  // your code here
51
51
  });
52
52
 
53
- Compiler functions will be called on matching elements when
53
+ The functions will be called on elements maching `.action` when
54
54
  the page loads, or whenever a matching fragment is [updated through Unpoly](/up.replace)
55
55
  later.
56
56
 
@@ -135,7 +135,7 @@ up.syntax = (($) ->
135
135
  { lat: 48.75, lng: 11.45, title: 'Ingolstadt' }
136
136
  ]"></div>
137
137
 
138
- The JSON will parsed and handed to your event handler as a second argument:
138
+ The JSON will parsed and handed to your compiler as a second argument:
139
139
 
140
140
  up.compiler('.google-map', function($element, pins) {
141
141
 
@@ -195,7 +195,7 @@ up.syntax = (($) ->
195
195
  @param {Function($element, data)} compiler
196
196
  The function to call when a matching element is inserted.
197
197
  The function takes the new element as the first argument (as a jQuery object).
198
- If the element has an `up-data` attribute, its value is parsed as JSON
198
+ If the element has an [`up-data`](/up-data) attribute, its value is parsed as JSON
199
199
  and passed as a second argument.
200
200
 
201
201
  The function may return a destructor function that destroys the compiled
@@ -324,11 +324,21 @@ up.syntax = (($) ->
324
324
  destroyer()
325
325
 
326
326
  ###*
327
- Checks if the given element has an `up-data` attribute.
327
+ Checks if the given element has an [`up-data`](/up-data) attribute.
328
328
  If yes, parses the attribute value as JSON and returns the parsed object.
329
329
 
330
330
  Returns an empty object if the element has no `up-data` attribute.
331
331
 
332
+ \#\#\#\# Example
333
+
334
+ You have an element with JSON data serialized into an `up-data` attribute:
335
+
336
+ <span class="person" up-data="{ age: 18, name: 'Bob' }">Bob</span>
337
+
338
+ Calling `up.syntax.data` will deserialize the JSON string into a Javascript object:
339
+
340
+ up.syntax.data('.person') // returns { age: 18, name: 'Bob' }
341
+
332
342
  @function up.syntax.data
333
343
  @param {String|Element|jQuery} elementOrSelector
334
344
  @return
@@ -338,15 +348,44 @@ up.syntax = (($) ->
338
348
  @experimental
339
349
  ###
340
350
 
341
- ###
351
+ ###*
342
352
  If an element annotated with [`up-data`] is inserted into the DOM,
343
353
  Up will parse the JSON and pass the resulting object to any matching
344
- [`up.compiler`](/up.syntax.compiler) handlers.
354
+ [`up.compiler`](/up.compiler) handlers.
355
+
356
+ For instance, a container for a [Google Map](https://developers.google.com/maps/documentation/javascript/tutorial)
357
+ might attach the location and names of its marker pins:
358
+
359
+ <div class="google-map" up-data="[
360
+ { lat: 48.36, lng: 10.99, title: 'Friedberg' },
361
+ { lat: 48.75, lng: 11.45, title: 'Ingolstadt' }
362
+ ]"></div>
363
+
364
+ The JSON will parsed and handed to your compiler as a second argument:
365
+
366
+ up.compiler('.google-map', function($element, pins) {
367
+
368
+ var map = new google.maps.Map($element);
369
+
370
+ pins.forEach(function(pin) {
371
+ var position = new google.maps.LatLng(pin.lat, pin.lng);
372
+ new google.maps.Marker({
373
+ position: position,
374
+ map: map,
375
+ title: pin.title
376
+ });
377
+ });
378
+
379
+ });
345
380
 
346
381
  Similarly, when an event is triggered on an element annotated with
347
382
  [`up-data`], the parsed object will be passed to any matching
348
383
  [`up.on`](/up.on) handlers.
349
384
 
385
+ up.on('click', '.google-map', function(event, $element, pins) {
386
+ console.log("There are %d pins on the clicked map", pins.length);
387
+ });
388
+
350
389
  @selector [up-data]
351
390
  @param {JSON} up-data
352
391
  A serialized JSON string
@@ -943,6 +943,7 @@ up.util = (($) ->
943
943
  if opts.relative == true
944
944
  coordinates = $element.position()
945
945
  else
946
+ # A relative context element is given
946
947
  $context = $(opts.relative)
947
948
  elementCoords = $element.offset()
948
949
  if $context.is(document)
@@ -968,9 +969,9 @@ up.util = (($) ->
968
969
  box.height = $element.outerHeight()
969
970
 
970
971
  if opts.full
971
- viewport = clientSize()
972
- box.right = viewport.width - (box.left + box.width)
973
- box.bottom = viewport.height - (box.top + box.height)
972
+ $viewport = up.layout.viewportOf($element)
973
+ box.right = $viewport.width() - (box.left + box.width)
974
+ box.bottom = $viewport.height() - (box.top + box.height)
974
975
  box
975
976
 
976
977
  ###*
@@ -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.22.0'
7
+ VERSION = '0.22.1'
8
8
  end
9
9
  end
@@ -49,15 +49,16 @@ describe 'up.link', ->
49
49
  # so we don't lose the Jasmine runner interface.
50
50
  up.history.config.popTargets = ['.container']
51
51
 
52
- respondWith = (html) =>
52
+ respondWith = (html, title) =>
53
53
  @lastRequest().respondWith
54
54
  status: 200
55
55
  contentType: 'text/html'
56
56
  responseText: "<div class='container'><div class='target'>#{html}</div></div>"
57
+ responseHeaders: { 'X-Up-Title': title }
57
58
 
58
- followAndRespond = ($link, html) ->
59
+ followAndRespond = ($link, html, title) ->
59
60
  promise = up.follow($link)
60
- respondWith(html)
61
+ respondWith(html, title)
61
62
  promise
62
63
 
63
64
  $link1 = affix('a[href="/one"][up-target=".target"]')
@@ -66,35 +67,41 @@ describe 'up.link', ->
66
67
  $container = affix('.container')
67
68
  $target = affix('.target').appendTo($container).text('original text')
68
69
 
69
- followAndRespond($link1, 'text from one').then =>
70
+ followAndRespond($link1, 'text from one', 'title from one').then =>
70
71
  expect($('.target')).toHaveText('text from one')
71
72
  expect(location.pathname).toEqual('/one')
73
+ expect(document.title).toEqual('title from one')
72
74
 
73
- followAndRespond($link2, 'text from two').then =>
75
+ followAndRespond($link2, 'text from two', 'title from two').then =>
74
76
  expect($('.target')).toHaveText('text from two')
75
77
  expect(location.pathname).toEqual('/two')
78
+ expect(document.title).toEqual('title from two')
76
79
 
77
- followAndRespond($link3, 'text from three').then =>
80
+ followAndRespond($link3, 'text from three', 'title from three').then =>
78
81
  expect($('.target')).toHaveText('text from three')
79
82
  expect(location.pathname).toEqual('/three')
83
+ expect(document.title).toEqual('title from three')
80
84
 
81
85
  history.back()
82
86
  @setTimer 50, =>
83
- respondWith('restored text from two')
87
+ respondWith('restored text from two', 'restored title from two')
84
88
  expect($('.target')).toHaveText('restored text from two')
85
89
  expect(location.pathname).toEqual('/two')
90
+ expect(document.title).toEqual('restored title from two')
86
91
 
87
92
  history.back()
88
93
  @setTimer 50, =>
89
- respondWith('restored text from one')
94
+ respondWith('restored text from one', 'restored title from one')
90
95
  expect($('.target')).toHaveText('restored text from one')
91
96
  expect(location.pathname).toEqual('/one')
97
+ expect(document.title).toEqual('restored title from one')
92
98
 
93
99
  history.forward()
94
100
  @setTimer 50, =>
95
101
  # Since the response is cached, we don't have to respond
96
- expect($('.target')).toHaveText('restored text from two')
102
+ expect($('.target')).toHaveText('restored text from two', 'restored title from two')
97
103
  expect(location.pathname).toEqual('/two')
104
+ expect(document.title).toEqual('restored title from two')
98
105
 
99
106
  done()
100
107
 
@@ -190,6 +197,27 @@ describe 'up.link', ->
190
197
  up.follow($link)
191
198
  expect(up.browser.loadPage).toHaveBeenCalledWith('/path', { method: 'PUT' })
192
199
 
200
+ describe 'up.link.makeFollowable', ->
201
+
202
+ it "adds [up-follow] to a link that wouldn't otherwise be handled by Unpoly", ->
203
+ $link = affix('a[href="/path"]').text('label')
204
+ up.link.makeFollowable($link)
205
+ expect($link.attr('up-follow')).toEqual('')
206
+
207
+ it "does not add [up-follow] to a link that is already [up-target]", ->
208
+ $link = affix('a[href="/path"][up-target=".target"]').text('label')
209
+ up.link.makeFollowable($link)
210
+ expect($link.attr('up-follow')).toBeMissing()
211
+
212
+ it "does not add [up-follow] to a link that is already [up-modal]", ->
213
+ $link = affix('a[href="/path"][up-modal=".target"]').text('label')
214
+ up.link.makeFollowable($link)
215
+ expect($link.attr('up-follow')).toBeMissing()
216
+
217
+ it "does not add [up-follow] to a link that is already [up-popup]", ->
218
+ $link = affix('a[href="/path"][up-popup=".target"]').text('label')
219
+ up.link.makeFollowable($link)
220
+ expect($link.attr('up-follow')).toBeMissing()
193
221
 
194
222
  describe 'up.visit', ->
195
223
 
@@ -301,6 +329,48 @@ describe 'up.link', ->
301
329
  Trigger.mousedown(@$link, metaKey: true)
302
330
  expect(@followSpy).not.toHaveBeenCalled()
303
331
 
332
+ describe '[up-dash]', ->
333
+
334
+ it "is a shortcut for [up-preload], [up-instant] and [up-target], using [up-dash]'s value as [up-target]", ->
335
+ $link = affix('a[href="/path"][up-dash=".target"]').text('label')
336
+ up.hello($link)
337
+ expect($link.attr('up-preload')).toEqual('')
338
+ expect($link.attr('up-instant')).toEqual('')
339
+ expect($link.attr('up-target')).toEqual('.target')
340
+
341
+ it "adds [up-follow] attribute if [up-dash]'s value is 'true'", ->
342
+ $link = affix('a[href="/path"][up-dash="true"]').text('label')
343
+ up.hello($link)
344
+ expect($link.attr('up-follow')).toEqual('')
345
+
346
+ it "adds [up-follow] attribute if [up-dash] is present, but has no value", ->
347
+ $link = affix('a[href="/path"][up-dash]').text('label')
348
+ up.hello($link)
349
+ expect($link.attr('up-follow')).toEqual('')
350
+
351
+ it "does not add an [up-follow] attribute if [up-dash] is 'true', but [up-target] is present", ->
352
+ $link = affix('a[href="/path"][up-dash="true"][up-target=".target"]').text('label')
353
+ up.hello($link)
354
+ expect($link.attr('up-follow')).toBeMissing()
355
+ expect($link.attr('up-target')).toEqual('.target')
356
+
357
+ it "does not add an [up-follow] attribute if [up-dash] is 'true', but [up-modal] is present", ->
358
+ $link = affix('a[href="/path"][up-dash="true"][up-modal=".target"]').text('label')
359
+ up.hello($link)
360
+ expect($link.attr('up-follow')).toBeMissing()
361
+ expect($link.attr('up-modal')).toEqual('.target')
362
+
363
+ it "does not add an [up-follow] attribute if [up-dash] is 'true', but [up-popup] is present", ->
364
+ $link = affix('a[href="/path"][up-dash="true"][up-popup=".target"]').text('label')
365
+ up.hello($link)
366
+ expect($link.attr('up-follow')).toBeMissing()
367
+ expect($link.attr('up-popup')).toEqual('.target')
368
+
369
+ it "removes the [up-dash] attribute when it's done", ->
370
+ $link = affix('a[href="/path"]').text('label')
371
+ up.hello($link)
372
+ expect($link.attr('up-dash')).toBeMissing()
373
+
304
374
  describe '[up-expand]', ->
305
375
 
306
376
  it 'copies up-related attributes of a contained link', ->
@@ -332,6 +402,31 @@ describe 'up.link', ->
332
402
  up.hello($area)
333
403
  expect($area.attr('up-follow')).toEqual('')
334
404
 
405
+ it 'can be used to enlarge the click area of a link', ->
406
+ $area = affix('div[up-expand] a[href="/path"]')
407
+ up.hello($area)
408
+ spyOn(up, 'replace')
409
+ $area.get(0).click()
410
+ expect(up.replace).toHaveBeenCalled()
411
+
412
+ it 'does not trigger multiple replaces when the user clicks on the expanded area of an up-instant link (bugfix)', ->
413
+ $area = affix('div[up-expand] a[href="/path"][up-instant]')
414
+ up.hello($area)
415
+ spyOn(up, 'replace')
416
+ Trigger.mousedown($area)
417
+ Trigger.click($area)
418
+ expect(up.replace.calls.count()).toEqual(1)
419
+
420
+ it 'does not add an up-follow attribute if the expanded link is [up-dash] with a selector (bugfix)', ->
421
+ $area = affix('div[up-expand] a[href="/path"][up-dash=".element"]')
422
+ up.hello($area)
423
+ expect($area.attr('up-follow')).toBeMissing()
424
+
425
+ it 'does not an up-follow attribute if the expanded link is [up-dash] without a selector (bugfix)', ->
426
+ $area = affix('div[up-expand] a[href="/path"][up-dash]')
427
+ up.hello($area)
428
+ expect($area.attr('up-follow')).toEqual('')
429
+
335
430
  describe 'with a CSS selector in the property value', ->
336
431
 
337
432
  it "expands the contained link that matches the selector", ->
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.22.0
4
+ version: 0.22.1
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-03-14 00:00:00.000000000 Z
11
+ date: 2016-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails