unpoly-rails 0.60.3 → 1.0.0

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.

Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -2
  3. data/CHANGELOG.md +84 -0
  4. data/README.md +1 -1
  5. data/Rakefile +11 -1
  6. data/dist/unpoly.js +226 -91
  7. data/dist/unpoly.min.js +4 -4
  8. data/lib/assets/javascripts/unpoly/browser.coffee.erb +10 -5
  9. data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +21 -12
  10. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +2 -2
  11. data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +1 -1
  12. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +11 -3
  13. data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +1 -0
  14. data/lib/assets/javascripts/unpoly/element.coffee.erb +9 -6
  15. data/lib/assets/javascripts/unpoly/event.coffee.erb +12 -4
  16. data/lib/assets/javascripts/unpoly/form.coffee.erb +85 -14
  17. data/lib/assets/javascripts/unpoly/fragment.coffee.erb +7 -3
  18. data/lib/assets/javascripts/unpoly/framework.coffee +7 -9
  19. data/lib/assets/javascripts/unpoly/link.coffee.erb +1 -1
  20. data/lib/assets/javascripts/unpoly/log.coffee +6 -2
  21. data/lib/assets/javascripts/unpoly/modal.coffee.erb +4 -2
  22. data/lib/assets/javascripts/unpoly/motion.coffee.erb +1 -1
  23. data/lib/assets/javascripts/unpoly/protocol.coffee +1 -1
  24. data/lib/assets/javascripts/unpoly/syntax.coffee.erb +3 -4
  25. data/lib/assets/javascripts/unpoly/util.coffee.erb +4 -2
  26. data/lib/assets/javascripts/unpoly/viewport.coffee.erb +26 -2
  27. data/lib/unpoly/rails/version.rb +1 -1
  28. data/package.json +1 -1
  29. data/spec_app/Gemfile +2 -4
  30. data/spec_app/Gemfile.lock +23 -27
  31. data/spec_app/app/views/compiler_test/timestamp.erb +1 -0
  32. data/spec_app/app/views/css_test/modal.erb +1 -1
  33. data/spec_app/app/views/css_test/popup.erb +1 -1
  34. data/spec_app/app/views/pages/start.erb +2 -1
  35. data/spec_app/app/views/replace_test/table.erb +16 -0
  36. data/spec_app/spec/javascripts/up/event_spec.js.coffee +34 -0
  37. data/spec_app/spec/javascripts/up/form_spec.js.coffee +128 -0
  38. data/spec_app/spec/javascripts/up/fragment_spec.js.coffee +36 -1
  39. data/spec_app/spec/javascripts/up/link_spec.js.coffee +7 -2
  40. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +23 -1
  41. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +2 -1
  42. data/spec_app/spec/javascripts/up/util_spec.js.coffee +28 -0
  43. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d297eb1edd21bf9c288e37bef6f5ddbfc2d1282e92e5bb7bf4326c01d7ea048
4
- data.tar.gz: dcf7b668e2a6ef3e41ad5e8bd5d5550588e2dcd4c922ca6876cce64f8c80b544
3
+ metadata.gz: 35e8d0b813a4cca7d75c07ddc4c71e86cb812603e30eaa5f0dffdde3ce0cdb7e
4
+ data.tar.gz: d347f58ceb2f9b96ebd6128de73fecd5452ddce462e4d6a8b204d423063a0239
5
5
  SHA512:
6
- metadata.gz: 0a083415b043d5a78c7ad32f08929115aa95099f5f4246916a6f0434e466e12588a6ac9b684ab1bcbcb007f91114adf993169a2e059ce619d3a0e3a60ea4c8c1
7
- data.tar.gz: 8e24600bf552ff77bcc0d2f12b68b264e3e7585cfe0113e4add4594c676d484fd748734c3399c2fe5d7866ac4f73b2d57d14b40e652f9fef7d1f59c8fccff7f1
6
+ metadata.gz: 5421ff4c7e59fae63661dfa909b84d4c90e307643334d0510bd1a418c820a182eb37c53d254afc211b9a59ab4debf7b9df03fb9b169c56127223c8167133543e
7
+ data.tar.gz: a968fe80575c7305480a96ae5898142133f62a9dfb3efb3f02e462b85ddc385da749c5a06a38bbf91ab4240513abde675bd03fb8fa5468ec8a9e4d058effbbf4
data/.ruby-version CHANGED
@@ -1,2 +1 @@
1
- 2.1.2
2
-
1
+ 2.3.8
data/CHANGELOG.md CHANGED
@@ -6,6 +6,90 @@ Changes to this project will be documented in this file.
6
6
  You may browse a formatted and hyperlinked version of this file at <https://unpoly.com/changes>.
7
7
 
8
8
 
9
+ 1.0.0
10
+ -----
11
+
12
+ For six years Unpoly has been released under a 0.x version number. To establish the maturity and stability of the project, we're releasing today's version as 1.0.0.
13
+
14
+ There are only three changes from 0.62.1:
15
+
16
+ - Fix a bug where `up.util.escapeHTML()`` would not escape single quotes.
17
+ - Unpoly will no longer wait a JavaScript execution task to boot after `DOMContentLoaded`. This may improve the stability of test suites that previously interacted with the page too soon.
18
+ - You may now disable the Unpoly banner in the development console with `up.log.config.banner = false`. (change by @hfjallemark).
19
+
20
+ This is the last release of the 0.x API line. We're tracking its code in the [`1.x-stable`](https://github.com/unpoly/unpoly/tree/1.x-stable), but expect little to no changes in the future.
21
+
22
+ The next release will be [Unpoly 2](https://triskweline.de/unpoly2-slides). It will include major (but mostly backwards compatible) renovations to its API, unlocking many use cases that were not possible with Unpoly 1.
23
+
24
+
25
+ 0.62.1
26
+ ------
27
+
28
+ This is another maintenance release while we're finishing [the next major version of Unpoly](https://groups.google.com/forum/#!topic/unpoly/FDdVjxbjNLg).
29
+
30
+ Community members were involved in every change of this release:
31
+
32
+ - [`up.submit()`](/up.submit) has a new options `{ params }`. It may be used to pass extra form [parameters](/up.Params) that will be submitted in addition to the parameters from the form. (fix by @robinvdvleuten)
33
+ - [`a[up-modal]`](/a-up-modal) will now honor an [`[up-cache]`](/a-up-target#up-cache) attribute on the same link. (fix by @adam12)
34
+ - Prevent destructor function from being called twice if [`up.destroy()`](/up.destroy) is called twice with the same element (reported by @kratob)
35
+ - On devices that don't show a vertical scrollbar, users can no longer scroll the underlying page while a [modal overlay](/up.modal) is open. (reported by @msurdi)
36
+
37
+
38
+ 0.62.0
39
+ ------
40
+
41
+ This release backports a number of accessibility improvements from [the next major version of Unpoly](https://groups.google.com/forum/#!topic/unpoly/FDdVjxbjNLg).
42
+ We encourage everyone to upgrade to this release in order to better support users with visual impairments.
43
+
44
+ The following changes are included:
45
+
46
+ - Links with an [`[up-instant]`](/a-up-instant) attribute can now be followed with the keyboard.
47
+ - Fragments that are being [destroyed](/up.destroy) now get an [`[aria-hidden=true]`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-hidden_attribute)
48
+ attribute while its disappearance is being animated. When a fragment is being swapped with a new version, the old fragment version is also
49
+ given `[aria-hidden=true]` while it's disappearing.
50
+ - [Modal dialogs](/up.modal) now get an [`[aria-modal=true]`](https://a11ysupport.io/tech/aria/aria-modal_attribute) attribute.
51
+
52
+ The next major version of Unpoly will include additional accessibility improvements. In particular the
53
+ new modal ("layer") implementation will implement all best practices for accessible dialogs.
54
+
55
+
56
+ 0.61.1
57
+ ------
58
+
59
+ This is a maintenance release while we're getting ready for [the next major version of Unpoly](https://groups.google.com/forum/#!topic/unpoly/FDdVjxbjNLg).
60
+
61
+ - Fix a bug where [`up.destroy()`](/up.destroy) wouldn't clean up the global jQuery cache. This is only relevant when using Unpoly together with jQuery.
62
+ - Fields outside a <form> are now recognized when they have a matching [form] attribute (fixes #85)
63
+ - [`up.form.fields()`](/up.form.fields) now accepts a jQuery collection as a first argument, as was already documented.
64
+
65
+
66
+ 0.61.0
67
+ ------
68
+
69
+ This release makes it easier to migrate to a recent version of Unpoly when your app still depends on jQuery.
70
+ Unpoly dropped its jQuery dependency with version 0.60.0, but retains optional jQuery support through functions like
71
+ [`up.$compiler()`](/up.$compiler) and [`up.$on()`](/up.$on). All Unpoly functions that take a native element as an
72
+ argument may also be called with a jQuery collection as an argument.
73
+
74
+ The following changes to the optional jQuery support were implemented:
75
+
76
+ - In an ES6 build pipeline, Unpoly's jQuery support no longer requires `window.jQuery` to be defined before
77
+ Unpoly is imported into the build. You still need to define `window.jQuery`, but you may do so at any time in your
78
+ scripts, regardless of load order.
79
+ - jQuery support functions like [`up.$compiler()`](/up.$compiler) now fail with a helpful message if the developer
80
+ forgets to define `window.jQuery`.
81
+
82
+ This release also exposes some convenience functions and selectors:
83
+
84
+ - New experimental function [`up.event.halt()`](/up.event.halt). It prevents the event from bubbling up the DOM.
85
+ It also prevents other event handlers bound on the same element. It also prevents the event's default action.
86
+ - New experimental function [`up.form.fields()`](/up.form.fields). It returns a list of form fields within the given element.
87
+ - The selector [`form[up-validate]`](/form-up-validate) is now supported. It performs
88
+ [server-side validation](/input-up-validate) when any fieldset within this form changes. Previously only the variant
89
+ [`input[up-validate]`](/input-up-validate) was supported.
90
+
91
+
92
+
9
93
  0.60.3
10
94
  ------
11
95
 
data/README.md CHANGED
@@ -31,7 +31,7 @@ Overview:
31
31
 
32
32
  Install dependencies for tests:
33
33
 
34
- - Install Ruby 2.1.2
34
+ - Install Ruby 2.3.8
35
35
  - Install Bundler by running `gem install bundler`
36
36
  - `cd` into `spec_app`
37
37
  - Install dependencies by running `bundle install`
data/Rakefile CHANGED
@@ -99,7 +99,7 @@ namespace :publish do
99
99
 
100
100
  desc 'Release new version to all package managers'
101
101
  task :release do
102
- Rake::Task['release'].invoke
102
+ Rake::Task['rubygems:publish'].invoke
103
103
  Rake::Task['npm:publish'].invoke
104
104
  end
105
105
 
@@ -108,6 +108,7 @@ namespace :publish do
108
108
  puts "Now remember to:"
109
109
  puts "- update unpoly.com so user see the updated CHANGELOG and CDN link"
110
110
  puts "- send a message to the e-mail group announcing the new release"
111
+ puts "- tweet a link to the CHANGELOG as @unpolyjs"
111
112
  end
112
113
 
113
114
  desc 'Build artifacts, push to git and release to package managers'
@@ -116,6 +117,15 @@ namespace :publish do
116
117
 
117
118
  end
118
119
 
120
+ namespace :rubygems do
121
+
122
+ task :publish do
123
+ puts 'Publishing to rubygems.org. If this seems to hang, enter your 2FA token.'
124
+ Rake::Task['release'].invoke
125
+ end
126
+
127
+ end
128
+
119
129
  namespace :npm do
120
130
 
121
131
  task :bump_version do
data/dist/unpoly.js CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  (function() {
7
7
  window.up = {
8
- version: "0.60.3"
8
+ version: "1.0.0"
9
9
  };
10
10
 
11
11
  }).call(this);
@@ -595,7 +595,7 @@ to not include another library in your asset bundle.
595
595
  @stable
596
596
  */
597
597
  isJQuery = function(object) {
598
- return up.browser.canJQuery() && (object instanceof jQuery);
598
+ return !!(object != null ? object.jquery : void 0);
599
599
  };
600
600
 
601
601
  /***
@@ -1305,7 +1305,8 @@ to not include another library in your asset bundle.
1305
1305
  "&": "&amp;",
1306
1306
  "<": "&lt;",
1307
1307
  ">": "&gt;",
1308
- '"': '&quot;'
1308
+ '"': '&quot;',
1309
+ "'": '&#x27;'
1309
1310
  };
1310
1311
 
1311
1312
  /***
@@ -1317,7 +1318,7 @@ to not include another library in your asset bundle.
1317
1318
  @stable
1318
1319
  */
1319
1320
  escapeHtml = function(string) {
1320
- return string.replace(/[&<>"]/g, function(char) {
1321
+ return string.replace(/[&<>"']/g, function(char) {
1321
1322
  return ESCAPE_HTML_ENTITY_MAP[char];
1322
1323
  });
1323
1324
  };
@@ -1898,8 +1899,10 @@ Internet Explorer 10 or lower
1898
1899
  */
1899
1900
 
1900
1901
  (function() {
1902
+ var slice = [].slice;
1903
+
1901
1904
  up.browser = (function() {
1902
- var canAnimationFrame, canConsole, canControlScrollRestoration, canCssTransition, canCustomElements, canDOMParser, canFormData, canInputEvent, canInspectFormData, canJQuery, canPromise, canPushState, isIE10OrWorse, isIE11, isSupported, navigate, popCookie, submitForm, u, url, whenConfirmed;
1905
+ var callJQuery, canAnimationFrame, canConsole, canControlScrollRestoration, canCssTransition, canCustomElements, canDOMParser, canFormData, canInputEvent, canInspectFormData, canJQuery, canPromise, canPushState, isIE10OrWorse, isIE11, isSupported, navigate, popCookie, submitForm, u, url, whenConfirmed;
1903
1906
  u = up.util;
1904
1907
 
1905
1908
  /***
@@ -2038,15 +2041,15 @@ Internet Explorer 10 or lower
2038
2041
  canCustomElements = u.memoize(function() {
2039
2042
  return !!window.customElements;
2040
2043
  });
2041
- canJQuery = u.memoize(function() {
2042
- return !!window.jQuery;
2043
- });
2044
2044
  canAnimationFrame = u.memoize(function() {
2045
2045
  return 'requestAnimationFrame' in window;
2046
2046
  });
2047
2047
  canControlScrollRestoration = u.memoize(function() {
2048
2048
  return 'scrollRestoration' in history;
2049
2049
  });
2050
+ canJQuery = function() {
2051
+ return !!window.jQuery;
2052
+ };
2050
2053
  popCookie = function(name) {
2051
2054
  var ref, value;
2052
2055
  value = (ref = document.cookie.match(new RegExp(name + "=(\\w+)"))) != null ? ref[1] : void 0;
@@ -2086,6 +2089,12 @@ Internet Explorer 10 or lower
2086
2089
  isSupported = function() {
2087
2090
  return !isIE10OrWorse() && canConsole() && canDOMParser() && canFormData() && canCssTransition() && canInputEvent() && canPromise() && canAnimationFrame();
2088
2091
  };
2092
+ callJQuery = function() {
2093
+ var args;
2094
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
2095
+ canJQuery() || up.fail("jQuery must be published as window.jQuery");
2096
+ return jQuery.apply(null, args);
2097
+ };
2089
2098
  return {
2090
2099
  url: url,
2091
2100
  navigate: navigate,
@@ -2094,11 +2103,12 @@ Internet Explorer 10 or lower
2094
2103
  canFormData: canFormData,
2095
2104
  canInspectFormData: canInspectFormData,
2096
2105
  canCustomElements: canCustomElements,
2097
- canJQuery: canJQuery,
2098
2106
  canControlScrollRestoration: canControlScrollRestoration,
2107
+ canJQuery: canJQuery,
2099
2108
  whenConfirmed: whenConfirmed,
2100
2109
  isSupported: isSupported,
2101
2110
  popCookie: popCookie,
2111
+ jQuery: callJQuery,
2102
2112
  isIE11: isIE11
2103
2113
  };
2104
2114
  })();
@@ -2346,7 +2356,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
2346
2356
  @function up.element.closest
2347
2357
  @param {Element} element
2348
2358
  The element on which to start the search.
2349
- @param {string}
2359
+ @param {string} selector
2350
2360
  The CSS selector to match.
2351
2361
  @return {Element|null|undefined} element
2352
2362
  The matching element.
@@ -2510,6 +2520,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
2510
2520
  [this WHATWG mailing list post](http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Apr/0094.html).
2511
2521
 
2512
2522
  @function up.element.show
2523
+ @param {Element} element
2513
2524
  @experimental
2514
2525
  */
2515
2526
  show = function(element) {
@@ -2548,8 +2559,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
2548
2559
  @param {Element} element
2549
2560
  The element for which to add or remove the class.
2550
2561
  @param {String} className
2551
- A boolean value to determine whether the class should be added or removed.
2552
- @param {String} state
2562
+ The class which should be added or removed.
2563
+ @param {Boolean} [newPresent]
2564
+ Pass `true` to add the class to the element or `false` to remove it.
2565
+
2553
2566
  If omitted, the class will be added if missing and removed if present.
2554
2567
  @experimental
2555
2568
  */
@@ -2762,11 +2775,11 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
2762
2775
  element.className // returns 'klass'
2763
2776
 
2764
2777
  @function up.element.affix
2765
- @params {Element} parent
2778
+ @param {Element} parent
2766
2779
  The parent to which to attach the created element.
2767
- @params {string} selector
2780
+ @param {string} selector
2768
2781
  The CSS selector from which to create an element.
2769
- @params {Object} attrs
2782
+ @param {Object} attrs
2770
2783
  An object of attributes to set on the created element.
2771
2784
  @param {Object} attrs.text
2772
2785
  The [text content](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) of the created element.
@@ -3419,32 +3432,32 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
3419
3432
  }
3420
3433
 
3421
3434
  BodyShifter.prototype.shift = function() {
3422
- var anchor, body, bodyRightPadding, bodyRightShift, elementRight, elementRightShift, i, len, overflowElement, ref, results, scrollbarWidth;
3423
- if (!up.viewport.rootHasVerticalScrollbar()) {
3424
- return;
3425
- }
3426
- body = document.body;
3435
+ var anchor, body, bodyRightPadding, bodyRightShift, elementRight, elementRightShift, i, len, overflowElement, ref, results, rootHadVerticalScrollbar, scrollbarWidth;
3436
+ rootHadVerticalScrollbar = up.viewport.rootHasVerticalScrollbar();
3427
3437
  overflowElement = up.viewport.rootOverflowElement();
3428
- scrollbarWidth = up.viewport.scrollbarWidth();
3429
- bodyRightPadding = e.styleNumber(body, 'paddingRight');
3430
- bodyRightShift = scrollbarWidth + bodyRightPadding;
3431
- this.unshiftFns.push(e.setTemporaryStyle(body, {
3432
- paddingRight: bodyRightShift
3433
- }));
3434
3438
  this.unshiftFns.push(e.setTemporaryStyle(overflowElement, {
3435
3439
  overflowY: 'hidden'
3436
3440
  }));
3437
- ref = up.viewport.anchoredRight();
3438
- results = [];
3439
- for (i = 0, len = ref.length; i < len; i++) {
3440
- anchor = ref[i];
3441
- elementRight = e.styleNumber(anchor, 'right');
3442
- elementRightShift = scrollbarWidth + elementRight;
3443
- results.push(this.unshiftFns.push(e.setTemporaryStyle(anchor, {
3444
- right: elementRightShift
3445
- })));
3441
+ if (rootHadVerticalScrollbar) {
3442
+ body = document.body;
3443
+ scrollbarWidth = up.viewport.scrollbarWidth();
3444
+ bodyRightPadding = e.styleNumber(body, 'paddingRight');
3445
+ bodyRightShift = scrollbarWidth + bodyRightPadding;
3446
+ this.unshiftFns.push(e.setTemporaryStyle(body, {
3447
+ paddingRight: bodyRightShift
3448
+ }));
3449
+ ref = up.viewport.anchoredRight();
3450
+ results = [];
3451
+ for (i = 0, len = ref.length; i < len; i++) {
3452
+ anchor = ref[i];
3453
+ elementRight = e.styleNumber(anchor, 'right');
3454
+ elementRightShift = scrollbarWidth + elementRight;
3455
+ results.push(this.unshiftFns.push(e.setTemporaryStyle(anchor, {
3456
+ right: elementRightShift
3457
+ })));
3458
+ }
3459
+ return results;
3446
3460
  }
3447
- return results;
3448
3461
  };
3449
3462
 
3450
3463
  BodyShifter.prototype.unshift = function() {
@@ -3774,7 +3787,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
3774
3787
 
3775
3788
  CompilePass.prototype.compileOneElement = function(compiler, element) {
3776
3789
  var compileArgs, data, destructorOrDestructors, elementArg, result;
3777
- elementArg = compiler.jQuery ? jQuery(element) : element;
3790
+ elementArg = compiler.jQuery ? up.browser.jQuery(element) : element;
3778
3791
  compileArgs = [elementArg];
3779
3792
  if (compiler.length !== 1) {
3780
3793
  data = up.syntax.data(element);
@@ -3788,7 +3801,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
3788
3801
 
3789
3802
  CompilePass.prototype.compileBatch = function(compiler, elements) {
3790
3803
  var compileArgs, dataList, elementsArgs, result;
3791
- elementsArgs = compiler.jQuery ? jQuery(elements) : elements;
3804
+ elementsArgs = compiler.jQuery ? up.browser.jQuery(elements) : elements;
3792
3805
  compileArgs = [elementsArgs];
3793
3806
  if (compiler.length !== 1) {
3794
3807
  dataList = u.map(elements, up.syntax.data);
@@ -4126,7 +4139,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
4126
4139
  element = e.closest(element, this.selector);
4127
4140
  }
4128
4141
  if (element) {
4129
- elementArg = this.jQuery ? jQuery(element) : element;
4142
+ elementArg = this.jQuery ? up.browser.jQuery(element) : element;
4130
4143
  args = [event, elementArg];
4131
4144
  expectedArgCount = this.callback.length;
4132
4145
  if (!(expectedArgCount === 1 || expectedArgCount === 2)) {
@@ -4683,8 +4696,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
4683
4696
 
4684
4697
  FollowVariant.prototype.onClick = function(event, link) {
4685
4698
  if (up.link.shouldProcessEvent(event, link)) {
4686
- if (e.matches(link, '[up-instant]')) {
4687
- return up.event.halt(event);
4699
+ if (e.matches(link, '[up-instant]') && link.upInstantSupported) {
4700
+ up.event.halt(event);
4701
+ link.upInstantSupported = false;
4688
4702
  } else {
4689
4703
  up.event.consumeAction(event);
4690
4704
  return this.followLink(link);
@@ -4696,6 +4710,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
4696
4710
 
4697
4711
  FollowVariant.prototype.onMousedown = function(event, link) {
4698
4712
  if (up.link.shouldProcessEvent(event, link)) {
4713
+ link.upInstantSupported = true;
4699
4714
  up.event.consumeAction(event);
4700
4715
  return this.followLink(link);
4701
4716
  }
@@ -5347,18 +5362,19 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
5347
5362
  if (u.isMissing(raw)) {
5348
5363
 
5349
5364
  } else if (raw instanceof this.constructor) {
5350
- return (ref = this.entries).push.apply(ref, raw.entries);
5365
+ (ref = this.entries).push.apply(ref, raw.entries);
5351
5366
  } else if (u.isArray(raw)) {
5352
- return (ref1 = this.entries).push.apply(ref1, raw);
5367
+ (ref1 = this.entries).push.apply(ref1, raw);
5353
5368
  } else if (u.isString(raw)) {
5354
- return this.addAllFromQuery(raw);
5369
+ this.addAllFromQuery(raw);
5355
5370
  } else if (u.isFormData(raw)) {
5356
- return this.addAllFromFormData(raw);
5371
+ this.addAllFromFormData(raw);
5357
5372
  } else if (u.isObject(raw)) {
5358
- return this.addAllFromObject(raw);
5373
+ this.addAllFromObject(raw);
5359
5374
  } else {
5360
- return up.fail("Unsupport params type: %o", raw);
5375
+ up.fail("Unsupport params type: %o", raw);
5361
5376
  }
5377
+ return this;
5362
5378
  };
5363
5379
 
5364
5380
  Params.prototype.addAllFromObject = function(object) {
@@ -6818,13 +6834,11 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6818
6834
  });
6819
6835
  isBooting = false;
6820
6836
  return up.event.onReady(function() {
6821
- return u.task(function() {
6822
- up.emit('up:app:boot', {
6823
- log: 'Booting user application'
6824
- });
6825
- return up.emit('up:app:booted', {
6826
- log: 'User application booted'
6827
- });
6837
+ up.emit('up:app:boot', {
6838
+ log: 'Booting user application'
6839
+ });
6840
+ return up.emit('up:app:booted', {
6841
+ log: 'User application booted'
6828
6842
  });
6829
6843
  });
6830
6844
  } else {
@@ -6951,7 +6965,7 @@ There are some advantages to using `up.on()`:
6951
6965
  for [event delegation](https://davidwalsh.name/event-delegate):
6952
6966
 
6953
6967
  var form = document.querySelector('form')
6954
- document.addEventListener(form, 'click', 'a', function(event, link) {
6968
+ up.on(form, 'click', 'a', function(event, link) {
6955
6969
  console.log("Click on a link %o within %o", link, form)
6956
6970
  })
6957
6971
 
@@ -7263,14 +7277,22 @@ There are some advantages to using `up.on()`:
7263
7277
  };
7264
7278
 
7265
7279
  /***
7266
- Stops the given event from propagating and prevents the default action.
7280
+ Prevents the event from bubbling up the DOM.
7281
+ Also prevents other event handlers bound on the same element.
7282
+ Also prevents the event's default action.
7283
+
7284
+ \#\#\# Example
7285
+
7286
+ up.on('click', 'link.disabled', function(event) {
7287
+ up.event.halt(event)
7288
+ })
7267
7289
 
7268
7290
  @function up.event.halt
7269
- @internal
7291
+ @param {Event} event
7292
+ @experimental
7270
7293
  */
7271
7294
  halt = function(event) {
7272
7295
  event.stopImmediatePropagation();
7273
- event.stopPropagation();
7274
7296
  return event.preventDefault();
7275
7297
  };
7276
7298
 
@@ -7579,7 +7601,7 @@ an existing cookie should be deleted.
7579
7601
  The parameter name can be configured as a string or as function that returns the parameter name.
7580
7602
  If no name is set, no token will be sent.
7581
7603
 
7582
- Defaults to the `content` attribute of a `<meta>` tag named `csrf-token`:
7604
+ Defaults to the `content` attribute of a `<meta>` tag named `csrf-param`:
7583
7605
 
7584
7606
  <meta name="csrf-param" content="authenticity_token" />
7585
7607
 
@@ -7680,12 +7702,15 @@ The output can be configured using the [`up.log.config`](/up.log.config) propert
7680
7702
  prints to the developer console.
7681
7703
  @param {string} [options.prefix='[UP] ']
7682
7704
  A string to prepend to Unpoly's logging messages so you can distinguish it from your own messages.
7705
+ @param {boolean} [options.banner=true]
7706
+ Print the Unpoly banner to the developer console.
7683
7707
  @stable
7684
7708
  */
7685
7709
  config = new up.Config({
7686
7710
  prefix: '[UP] ',
7687
7711
  enabled: sessionStore.get('enabled'),
7688
- collapse: false
7712
+ collapse: false,
7713
+ banner: true
7689
7714
  });
7690
7715
  reset = function() {
7691
7716
  return config.reset();
@@ -7879,7 +7904,9 @@ The output can be configured using the [`up.log.config`](/up.log.config) propert
7879
7904
  }
7880
7905
  return console.log(banner);
7881
7906
  };
7882
- up.on('up:framework:booted', printBanner);
7907
+ if (config.banner) {
7908
+ up.on('up:framework:booted', printBanner);
7909
+ }
7883
7910
  up.on('up:framework:reset', reset);
7884
7911
  setEnabled = function(value) {
7885
7912
  sessionStore.set('enabled', value);
@@ -8234,7 +8261,7 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
8234
8261
  /***
8235
8262
  Registers a [compiler](/up.compiler) that is run before all other compilers.
8236
8263
 
8237
- Use `up.macro()` to register a compiler that sets multiply Unpoly attributes.
8264
+ Use `up.macro()` to register a compiler that sets multiple Unpoly attributes.
8238
8265
 
8239
8266
  \#\#\# Example
8240
8267
 
@@ -8413,15 +8440,14 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
8413
8440
  var cleanables;
8414
8441
  cleanables = e.subtree(fragment, '.up-can-clean');
8415
8442
  return u.each(cleanables, function(cleanable) {
8416
- var destructor, destructors, i, len, results;
8417
- if (destructors = cleanable.upDestructors) {
8418
- results = [];
8443
+ var destructor, destructors, i, len;
8444
+ if (destructors = u.pluckKey(cleanable, 'upDestructors')) {
8419
8445
  for (i = 0, len = destructors.length; i < len; i++) {
8420
8446
  destructor = destructors[i];
8421
- results.push(destructor());
8447
+ destructor();
8422
8448
  }
8423
- return results;
8424
8449
  }
8450
+ return cleanable.classList.remove('up-can-clean');
8425
8451
  });
8426
8452
  };
8427
8453
 
@@ -9380,13 +9406,37 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
9380
9406
 
9381
9407
  The scroll positions will be associated with the current URL.
9382
9408
  They can later be restored by calling [`up.viewport.restoreScroll()`](/up.viewport.restoreScroll)
9383
- at the same URL.
9409
+ at the same URL, or by following a link with an [`[up-restore-scroll]`](/a-up-follow#up-restore-scroll)
9410
+ attribute.
9411
+
9412
+ Unpoly automatically saves scroll positions before a [fragment update](/up.replace)
9413
+ you will rarely need to call this function yourself.
9414
+
9415
+ \#\#\# Examples
9384
9416
 
9385
- Unpoly automatically saves scroll positions whenever a fragment was updated on the page.
9417
+ Should you need to save the current scroll positions outside of a [fragment update](/up.replace),
9418
+ you may call:
9419
+
9420
+ up.viewport.saveScroll()
9421
+
9422
+ Instead of saving the current scroll positions for the current URL, you may also pass another
9423
+ url or vertical scroll positionsfor each viewport:
9424
+
9425
+ up.viewport.saveScroll({
9426
+ url: '/inbox',
9427
+ tops: {
9428
+ 'body': 0,
9429
+ '.sidebar', 100,
9430
+ '.main', 320
9431
+ }
9432
+ })
9386
9433
 
9387
9434
  @function up.viewport.saveScroll
9388
9435
  @param {string} [options.url]
9436
+ The URL for which to save scroll positions.
9437
+ If omitted, the current browser location is used.
9389
9438
  @param {Object<string, number>} [options.tops]
9439
+ An object mapping viewport selectors to vertical scroll positions in pixels.
9390
9440
  @experimental
9391
9441
  */
9392
9442
  saveScroll = function(options) {
@@ -9767,7 +9817,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
9767
9817
 
9768
9818
  \#\#\# Example
9769
9819
 
9770
- Let's say your curent HTML looks like this:
9820
+ Let's say your current HTML looks like this:
9771
9821
 
9772
9822
  <div class="one">old one</div>
9773
9823
  <div class="two">old two</div>
@@ -10018,7 +10068,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
10018
10068
 
10019
10069
  \#\#\# Example
10020
10070
 
10021
- Let's say your curent HTML looks like this:
10071
+ Let's say your current HTML looks like this:
10022
10072
 
10023
10073
  <div class="one">old one</div>
10024
10074
  <div class="two">old two</div>
@@ -10568,7 +10618,11 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
10568
10618
  var parent;
10569
10619
  parent = element.parentNode;
10570
10620
  up.syntax.clean(element);
10571
- e.remove(element);
10621
+ if (up.browser.canJQuery()) {
10622
+ jQuery(element).remove();
10623
+ } else {
10624
+ e.remove(element);
10625
+ }
10572
10626
  return emitFragmentDestroyed(element, {
10573
10627
  parent: parent,
10574
10628
  log: options.log
@@ -10593,7 +10647,8 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
10593
10647
  @stable
10594
10648
  */
10595
10649
  markElementAsDestroying = function(element) {
10596
- return element.classList.add('up-destroying');
10650
+ element.classList.add('up-destroying');
10651
+ return element.setAttribute('aria-hidden', 'true');
10597
10652
  };
10598
10653
 
10599
10654
  /***
@@ -10789,7 +10844,7 @@ You can define custom animations using [`up.transition()`](/up.transition) and
10789
10844
 
10790
10845
  You can pass additional options:
10791
10846
 
10792
- up.animate('warning', '.fade-in', {
10847
+ up.animate('.warning', 'fade-in', {
10793
10848
  delay: 1000,
10794
10849
  duration: 250,
10795
10850
  easing: 'linear'
@@ -12107,7 +12162,7 @@ This makes for an unfriendly experience:
12107
12162
  - State changes caused by AJAX updates get lost during the page transition.
12108
12163
  - Unsaved form changes get lost during the page transition.
12109
12164
  - The JavaScript VM is reset during the page transition.
12110
- - If the page layout is composed from multiple srollable containers
12165
+ - If the page layout is composed from multiple scrollable containers
12111
12166
  (e.g. a pane view), the scroll positions get lost during the page transition.
12112
12167
  - The user sees a "flash" as the browser loads and renders the new page,
12113
12168
  even if large portions of the old and new page are the same (navigation, layout, etc.).
@@ -12844,16 +12899,42 @@ open dialogs with sub-forms, etc. all without losing form state.
12844
12899
  @function up.form.fieldSelector
12845
12900
  @internal
12846
12901
  */
12847
- fieldSelector = function() {
12848
- return config.fields.join(',');
12902
+ fieldSelector = function(suffix) {
12903
+ if (suffix == null) {
12904
+ suffix = '';
12905
+ }
12906
+ return config.fields.map(function(field) {
12907
+ return field + suffix;
12908
+ }).join(',');
12849
12909
  };
12850
12910
 
12851
12911
  /***
12912
+ Returns a list of form fields within the given element.
12913
+
12914
+ You can configure what Unpoly considers a form field by adding CSS selectors to the
12915
+ [`up.form.config.fields`](/up.form.config#config.fields) array.
12916
+
12917
+ If the given element is itself a form field, a list of that given element is returned.
12918
+
12852
12919
  @function up.form.fields
12853
- @internal
12920
+ @param {Element|jQuery} root
12921
+ The element to scan for contained form fields.
12922
+
12923
+ If the element is itself a form field, a list of that element is returned.
12924
+ @return {NodeList<Element>|Array<Element>}
12925
+ @experimental
12854
12926
  */
12855
12927
  findFields = function(root) {
12856
- return e.subtree(root, fieldSelector());
12928
+ var fields, outsideFieldSelector, outsideFields;
12929
+ root = e.get(root);
12930
+ fields = e.subtree(root, fieldSelector());
12931
+ if (e.matches(root, 'form[id]')) {
12932
+ outsideFieldSelector = fieldSelector(e.attributeSelector('form', root.id));
12933
+ outsideFields = e.all(outsideFieldSelector);
12934
+ fields.push.apply(fields, outsideFields);
12935
+ fields = u.uniq(fields);
12936
+ }
12937
+ return fields;
12857
12938
  };
12858
12939
 
12859
12940
  /****
@@ -12980,6 +13061,9 @@ open dialogs with sub-forms, etc. all without losing form state.
12980
13061
  If set to `'auto'` (default), Unpoly will try to find a match in the form's layer.
12981
13062
  @param {string} [options.failLayer='auto']
12982
13063
  The name of the layer that ought to be updated if the server sends a non-200 status code.
13064
+ @param {Object|FormData|string|Array|up.Params} [options.params]
13065
+ Extra form [parameters](/up.Params) that will be submitted in addition to
13066
+ the parameters from the form.
12983
13067
  @return {Promise}
12984
13068
  A promise for the successful form submission.
12985
13069
  @stable
@@ -13029,7 +13113,7 @@ open dialogs with sub-forms, etc. all without losing form state.
13029
13113
  if (options.failLayer == null) {
13030
13114
  options.failLayer = form.getAttribute('up-fail-layer');
13031
13115
  }
13032
- options.params = up.Params.fromForm(form);
13116
+ options.params = up.Params.fromForm(form).addAll(options.params);
13033
13117
  options = u.merge(options, up.motion.animateOptions(options, form));
13034
13118
  if (options.validate) {
13035
13119
  options.headers || (options.headers = {});
@@ -13379,7 +13463,7 @@ open dialogs with sub-forms, etc. all without losing form state.
13379
13463
 
13380
13464
  \#\#\# Redirects
13381
13465
 
13382
- Unpoly requires an additional response headers to detect redirects,
13466
+ Unpoly requires an additional response header to detect redirects,
13383
13467
  which are otherwise undetectable for an AJAX client.
13384
13468
 
13385
13469
  After the form's action performs a redirect, the next response should echo
@@ -13614,7 +13698,19 @@ open dialogs with sub-forms, etc. all without losing form state.
13614
13698
  This defaults to a fieldset or form group around the validating field.
13615
13699
  @stable
13616
13700
  */
13617
- up.on('change', '[up-validate]', function(event, field) {
13701
+
13702
+ /***
13703
+ Performs [server-side validation](/input-up-validate) when any fieldset within this form changes.
13704
+
13705
+ You can configure what Unpoly considers a fieldset by adding CSS selectors to the
13706
+ [`up.form.config.validateTargets`](/up.form.config#config.validateTargets) array.
13707
+
13708
+ @selector form[up-validate]
13709
+ @stable
13710
+ */
13711
+ up.on('change', '[up-validate]', function(event) {
13712
+ var field;
13713
+ field = findFields(event.target)[0];
13618
13714
  return u.muteRejection(validate(field));
13619
13715
  });
13620
13716
 
@@ -13732,18 +13828,25 @@ open dialogs with sub-forms, etc. all without losing form state.
13732
13828
 
13733
13829
  The programmatic variant of this is the [`up.observe()`](/up.observe) function.
13734
13830
 
13735
- \#\#\# Examples
13831
+ \#\#\# Example
13736
13832
 
13737
13833
  The following would run a global `showSuggestions(value)` function
13738
13834
  whenever the `<input>` changes:
13739
13835
 
13740
- <form>
13741
- <input name="query" up-observe="showSuggestions(value)">
13742
- </form>
13836
+ <input name="query" up-observe="showSuggestions(value)">
13837
+
13838
+ Note that the parameter name in the markup must be called `value` or it will not work.
13839
+ The parameter name can be called whatever you want in the JavaScript, however.
13840
+
13841
+ Also note that the function must be declared on the `window` object to work, like so:
13842
+
13843
+ window.showSuggestions = function(selectedValue) {
13844
+ console.log(`Called showSuggestions() with ${selectedValue}`);
13845
+ }
13743
13846
 
13744
13847
  \#\#\# Callback context
13745
13848
 
13746
- The script given to `up-observe` runs with the following context:
13849
+ The script given to `[up-observe]` runs with the following context:
13747
13850
 
13748
13851
  | Name | Type | Description |
13749
13852
  | -------- | --------- | ------------------------------------- |
@@ -13751,6 +13854,20 @@ open dialogs with sub-forms, etc. all without losing form state.
13751
13854
  | `this` | `Element` | The form field |
13752
13855
  | `$field` | `jQuery` | The form field as a jQuery collection |
13753
13856
 
13857
+ \#\#\# Observing radio buttons
13858
+
13859
+ Multiple radio buttons with the same `[name]` (a radio button group)
13860
+ produce a single value for the form.
13861
+
13862
+ To observe radio buttons group, use the `[up-observe]` attribute on an
13863
+ element that contains all radio button elements with a given name:
13864
+
13865
+ <div up-observe="formatSelected(value)">
13866
+ <input type="radio" name="format" value="html"> HTML format
13867
+ <input type="radio" name="format" value="pdf"> PDF format
13868
+ <input type="radio" name="format" value="txt"> Text format
13869
+ </div>
13870
+
13754
13871
  @selector input[up-observe]
13755
13872
  @param {string} up-observe
13756
13873
  The code to run when the field's value changes.
@@ -13799,7 +13916,7 @@ open dialogs with sub-forms, etc. all without losing form state.
13799
13916
  });
13800
13917
 
13801
13918
  /***
13802
- [Observes](/up.observe) this form field and submits the form when its value changes.
13919
+ Submits this field's form when this field changes its values.
13803
13920
 
13804
13921
  Both the form and the changed field will be assigned a CSS class [`up-active`](/form-up-active)
13805
13922
  while the autosubmitted form is loading.
@@ -13815,6 +13932,20 @@ open dialogs with sub-forms, etc. all without losing form state.
13815
13932
  <input type="checkbox" name="archive"> Include archive
13816
13933
  </form>
13817
13934
 
13935
+ \#\#\# Auto-submitting radio buttons
13936
+
13937
+ Multiple radio buttons with the same `[name]` (a radio button group)
13938
+ produce a single value for the form.
13939
+
13940
+ To auto-submit radio buttons group, use the `[up-submit]` attribute on an
13941
+ element that contains all radio button elements with a given name:
13942
+
13943
+ <div up-autosubmit>
13944
+ <input type="radio" name="format" value="html"> HTML format
13945
+ <input type="radio" name="format" value="pdf"> PDF format
13946
+ <input type="radio" name="format" value="txt"> Text format
13947
+ </div>
13948
+
13818
13949
  @selector input[up-autosubmit]
13819
13950
  @param {string} up-delay
13820
13951
  The number of miliseconds to wait after a change before the form is submitted.
@@ -13822,7 +13953,7 @@ open dialogs with sub-forms, etc. all without losing form state.
13822
13953
  */
13823
13954
 
13824
13955
  /***
13825
- [Observes](/up.observe) this form and submits the form when *any* field changes.
13956
+ Submits the form when *any* field changes.
13826
13957
 
13827
13958
  Both the form and the field will be assigned a CSS class [`up-active`](/form-up-active)
13828
13959
  while the autosubmitted form is loading.
@@ -14698,6 +14829,7 @@ or function.
14698
14829
  var closeElement, contentElement, dialogStyles, html, modalElement;
14699
14830
  html = templateHtml();
14700
14831
  state.modalElement = modalElement = e.createFromHtml(html);
14832
+ modalElement.setAttribute('aria-modal', 'true');
14701
14833
  modalElement.setAttribute('up-flavor', state.flavor);
14702
14834
  if (u.isPresent(state.position)) {
14703
14835
  modalElement.setAttribute('up-position', state.position);
@@ -14736,7 +14868,7 @@ or function.
14736
14868
  var link = document.querySelector('a')
14737
14869
  up.modal.follow(link)
14738
14870
 
14739
- Any option attributes for [`a[up-modal]`](/a.up-modal) will be honored.
14871
+ Any option attributes for [`a[up-modal]`](/a-up-modal) will be honored.
14740
14872
 
14741
14873
  Emits events [`up:modal:open`](/up:modal:open) and [`up:modal:opened`](/up:modal:opened).
14742
14874
 
@@ -14919,6 +15051,9 @@ or function.
14919
15051
  if (options.failLayer == null) {
14920
15052
  options.failLayer = (ref12 = link.getAttribute('up-fail-layer')) != null ? ref12 : 'auto';
14921
15053
  }
15054
+ if (options.cache == null) {
15055
+ options.cache = e.booleanAttr(link, 'up-cache');
15056
+ }
14922
15057
  animateOptions = up.motion.animateOptions(options, link, {
14923
15058
  duration: flavorDefault('openDuration', options.flavor),
14924
15059
  easing: flavorDefault('openEasing', options.flavor)
@@ -15175,7 +15310,7 @@ or function.
15175
15310
 
15176
15311
  Clicking would request the path `/blog` and select `.blog-list` from
15177
15312
  the HTML response. Unpoly will dim the page
15178
- and place the matching `.blog-list` tag will be placed in
15313
+ and place the matching `.blog-list` tag in
15179
15314
  a modal dialog.
15180
15315
 
15181
15316
  @selector a[up-modal]