unpoly-rails 0.22.1 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/design/positioning.txt +28 -0
  4. data/dist/unpoly.css +27 -20
  5. data/dist/unpoly.js +171 -59
  6. data/dist/unpoly.min.css +1 -1
  7. data/dist/unpoly.min.js +3 -3
  8. data/lib/assets/javascripts/unpoly/browser.js.coffee +12 -0
  9. data/lib/assets/javascripts/unpoly/bus.js.coffee +21 -22
  10. data/lib/assets/javascripts/unpoly/form.js.coffee +9 -5
  11. data/lib/assets/javascripts/unpoly/layout.js.coffee +3 -2
  12. data/lib/assets/javascripts/unpoly/link.js.coffee +3 -2
  13. data/lib/assets/javascripts/unpoly/navigation.js.coffee +2 -2
  14. data/lib/assets/javascripts/unpoly/proxy.js.coffee +11 -9
  15. data/lib/assets/javascripts/unpoly/tooltip.js.coffee +9 -2
  16. data/lib/assets/javascripts/unpoly/util.js.coffee +79 -11
  17. data/lib/assets/stylesheets/unpoly/tooltip.css.sass +32 -22
  18. data/lib/unpoly/rails/version.rb +1 -1
  19. data/spec_app/Gemfile.lock +1 -1
  20. data/spec_app/app/assets/images/grid.png +0 -0
  21. data/spec_app/app/assets/javascripts/integration_test.coffee +2 -0
  22. data/spec_app/app/assets/javascripts/jasmine_specs.coffee +7 -0
  23. data/spec_app/app/assets/stylesheets/integration_test.sass +24 -0
  24. data/spec_app/app/assets/stylesheets/jasmine_specs.sass +1 -0
  25. data/spec_app/app/controllers/{test_controller.rb → binding_test_controller.rb} +1 -1
  26. data/spec_app/app/controllers/css_test_controller.rb +5 -0
  27. data/spec_app/app/controllers/form_test/basics_controller.rb +14 -0
  28. data/spec_app/app/controllers/form_test/uploads_controller.rb +15 -0
  29. data/spec_app/app/controllers/pages_controller.rb +5 -0
  30. data/spec_app/app/views/css_test/tooltip.erb +15 -0
  31. data/spec_app/app/views/form_test/basics/new.erb +33 -0
  32. data/spec_app/app/views/form_test/submission_result.erb +30 -0
  33. data/spec_app/app/views/form_test/uploads/new.erb +27 -0
  34. data/spec_app/app/views/layouts/integration_test.erb +14 -0
  35. data/spec_app/app/views/pages/start.erb +25 -0
  36. data/spec_app/config/initializers/assets.rb +4 -1
  37. data/spec_app/config/routes.rb +8 -2
  38. data/spec_app/spec/controllers/{test_controller_spec.rb → binding_test_controller_spec.rb} +1 -1
  39. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +9 -0
  40. data/spec_app/spec/javascripts/support/jasmine.yml +2 -2
  41. data/spec_app/spec/javascripts/up/form_spec.js.coffee +21 -1
  42. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +54 -17
  43. metadata +21 -13
  44. data/spec_app/app/assets/javascripts/application.js +0 -20
  45. data/spec_app/app/assets/stylesheets/application.css +0 -17
  46. data/spec_app/app/assets/stylesheets/blocks/card.css.sass +0 -11
  47. data/spec_app/app/assets/stylesheets/blocks/controls.css.sass +0 -7
  48. data/spec_app/app/assets/stylesheets/blocks/menu.css.sass +0 -13
  49. data/spec_app/app/assets/stylesheets/blocks/panel.css.sass +0 -8
  50. data/spec_app/app/assets/stylesheets/jasmine_specs.css +0 -5
  51. data/spec_app/app/controllers/concerns/.keep +0 -0
  52. data/spec_app/app/views/layouts/application.html.erb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6109418137600ed7280a7f3ecb2adb7ab5da2b4f
4
- data.tar.gz: 118d634ab654710610a010e42d0d55223cd65a6b
3
+ metadata.gz: ec9d0678d3c0fa042de8cb5e10f94014dfbe7f36
4
+ data.tar.gz: 28e851c819c201c8e65fd1e1945a3b44f4310e56
5
5
  SHA512:
6
- metadata.gz: 4bd0e2d984e5c55654d201fd095eb4424105000d46f1d22273190f8fea325189a9727152a16d5bf549eb9a990f49f3ef9f5366ff06260b012ad81b7343629e87
7
- data.tar.gz: 4f8a3ba9acf52274f0a26a21a600e4d0092694366b935de0ba1e992283f43bbf7b2b6979ef844335ab9d7bf16e985362da3ae3a0c67848ee4ff2ef5425730698
6
+ metadata.gz: 8a70cad251b68e888be109193209eea3101aab04efb98a62abd0e2a282ef10977f64569c208cbd9041c4f7c9bc74ea5147e140341badf15b5f58c91eb1e4efc8
7
+ data.tar.gz: 6b13838de87ece08a23be26531c3bfa0258cffc958f3495d0a692288bba6bf3859c55e020cd63c15842c37227e5f618c3484415c9530e3dd19912797b6e001c3
data/CHANGELOG.md CHANGED
@@ -14,6 +14,21 @@ Unreleased
14
14
  ### Breaking changes
15
15
 
16
16
 
17
+ 0.23.0
18
+ ------
19
+
20
+ ### Compatible changes
21
+
22
+ - Unpoly forms can now [submit](/up.submit) file uploads via AJAX.
23
+ - You can now position [tooltips](/up-tooltip) on the left or right side of an element.
24
+
25
+
26
+ ### Breaking changes
27
+
28
+ - Tooltips have a darker background color.
29
+ - The tooltip CSS has been changed to be easier to override.
30
+
31
+
17
32
  0.22.1
18
33
  ------
19
34
 
@@ -0,0 +1,28 @@
1
+ Macht es jemals sinn von rechts oder von rechts zu positionieren?
2
+ Wenn dann Inhalt unten dran kommt verschiebt sich alles?
3
+
4
+
5
+
6
+ Tooltip
7
+ top { left, top
8
+ right
9
+ bottom
10
+ left
11
+
12
+ Popup
13
+ top-left then stretch rightwards
14
+ bottom-left then stretch rightwards
15
+ top-right then stretch leftwards
16
+ bottom-right then stretch leftwards
17
+
18
+
19
+ Popup
20
+ Menu?
21
+ Context?
22
+ Dropdown?
23
+ Popover?
24
+
25
+
26
+
27
+ up.positioning
28
+
data/dist/unpoly.css CHANGED
@@ -62,37 +62,44 @@
62
62
  padding: 15px;
63
63
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); }
64
64
  .up-tooltip {
65
- z-index: 30000;
66
65
  position: absolute;
67
- background-color: #666;
66
+ z-index: 30000;
67
+ background-color: #111;
68
68
  color: white;
69
69
  padding: 6px 9px;
70
70
  white-space: nowrap; }
71
+ .up-tooltip:after {
72
+ content: "";
73
+ position: absolute;
74
+ display: block;
75
+ width: 0;
76
+ height: 0;
77
+ border: 8px solid transparent; }
71
78
  .up-tooltip[up-position=top] {
72
79
  margin-top: -6px; }
73
80
  .up-tooltip[up-position=top]:after {
74
- content: "";
75
- position: absolute;
76
- border-style: solid;
77
- border-width: 8px 8px 0;
78
- border-color: #666 transparent;
79
- display: block;
80
- width: 0;
81
- z-index: 1;
82
- bottom: -8px;
81
+ border-top-color: #111;
82
+ bottom: -16px;
83
83
  left: 50%;
84
84
  margin-left: -8px; }
85
+ .up-tooltip[up-position=left] {
86
+ margin-left: -6px; }
87
+ .up-tooltip[up-position=left]:after {
88
+ border-left-color: #111;
89
+ right: -16px;
90
+ top: 50%;
91
+ margin-top: -8px; }
92
+ .up-tooltip[up-position=right] {
93
+ margin-left: 6px; }
94
+ .up-tooltip[up-position=right]:after {
95
+ border-right-color: #111;
96
+ left: -16px;
97
+ top: 50%;
98
+ margin-top: -8px; }
85
99
  .up-tooltip[up-position=bottom] {
86
100
  margin-top: 6px; }
87
101
  .up-tooltip[up-position=bottom]:after {
88
- content: "";
89
- position: absolute;
90
- border-style: solid;
91
- border-width: 0 8px 8px;
92
- border-color: #666 transparent;
93
- display: block;
94
- width: 0;
95
- z-index: 1;
96
- top: -8px;
102
+ border-bottom-color: #111;
103
+ top: -16px;
97
104
  left: 50%;
98
105
  margin-left: -8px; }
data/dist/unpoly.js CHANGED
@@ -27,7 +27,7 @@ that might save you from loading something like [Underscore.js](http://underscor
27
27
  @function up.util.memoize
28
28
  @internal
29
29
  */
30
- var $createElementFromSelector, $createPlaceholder, ANIMATION_DEFERRED_KEY, all, any, cache, castedAttr, clientSize, compact, config, contains, copy, copyAttributes, createElement, createElementFromHtml, cssAnimate, detect, each, error, escapePressed, except, extend, findWithSelf, finishCssAnimate, fixedToAbsolute, forceCompositing, intersect, isArray, isBlank, isDeferred, isDefined, isElement, isFunction, isGiven, isHash, isJQuery, isMissing, isNull, isNumber, isObject, isPresent, isPromise, isStandardPort, isString, isUndefined, isUnmodifiedKeyEvent, isUnmodifiedMouseEvent, last, locationFromXhr, map, measure, memoize, merge, methodFromXhr, multiSelector, nextFrame, nonUpClasses, normalizeMethod, normalizeUrl, nullJQuery, offsetParent, once, only, option, options, parseUrl, pluckData, presence, presentAttr, reject, remove, requestDataAsArray, requestDataAsQuery, resolvableWhen, resolvedDeferred, resolvedPromise, scrollbarWidth, select, selectorForElement, setMissingAttrs, temporaryCss, times, titleFromXhr, toArray, trim, unJQuery, uniq, unresolvableDeferred, unresolvablePromise, unwrapElement;
30
+ var $createElementFromSelector, $createPlaceholder, ANIMATION_DEFERRED_KEY, all, any, appendRequestData, cache, castedAttr, clientSize, compact, config, contains, copy, copyAttributes, createElement, createElementFromHtml, cssAnimate, detect, each, error, escapePressed, except, extend, findWithSelf, finishCssAnimate, fixedToAbsolute, forceCompositing, intersect, isArray, isBlank, isDeferred, isDefined, isElement, isFormData, isFunction, isGiven, isHash, isJQuery, isMissing, isNull, isNumber, isObject, isPresent, isPromise, isStandardPort, isString, isUndefined, isUnmodifiedKeyEvent, isUnmodifiedMouseEvent, last, locationFromXhr, map, measure, memoize, merge, methodFromXhr, multiSelector, nextFrame, nonUpClasses, normalizeMethod, normalizeUrl, nullJQuery, offsetParent, once, only, option, options, parseUrl, pluckData, presence, presentAttr, reject, remove, requestDataAsArray, requestDataAsQuery, requestDataFromForm, resolvableWhen, resolvedDeferred, resolvedPromise, scrollbarWidth, select, selectorForElement, setMissingAttrs, temporaryCss, times, titleFromXhr, toArray, trim, unJQuery, uniq, unresolvableDeferred, unresolvablePromise, unwrapElement;
31
31
  memoize = function(func) {
32
32
  var cache, cached;
33
33
  cache = void 0;
@@ -602,6 +602,20 @@ that might save you from loading something like [Underscore.js](http://underscor
602
602
  return Object.prototype.toString.call(object) === '[object Array]';
603
603
  };
604
604
 
605
+ /**
606
+ Returns whether the given argument is a `FormData` instance.
607
+
608
+ Always returns `false` in browsers that don't support `FormData`.
609
+
610
+ @function up.util.isFormData
611
+ @param object
612
+ @return {Boolean}
613
+ @internal
614
+ */
615
+ isFormData = function(object) {
616
+ return up.browser.canFormData() && object instanceof FormData;
617
+ };
618
+
605
619
  /**
606
620
  Converts the given array-like argument into an array.
607
621
 
@@ -1732,20 +1746,24 @@ that might save you from loading something like [Underscore.js](http://underscor
1732
1746
  */
1733
1747
  requestDataAsArray = function(data) {
1734
1748
  var array, i, len, pair, part, query, ref;
1735
- query = requestDataAsQuery(data);
1736
- array = [];
1737
- ref = query.split('&');
1738
- for (i = 0, len = ref.length; i < len; i++) {
1739
- part = ref[i];
1740
- if (isPresent(part)) {
1741
- pair = part.split('=');
1742
- array.push({
1743
- name: decodeURIComponent(pair[0]),
1744
- value: decodeURIComponent(pair[1])
1745
- });
1749
+ if (isFormData(data)) {
1750
+ return up.error('Cannot convert FormData into an array');
1751
+ } else {
1752
+ query = requestDataAsQuery(data);
1753
+ array = [];
1754
+ ref = query.split('&');
1755
+ for (i = 0, len = ref.length; i < len; i++) {
1756
+ part = ref[i];
1757
+ if (isPresent(part)) {
1758
+ pair = part.split('=');
1759
+ array.push({
1760
+ name: decodeURIComponent(pair[0]),
1761
+ value: decodeURIComponent(pair[1])
1762
+ });
1763
+ }
1746
1764
  }
1765
+ return array;
1747
1766
  }
1748
- return array;
1749
1767
  };
1750
1768
 
1751
1769
  /**
@@ -1757,7 +1775,9 @@ that might save you from loading something like [Underscore.js](http://underscor
1757
1775
  */
1758
1776
  requestDataAsQuery = function(data) {
1759
1777
  var query;
1760
- if (data) {
1778
+ if (isFormData(data)) {
1779
+ return up.error('Cannot convert FormData into a query string');
1780
+ } else if (isPresent(data)) {
1761
1781
  query = $.param(data);
1762
1782
  query = query.replace(/\+/g, '%20');
1763
1783
  return query;
@@ -1766,6 +1786,64 @@ that might save you from loading something like [Underscore.js](http://underscor
1766
1786
  }
1767
1787
  };
1768
1788
 
1789
+ /**
1790
+ Serializes the given form into a request data representation.
1791
+
1792
+ @function up.util.requestDataFromForm
1793
+ @return {Array|FormData}
1794
+ @internal
1795
+ */
1796
+ requestDataFromForm = function(form) {
1797
+ var $form, hasFileInputs;
1798
+ $form = $(form);
1799
+ hasFileInputs = $form.find('input[type=file]').length;
1800
+ if (hasFileInputs && up.browser.canFormData()) {
1801
+ return new FormData($form.get(0));
1802
+ } else {
1803
+ return $form.serializeArray();
1804
+ }
1805
+ };
1806
+
1807
+ /**
1808
+ Adds a key/value pair to the given request data representation.
1809
+
1810
+ This mutates the given `data` if `data` is a `FormData`, an object
1811
+ or an array. When `data` is `String` a new string with the appended key/value
1812
+ pair is returned.
1813
+
1814
+ @function up.util.appendRequestData
1815
+ @param {FormData|Object|Array|Undefined|Null} data
1816
+ @param {String} key
1817
+ @param {String|Blob|File} value
1818
+ @internal
1819
+ */
1820
+ appendRequestData = function(data, name, value) {
1821
+ var newPair;
1822
+ if (isFormData(data)) {
1823
+ data.append(name, value);
1824
+ } else if (isArray(data)) {
1825
+ data.push({
1826
+ name: name,
1827
+ value: value
1828
+ });
1829
+ } else if (isObject(data)) {
1830
+ data[name] = value;
1831
+ } else if (isString(data) || isMissing(data)) {
1832
+ newPair = requestDataAsQuery([
1833
+ {
1834
+ name: name,
1835
+ value: value
1836
+ }
1837
+ ]);
1838
+ if (isPresent(data)) {
1839
+ data = [data, newPair].join('&');
1840
+ } else {
1841
+ data = newPair;
1842
+ }
1843
+ }
1844
+ return data;
1845
+ };
1846
+
1769
1847
  /**
1770
1848
  Throws a fatal error with the given message.
1771
1849
 
@@ -1800,6 +1878,8 @@ that might save you from loading something like [Underscore.js](http://underscor
1800
1878
  return {
1801
1879
  requestDataAsArray: requestDataAsArray,
1802
1880
  requestDataAsQuery: requestDataAsQuery,
1881
+ appendRequestData: appendRequestData,
1882
+ requestDataFromForm: requestDataFromForm,
1803
1883
  offsetParent: offsetParent,
1804
1884
  fixedToAbsolute: fixedToAbsolute,
1805
1885
  presentAttr: presentAttr,
@@ -1845,6 +1925,8 @@ that might save you from loading something like [Underscore.js](http://underscor
1845
1925
  isPromise: isPromise,
1846
1926
  isDeferred: isDeferred,
1847
1927
  isHash: isHash,
1928
+ isArray: isArray,
1929
+ isFormData: isFormData,
1848
1930
  isUnmodifiedKeyEvent: isUnmodifiedKeyEvent,
1849
1931
  isUnmodifiedMouseEvent: isUnmodifiedMouseEvent,
1850
1932
  nullJQuery: nullJQuery,
@@ -1859,7 +1941,6 @@ that might save you from loading something like [Underscore.js](http://underscor
1859
1941
  copyAttributes: copyAttributes,
1860
1942
  findWithSelf: findWithSelf,
1861
1943
  contains: contains,
1862
- isArray: isArray,
1863
1944
  toArray: toArray,
1864
1945
  castedAttr: castedAttr,
1865
1946
  locationFromXhr: locationFromXhr,
@@ -2016,7 +2097,7 @@ we can't currently get rid off.
2016
2097
  var slice = [].slice;
2017
2098
 
2018
2099
  up.browser = (function($) {
2019
- var CONSOLE_PLACEHOLDERS, canCssTransition, canInputEvent, canLogSubstitution, canPushState, confirm, initialRequestMethod, installPolyfills, isIE8OrWorse, isIE9OrWorse, isRecentJQuery, isSupported, loadPage, popCookie, puts, sprintf, u, url;
2100
+ var CONSOLE_PLACEHOLDERS, canCssTransition, canFormData, canInputEvent, canLogSubstitution, canPushState, confirm, initialRequestMethod, installPolyfills, isIE8OrWorse, isIE9OrWorse, isRecentJQuery, isSupported, loadPage, popCookie, puts, sprintf, u, url;
2020
2101
  u = up.util;
2021
2102
 
2022
2103
  /**
@@ -2178,6 +2259,18 @@ we can't currently get rid off.
2178
2259
  return 'oninput' in document.createElement('input');
2179
2260
  });
2180
2261
 
2262
+ /**
2263
+ Returns whether this browser supports the [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
2264
+ interface.
2265
+
2266
+ @function up.browser.canFormData
2267
+ @return {Boolean}
2268
+ @experimental
2269
+ */
2270
+ canFormData = u.memoize(function() {
2271
+ return !!window.FormData;
2272
+ });
2273
+
2181
2274
  /**
2182
2275
  Returns whether this browser supports
2183
2276
  [string substitution](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions)
@@ -2276,6 +2369,7 @@ we can't currently get rid off.
2276
2369
  canPushState: canPushState,
2277
2370
  canCssTransition: canCssTransition,
2278
2371
  canInputEvent: canInputEvent,
2372
+ canFormData: canFormData,
2279
2373
  canLogSubstitution: canLogSubstitution,
2280
2374
  isSupported: isSupported,
2281
2375
  installPolyfills: installPolyfills,
@@ -2321,14 +2415,13 @@ use the more convenient [`up.on`](/up.on):
2321
2415
  // the clicked <button> element
2322
2416
  });
2323
2417
 
2324
- This is roughly equivalent to binding an event listener to `document`
2325
- using jQuery's [`on`](http://api.jquery.com/on/).
2418
+ This improves jQuery's [`on`](http://api.jquery.com/on/) in multiple ways:
2326
2419
 
2327
2420
  - Event listeners on [unsupported browsers](/up.browser.isSupported) are silently discarded,
2328
2421
  leaving you with an application without Javascript. This is typically preferable to
2329
2422
  a soup of randomly broken Javascript in ancient browsers.
2330
2423
  - A jQuery object with the target element is automatically passed to the event handler
2331
- as a second argument.
2424
+ as a second argument. You no longer need to write `$(this)` in the handler function.
2332
2425
  - You use an [`up-data`](/up-data) attribute to [attach structured data](/up.on#attaching-structured-data)
2333
2426
  to observed elements.
2334
2427
 
@@ -2416,25 +2509,7 @@ using jQuery's [`on`](http://api.jquery.com/on/).
2416
2509
  console.log("This is %o who is %o years old", data.name, data.age);
2417
2510
  });
2418
2511
 
2419
- \#\#\#\# Migrating jQuery event handlers to `up.on`
2420
-
2421
- Within the event handler, Unpoly will bind `this` to the
2422
- native DOM element to help you migrate your existing jQuery code to
2423
- this new syntax.
2424
-
2425
- So if you had this before:
2426
-
2427
- $(document).on('click', '.button', function() {
2428
- $(this).something();
2429
- });
2430
-
2431
- ... you can simply copy the event handler to `up.on`:
2432
-
2433
- up.on('click', '.button', function() {
2434
- $(this).something();
2435
- });
2436
-
2437
- \#\#\#\# Stopping to listen
2512
+ \#\#\#\# Unbinding an event listener
2438
2513
 
2439
2514
  `up.on` returns a function that unbinds the event listeners when called:
2440
2515
 
@@ -2458,6 +2533,24 @@ using jQuery's [`on`](http://api.jquery.com/on/).
2458
2533
  // Unbind the listener
2459
2534
  up.off('click', listener)
2460
2535
 
2536
+ \#\#\#\# Migrating jQuery event handlers to `up.on`
2537
+
2538
+ Within the event handler, Unpoly will bind `this` to the
2539
+ native DOM element to help you migrate your existing jQuery code to
2540
+ this new syntax.
2541
+
2542
+ So if you had this before:
2543
+
2544
+ $(document).on('click', '.button', function() {
2545
+ $(this).something();
2546
+ });
2547
+
2548
+ ... you can simply copy the event handler to `up.on`:
2549
+
2550
+ up.on('click', '.button', function() {
2551
+ $(this).something();
2552
+ });
2553
+
2461
2554
  @function up.on
2462
2555
  @param {String} events
2463
2556
  A space-separated list of event names to bind.
@@ -3810,11 +3903,16 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
3810
3903
  @param {String|Element|jQuery} selectorOrElement
3811
3904
  @internal
3812
3905
  */
3813
- viewportOf = function(selectorOrElement) {
3906
+ viewportOf = function(selectorOrElement, options) {
3814
3907
  var $element, $viewport;
3908
+ if (options == null) {
3909
+ options = {};
3910
+ }
3815
3911
  $element = $(selectorOrElement);
3816
3912
  $viewport = viewportSelector().seekUp($element);
3817
- $viewport.length || u.error("Could not find viewport for %o", $element);
3913
+ if ($viewport.length === 0 && options.strict !== false) {
3914
+ u.error("Could not find viewport for %o", $element);
3915
+ }
3818
3916
  return $viewport;
3819
3917
  };
3820
3918
 
@@ -6070,15 +6168,15 @@ the user performs the click.
6070
6168
  show = function() { $element.show() };
6071
6169
  hide = function() { $element.hide() };
6072
6170
 
6073
- showOff = up.on('up:proxy:slow', show);
6074
- hideOff = up.on('up:proxy:recover', hide);
6171
+ up.on('up:proxy:slow', show);
6172
+ up.on('up:proxy:recover', hide);
6075
6173
 
6076
6174
  hide();
6077
6175
 
6078
6176
  // Clean up when the element is removed from the DOM
6079
6177
  return function() {
6080
- showOff();
6081
- hideOff();
6178
+ up.off('up:proxy:slow', show);
6179
+ up.off('up:proxy:recover', hide);
6082
6180
  };
6083
6181
 
6084
6182
  });
@@ -6140,14 +6238,14 @@ the user performs the click.
6140
6238
  request = u.copy(request);
6141
6239
  request.headers || (request.headers = {});
6142
6240
  request.headers['X-Up-Target'] = request.target;
6143
- request.data = u.requestDataAsArray(request.data);
6144
6241
  if (u.contains(config.wrapMethods, request.method)) {
6145
- request.data.push({
6146
- name: config.wrapMethodParam,
6147
- value: request.method
6148
- });
6242
+ request.data = u.appendRequestData(request.data, config.wrapMethodParam, request.method);
6149
6243
  request.method = 'POST';
6150
6244
  }
6245
+ if (u.isFormData(request.data)) {
6246
+ request.contentType = false;
6247
+ request.processData = false;
6248
+ }
6151
6249
  promise = $.ajax(request);
6152
6250
  promise.done(function(data, textStatus, xhr) {
6153
6251
  return responseReceived(request, xhr);
@@ -6308,8 +6406,8 @@ attribute. The value of this attribute is a CSS selector that indicates which pa
6308
6406
  fragment to update. The rest of the page will remain unchanged.
6309
6407
 
6310
6408
 
6311
- Exammple
6312
- --------
6409
+ Example
6410
+ -------
6313
6411
 
6314
6412
  Let's say we are rendering three pages with a tabbed navigation to switch between screens:
6315
6413
 
@@ -6702,6 +6800,7 @@ Read on
6702
6800
 
6703
6801
  /**
6704
6802
  Marks up the current link to be followed *as fast as possible*.
6803
+
6705
6804
  This is done by:
6706
6805
 
6707
6806
  - [Following the link through AJAX](/up-target) instead of a full page load
@@ -6930,7 +7029,7 @@ open dialogs with sub-forms, etc. all without losing form state.
6930
7029
  @stable
6931
7030
  */
6932
7031
  submit = function(formOrSelector, options) {
6933
- var $form, hasFileInputs, promise, target, url;
7032
+ var $form, canAjaxSubmit, canHistoryOption, hasFileInputs, promise, target, url;
6934
7033
  $form = $(formOrSelector).closest('form');
6935
7034
  options = u.options(options);
6936
7035
  target = u.option(options.target, $form.attr('up-target'), 'body');
@@ -6945,18 +7044,20 @@ open dialogs with sub-forms, etc. all without losing form state.
6945
7044
  options.cache = u.option(options.cache, u.castedAttr($form, 'up-cache'));
6946
7045
  options.restoreScroll = u.option(options.restoreScroll, u.castedAttr($form, 'up-restore-scroll'));
6947
7046
  options.origin = u.option(options.origin, $form);
6948
- options.data = $form.serializeArray();
7047
+ options.data = up.util.requestDataFromForm($form);
6949
7048
  options = u.merge(options, up.motion.animateOptions(options, $form));
6950
7049
  hasFileInputs = $form.find('input[type=file]').length;
7050
+ canAjaxSubmit = !hasFileInputs || u.isFormData(options.data);
7051
+ canHistoryOption = up.browser.canPushState() || options.history === false;
6951
7052
  if (options.validate) {
6952
7053
  options.headers || (options.headers = {});
6953
7054
  options.headers['X-Up-Validate'] = options.validate;
6954
- if (hasFileInputs) {
7055
+ if (!canAjaxSubmit) {
6955
7056
  return u.unresolvablePromise();
6956
7057
  }
6957
7058
  }
6958
7059
  $form.addClass('up-active');
6959
- if (hasFileInputs || (!up.browser.canPushState() && options.history !== false)) {
7060
+ if (!(canAjaxSubmit && canHistoryOption)) {
6960
7061
  $form.get(0).submit();
6961
7062
  return u.unresolvablePromise();
6962
7063
  }
@@ -8802,7 +8903,7 @@ The tooltip element is appended to the end of `<body>`.
8802
8903
  @property up.tooltip.config
8803
8904
  @param {String} [config.position]
8804
8905
  The default position of tooltips relative to the element.
8805
- Can be either `"top"` or `"bottom"`.
8906
+ Can be `'top'`, `'right'`, `'bottom'` or `'left'`.
8806
8907
  @param {String} [config.openAnimation='fade-in']
8807
8908
  The animation used to open a tooltip.
8808
8909
  @param {String} [config.closeAnimation='fade-out']
@@ -8828,6 +8929,16 @@ The tooltip element is appended to the end of `<body>`.
8828
8929
  left: linkBox.left + 0.5 * (linkBox.width - tooltipBox.width),
8829
8930
  top: linkBox.top - tooltipBox.height
8830
8931
  };
8932
+ case "left":
8933
+ return {
8934
+ left: linkBox.left - tooltipBox.width,
8935
+ top: linkBox.top + 0.5 * (linkBox.height - tooltipBox.height)
8936
+ };
8937
+ case "right":
8938
+ return {
8939
+ left: linkBox.left + linkBox.width,
8940
+ top: linkBox.top + 0.5 * (linkBox.height - tooltipBox.height)
8941
+ };
8831
8942
  case "bottom":
8832
8943
  return {
8833
8944
  left: linkBox.left + 0.5 * (linkBox.width - tooltipBox.width),
@@ -8864,7 +8975,8 @@ The tooltip element is appended to the end of `<body>`.
8864
8975
  @param {String} [options.html]
8865
8976
  The HTML to display in the tooltip.
8866
8977
  @param {String} [options.position='top']
8867
- The position of the tooltip. Known values are `top` and `bottom`.
8978
+ The position of the tooltip.
8979
+ Can be `'top'`, `'right'`, `'bottom'` or `'left'`.
8868
8980
  @param {String} [options.animation]
8869
8981
  The animation to use when opening the tooltip.
8870
8982
  @return {Promise}
@@ -8969,8 +9081,8 @@ The tooltip element is appended to the end of `<body>`.
8969
9081
  }).call(this);
8970
9082
 
8971
9083
  /**
8972
- Fast interaction feedback
8973
- =========================
9084
+ Navigation bars
9085
+ ===============
8974
9086
 
8975
9087
  Unpoly automatically marks up link elements with classes indicating that
8976
9088
  they are currently loading (class `up-active`) or linking