upjs-rails 0.17.0 → 0.18.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -1
- data/dist/up.js +929 -374
- data/dist/up.min.js +2 -2
- data/lib/assets/javascripts/up/browser.js.coffee +31 -14
- data/lib/assets/javascripts/up/bus.js.coffee +87 -22
- data/lib/assets/javascripts/up/flow.js.coffee +119 -43
- data/lib/assets/javascripts/up/form.js.coffee +188 -57
- data/lib/assets/javascripts/up/link.js.coffee +57 -21
- data/lib/assets/javascripts/up/modal.js.coffee +77 -63
- data/lib/assets/javascripts/up/motion.js.coffee +10 -9
- data/lib/assets/javascripts/up/popup.js.coffee +54 -40
- data/lib/assets/javascripts/up/proxy.js.coffee +46 -17
- data/lib/assets/javascripts/up/rails.js.coffee +22 -4
- data/lib/assets/javascripts/up/syntax.js.coffee +2 -2
- data/lib/assets/javascripts/up/util.js.coffee +100 -16
- data/lib/upjs/rails/inspector.rb +3 -3
- data/lib/upjs/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +1 -4
- data/spec_app/app/controllers/test_controller.rb +2 -2
- data/spec_app/spec/controllers/test_controller_spec.rb +5 -5
- data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +9 -0
- data/spec_app/spec/javascripts/helpers/knife.js.coffee +0 -1
- data/spec_app/spec/javascripts/helpers/reset_path.js.coffee +4 -5
- data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +8 -0
- data/spec_app/spec/javascripts/up/bus_spec.js.coffee +26 -0
- data/spec_app/spec/javascripts/up/flow_spec.js.coffee +203 -91
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +244 -49
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +8 -2
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +83 -30
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +23 -17
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +4 -4
- data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +26 -16
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +45 -13
- data/spec_app/spec/javascripts/up/rails_spec.js.coffee +48 -0
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +48 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0282df3df026ad3d48b9f10614eb73790b146243
|
4
|
+
data.tar.gz: 1fd5ddad76f7ab45668da13b90e7727a24d7f4ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b2c33b0c3835ebac5f42bd58f90536da481cce4ab252b3295f1b6d727ba875ec2a0543fc3e28baa16500ae8cd6767d3fe1af41625afd9740017c5f982dd24b9
|
7
|
+
data.tar.gz: 10773603d25db7f0aaf99eea17926ab4b253378834900780f95627c4b71eeec7f87e9cbb515eee1151b7ff4b26b682ff9fa5a4a1f36c2ed3e8e88876c7b2c8d6
|
data/CHANGELOG.md
CHANGED
@@ -8,6 +8,51 @@ This project mostly adheres to [Semantic Versioning](http://semver.org/).
|
|
8
8
|
Unreleased
|
9
9
|
----------
|
10
10
|
|
11
|
+
### Compatible changes
|
12
|
+
|
13
|
+
### Breaking changes
|
14
|
+
|
15
|
+
|
16
|
+
0.18.0
|
17
|
+
------
|
18
|
+
|
19
|
+
### Compatible changes
|
20
|
+
|
21
|
+
- New UJS attribute [`[up-toggle]`](/up-toggle) to show or hide part of a form if certain options are selected or boxes are checked.
|
22
|
+
- Links can now have an optional `up-confirm` attribute. This opens a confirmation dialog with the given message
|
23
|
+
before the link is followed or the modal/popup is opened.
|
24
|
+
- New function [`up.off`](/up.off). This unregisters an event listener previously bound with [`up.on`](/up.on).
|
25
|
+
- If a container contains more than one link, you can now set the value of the [`up-expand`](/up-expand)
|
26
|
+
attribute to a CSS selector to define which link should be expanded.
|
27
|
+
- You can now configure a list of idempotent HTTP methods in [`up.proxy.config.safeMethods`](/up.proxy.config).
|
28
|
+
The proxy cache will only cache idempotent requests and will clear the entire
|
29
|
+
cache after a non-idempotent request.
|
30
|
+
- Loading modals and popups will now open if there is a fragment update between the modal/popup's
|
31
|
+
request and response.
|
32
|
+
- [`up.follow`](/up.follow) and [`up.replace`](/up.replace) now have an option `{ failTarget }`.
|
33
|
+
Use it to define the selector to replace if the server responds with a non-200 status code.
|
34
|
+
- [`[up-target]`](/up-target) and [`up-follow`](/up.replace) now have a modifying attribute `up-fail-target`.
|
35
|
+
Use it to define the selector to replace if the server responds with a non-200 status code.
|
36
|
+
- New utility method [`up.util.reject`](/up.util.reject)
|
37
|
+
- New utility method [`up.util.only`](/up.util.only)
|
38
|
+
- New utility method [`up.util.except`](/up.util.except)
|
39
|
+
- Fix a bug where modals could no longer be opened on some browsers
|
40
|
+
|
41
|
+
### Breaking changes
|
42
|
+
|
43
|
+
- By default Up.js now converts `PUT`, `PATCH` and `DELETE` requests to `POST` requests
|
44
|
+
that carry their original method in a form parameter named `_method`.
|
45
|
+
This is to [prevent unexpected redirect behavior](https://makandracards.com/makandra/38347).
|
46
|
+
|
47
|
+
Web frameworks like Ruby on Rails or Sinatra are aware of the `_method` parameter and use
|
48
|
+
its value as the method for routing.
|
49
|
+
|
50
|
+
You can configure this behavior in [`up.proxy.config.wrapMethods`](/up.proxy.config)
|
51
|
+
and [`up.proxy.config.wrapMethodParam`](/up.proxy.config).
|
52
|
+
- The requested selector is now sent to the server as a request header `X-Up-Target`
|
53
|
+
(this used to be `X-Up-Selector`). If you are using `upjs-rails`, you can access it
|
54
|
+
through `up.target` (this used to be `up.selector`).
|
55
|
+
|
11
56
|
|
12
57
|
0.17.0
|
13
58
|
------
|
@@ -67,7 +112,7 @@ Unreleased
|
|
67
112
|
|
68
113
|
### Compatible changes
|
69
114
|
|
70
|
-
- New function [`up.autosubmit`](/up.autosubmit) and
|
115
|
+
- New function [`up.autosubmit`](/up.autosubmit) and selector [`[up-autosubmit]`](/up-autosubmit) to
|
71
116
|
observe a form or field and submit the form when a value changes.
|
72
117
|
- [`up.observe`](/up.observe) and [`[up-observe]`](/up-observe) can now be applied
|
73
118
|
to `<form>` tags. The callback is run when any field in the form changes.
|
data/dist/up.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, ANIMATION_PROMISE_KEY, CONSOLE_PLACEHOLDERS,
|
30
|
+
var $createElementFromSelector, ANIMATION_PROMISE_KEY, CONSOLE_PLACEHOLDERS, any, cache, castedAttr, clientSize, compact, config, contains, copy, copyAttributes, createElement, createElementFromHtml, cssAnimate, debug, detect, each, error, escapePressed, evalConsoleTemplate, 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, presence, presentAttr, reject, remove, requestDataAsArray, requestDataAsQueryString, resolvableWhen, resolvedDeferred, resolvedPromise, scrollbarWidth, select, selectorForElement, setMissingAttrs, temporaryCss, times, titleFromXhr, toArray, trim, unJQuery, uniq, unresolvableDeferred, unresolvablePromise, unwrapElement, warn;
|
31
31
|
memoize = function(func) {
|
32
32
|
var cache, cached;
|
33
33
|
cache = void 0;
|
@@ -44,19 +44,6 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
44
44
|
};
|
45
45
|
};
|
46
46
|
|
47
|
-
/**
|
48
|
-
@function up.util.ajax
|
49
|
-
@internal
|
50
|
-
*/
|
51
|
-
ajax = function(request) {
|
52
|
-
request = copy(request);
|
53
|
-
if (request.selector) {
|
54
|
-
request.headers || (request.headers = {});
|
55
|
-
request.headers['X-Up-Selector'] = request.selector;
|
56
|
-
}
|
57
|
-
return $.ajax(request);
|
58
|
-
};
|
59
|
-
|
60
47
|
/**
|
61
48
|
Returns if the given port is the default port for the given protocol.
|
62
49
|
|
@@ -307,7 +294,7 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
307
294
|
@experimental
|
308
295
|
*/
|
309
296
|
selectorForElement = function(element) {
|
310
|
-
var $element,
|
297
|
+
var $element, classes, id, j, klass, len, name, selector, upId;
|
311
298
|
$element = $(element);
|
312
299
|
selector = void 0;
|
313
300
|
debug("Creating selector from element %o", $element.get(0));
|
@@ -317,8 +304,8 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
317
304
|
selector = "#" + id;
|
318
305
|
} else if (name = presence($element.attr("name"))) {
|
319
306
|
selector = "[name='" + name + "']";
|
320
|
-
} else if (
|
321
|
-
|
307
|
+
} else if (classes = presence(nonUpClasses($element))) {
|
308
|
+
console.log("using klass!", classes);
|
322
309
|
selector = '';
|
323
310
|
for (j = 0, len = classes.length; j < len; j++) {
|
324
311
|
klass = classes[j];
|
@@ -329,6 +316,14 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
329
316
|
}
|
330
317
|
return selector;
|
331
318
|
};
|
319
|
+
nonUpClasses = function($element) {
|
320
|
+
var classString, classes;
|
321
|
+
classString = $element.attr('class') || '';
|
322
|
+
classes = classString.split(' ');
|
323
|
+
return select(classes, function(klass) {
|
324
|
+
return isPresent(klass) && !klass.match(/^up-/);
|
325
|
+
});
|
326
|
+
};
|
332
327
|
createElementFromHtml = function(html) {
|
333
328
|
var anything, bodyElement, bodyMatch, bodyPattern, capture, closeTag, headElement, htmlElement, openTag, titleElement, titleMatch, titlePattern;
|
334
329
|
openTag = function(tag) {
|
@@ -890,6 +885,35 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
890
885
|
return matches;
|
891
886
|
};
|
892
887
|
|
888
|
+
/**
|
889
|
+
Returns all elements from the given array that do not return
|
890
|
+
a truthy value when passed to the given function.
|
891
|
+
|
892
|
+
@function up.util.reject
|
893
|
+
@param {Array<T>} array
|
894
|
+
@return {Array<T>}
|
895
|
+
@stable
|
896
|
+
*/
|
897
|
+
reject = function(array, tester) {
|
898
|
+
return select(array, function(element) {
|
899
|
+
return !tester(element);
|
900
|
+
});
|
901
|
+
};
|
902
|
+
|
903
|
+
/**
|
904
|
+
Returns the intersection of the given two arrays.
|
905
|
+
|
906
|
+
Implementation is not optimized. Don't use it for large arrays.
|
907
|
+
|
908
|
+
@function up.util.intersect
|
909
|
+
@internal
|
910
|
+
*/
|
911
|
+
intersect = function(array1, array2) {
|
912
|
+
return select(array1, function(element) {
|
913
|
+
return contains(array2, element);
|
914
|
+
});
|
915
|
+
};
|
916
|
+
|
893
917
|
/**
|
894
918
|
Returns the first [present](/up.util.isPresent) element attribute
|
895
919
|
among the given list of attribute names.
|
@@ -1299,6 +1323,26 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
1299
1323
|
return filtered;
|
1300
1324
|
};
|
1301
1325
|
|
1326
|
+
/**
|
1327
|
+
Returns a copy of the given object that contains all except
|
1328
|
+
the given properties.
|
1329
|
+
|
1330
|
+
@function up.util.except
|
1331
|
+
@param {Object} object
|
1332
|
+
@param {Array} keys...
|
1333
|
+
@stable
|
1334
|
+
*/
|
1335
|
+
except = function() {
|
1336
|
+
var filtered, j, len, object, properties, property;
|
1337
|
+
object = arguments[0], properties = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
1338
|
+
filtered = copy(object);
|
1339
|
+
for (j = 0, len = properties.length; j < len; j++) {
|
1340
|
+
property = properties[j];
|
1341
|
+
delete filtered[property];
|
1342
|
+
}
|
1343
|
+
return filtered;
|
1344
|
+
};
|
1345
|
+
|
1302
1346
|
/**
|
1303
1347
|
@function up.util.isUnmodifiedKeyEvent
|
1304
1348
|
@internal
|
@@ -1720,7 +1764,61 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
1720
1764
|
bottom: ''
|
1721
1765
|
});
|
1722
1766
|
};
|
1767
|
+
|
1768
|
+
/**
|
1769
|
+
Normalizes the given params object to the form returned by
|
1770
|
+
[`jQuery.serializeArray`](https://api.jquery.com/serializeArray/).
|
1771
|
+
|
1772
|
+
@function up.util.requestDataAsArray
|
1773
|
+
@param {Object|Array|Undefined|Null} data
|
1774
|
+
@internal
|
1775
|
+
*/
|
1776
|
+
requestDataAsArray = function(data) {
|
1777
|
+
var name, results, value;
|
1778
|
+
if (isMissing(data)) {
|
1779
|
+
return [];
|
1780
|
+
} else if (isArray(data)) {
|
1781
|
+
return data;
|
1782
|
+
} else if (isObject(data)) {
|
1783
|
+
results = [];
|
1784
|
+
for (name in data) {
|
1785
|
+
value = data[name];
|
1786
|
+
results.push({
|
1787
|
+
name: name,
|
1788
|
+
value: value
|
1789
|
+
});
|
1790
|
+
}
|
1791
|
+
return results;
|
1792
|
+
} else {
|
1793
|
+
return error('Unknown options.data type for %o', data);
|
1794
|
+
}
|
1795
|
+
};
|
1796
|
+
|
1797
|
+
/**
|
1798
|
+
Returns an URL-encoded query string for the given params object.
|
1799
|
+
|
1800
|
+
@function up.util.requestDataAsQueryString
|
1801
|
+
@param {Object|Array|Undefined|Null} data
|
1802
|
+
@internal
|
1803
|
+
*/
|
1804
|
+
requestDataAsQueryString = function(data) {
|
1805
|
+
var array, query;
|
1806
|
+
array = requestDataAsArray(data);
|
1807
|
+
query = '';
|
1808
|
+
if (isPresent(array)) {
|
1809
|
+
query += '?';
|
1810
|
+
each(array, function(field, index) {
|
1811
|
+
if (index !== 0) {
|
1812
|
+
query += '&';
|
1813
|
+
}
|
1814
|
+
return query += encodeURIComponent(field.name) + '=' + encodeURIComponent(field.value);
|
1815
|
+
});
|
1816
|
+
}
|
1817
|
+
return query;
|
1818
|
+
};
|
1723
1819
|
return {
|
1820
|
+
requestDataAsArray: requestDataAsArray,
|
1821
|
+
requestDataAsQueryString: requestDataAsQueryString,
|
1724
1822
|
offsetParent: offsetParent,
|
1725
1823
|
fixedToAbsolute: fixedToAbsolute,
|
1726
1824
|
presentAttr: presentAttr,
|
@@ -1731,7 +1829,6 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
1731
1829
|
createElementFromHtml: createElementFromHtml,
|
1732
1830
|
$createElementFromSelector: $createElementFromSelector,
|
1733
1831
|
selectorForElement: selectorForElement,
|
1734
|
-
ajax: ajax,
|
1735
1832
|
extend: extend,
|
1736
1833
|
copy: copy,
|
1737
1834
|
merge: merge,
|
@@ -1746,6 +1843,8 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
1746
1843
|
any: any,
|
1747
1844
|
detect: detect,
|
1748
1845
|
select: select,
|
1846
|
+
reject: reject,
|
1847
|
+
intersect: intersect,
|
1749
1848
|
compact: compact,
|
1750
1849
|
uniq: uniq,
|
1751
1850
|
last: last,
|
@@ -1787,6 +1886,7 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
1787
1886
|
methodFromXhr: methodFromXhr,
|
1788
1887
|
clientSize: clientSize,
|
1789
1888
|
only: only,
|
1889
|
+
except: except,
|
1790
1890
|
trim: trim,
|
1791
1891
|
unresolvableDeferred: unresolvableDeferred,
|
1792
1892
|
unresolvablePromise: unresolvablePromise,
|
@@ -1827,32 +1927,42 @@ we can't currently get rid off.
|
|
1827
1927
|
var slice = [].slice;
|
1828
1928
|
|
1829
1929
|
up.browser = (function($) {
|
1830
|
-
var canCssTransition, canInputEvent, canLogSubstitution, canPushState, initialRequestMethod, isIE8OrWorse, isIE9OrWorse, isRecentJQuery, isSupported, loadPage, popCookie, puts, u, url;
|
1930
|
+
var canCssTransition, canInputEvent, canLogSubstitution, canPushState, confirm, initialRequestMethod, isIE8OrWorse, isIE9OrWorse, isRecentJQuery, isSupported, loadPage, popCookie, puts, u, url;
|
1831
1931
|
u = up.util;
|
1932
|
+
|
1933
|
+
/**
|
1934
|
+
@method up.browser.loadPage
|
1935
|
+
@param {String} url
|
1936
|
+
@param {String} [options.method='get']
|
1937
|
+
@param {Object|Array} [options.data]
|
1938
|
+
@internal
|
1939
|
+
*/
|
1832
1940
|
loadPage = function(url, options) {
|
1833
|
-
var $form,
|
1941
|
+
var $form, addField, csrfField, method;
|
1834
1942
|
if (options == null) {
|
1835
1943
|
options = {};
|
1836
1944
|
}
|
1837
1945
|
method = u.option(options.method, 'get').toLowerCase();
|
1838
1946
|
if (method === 'get') {
|
1839
|
-
return location.href = url;
|
1840
|
-
} else
|
1841
|
-
target = options.target;
|
1842
|
-
csrfToken = $.rails.csrfToken();
|
1843
|
-
csrfParam = $.rails.csrfParam();
|
1947
|
+
return location.href = url + u.requestDataAsQueryString(options.data);
|
1948
|
+
} else {
|
1844
1949
|
$form = $("<form method='post' action='" + url + "'></form>");
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1850
|
-
|
1950
|
+
addField = function(field) {
|
1951
|
+
var $field;
|
1952
|
+
$field = $('<input type="hidden">');
|
1953
|
+
$field.attr(field.name, field.value);
|
1954
|
+
return $field.appendTo($form);
|
1955
|
+
};
|
1956
|
+
addField({
|
1957
|
+
name: up.proxy.config.wrapMethodParam,
|
1958
|
+
value: method
|
1959
|
+
});
|
1960
|
+
if (csrfField = up.rails.csrfField()) {
|
1961
|
+
addField(csrfField);
|
1851
1962
|
}
|
1852
|
-
|
1963
|
+
u.each(u.requestDataAsArray(options.data), addField);
|
1964
|
+
$form.hide().appendTo('body');
|
1853
1965
|
return $form.submit();
|
1854
|
-
} else {
|
1855
|
-
return error("Can't fake a " + (method.toUpperCase()) + " request without Rails UJS");
|
1856
1966
|
}
|
1857
1967
|
};
|
1858
1968
|
|
@@ -1945,7 +2055,7 @@ we can't currently get rid off.
|
|
1945
2055
|
console.log("Hello %o!", "Judy");
|
1946
2056
|
|
1947
2057
|
@function up.browser.canLogSubstitution
|
1948
|
-
@return
|
2058
|
+
@return {Boolean}
|
1949
2059
|
@internal
|
1950
2060
|
*/
|
1951
2061
|
canLogSubstitution = u.memoize(function() {
|
@@ -1967,6 +2077,19 @@ we can't currently get rid off.
|
|
1967
2077
|
}
|
1968
2078
|
return value;
|
1969
2079
|
};
|
2080
|
+
|
2081
|
+
/**
|
2082
|
+
@function up,browser.confirm
|
2083
|
+
@return {Promise}
|
2084
|
+
@internal
|
2085
|
+
*/
|
2086
|
+
confirm = function(message) {
|
2087
|
+
if (u.isBlank(message) || confirm(message)) {
|
2088
|
+
return u.resolvedPromise();
|
2089
|
+
} else {
|
2090
|
+
return u.unresolvablePromise();
|
2091
|
+
}
|
2092
|
+
};
|
1970
2093
|
initialRequestMethod = u.memoize(function() {
|
1971
2094
|
return (popCookie('_up_request_method') || 'get').toLowerCase();
|
1972
2095
|
});
|
@@ -1993,6 +2116,7 @@ we can't currently get rid off.
|
|
1993
2116
|
return {
|
1994
2117
|
url: url,
|
1995
2118
|
loadPage: loadPage,
|
2119
|
+
confirm: confirm,
|
1996
2120
|
canPushState: canPushState,
|
1997
2121
|
canCssTransition: canCssTransition,
|
1998
2122
|
canInputEvent: canInputEvent,
|
@@ -2049,14 +2173,17 @@ and call `preventDefault()` on the `event` object:
|
|
2049
2173
|
var slice = [].slice;
|
2050
2174
|
|
2051
2175
|
up.bus = (function($) {
|
2052
|
-
var boot,
|
2176
|
+
var boot, emit, emitReset, forgetUpDescription, live, liveUpDescriptions, nextUpDescriptionNumber, nobodyPrevents, onEscape, rememberUpDescription, restoreSnapshot, snapshot, u, unbind, upDescriptionNumber, upDescriptionToJqueryDescription, upListenerToJqueryListener;
|
2053
2177
|
u = up.util;
|
2054
|
-
|
2055
|
-
|
2178
|
+
liveUpDescriptions = {};
|
2179
|
+
nextUpDescriptionNumber = 0;
|
2056
2180
|
|
2057
2181
|
/**
|
2058
|
-
|
2059
|
-
|
2182
|
+
Convert an Up.js style listener (second argument is the event target
|
2183
|
+
as a jQuery collection) to a vanilla jQuery listener
|
2184
|
+
|
2185
|
+
@function upListenerToJqueryListener
|
2186
|
+
@internal
|
2060
2187
|
*/
|
2061
2188
|
upListenerToJqueryListener = function(upListener) {
|
2062
2189
|
return function(event) {
|
@@ -2066,6 +2193,30 @@ and call `preventDefault()` on the `event` object:
|
|
2066
2193
|
};
|
2067
2194
|
};
|
2068
2195
|
|
2196
|
+
/**
|
2197
|
+
Converts an argument list for `up.on` to an argument list for `jQuery.on`.
|
2198
|
+
This involves rewriting the listener signature in the last argument slot.
|
2199
|
+
|
2200
|
+
@function upDescriptionToJqueryDescription
|
2201
|
+
@internal
|
2202
|
+
*/
|
2203
|
+
upDescriptionToJqueryDescription = function(upDescription, isNew) {
|
2204
|
+
var jqueryDescription, jqueryListener, upListener;
|
2205
|
+
jqueryDescription = u.copy(upDescription);
|
2206
|
+
upListener = jqueryDescription.pop();
|
2207
|
+
jqueryListener = void 0;
|
2208
|
+
if (isNew) {
|
2209
|
+
jqueryListener = upListenerToJqueryListener(upListener);
|
2210
|
+
upListener._asJqueryListener = jqueryListener;
|
2211
|
+
upListener._descriptionNumber = ++nextUpDescriptionNumber;
|
2212
|
+
} else {
|
2213
|
+
jqueryListener = upListener._asJqueryListener;
|
2214
|
+
jqueryListener || u.error('up.off: The event listener %o was never registered through up.on');
|
2215
|
+
}
|
2216
|
+
jqueryDescription.push(jqueryListener);
|
2217
|
+
return jqueryDescription;
|
2218
|
+
};
|
2219
|
+
|
2069
2220
|
/**
|
2070
2221
|
Listens to an event on `document`.
|
2071
2222
|
|
@@ -2085,7 +2236,6 @@ and call `preventDefault()` on the `event` object:
|
|
2085
2236
|
Other than jQuery, Up.js will silently discard event listeners
|
2086
2237
|
on [unsupported browsers](/up.browser.isSupported).
|
2087
2238
|
|
2088
|
-
|
2089
2239
|
\#\#\#\# Attaching structured data
|
2090
2240
|
|
2091
2241
|
In case you want to attach structured data to the event you're observing,
|
@@ -2100,7 +2250,6 @@ and call `preventDefault()` on the `event` object:
|
|
2100
2250
|
console.log("This is %o who is %o years old", data.name, data.age);
|
2101
2251
|
});
|
2102
2252
|
|
2103
|
-
|
2104
2253
|
\#\#\#\# Migrating jQuery event handlers to `up.on`
|
2105
2254
|
|
2106
2255
|
Within the event handler, Up.js will bind `this` to the
|
@@ -2119,6 +2268,12 @@ and call `preventDefault()` on the `event` object:
|
|
2119
2268
|
$(this).something();
|
2120
2269
|
});
|
2121
2270
|
|
2271
|
+
\#\#\#\# Stopping to listen
|
2272
|
+
|
2273
|
+
`up.on` returns a function that unbinds the event listeners when called.
|
2274
|
+
|
2275
|
+
There is also a function [`up.off`](/up.off) which you can use for the same purpose.
|
2276
|
+
|
2122
2277
|
@function up.on
|
2123
2278
|
@param {String} events
|
2124
2279
|
A space-separated list of event names to bind.
|
@@ -2136,23 +2291,60 @@ and call `preventDefault()` on the `event` object:
|
|
2136
2291
|
@stable
|
2137
2292
|
*/
|
2138
2293
|
live = function() {
|
2139
|
-
var
|
2140
|
-
|
2294
|
+
var jqueryDescription, ref, upDescription;
|
2295
|
+
upDescription = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
2141
2296
|
if (!up.browser.isSupported()) {
|
2142
2297
|
return (function() {});
|
2143
2298
|
}
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
description[lastIndex] = upListenerToJqueryListener(behavior);
|
2148
|
-
liveDescriptions.push(description);
|
2149
|
-
$document = $(document);
|
2150
|
-
$document.on.apply($document, description);
|
2299
|
+
jqueryDescription = upDescriptionToJqueryDescription(upDescription, true);
|
2300
|
+
rememberUpDescription(upDescription);
|
2301
|
+
(ref = $(document)).on.apply(ref, jqueryDescription);
|
2151
2302
|
return function() {
|
2152
|
-
return
|
2303
|
+
return unbind.apply(null, upDescription);
|
2153
2304
|
};
|
2154
2305
|
};
|
2155
2306
|
|
2307
|
+
/**
|
2308
|
+
Unregisters an event listener previously bound with [`up.on`](/up.on).
|
2309
|
+
|
2310
|
+
\#\#\#\# Example
|
2311
|
+
|
2312
|
+
Let's say you are listing to clicks on `.button` elements:
|
2313
|
+
|
2314
|
+
var listener = function() { };
|
2315
|
+
up.on('click', '.button', listener);
|
2316
|
+
|
2317
|
+
You can stop listening to these events like this:
|
2318
|
+
|
2319
|
+
up.off('click', '.button', listener);
|
2320
|
+
|
2321
|
+
Note that you need to pass `up.off` a reference to the same listener function
|
2322
|
+
that was passed to `up.on` earlier.
|
2323
|
+
|
2324
|
+
@function up.off
|
2325
|
+
@stable
|
2326
|
+
*/
|
2327
|
+
unbind = function() {
|
2328
|
+
var jqueryDescription, ref, upDescription;
|
2329
|
+
upDescription = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
2330
|
+
jqueryDescription = upDescriptionToJqueryDescription(upDescription, false);
|
2331
|
+
forgetUpDescription(upDescription);
|
2332
|
+
return (ref = $(document)).off.apply(ref, jqueryDescription);
|
2333
|
+
};
|
2334
|
+
rememberUpDescription = function(upDescription) {
|
2335
|
+
var number;
|
2336
|
+
number = upDescriptionNumber(upDescription);
|
2337
|
+
return liveUpDescriptions[number] = upDescription;
|
2338
|
+
};
|
2339
|
+
forgetUpDescription = function(upDescription) {
|
2340
|
+
var number;
|
2341
|
+
number = upDescriptionNumber(upDescription);
|
2342
|
+
return delete liveUpDescriptions[number];
|
2343
|
+
};
|
2344
|
+
upDescriptionNumber = function(upDescription) {
|
2345
|
+
return u.last(upDescription)._descriptionNumber;
|
2346
|
+
};
|
2347
|
+
|
2156
2348
|
/**
|
2157
2349
|
Emits a event with the given name and properties.
|
2158
2350
|
|
@@ -2179,7 +2371,7 @@ and call `preventDefault()` on the `event` object:
|
|
2179
2371
|
will by default include properties like `preventDefault()`
|
2180
2372
|
or `stopPropagation()`.
|
2181
2373
|
@param {jQuery} [eventProps.$element=$(document)]
|
2182
|
-
The element on which the event is
|
2374
|
+
The element on which the event is triggered.
|
2183
2375
|
@experimental
|
2184
2376
|
*/
|
2185
2377
|
emit = function(eventName, eventProps) {
|
@@ -2236,7 +2428,13 @@ and call `preventDefault()` on the `event` object:
|
|
2236
2428
|
@internal
|
2237
2429
|
*/
|
2238
2430
|
snapshot = function() {
|
2239
|
-
|
2431
|
+
var description, i, len, results;
|
2432
|
+
results = [];
|
2433
|
+
for (i = 0, len = liveUpDescriptions.length; i < len; i++) {
|
2434
|
+
description = liveUpDescriptions[i];
|
2435
|
+
results.push(description._isDefault = true);
|
2436
|
+
}
|
2437
|
+
return results;
|
2240
2438
|
};
|
2241
2439
|
|
2242
2440
|
/**
|
@@ -2246,14 +2444,16 @@ and call `preventDefault()` on the `event` object:
|
|
2246
2444
|
@internal
|
2247
2445
|
*/
|
2248
2446
|
restoreSnapshot = function() {
|
2249
|
-
var description, i, len,
|
2250
|
-
|
2251
|
-
description
|
2252
|
-
|
2253
|
-
|
2254
|
-
|
2447
|
+
var description, doomedDescriptions, i, len, results;
|
2448
|
+
doomedDescriptions = u.reject(liveUpDescriptions, function(description) {
|
2449
|
+
return description._isDefault;
|
2450
|
+
});
|
2451
|
+
results = [];
|
2452
|
+
for (i = 0, len = doomedDescriptions.length; i < len; i++) {
|
2453
|
+
description = doomedDescriptions[i];
|
2454
|
+
results.push(unbind.apply(null, description));
|
2255
2455
|
}
|
2256
|
-
return
|
2456
|
+
return results;
|
2257
2457
|
};
|
2258
2458
|
|
2259
2459
|
/**
|
@@ -2306,7 +2506,9 @@ and call `preventDefault()` on the `event` object:
|
|
2306
2506
|
live('up:framework:boot', snapshot);
|
2307
2507
|
live('up:framework:reset', restoreSnapshot);
|
2308
2508
|
return {
|
2509
|
+
knife: eval(typeof Knife !== "undefined" && Knife !== null ? Knife.point : void 0),
|
2309
2510
|
on: live,
|
2511
|
+
off: unbind,
|
2310
2512
|
emit: emit,
|
2311
2513
|
nobodyPrevents: nobodyPrevents,
|
2312
2514
|
onEscape: onEscape,
|
@@ -2317,6 +2519,8 @@ and call `preventDefault()` on the `event` object:
|
|
2317
2519
|
|
2318
2520
|
up.on = up.bus.on;
|
2319
2521
|
|
2522
|
+
up.off = up.bus.off;
|
2523
|
+
|
2320
2524
|
up.emit = up.bus.emit;
|
2321
2525
|
|
2322
2526
|
up.reset = up.bus.emitReset;
|
@@ -2692,11 +2896,11 @@ later.
|
|
2692
2896
|
up.on('ready', (function() {
|
2693
2897
|
return hello(document.body);
|
2694
2898
|
}));
|
2695
|
-
up.on('up:fragment:inserted', function(event) {
|
2696
|
-
return compile(
|
2899
|
+
up.on('up:fragment:inserted', function(event, $element) {
|
2900
|
+
return compile($element);
|
2697
2901
|
});
|
2698
|
-
up.on('up:fragment:destroy', function(event) {
|
2699
|
-
return runDestroyers(
|
2902
|
+
up.on('up:fragment:destroy', function(event, $element) {
|
2903
|
+
return runDestroyers($element);
|
2700
2904
|
});
|
2701
2905
|
up.on('up:framework:boot', snapshot);
|
2702
2906
|
up.on('up:framework:reset', reset);
|
@@ -3561,7 +3765,7 @@ are based on this module.
|
|
3561
3765
|
|
3562
3766
|
(function() {
|
3563
3767
|
up.flow = (function($) {
|
3564
|
-
var autofocus, destroy, elementsInserted, findOldFragment, first, implant, isRealElement, oldFragmentNotFound, parseImplantSteps, parseResponse, reload, replace, resolveSelector, setSource, source, swapElements, u;
|
3768
|
+
var autofocus, destroy, elementsInserted, findOldFragment, first, implant, isRealElement, oldFragmentNotFound, parseImplantSteps, parseResponse, processResponse, reload, replace, resolveSelector, setSource, source, swapElements, u;
|
3565
3769
|
u = up.util;
|
3566
3770
|
setSource = function(element, sourceUrl) {
|
3567
3771
|
var $element;
|
@@ -3571,6 +3775,14 @@ are based on this module.
|
|
3571
3775
|
}
|
3572
3776
|
return $element.attr("up-source", sourceUrl);
|
3573
3777
|
};
|
3778
|
+
|
3779
|
+
/**
|
3780
|
+
Returns the URL the given element was retrieved from.
|
3781
|
+
|
3782
|
+
@method up.flow.source
|
3783
|
+
@param {String|Element|jQuery} selectorOrElement
|
3784
|
+
@experimental
|
3785
|
+
*/
|
3574
3786
|
source = function(selectorOrElement) {
|
3575
3787
|
var $element;
|
3576
3788
|
$element = $(selectorOrElement).closest('[up-source]');
|
@@ -3578,15 +3790,22 @@ are based on this module.
|
|
3578
3790
|
};
|
3579
3791
|
|
3580
3792
|
/**
|
3793
|
+
Resolves the given selector (which might contain `&` references)
|
3794
|
+
to an absolute selector.
|
3795
|
+
|
3581
3796
|
@function up.flow.resolveSelector
|
3797
|
+
@param {String|Element|jQuery} selectorOrElement
|
3798
|
+
@param {String|Element|jQuery} origin
|
3799
|
+
The element that this selector resolution is relative to.
|
3800
|
+
That element's selector will be substituted for `&`.
|
3582
3801
|
@internal
|
3583
3802
|
*/
|
3584
|
-
resolveSelector = function(selectorOrElement,
|
3585
|
-
var
|
3803
|
+
resolveSelector = function(selectorOrElement, origin) {
|
3804
|
+
var originSelector, selector;
|
3586
3805
|
if (u.isString(selectorOrElement)) {
|
3587
3806
|
selector = selectorOrElement;
|
3588
3807
|
if (u.contains(selector, '&')) {
|
3589
|
-
if (origin
|
3808
|
+
if (origin) {
|
3590
3809
|
originSelector = u.selectorForElement(origin);
|
3591
3810
|
selector = selector.replace(/\&/, originSelector);
|
3592
3811
|
} else {
|
@@ -3662,7 +3881,7 @@ are based on this module.
|
|
3662
3881
|
\#\#\#\# Optimizing response rendering
|
3663
3882
|
|
3664
3883
|
The server is free to optimize Up.js requests by only rendering the HTML fragment
|
3665
|
-
that is being updated. The request's `X-Up-
|
3884
|
+
that is being updated. The request's `X-Up-Target` header will contain
|
3666
3885
|
the CSS selector for the updating fragment.
|
3667
3886
|
|
3668
3887
|
If you are using the `upjs-rails` gem you can also access the selector via
|
@@ -3680,8 +3899,17 @@ are based on this module.
|
|
3680
3899
|
here, in which case a selector will be inferred from the element's class and ID.
|
3681
3900
|
@param {String} url
|
3682
3901
|
The URL to fetch from the server.
|
3683
|
-
@param {String} [options.
|
3902
|
+
@param {String} [options.failTarget='body']
|
3903
|
+
The CSS selector to update if the server sends a non-200 status code.
|
3684
3904
|
@param {String} [options.title]
|
3905
|
+
@param {String} [options.method='get']
|
3906
|
+
@param {Object|Array} [options.data]
|
3907
|
+
Parameters that should be sent as the request's payload.
|
3908
|
+
|
3909
|
+
Parameters can either be passed as an object (where the property names become
|
3910
|
+
the param names and the property values become the param values) or as
|
3911
|
+
an array of `{ name: 'param-name', value: 'param-value' }` objects
|
3912
|
+
(compare to jQuery's [`serializeArray`](https://api.jquery.com/serializeArray/)).
|
3685
3913
|
@param {String} [options.transition='none']
|
3686
3914
|
@param {String|Boolean} [options.history=true]
|
3687
3915
|
If a `String` is given, it is used as the URL the browser's location bar and history.
|
@@ -3713,50 +3941,95 @@ are based on this module.
|
|
3713
3941
|
@stable
|
3714
3942
|
*/
|
3715
3943
|
replace = function(selectorOrElement, url, options) {
|
3716
|
-
var promise, request,
|
3944
|
+
var failTarget, promise, request, target;
|
3717
3945
|
u.debug("Replace %o with %o (options %o)", selectorOrElement, url, options);
|
3718
3946
|
options = u.options(options);
|
3719
|
-
|
3947
|
+
target = resolveSelector(selectorOrElement, options.origin);
|
3948
|
+
failTarget = u.option(options.failTarget, 'body');
|
3949
|
+
failTarget = resolveSelector(failTarget, options.origin);
|
3720
3950
|
if (!up.browser.canPushState() && options.history !== false) {
|
3721
3951
|
if (!options.preload) {
|
3722
|
-
up.browser.loadPage(url, u.only(options, 'method'));
|
3952
|
+
up.browser.loadPage(url, u.only(options, 'method', 'data'));
|
3723
3953
|
}
|
3724
3954
|
return u.unresolvablePromise();
|
3725
3955
|
}
|
3726
3956
|
request = {
|
3727
3957
|
url: url,
|
3728
3958
|
method: options.method,
|
3729
|
-
|
3959
|
+
data: options.data,
|
3960
|
+
target: target,
|
3961
|
+
failTarget: failTarget,
|
3730
3962
|
cache: options.cache,
|
3731
3963
|
preload: options.preload,
|
3732
3964
|
headers: options.headers
|
3733
3965
|
};
|
3734
3966
|
promise = up.proxy.ajax(request);
|
3735
3967
|
promise.done(function(html, textStatus, xhr) {
|
3736
|
-
|
3737
|
-
|
3738
|
-
|
3968
|
+
return processResponse(true, target, url, request, xhr, options);
|
3969
|
+
});
|
3970
|
+
promise.fail(function(xhr, textStatus, errorThrown) {
|
3971
|
+
return processResponse(false, failTarget, url, request, xhr, options);
|
3972
|
+
});
|
3973
|
+
return promise;
|
3974
|
+
};
|
3975
|
+
|
3976
|
+
/**
|
3977
|
+
@internal
|
3978
|
+
*/
|
3979
|
+
processResponse = function(isSuccess, selector, url, request, xhr, options) {
|
3980
|
+
var isReloadable, newRequest, urlFromServer;
|
3981
|
+
options.method = u.normalizeMethod(u.option(u.methodFromXhr(xhr), options.method));
|
3982
|
+
options.title = u.option(u.titleFromXhr(xhr), options.title);
|
3983
|
+
isReloadable = options.method === 'GET';
|
3984
|
+
if (urlFromServer = u.locationFromXhr(xhr)) {
|
3985
|
+
url = urlFromServer;
|
3986
|
+
if (isSuccess) {
|
3739
3987
|
newRequest = {
|
3740
|
-
url:
|
3988
|
+
url: url,
|
3741
3989
|
method: u.methodFromXhr(xhr),
|
3742
|
-
|
3990
|
+
target: selector
|
3743
3991
|
};
|
3744
3992
|
up.proxy.alias(request, newRequest);
|
3745
|
-
url = currentLocation;
|
3746
|
-
}
|
3747
|
-
if (options.history !== false) {
|
3748
|
-
options.history = url;
|
3749
3993
|
}
|
3750
|
-
|
3751
|
-
|
3994
|
+
} else if (isReloadable) {
|
3995
|
+
url = url + u.requestDataAsQueryString(options.data);
|
3996
|
+
}
|
3997
|
+
if (isSuccess) {
|
3998
|
+
if (isReloadable) {
|
3999
|
+
if (!(options.history === false || u.isString(options.history))) {
|
4000
|
+
options.history = url;
|
4001
|
+
}
|
4002
|
+
if (!(options.source === false || u.isString(options.source))) {
|
4003
|
+
options.source = url;
|
4004
|
+
}
|
4005
|
+
} else {
|
4006
|
+
if (!u.isString(options.history)) {
|
4007
|
+
options.history = false;
|
4008
|
+
}
|
4009
|
+
if (!u.isString(options.source)) {
|
4010
|
+
options.source = 'keep';
|
4011
|
+
}
|
3752
4012
|
}
|
3753
|
-
|
3754
|
-
|
3755
|
-
|
4013
|
+
} else {
|
4014
|
+
options.transition = options.failTransition;
|
4015
|
+
options.failTransition = void 0;
|
4016
|
+
if (isReloadable) {
|
4017
|
+
if (options.history !== false) {
|
4018
|
+
options.history = url;
|
4019
|
+
}
|
4020
|
+
if (options.source !== false) {
|
4021
|
+
options.source = url;
|
4022
|
+
}
|
4023
|
+
} else {
|
4024
|
+
options.source = 'keep';
|
4025
|
+
options.history = false;
|
3756
4026
|
}
|
3757
|
-
}
|
3758
|
-
|
3759
|
-
|
4027
|
+
}
|
4028
|
+
if (options.preload) {
|
4029
|
+
return u.resolvedPromise();
|
4030
|
+
} else {
|
4031
|
+
return implant(selector, xhr.responseText, options);
|
4032
|
+
}
|
3760
4033
|
};
|
3761
4034
|
|
3762
4035
|
/**
|
@@ -3792,34 +4065,41 @@ are based on this module.
|
|
3792
4065
|
@param {String} html
|
3793
4066
|
@param {Object} [options]
|
3794
4067
|
See options for [`up.replace`](/up.replace).
|
4068
|
+
@return {Promise}
|
4069
|
+
A promise that will be resolved then the selector was updated
|
4070
|
+
and all animation has finished.
|
3795
4071
|
@experimental
|
3796
4072
|
*/
|
3797
4073
|
implant = function(selectorOrElement, html, options) {
|
3798
|
-
var $new, $old, j, len, ref, ref1,
|
3799
|
-
selector = resolveSelector(selectorOrElement, options);
|
4074
|
+
var $new, $old, deferred, deferreds, j, len, ref, ref1, ref2, response, selector, step;
|
3800
4075
|
options = u.options(options, {
|
3801
4076
|
historyMethod: 'push',
|
3802
4077
|
requireMatch: true
|
3803
4078
|
});
|
3804
|
-
|
4079
|
+
selector = resolveSelector(selectorOrElement, options.origin);
|
3805
4080
|
response = parseResponse(html, options);
|
3806
4081
|
options.title || (options.title = response.title());
|
3807
4082
|
if (options.saveScroll !== false) {
|
3808
4083
|
up.layout.saveScroll();
|
3809
4084
|
}
|
4085
|
+
if (typeof options.beforeSwap === "function") {
|
4086
|
+
options.beforeSwap($old, $new);
|
4087
|
+
}
|
4088
|
+
deferreds = [];
|
3810
4089
|
ref = parseImplantSteps(selector, options);
|
3811
|
-
results = [];
|
3812
4090
|
for (j = 0, len = ref.length; j < len; j++) {
|
3813
4091
|
step = ref[j];
|
3814
4092
|
$old = findOldFragment(step.selector, options);
|
3815
4093
|
$new = (ref1 = response.find(step.selector)) != null ? ref1.first() : void 0;
|
3816
4094
|
if ($old && $new) {
|
3817
|
-
|
3818
|
-
|
3819
|
-
results.push(void 0);
|
4095
|
+
deferred = swapElements($old, $new, step.pseudoClass, step.transition, options);
|
4096
|
+
deferreds.push(deferred);
|
3820
4097
|
}
|
3821
4098
|
}
|
3822
|
-
|
4099
|
+
if (typeof options.afterSwap === "function") {
|
4100
|
+
options.afterSwap($old, $new);
|
4101
|
+
}
|
4102
|
+
return (ref2 = up.motion).when.apply(ref2, deferreds);
|
3823
4103
|
};
|
3824
4104
|
findOldFragment = function(selector, options) {
|
3825
4105
|
return first(".up-popup " + selector) || first(".up-modal " + selector) || first(selector) || oldFragmentNotFound(selector, options);
|
@@ -3868,8 +4148,13 @@ are based on this module.
|
|
3868
4148
|
});
|
3869
4149
|
};
|
3870
4150
|
swapElements = function($old, $new, pseudoClass, transition, options) {
|
3871
|
-
var $wrapper, insertionMethod;
|
4151
|
+
var $wrapper, insertionMethod, promise, replacement;
|
3872
4152
|
transition || (transition = 'none');
|
4153
|
+
if (options.source === 'keep') {
|
4154
|
+
options = u.merge(options, {
|
4155
|
+
source: source($old)
|
4156
|
+
});
|
4157
|
+
}
|
3873
4158
|
up.motion.finish($old);
|
3874
4159
|
if (pseudoClass) {
|
3875
4160
|
insertionMethod = pseudoClass === 'before' ? 'prepend' : 'append';
|
@@ -3877,21 +4162,25 @@ are based on this module.
|
|
3877
4162
|
$old[insertionMethod]($wrapper);
|
3878
4163
|
u.copyAttributes($new, $old);
|
3879
4164
|
elementsInserted($wrapper.children(), options);
|
3880
|
-
|
4165
|
+
promise = up.layout.revealOrRestoreScroll($wrapper, options);
|
4166
|
+
promise = promise.then(function() {
|
3881
4167
|
return up.animate($wrapper, transition, options);
|
3882
|
-
}).then(function() {
|
3883
|
-
u.unwrapElement($wrapper);
|
3884
4168
|
});
|
4169
|
+
promise = promise.then(function() {
|
4170
|
+
return u.unwrapElement($wrapper);
|
4171
|
+
});
|
4172
|
+
return promise;
|
3885
4173
|
} else {
|
3886
|
-
|
3887
|
-
|
3888
|
-
|
3889
|
-
|
3890
|
-
|
3891
|
-
u.error('Cannot apply transitions to body-elements (%o)', transition);
|
3892
|
-
}
|
3893
|
-
return up.morph($old, $new, transition, options);
|
4174
|
+
replacement = function() {
|
4175
|
+
$new.insertBefore($old);
|
4176
|
+
elementsInserted($new, options);
|
4177
|
+
if ($old.is('body') && transition !== 'none') {
|
4178
|
+
u.error('Cannot apply transitions to body-elements (%o)', transition);
|
3894
4179
|
}
|
4180
|
+
return up.morph($old, $new, transition, options);
|
4181
|
+
};
|
4182
|
+
return destroy($old, {
|
4183
|
+
animation: replacement
|
3895
4184
|
});
|
3896
4185
|
}
|
3897
4186
|
};
|
@@ -3907,6 +4196,7 @@ are based on this module.
|
|
3907
4196
|
for (i = j = 0, len = disjunction.length; j < len; i = ++j) {
|
3908
4197
|
selectorAtom = disjunction[i];
|
3909
4198
|
selectorParts = selectorAtom.match(/^(.+?)(?:\:(before|after))?$/);
|
4199
|
+
selectorParts || u.error('Could not parse selector atom %o', selectorAtom);
|
3910
4200
|
selector = selectorParts[1];
|
3911
4201
|
if (selector === 'html') {
|
3912
4202
|
selector = 'body';
|
@@ -4006,7 +4296,7 @@ are based on this module.
|
|
4006
4296
|
$element: $element
|
4007
4297
|
})) {
|
4008
4298
|
options = u.options(options, {
|
4009
|
-
animation:
|
4299
|
+
animation: false
|
4010
4300
|
});
|
4011
4301
|
animateOptions = up.motion.animateOptions(options);
|
4012
4302
|
$element.addClass('up-destroying');
|
@@ -4090,11 +4380,13 @@ are based on this module.
|
|
4090
4380
|
return setSource(document.body, up.browser.url());
|
4091
4381
|
});
|
4092
4382
|
return {
|
4383
|
+
knife: eval(typeof Knife !== "undefined" && Knife !== null ? Knife.point : void 0),
|
4093
4384
|
replace: replace,
|
4094
4385
|
reload: reload,
|
4095
4386
|
destroy: destroy,
|
4096
4387
|
implant: implant,
|
4097
4388
|
first: first,
|
4389
|
+
source: source,
|
4098
4390
|
resolveSelector: resolveSelector
|
4099
4391
|
};
|
4100
4392
|
})(jQuery);
|
@@ -4272,9 +4564,8 @@ or [transitions](/up.transition) using Javascript or CSS.
|
|
4272
4564
|
finish($element);
|
4273
4565
|
options = animateOptions(options);
|
4274
4566
|
if (animation === 'none' || animation === false) {
|
4275
|
-
none();
|
4276
|
-
}
|
4277
|
-
if (u.isFunction(animation)) {
|
4567
|
+
return none();
|
4568
|
+
} else if (u.isFunction(animation)) {
|
4278
4569
|
return assertIsDeferred(animation($element, options), animation);
|
4279
4570
|
} else if (u.isString(animation)) {
|
4280
4571
|
return animate($element, findAnimation(animation), options);
|
@@ -4286,7 +4577,7 @@ or [transitions](/up.transition) using Javascript or CSS.
|
|
4286
4577
|
return u.resolvedDeferred();
|
4287
4578
|
}
|
4288
4579
|
} else {
|
4289
|
-
return u.error("Unknown animation type %o", animation);
|
4580
|
+
return u.error("Unknown animation type for %o", animation);
|
4290
4581
|
}
|
4291
4582
|
};
|
4292
4583
|
|
@@ -4453,7 +4744,7 @@ or [transitions](/up.transition) using Javascript or CSS.
|
|
4453
4744
|
@stable
|
4454
4745
|
*/
|
4455
4746
|
morph = function(source, target, transitionOrName, options) {
|
4456
|
-
var $new, $old, animation,
|
4747
|
+
var $new, $old, animation, parsedOptions, parts, transition;
|
4457
4748
|
u.debug('Morphing %o to %o (using %o)', source, target, transitionOrName);
|
4458
4749
|
$old = $(source);
|
4459
4750
|
$new = $(target);
|
@@ -4462,12 +4753,11 @@ or [transitions](/up.transition) using Javascript or CSS.
|
|
4462
4753
|
if (isEnabled()) {
|
4463
4754
|
finish($old);
|
4464
4755
|
finish($new);
|
4465
|
-
if (transitionOrName === 'none' || transitionOrName === false
|
4466
|
-
|
4467
|
-
|
4468
|
-
|
4469
|
-
|
4470
|
-
return deferred;
|
4756
|
+
if (transitionOrName === 'none' || transitionOrName === false) {
|
4757
|
+
return skipMorph($old, $new, parsedOptions);
|
4758
|
+
} else if (animation = animations[transitionOrName]) {
|
4759
|
+
skipMorph($old, $new, parsedOptions);
|
4760
|
+
return animate($new, animation, parsedOptions);
|
4471
4761
|
} else if (transition = u.presence(transitionOrName, u.isFunction) || transitions[transitionOrName]) {
|
4472
4762
|
return withGhosts($old, $new, parsedOptions, function($oldGhost, $newGhost) {
|
4473
4763
|
var transitionPromise;
|
@@ -4871,7 +5161,7 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
4871
5161
|
var slice = [].slice;
|
4872
5162
|
|
4873
5163
|
up.proxy = (function($) {
|
4874
|
-
var $waitingLink,
|
5164
|
+
var $waitingLink, ajax, alias, busy, busyDelayTimer, busyEventEmitted, cache, cacheKey, cancelBusyDelay, cancelPreloadDelay, checkPreload, clear, config, get, idle, isIdempotent, load, loadEnded, loadOrQueue, loadStarted, normalizeRequest, pendingCount, pokeQueue, preload, preloadDelayTimer, queue, queuedRequests, remove, reset, set, startPreloadDelay, u;
|
4875
5165
|
u = up.util;
|
4876
5166
|
$waitingLink = void 0;
|
4877
5167
|
preloadDelayTimer = void 0;
|
@@ -4903,6 +5193,16 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
4903
5193
|
|
4904
5194
|
Note that your browser might [impose its own request limit](http://www.browserscope.org/?category=network)
|
4905
5195
|
regardless of what you configure here.
|
5196
|
+
@param {Array<String>} [config.wrapMethods]
|
5197
|
+
An array of uppercase HTTP method names. AJAX requests with one of these methods
|
5198
|
+
will be converted into a `POST` request and carry their original method as a `_method`
|
5199
|
+
parameter. This is to [prevent unexpected redirect behavior](https://makandracards.com/makandra/38347).
|
5200
|
+
@param {String} [config.wrapMethodParam]
|
5201
|
+
The name of the POST parameter when wrapping HTTP methods in a `POST` request.
|
5202
|
+
@param {Array<String>} [config.safeMethods]
|
5203
|
+
An array of uppercase HTTP method names that are considered idempotent.
|
5204
|
+
The proxy cache will only cache idempotent requests and will clear the entire
|
5205
|
+
cache after a non-idempotent request.
|
4906
5206
|
@stable
|
4907
5207
|
*/
|
4908
5208
|
config = u.config({
|
@@ -4910,11 +5210,14 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
4910
5210
|
preloadDelay: 75,
|
4911
5211
|
cacheSize: 70,
|
4912
5212
|
cacheExpiry: 1000 * 60 * 5,
|
4913
|
-
maxRequests: 4
|
5213
|
+
maxRequests: 4,
|
5214
|
+
wrapMethods: ['PATCH', 'PUT', 'DELETE'],
|
5215
|
+
wrapMethodParam: '_method',
|
5216
|
+
safeMethods: ['GET', 'OPTIONS', 'HEAD']
|
4914
5217
|
});
|
4915
5218
|
cacheKey = function(request) {
|
4916
5219
|
normalizeRequest(request);
|
4917
|
-
return [request.url, request.method, request.data, request.
|
5220
|
+
return [request.url, request.method, request.data, request.target].join('|');
|
4918
5221
|
};
|
4919
5222
|
cache = u.cache({
|
4920
5223
|
size: function() {
|
@@ -4942,14 +5245,14 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
4942
5245
|
var candidate, candidates, i, len, requestForBody, requestForHtml, response;
|
4943
5246
|
request = normalizeRequest(request);
|
4944
5247
|
candidates = [request];
|
4945
|
-
if (request.
|
5248
|
+
if (request.target !== 'html') {
|
4946
5249
|
requestForHtml = u.merge(request, {
|
4947
|
-
|
5250
|
+
target: 'html'
|
4948
5251
|
});
|
4949
5252
|
candidates.push(requestForHtml);
|
4950
|
-
if (request.
|
5253
|
+
if (request.target !== 'body') {
|
4951
5254
|
requestForBody = u.merge(request, {
|
4952
|
-
|
5255
|
+
target: 'body'
|
4953
5256
|
});
|
4954
5257
|
candidates.push(requestForBody);
|
4955
5258
|
}
|
@@ -4968,7 +5271,7 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
4968
5271
|
@function up.proxy.set
|
4969
5272
|
@param {String} request.url
|
4970
5273
|
@param {String} [request.method='GET']
|
4971
|
-
@param {String} [request.
|
5274
|
+
@param {String} [request.target='body']
|
4972
5275
|
@param {Promise} response
|
4973
5276
|
A promise for the response that is API-compatible with the
|
4974
5277
|
promise returned by [`jQuery.ajax`](http://api.jquery.com/jquery.ajax/).
|
@@ -4985,7 +5288,7 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
4985
5288
|
@function up.proxy.remove
|
4986
5289
|
@param {String} request.url
|
4987
5290
|
@param {String} [request.method='GET']
|
4988
|
-
@param {String} [request.
|
5291
|
+
@param {String} [request.target='body']
|
4989
5292
|
@experimental
|
4990
5293
|
*/
|
4991
5294
|
remove = cache.remove;
|
@@ -5026,7 +5329,7 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
5026
5329
|
if (request.url) {
|
5027
5330
|
request.url = u.normalizeUrl(request.url);
|
5028
5331
|
}
|
5029
|
-
request.
|
5332
|
+
request.target || (request.target = 'body');
|
5030
5333
|
request._normalized = true;
|
5031
5334
|
}
|
5032
5335
|
return request;
|
@@ -5049,13 +5352,15 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
5049
5352
|
@function up.proxy.ajax
|
5050
5353
|
@param {String} request.url
|
5051
5354
|
@param {String} [request.method='GET']
|
5052
|
-
@param {String} [request.
|
5355
|
+
@param {String} [request.target='body']
|
5053
5356
|
@param {Boolean} [request.cache]
|
5054
5357
|
Whether to use a cached response, if available.
|
5055
5358
|
If set to `false` a network connection will always be attempted.
|
5056
5359
|
@param {Object} [request.headers={}]
|
5057
5360
|
An object of additional header key/value pairs to send along
|
5058
5361
|
with the request.
|
5362
|
+
@param {Object} [request.data={}]
|
5363
|
+
An object of request parameters.
|
5059
5364
|
@return
|
5060
5365
|
A promise for the response that is API-compatible with the
|
5061
5366
|
promise returned by [`jQuery.ajax`](http://api.jquery.com/jquery.ajax/).
|
@@ -5065,7 +5370,7 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
5065
5370
|
var forceCache, ignoreCache, pending, promise, request;
|
5066
5371
|
forceCache = options.cache === true;
|
5067
5372
|
ignoreCache = options.cache === false;
|
5068
|
-
request = u.only(options, 'url', 'method', 'data', '
|
5373
|
+
request = u.only(options, 'url', 'method', 'data', 'target', 'headers', '_normalized');
|
5069
5374
|
pending = true;
|
5070
5375
|
if (!isIdempotent(request) && !forceCache) {
|
5071
5376
|
clear();
|
@@ -5085,7 +5390,6 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
5085
5390
|
}
|
5086
5391
|
return promise;
|
5087
5392
|
};
|
5088
|
-
SAFE_HTTP_METHODS = ['GET', 'OPTIONS', 'HEAD'];
|
5089
5393
|
|
5090
5394
|
/**
|
5091
5395
|
Returns `true` if the proxy is not currently waiting
|
@@ -5190,9 +5494,20 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
5190
5494
|
};
|
5191
5495
|
load = function(request) {
|
5192
5496
|
var promise;
|
5193
|
-
u.debug('
|
5497
|
+
u.debug('Fetching %o via %o', request.url, request.method);
|
5194
5498
|
up.emit('up:proxy:load', request);
|
5195
|
-
|
5499
|
+
request = u.copy(request);
|
5500
|
+
request.headers || (request.headers = {});
|
5501
|
+
request.headers['X-Up-Target'] = request.target;
|
5502
|
+
request.data = u.requestDataAsArray(request.data);
|
5503
|
+
if (u.contains(config.wrapMethods, request.method)) {
|
5504
|
+
request.data.push({
|
5505
|
+
name: config.wrapMethodParam,
|
5506
|
+
value: request.method
|
5507
|
+
});
|
5508
|
+
request.method = 'POST';
|
5509
|
+
}
|
5510
|
+
promise = $.ajax(request);
|
5196
5511
|
promise.always(function() {
|
5197
5512
|
up.emit('up:proxy:received', request);
|
5198
5513
|
return pokeQueue();
|
@@ -5223,7 +5538,7 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
5223
5538
|
@event up:proxy:load
|
5224
5539
|
@param event.url
|
5225
5540
|
@param event.method
|
5226
|
-
@param event.
|
5541
|
+
@param event.target
|
5227
5542
|
@experimental
|
5228
5543
|
*/
|
5229
5544
|
|
@@ -5234,12 +5549,12 @@ You can change (or remove) this delay by [configuring `up.proxy`](/up.proxy.conf
|
|
5234
5549
|
@event up:proxy:received
|
5235
5550
|
@param event.url
|
5236
5551
|
@param event.method
|
5237
|
-
@param event.
|
5552
|
+
@param event.target
|
5238
5553
|
@experimental
|
5239
5554
|
*/
|
5240
5555
|
isIdempotent = function(request) {
|
5241
5556
|
normalizeRequest(request);
|
5242
|
-
return u.contains(
|
5557
|
+
return u.contains(config.safeMethods, request.method);
|
5243
5558
|
};
|
5244
5559
|
checkPreload = function($link) {
|
5245
5560
|
var curriedPreload, delay;
|
@@ -5407,7 +5722,7 @@ Read on
|
|
5407
5722
|
|
5408
5723
|
(function() {
|
5409
5724
|
up.link = (function($) {
|
5410
|
-
var allowDefault, childClicked, follow, followMethod, followVariantSelectors, isFollowable, makeFollowable,
|
5725
|
+
var allowDefault, childClicked, follow, followMethod, followVariantSelectors, isFollowable, makeFollowable, onAction, shouldProcessLinkEvent, u, visit;
|
5411
5726
|
u = up.util;
|
5412
5727
|
|
5413
5728
|
/**
|
@@ -5456,8 +5771,13 @@ Read on
|
|
5456
5771
|
or any element that is marked up with an `up-href` attribute.
|
5457
5772
|
@param {String} [options.target]
|
5458
5773
|
The selector to replace.
|
5459
|
-
Defaults to the `up-target` attribute on `link`,
|
5460
|
-
|
5774
|
+
Defaults to the `up-target` attribute on `link`, or to `body` if such an attribute does not exist.
|
5775
|
+
@param {String} [options.failTarget]
|
5776
|
+
The selector to replace if the server responds with a non-200 status code.
|
5777
|
+
Defaults to the `up-fail-target` attribute on `link`, or to `body` if such an attribute does not exist.
|
5778
|
+
@param {String} [options.confirm]
|
5779
|
+
A message that will be displayed in a cancelable confirmation dialog
|
5780
|
+
before the link is followed.
|
5461
5781
|
@param {Function|String} [options.transition]
|
5462
5782
|
A transition function or name.
|
5463
5783
|
@param {Number} [options.duration]
|
@@ -5484,20 +5804,25 @@ Read on
|
|
5484
5804
|
@stable
|
5485
5805
|
*/
|
5486
5806
|
follow = function(linkOrSelector, options) {
|
5487
|
-
var $link,
|
5807
|
+
var $link, target, url;
|
5488
5808
|
$link = $(linkOrSelector);
|
5489
5809
|
options = u.options(options);
|
5490
5810
|
url = u.option($link.attr('up-href'), $link.attr('href'));
|
5491
|
-
|
5492
|
-
options.
|
5811
|
+
target = u.option(options.target, $link.attr('up-target'), 'body');
|
5812
|
+
options.failTarget = u.option(options.failTarget, $link.attr('up-fail-target'), 'body');
|
5813
|
+
options.transition = u.option(options.transition, u.castedAttr($link, 'up-transition'), 'none');
|
5814
|
+
options.failTransition = u.option(options.failTransition, u.castedAttr($link, 'up-fail-transition'), 'none');
|
5493
5815
|
options.history = u.option(options.history, u.castedAttr($link, 'up-history'));
|
5494
5816
|
options.reveal = u.option(options.reveal, u.castedAttr($link, 'up-reveal'), true);
|
5495
5817
|
options.cache = u.option(options.cache, u.castedAttr($link, 'up-cache'));
|
5496
5818
|
options.restoreScroll = u.option(options.restoreScroll, u.castedAttr($link, 'up-restore-scroll'));
|
5497
5819
|
options.method = followMethod($link, options);
|
5498
5820
|
options.origin = u.option(options.origin, $link);
|
5821
|
+
options.confirm = u.option(options.confirm, $link.attr('up-confirm'));
|
5499
5822
|
options = u.merge(options, up.motion.animateOptions(options, $link));
|
5500
|
-
return up.
|
5823
|
+
return up.browser.confirm(options.confirm).then(function() {
|
5824
|
+
return up.replace(target, url, options);
|
5825
|
+
});
|
5501
5826
|
};
|
5502
5827
|
|
5503
5828
|
/**
|
@@ -5541,7 +5866,7 @@ Read on
|
|
5541
5866
|
@internal
|
5542
5867
|
*/
|
5543
5868
|
allowDefault = function(event) {};
|
5544
|
-
|
5869
|
+
onAction = function(selector, handler) {
|
5545
5870
|
followVariantSelectors.push(selector);
|
5546
5871
|
up.on('click', "a" + selector + ", [up-href]" + selector, function(event, $link) {
|
5547
5872
|
if (shouldProcessLinkEvent(event, $link)) {
|
@@ -5635,9 +5960,14 @@ Read on
|
|
5635
5960
|
@selector a[up-target]
|
5636
5961
|
@param {String} up-target
|
5637
5962
|
The CSS selector to replace
|
5963
|
+
@param [up-fail-target='body']
|
5964
|
+
The selector to replace if the server responds with a non-200 status code.
|
5638
5965
|
@param {String} [up-href]
|
5639
5966
|
The destination URL to follow.
|
5640
5967
|
If omitted, the the link's `href` attribute will be used.
|
5968
|
+
@param {String} [up-confirm]
|
5969
|
+
A message that will be displayed in a cancelable confirmation dialog
|
5970
|
+
before the link is followed.
|
5641
5971
|
@param {String} [up-reveal='true']
|
5642
5972
|
Whether to reveal the target element within its viewport before updating.
|
5643
5973
|
@param {String} [up-restore-scroll='false']
|
@@ -5651,7 +5981,7 @@ Read on
|
|
5651
5981
|
Set this to `'false'` to prevent the current URL from being updated.
|
5652
5982
|
@stable
|
5653
5983
|
*/
|
5654
|
-
|
5984
|
+
onAction('[up-target]', function($link) {
|
5655
5985
|
return follow($link);
|
5656
5986
|
});
|
5657
5987
|
|
@@ -5699,9 +6029,14 @@ Read on
|
|
5699
6029
|
opening the destination in a new tab.
|
5700
6030
|
|
5701
6031
|
@selector a[up-follow]
|
6032
|
+
@param [up-fail-target='body']
|
6033
|
+
The selector to replace if the server responds with a non-200 status code.
|
5702
6034
|
@param [up-href]
|
5703
6035
|
The destination URL to follow.
|
5704
6036
|
If omitted, the the link's `href` attribute will be used.
|
6037
|
+
@param {String} [up-confirm]
|
6038
|
+
A message that will be displayed in a cancelable confirmation dialog
|
6039
|
+
before the link is followed.
|
5705
6040
|
@param [up-history]
|
5706
6041
|
Set this to `'false'` to prevent the current URL from being updated.
|
5707
6042
|
@param [up-restore-scroll='false']
|
@@ -5709,7 +6044,7 @@ Read on
|
|
5709
6044
|
within the response.
|
5710
6045
|
@stable
|
5711
6046
|
*/
|
5712
|
-
|
6047
|
+
onAction('[up-follow]', function($link) {
|
5713
6048
|
return follow($link);
|
5714
6049
|
});
|
5715
6050
|
|
@@ -5732,27 +6067,46 @@ Read on
|
|
5732
6067
|
|
5733
6068
|
`up-expand` also expands links that open [modals](/up.modal) or [popups](/up.popup).
|
5734
6069
|
|
6070
|
+
\#\#\#\# Elements with multiple contained links
|
6071
|
+
|
6072
|
+
If a container contains more than one link, you can set the value of the
|
6073
|
+
`up-expand` attribute to a CSS selector to define which link should be expanded:
|
6074
|
+
|
6075
|
+
<div class="notification" up-expand=".close">
|
6076
|
+
Record was saved!
|
6077
|
+
<a class="details" href="/records/5">Details</a>
|
6078
|
+
<a class="close" href="/records">Close</a>
|
6079
|
+
</div>
|
6080
|
+
|
5735
6081
|
@selector [up-expand]
|
6082
|
+
@param {String} [up-expand]
|
6083
|
+
A CSS selector that defines which containing link should be expanded.
|
6084
|
+
|
6085
|
+
If omitted, the first contained link will be expanded.
|
5736
6086
|
@stable
|
5737
6087
|
*/
|
5738
6088
|
up.compiler('[up-expand]', function($area) {
|
5739
|
-
var attribute, i, len, link, name, newAttrs, ref, upAttributePattern;
|
5740
|
-
|
5741
|
-
|
5742
|
-
|
5743
|
-
|
5744
|
-
|
5745
|
-
|
5746
|
-
|
5747
|
-
|
5748
|
-
|
5749
|
-
|
5750
|
-
|
6089
|
+
var $childLinks, attribute, i, len, link, name, newAttrs, ref, selector, upAttributePattern;
|
6090
|
+
$childLinks = $area.find('a, [up-href]');
|
6091
|
+
if (selector = $area.attr('up-expand')) {
|
6092
|
+
$childLinks = $childLinks.filter(selector);
|
6093
|
+
}
|
6094
|
+
if (link = $childLinks.get(0)) {
|
6095
|
+
upAttributePattern = /^up-/;
|
6096
|
+
newAttrs = {};
|
6097
|
+
newAttrs['up-href'] = $(link).attr('href');
|
6098
|
+
ref = link.attributes;
|
6099
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
6100
|
+
attribute = ref[i];
|
6101
|
+
name = attribute.name;
|
6102
|
+
if (name.match(upAttributePattern)) {
|
6103
|
+
newAttrs[name] = attribute.value;
|
6104
|
+
}
|
5751
6105
|
}
|
6106
|
+
u.setMissingAttrs($area, newAttrs);
|
6107
|
+
$area.removeAttr('up-expand');
|
6108
|
+
return makeFollowable($area);
|
5752
6109
|
}
|
5753
|
-
u.setMissingAttrs($area, newAttrs);
|
5754
|
-
$area.removeAttr('up-expand');
|
5755
|
-
return makeFollowable($area);
|
5756
6110
|
});
|
5757
6111
|
|
5758
6112
|
/**
|
@@ -5797,7 +6151,7 @@ Read on
|
|
5797
6151
|
shouldProcessLinkEvent: shouldProcessLinkEvent,
|
5798
6152
|
childClicked: childClicked,
|
5799
6153
|
followMethod: followMethod,
|
5800
|
-
|
6154
|
+
onAction: onAction
|
5801
6155
|
};
|
5802
6156
|
})(jQuery);
|
5803
6157
|
|
@@ -5822,7 +6176,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
5822
6176
|
var slice = [].slice;
|
5823
6177
|
|
5824
6178
|
up.form = (function($) {
|
5825
|
-
var autosubmit, config, observe, observeForm, reset, resolveValidateTarget, submit, u, validate;
|
6179
|
+
var autosubmit, config, currentValuesForToggle, observe, observeForm, reset, resolveValidateTarget, submit, toggleTargets, u, validate;
|
5826
6180
|
u = up.util;
|
5827
6181
|
|
5828
6182
|
/**
|
@@ -5924,77 +6278,41 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
5924
6278
|
@stable
|
5925
6279
|
*/
|
5926
6280
|
submit = function(formOrSelector, options) {
|
5927
|
-
var $form,
|
6281
|
+
var $form, hasFileInputs, promise, target, url;
|
5928
6282
|
$form = $(formOrSelector).closest('form');
|
5929
6283
|
options = u.options(options);
|
5930
|
-
|
5931
|
-
successSelector = up.flow.resolveSelector(successSelector, options);
|
5932
|
-
failureSelector = u.option(options.failTarget, $form.attr('up-fail-target')) || u.selectorForElement($form);
|
5933
|
-
failureSelector = up.flow.resolveSelector(failureSelector, options);
|
5934
|
-
historyOption = u.option(options.history, u.castedAttr($form, 'up-history'), true);
|
5935
|
-
successTransition = u.option(options.transition, u.castedAttr($form, 'up-transition'));
|
5936
|
-
failureTransition = u.option(options.failTransition, u.castedAttr($form, 'up-fail-transition'), successTransition);
|
5937
|
-
httpMethod = u.option(options.method, $form.attr('up-method'), $form.attr('data-method'), $form.attr('method'), 'post').toUpperCase();
|
5938
|
-
headers = u.option(options.headers, {});
|
5939
|
-
implantOptions = {};
|
5940
|
-
implantOptions.reveal = u.option(options.reveal, u.castedAttr($form, 'up-reveal'), true);
|
5941
|
-
implantOptions.cache = u.option(options.cache, u.castedAttr($form, 'up-cache'));
|
5942
|
-
implantOptions.restoreScroll = u.option(options.restoreScroll, u.castedAttr($form, 'up-restore-scroll'));
|
5943
|
-
implantOptions.origin = u.option(options.origin, $form);
|
5944
|
-
implantOptions = u.extend(implantOptions, up.motion.animateOptions(options, $form));
|
5945
|
-
useCache = u.option(options.cache, u.castedAttr($form, 'up-cache'));
|
6284
|
+
target = u.option(options.target, $form.attr('up-target'), 'body');
|
5946
6285
|
url = u.option(options.url, $form.attr('action'), up.browser.url());
|
6286
|
+
options.failTarget = u.option(options.failTarget, $form.attr('up-fail-target')) || u.selectorForElement($form);
|
6287
|
+
options.history = u.option(options.history, u.castedAttr($form, 'up-history'), true);
|
6288
|
+
options.transition = u.option(options.transition, u.castedAttr($form, 'up-transition'), 'none');
|
6289
|
+
options.failTransition = u.option(options.failTransition, u.castedAttr($form, 'up-fail-transition'), 'none');
|
6290
|
+
options.method = u.option(options.method, $form.attr('up-method'), $form.attr('data-method'), $form.attr('method'), 'post').toUpperCase();
|
6291
|
+
options.headers = u.option(options.headers, {});
|
6292
|
+
options.reveal = u.option(options.reveal, u.castedAttr($form, 'up-reveal'), true);
|
6293
|
+
options.cache = u.option(options.cache, u.castedAttr($form, 'up-cache'));
|
6294
|
+
options.restoreScroll = u.option(options.restoreScroll, u.castedAttr($form, 'up-restore-scroll'));
|
6295
|
+
options.origin = u.option(options.origin, $form);
|
6296
|
+
options.data = $form.serializeArray();
|
6297
|
+
options = u.merge(options, up.motion.animateOptions(options, $form));
|
5947
6298
|
hasFileInputs = $form.find('input[type=file]').length;
|
5948
6299
|
if (options.validate) {
|
5949
|
-
headers
|
6300
|
+
options.headers || (options.headers = {});
|
6301
|
+
options.headers['X-Up-Validate'] = options.validate;
|
5950
6302
|
if (hasFileInputs) {
|
5951
6303
|
return u.unresolvablePromise();
|
5952
6304
|
}
|
5953
6305
|
}
|
5954
6306
|
$form.addClass('up-active');
|
5955
|
-
if (hasFileInputs || (!up.browser.canPushState() &&
|
6307
|
+
if (hasFileInputs || (!up.browser.canPushState() && options.history !== false)) {
|
5956
6308
|
$form.get(0).submit();
|
5957
6309
|
return u.unresolvablePromise();
|
5958
6310
|
}
|
5959
|
-
|
5960
|
-
|
5961
|
-
method: httpMethod,
|
5962
|
-
data: $form.serialize(),
|
5963
|
-
selector: successSelector,
|
5964
|
-
cache: useCache,
|
5965
|
-
headers: headers
|
5966
|
-
};
|
5967
|
-
successUrl = function(xhr) {
|
5968
|
-
var currentLocation;
|
5969
|
-
url = void 0;
|
5970
|
-
if (u.isGiven(historyOption)) {
|
5971
|
-
if (historyOption === false || u.isString(historyOption)) {
|
5972
|
-
url = historyOption;
|
5973
|
-
} else if (currentLocation = u.locationFromXhr(xhr)) {
|
5974
|
-
url = currentLocation;
|
5975
|
-
} else if (request.type === 'GET') {
|
5976
|
-
url = request.url + '?' + request.data;
|
5977
|
-
}
|
5978
|
-
}
|
5979
|
-
return u.option(url, false);
|
5980
|
-
};
|
5981
|
-
return up.proxy.ajax(request).always(function() {
|
6311
|
+
promise = up.replace(target, url, options);
|
6312
|
+
promise.always(function() {
|
5982
6313
|
return $form.removeClass('up-active');
|
5983
|
-
}).done(function(html, textStatus, xhr) {
|
5984
|
-
var successOptions;
|
5985
|
-
successOptions = u.merge(implantOptions, {
|
5986
|
-
history: successUrl(xhr),
|
5987
|
-
transition: successTransition
|
5988
|
-
});
|
5989
|
-
return up.flow.implant(successSelector, html, successOptions);
|
5990
|
-
}).fail(function(xhr, textStatus, errorThrown) {
|
5991
|
-
var failureOptions, html;
|
5992
|
-
html = xhr.responseText;
|
5993
|
-
failureOptions = u.merge(implantOptions, {
|
5994
|
-
transition: failureTransition
|
5995
|
-
});
|
5996
|
-
return up.flow.implant(failureSelector, html, failureOptions);
|
5997
6314
|
});
|
6315
|
+
return promise;
|
5998
6316
|
};
|
5999
6317
|
|
6000
6318
|
/**
|
@@ -6172,7 +6490,6 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
6172
6490
|
@stable
|
6173
6491
|
*/
|
6174
6492
|
autosubmit = function(selectorOrElement, options) {
|
6175
|
-
console.log("autosubmit %o", selectorOrElement);
|
6176
6493
|
return observe(selectorOrElement, options, function(value, $field) {
|
6177
6494
|
var $form;
|
6178
6495
|
$form = $field.closest('form');
|
@@ -6188,7 +6505,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
6188
6505
|
if (u.isBlank(target)) {
|
6189
6506
|
target || (target = u.detect(config.validateTargets, function(defaultTarget) {
|
6190
6507
|
var resolvedDefault;
|
6191
|
-
resolvedDefault = up.flow.resolveSelector(defaultTarget, options);
|
6508
|
+
resolvedDefault = up.flow.resolveSelector(defaultTarget, options.origin);
|
6192
6509
|
return $field.closest(resolvedDefault).length;
|
6193
6510
|
}));
|
6194
6511
|
}
|
@@ -6240,6 +6557,109 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
6240
6557
|
promise = up.submit($form, options);
|
6241
6558
|
return promise;
|
6242
6559
|
};
|
6560
|
+
currentValuesForToggle = function($field) {
|
6561
|
+
var $checkedButton, value, values;
|
6562
|
+
values = void 0;
|
6563
|
+
if ($field.is('input[type=checkbox]')) {
|
6564
|
+
if ($field.is(':checked')) {
|
6565
|
+
values = [':checked', ':present', $field.val()];
|
6566
|
+
} else {
|
6567
|
+
values = [':unchecked', ':blank'];
|
6568
|
+
}
|
6569
|
+
} else if ($field.is('input[type=radio]')) {
|
6570
|
+
console.log('-- it is a radio button --');
|
6571
|
+
$checkedButton = $field.closest('form, body').find("input[type='radio'][name='" + ($field.attr('name')) + "']:checked");
|
6572
|
+
console.log('checked button is %o', $checkedButton);
|
6573
|
+
console.log('checked button val is %o', $checkedButton.val());
|
6574
|
+
if ($checkedButton.length) {
|
6575
|
+
values = [':checked', ':present', $checkedButton.val()];
|
6576
|
+
} else {
|
6577
|
+
values = [':unchecked', ':blank'];
|
6578
|
+
}
|
6579
|
+
} else {
|
6580
|
+
console.log('-- else -- for %o', $field);
|
6581
|
+
value = $field.val();
|
6582
|
+
if (u.isPresent(value)) {
|
6583
|
+
values = [':present', value];
|
6584
|
+
} else {
|
6585
|
+
values = [':blank'];
|
6586
|
+
}
|
6587
|
+
}
|
6588
|
+
return values;
|
6589
|
+
};
|
6590
|
+
currentValuesForToggle = function($field) {
|
6591
|
+
var $checkedButton, meta, value, values;
|
6592
|
+
if ($field.is('input[type=checkbox]')) {
|
6593
|
+
if ($field.is(':checked')) {
|
6594
|
+
value = $field.val();
|
6595
|
+
meta = ':checked';
|
6596
|
+
} else {
|
6597
|
+
meta = ':unchecked';
|
6598
|
+
}
|
6599
|
+
} else if ($field.is('input[type=radio]')) {
|
6600
|
+
$checkedButton = $field.closest('form, body').find("input[type='radio'][name='" + ($field.attr('name')) + "']:checked");
|
6601
|
+
if ($checkedButton.length) {
|
6602
|
+
meta = ':checked';
|
6603
|
+
value = $checkedButton.val();
|
6604
|
+
} else {
|
6605
|
+
meta = ':unchecked';
|
6606
|
+
}
|
6607
|
+
} else {
|
6608
|
+
value = $field.val();
|
6609
|
+
}
|
6610
|
+
values = [];
|
6611
|
+
if (u.isPresent(value)) {
|
6612
|
+
values.push(value);
|
6613
|
+
values.push(':present');
|
6614
|
+
} else {
|
6615
|
+
values.push(':blank');
|
6616
|
+
}
|
6617
|
+
if (u.isPresent(meta)) {
|
6618
|
+
values.push(meta);
|
6619
|
+
}
|
6620
|
+
return values;
|
6621
|
+
};
|
6622
|
+
|
6623
|
+
/**
|
6624
|
+
Shows or hides a target selector depending on the value.
|
6625
|
+
|
6626
|
+
See [`[up-toggle]`](/up-toggle) for more documentation and examples.
|
6627
|
+
|
6628
|
+
This function does not currently have a very useful API outside
|
6629
|
+
of our use for `up-toggle`'s UJS behavior, that's why it's currently
|
6630
|
+
still marked `@internal`.
|
6631
|
+
|
6632
|
+
@function up.form.toggle
|
6633
|
+
@param {String|Element|jQuery} fieldOrSelector
|
6634
|
+
@param {String} [options.target]
|
6635
|
+
The target selectors to toggle.
|
6636
|
+
Defaults to an `up-toggle` attribute on the given field.
|
6637
|
+
@internal
|
6638
|
+
*/
|
6639
|
+
toggleTargets = function(fieldOrSelector, options) {
|
6640
|
+
var $field, fieldValues, targets;
|
6641
|
+
$field = $(fieldOrSelector);
|
6642
|
+
options = u.options(options);
|
6643
|
+
targets = u.option(options.target, $field.attr('up-toggle'));
|
6644
|
+
u.isPresent(targets) || u.error("No toggle target given for %o", $field);
|
6645
|
+
fieldValues = currentValuesForToggle($field);
|
6646
|
+
return $(targets).each(function() {
|
6647
|
+
var $target, hideValues, show, showValues;
|
6648
|
+
$target = $(this);
|
6649
|
+
if (hideValues = $target.attr('up-hide-for')) {
|
6650
|
+
hideValues = hideValues.split(' ');
|
6651
|
+
show = u.intersect(fieldValues, hideValues).length === 0;
|
6652
|
+
} else {
|
6653
|
+
if (showValues = $target.attr('up-show-for')) {
|
6654
|
+
showValues = showValues.split(' ');
|
6655
|
+
} else {
|
6656
|
+
showValues = [':present', ':checked'];
|
6657
|
+
}
|
6658
|
+
show = u.intersect(fieldValues, showValues).length > 0;
|
6659
|
+
}
|
6660
|
+
return $target.toggle(show);
|
6661
|
+
});
|
6662
|
+
};
|
6243
6663
|
|
6244
6664
|
/**
|
6245
6665
|
Forms with an `up-target` attribute are [submitted via AJAX](/up.submit)
|
@@ -6294,7 +6714,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
6294
6714
|
|
6295
6715
|
When the form's action performs a redirect, the server should echo
|
6296
6716
|
the new request's URL as a response header `X-Up-Location`
|
6297
|
-
and the request's HTTP method as `X-Up-Method`.
|
6717
|
+
and the request's HTTP method as `X-Up-Method: GET`.
|
6298
6718
|
|
6299
6719
|
If you are using Up.js via the `upjs-rails` gem, these headers
|
6300
6720
|
are set automatically for every request.
|
@@ -6490,6 +6910,83 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
6490
6910
|
return validate($field);
|
6491
6911
|
});
|
6492
6912
|
|
6913
|
+
/**
|
6914
|
+
Show or hide part of a form if certain options are selected or boxes are checked.
|
6915
|
+
|
6916
|
+
\#\#\#\# Example
|
6917
|
+
|
6918
|
+
The triggering input gets an `up-toggle` attribute with a selector for the elements to show or hide:
|
6919
|
+
|
6920
|
+
<select name="advancedness" up-toggle=".target">
|
6921
|
+
<option value="basic">Basic parts</option>
|
6922
|
+
<option value="advanced">Advanced parts</option>
|
6923
|
+
<option value="very-advanced">Very advanced parts</option>
|
6924
|
+
</select>
|
6925
|
+
|
6926
|
+
The target elements get a space-separated list of select values for which they are shown or hidden:
|
6927
|
+
|
6928
|
+
<div class="target" up-show-for="basic">
|
6929
|
+
only shown for advancedness = basic
|
6930
|
+
</div>
|
6931
|
+
|
6932
|
+
<div class="target" up-hide-for="basic">
|
6933
|
+
hidden for advancedness = basic
|
6934
|
+
</div>
|
6935
|
+
|
6936
|
+
<div class="target" up-show-for="advanced very-advanced">
|
6937
|
+
shown for advancedness = advanced or very-advanced
|
6938
|
+
</div>
|
6939
|
+
|
6940
|
+
For checkboxes you can also use the pseudo-values `:checked` or `:unchecked` like so:
|
6941
|
+
|
6942
|
+
<input type="checkbox" name="flag" up-toggle=".target">
|
6943
|
+
|
6944
|
+
<div class="target" up-show-for=":checked">
|
6945
|
+
only shown when checkbox is checked
|
6946
|
+
</div>
|
6947
|
+
|
6948
|
+
You can also use the pseudo-values `:blank` to match an empty input value,
|
6949
|
+
or `:present` to match a non-empty input value:
|
6950
|
+
|
6951
|
+
<input type="text" name="email" up-toggle=".target">
|
6952
|
+
|
6953
|
+
<div class="target" up-show-for=":blank">
|
6954
|
+
please enter an email address
|
6955
|
+
</div>
|
6956
|
+
|
6957
|
+
@selector [up-toggle]
|
6958
|
+
@stable
|
6959
|
+
*/
|
6960
|
+
|
6961
|
+
/**
|
6962
|
+
Show this element only if a form field has a given value.
|
6963
|
+
|
6964
|
+
See [`[up-toggle]`](/up-toggle) for more documentation and examples.
|
6965
|
+
|
6966
|
+
@selector [up-show-for]
|
6967
|
+
@param up-show-for
|
6968
|
+
A space-separated list of values for which to show this element.
|
6969
|
+
@stable
|
6970
|
+
*/
|
6971
|
+
|
6972
|
+
/**
|
6973
|
+
Hide this element if a form field has a given value.
|
6974
|
+
|
6975
|
+
See [`[up-toggle]`](/up-toggle) for more documentation and examples.
|
6976
|
+
|
6977
|
+
@selector [up-hide-for]
|
6978
|
+
@param up-hide-for
|
6979
|
+
A space-separated list of values for which to show this element.
|
6980
|
+
@stable
|
6981
|
+
*/
|
6982
|
+
up.on('change', '[up-toggle]', function(event, $field) {
|
6983
|
+
console.log("CHANGE EVENT");
|
6984
|
+
return toggleTargets($field);
|
6985
|
+
});
|
6986
|
+
up.compiler('[up-toggle]', function($field) {
|
6987
|
+
return toggleTargets($field);
|
6988
|
+
});
|
6989
|
+
|
6493
6990
|
/**
|
6494
6991
|
Observes this field or form and runs a callback when a value changes.
|
6495
6992
|
|
@@ -6558,7 +7055,8 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
6558
7055
|
config: config,
|
6559
7056
|
submit: submit,
|
6560
7057
|
observe: observe,
|
6561
|
-
validate: validate
|
7058
|
+
validate: validate,
|
7059
|
+
toggleTargets: toggleTargets
|
6562
7060
|
};
|
6563
7061
|
})(jQuery);
|
6564
7062
|
|
@@ -6619,7 +7117,7 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
6619
7117
|
|
6620
7118
|
(function() {
|
6621
7119
|
up.popup = (function($) {
|
6622
|
-
var attach, autoclose, close, config, contains, coveredUrl,
|
7120
|
+
var attach, autoclose, close, config, contains, coveredUrl, createFrame, currentUrl, discardHistory, ensureInViewport, isOpen, reset, setPosition, u;
|
6623
7121
|
u = up.util;
|
6624
7122
|
|
6625
7123
|
/**
|
@@ -6641,9 +7139,7 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
6641
7139
|
@experimental
|
6642
7140
|
*/
|
6643
7141
|
coveredUrl = function() {
|
6644
|
-
|
6645
|
-
$popup = $('.up-popup');
|
6646
|
-
return $popup.attr('up-covered-url');
|
7142
|
+
return $('.up-popup').attr('up-covered-url');
|
6647
7143
|
};
|
6648
7144
|
|
6649
7145
|
/**
|
@@ -6669,11 +7165,13 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
6669
7165
|
history: false
|
6670
7166
|
});
|
6671
7167
|
reset = function() {
|
6672
|
-
close(
|
7168
|
+
close({
|
7169
|
+
animation: false
|
7170
|
+
});
|
6673
7171
|
return config.reset();
|
6674
7172
|
};
|
6675
|
-
setPosition = function($link,
|
6676
|
-
var css, linkBox;
|
7173
|
+
setPosition = function($link, position) {
|
7174
|
+
var $popup, css, linkBox;
|
6677
7175
|
linkBox = u.measure($link, {
|
6678
7176
|
full: true
|
6679
7177
|
});
|
@@ -6703,6 +7201,7 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
6703
7201
|
return u.error("Unknown position %o", position);
|
6704
7202
|
}
|
6705
7203
|
})();
|
7204
|
+
$popup = $('.up-popup');
|
6706
7205
|
$popup.attr('up-position', position);
|
6707
7206
|
$popup.css(css);
|
6708
7207
|
return ensureInViewport($popup);
|
@@ -6741,42 +7240,34 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
6741
7240
|
}
|
6742
7241
|
}
|
6743
7242
|
};
|
6744
|
-
rememberHistory = function() {
|
6745
|
-
var $popup;
|
6746
|
-
$popup = $('.up-popup');
|
6747
|
-
$popup.attr('up-covered-url', up.browser.url());
|
6748
|
-
return $popup.attr('up-covered-title', document.title);
|
6749
|
-
};
|
6750
7243
|
discardHistory = function() {
|
6751
7244
|
var $popup;
|
6752
7245
|
$popup = $('.up-popup');
|
6753
7246
|
$popup.removeAttr('up-covered-url');
|
6754
7247
|
return $popup.removeAttr('up-covered-title');
|
6755
7248
|
};
|
6756
|
-
|
7249
|
+
createFrame = function(target, options) {
|
6757
7250
|
var $placeholder, $popup;
|
6758
7251
|
$popup = u.$createElementFromSelector('.up-popup');
|
6759
|
-
if (sticky) {
|
7252
|
+
if (options.sticky) {
|
6760
7253
|
$popup.attr('up-sticky', '');
|
6761
7254
|
}
|
6762
|
-
$
|
7255
|
+
$popup.attr('up-covered-url', up.browser.url());
|
7256
|
+
$popup.attr('up-covered-title', document.title);
|
7257
|
+
$placeholder = u.$createElementFromSelector(target);
|
6763
7258
|
$placeholder.appendTo($popup);
|
6764
7259
|
$popup.appendTo(document.body);
|
6765
|
-
rememberHistory();
|
6766
|
-
$popup.hide();
|
6767
7260
|
return $popup;
|
6768
7261
|
};
|
6769
|
-
|
6770
|
-
|
6771
|
-
|
6772
|
-
|
6773
|
-
|
6774
|
-
|
6775
|
-
|
6776
|
-
|
6777
|
-
|
6778
|
-
});
|
6779
|
-
}
|
7262
|
+
|
7263
|
+
/**
|
7264
|
+
Returns whether popup modal is currently open.
|
7265
|
+
|
7266
|
+
@function up.popup.isOpen
|
7267
|
+
@stable
|
7268
|
+
*/
|
7269
|
+
isOpen = function() {
|
7270
|
+
return $('.up-popup').length > 0;
|
6780
7271
|
};
|
6781
7272
|
|
6782
7273
|
/**
|
@@ -6791,6 +7282,9 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
6791
7282
|
Defines where the popup is attached to the opening element.
|
6792
7283
|
|
6793
7284
|
Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
|
7285
|
+
@param {String} [options.confirm]
|
7286
|
+
A message that will be displayed in a cancelable confirmation dialog
|
7287
|
+
before the modal is being opened.
|
6794
7288
|
@param {String} [options.animation]
|
6795
7289
|
The animation to use when opening the popup.
|
6796
7290
|
@param {Number} [options.duration]
|
@@ -6804,37 +7298,56 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
6804
7298
|
open even if the page changes in the background.
|
6805
7299
|
@param {Object} [options.history=false]
|
6806
7300
|
@return {Promise}
|
6807
|
-
A promise that will be resolved when the popup has been loaded and
|
7301
|
+
A promise that will be resolved when the popup has been loaded and
|
7302
|
+
the opening animation has completed.
|
6808
7303
|
@stable
|
6809
7304
|
*/
|
6810
7305
|
attach = function(linkOrSelector, options) {
|
6811
|
-
var $link, animateOptions,
|
7306
|
+
var $link, animateOptions, target, url;
|
6812
7307
|
$link = $(linkOrSelector);
|
6813
7308
|
$link.length || u.error('Cannot attach popup to non-existing element %o', linkOrSelector);
|
6814
7309
|
options = u.options(options);
|
6815
7310
|
url = u.option(options.url, $link.attr('href'));
|
6816
|
-
|
6817
|
-
position = u.option(options.position, $link.attr('up-position'), config.position);
|
6818
|
-
animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation);
|
6819
|
-
sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'));
|
6820
|
-
history = up.browser.canPushState() ? u.option(options.history, u.castedAttr($link, 'up-history'), config.history) : false;
|
7311
|
+
target = u.option(options.target, $link.attr('up-popup'), 'body');
|
7312
|
+
options.position = u.option(options.position, $link.attr('up-position'), config.position);
|
7313
|
+
options.animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation);
|
7314
|
+
options.sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'));
|
7315
|
+
options.history = up.browser.canPushState() ? u.option(options.history, u.castedAttr($link, 'up-history'), config.history) : false;
|
7316
|
+
options.confirm = u.option(options.confirm, $link.attr('up-confirm'));
|
6821
7317
|
animateOptions = up.motion.animateOptions(options, $link);
|
6822
|
-
|
6823
|
-
|
6824
|
-
|
6825
|
-
|
6826
|
-
|
6827
|
-
|
6828
|
-
|
6829
|
-
|
6830
|
-
|
6831
|
-
|
6832
|
-
|
6833
|
-
|
6834
|
-
|
6835
|
-
|
6836
|
-
|
6837
|
-
|
7318
|
+
return up.browser.confirm(options.confirm).then(function() {
|
7319
|
+
var promise, wasOpen;
|
7320
|
+
if (up.bus.nobodyPrevents('up:popup:open', {
|
7321
|
+
url: url
|
7322
|
+
})) {
|
7323
|
+
wasOpen = isOpen();
|
7324
|
+
if (wasOpen) {
|
7325
|
+
close({
|
7326
|
+
animation: false
|
7327
|
+
});
|
7328
|
+
}
|
7329
|
+
options.beforeSwap = function() {
|
7330
|
+
return createFrame(target, options);
|
7331
|
+
};
|
7332
|
+
promise = up.replace(target, url, u.merge(options, {
|
7333
|
+
animation: false
|
7334
|
+
}));
|
7335
|
+
promise = promise.then(function() {
|
7336
|
+
return setPosition($link, options.position);
|
7337
|
+
});
|
7338
|
+
if (!wasOpen) {
|
7339
|
+
promise = promise.then(function() {
|
7340
|
+
return up.animate($('.up-popup'), options.animation, animateOptions);
|
7341
|
+
});
|
7342
|
+
}
|
7343
|
+
promise = promise.then(function() {
|
7344
|
+
return up.emit('up:popup:opened');
|
7345
|
+
});
|
7346
|
+
return promise;
|
7347
|
+
} else {
|
7348
|
+
return u.unresolvableDeferred();
|
7349
|
+
}
|
7350
|
+
});
|
6838
7351
|
};
|
6839
7352
|
|
6840
7353
|
/**
|
@@ -6948,12 +7461,15 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
6948
7461
|
Defines where the popup is attached to the opening element.
|
6949
7462
|
|
6950
7463
|
Valid values are `bottom-right`, `bottom-left`, `top-right` and `top-left`.
|
7464
|
+
@param {String} [up-confirm]
|
7465
|
+
A message that will be displayed in a cancelable confirmation dialog
|
7466
|
+
before the popup is opened.
|
6951
7467
|
@param [up-sticky]
|
6952
7468
|
If set to `true`, the popup remains
|
6953
7469
|
open even if the page changes in the background.
|
6954
7470
|
@stable
|
6955
7471
|
*/
|
6956
|
-
up.link.
|
7472
|
+
up.link.onAction('[up-popup]', function($link) {
|
6957
7473
|
if ($link.is('.up-current')) {
|
6958
7474
|
return close();
|
6959
7475
|
} else {
|
@@ -7020,7 +7536,8 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7020
7536
|
},
|
7021
7537
|
source: function() {
|
7022
7538
|
return up.error('up.popup.source no longer exists. Please use up.popup.url instead.');
|
7023
|
-
}
|
7539
|
+
},
|
7540
|
+
isOpen: isOpen
|
7024
7541
|
};
|
7025
7542
|
})(jQuery);
|
7026
7543
|
|
@@ -7086,7 +7603,7 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7086
7603
|
|
7087
7604
|
(function() {
|
7088
7605
|
up.modal = (function($) {
|
7089
|
-
var autoclose, close, config, contains, coveredUrl,
|
7606
|
+
var autoclose, close, config, contains, coveredUrl, createFrame, currentUrl, discardHistory, follow, isOpen, open, reset, shiftElements, templateHtml, u, unshiftElements, unshifters, visit;
|
7090
7607
|
u = up.util;
|
7091
7608
|
|
7092
7609
|
/**
|
@@ -7161,12 +7678,12 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7161
7678
|
@experimental
|
7162
7679
|
*/
|
7163
7680
|
coveredUrl = function() {
|
7164
|
-
|
7165
|
-
$modal = $('.up-modal');
|
7166
|
-
return $modal.attr('up-covered-url');
|
7681
|
+
return $('.up-modal').attr('up-covered-url');
|
7167
7682
|
};
|
7168
7683
|
reset = function() {
|
7169
|
-
close(
|
7684
|
+
close({
|
7685
|
+
animation: false
|
7686
|
+
});
|
7170
7687
|
currentUrl = void 0;
|
7171
7688
|
return config.reset();
|
7172
7689
|
};
|
@@ -7179,20 +7696,15 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7179
7696
|
return template;
|
7180
7697
|
}
|
7181
7698
|
};
|
7182
|
-
rememberHistory = function() {
|
7183
|
-
var $modal;
|
7184
|
-
$modal = $('.up-modal');
|
7185
|
-
$modal.attr('up-covered-url', up.browser.url());
|
7186
|
-
return $modal.attr('up-covered-title', document.title);
|
7187
|
-
};
|
7188
7699
|
discardHistory = function() {
|
7189
7700
|
var $modal;
|
7190
7701
|
$modal = $('.up-modal');
|
7191
7702
|
$modal.removeAttr('up-covered-url');
|
7192
7703
|
return $modal.removeAttr('up-covered-title');
|
7193
7704
|
};
|
7194
|
-
|
7705
|
+
createFrame = function(target, options) {
|
7195
7706
|
var $content, $dialog, $modal, $placeholder;
|
7707
|
+
shiftElements();
|
7196
7708
|
$modal = $(templateHtml());
|
7197
7709
|
if (options.sticky) {
|
7198
7710
|
$modal.attr('up-sticky', '');
|
@@ -7210,14 +7722,12 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7210
7722
|
$dialog.css('height', options.height);
|
7211
7723
|
}
|
7212
7724
|
$content = $modal.find('.up-modal-content');
|
7213
|
-
$placeholder = u.$createElementFromSelector(
|
7725
|
+
$placeholder = u.$createElementFromSelector(target);
|
7214
7726
|
$placeholder.appendTo($content);
|
7215
7727
|
$modal.appendTo(document.body);
|
7216
|
-
rememberHistory();
|
7217
|
-
$modal.hide();
|
7218
7728
|
return $modal;
|
7219
7729
|
};
|
7220
|
-
|
7730
|
+
unshifters = [];
|
7221
7731
|
shiftElements = function() {
|
7222
7732
|
var bodyRightPadding, bodyRightShift, scrollbarWidth, unshiftBody;
|
7223
7733
|
scrollbarWidth = u.scrollbarWidth();
|
@@ -7227,29 +7737,35 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7227
7737
|
'padding-right': bodyRightShift + "px",
|
7228
7738
|
'overflow-y': 'hidden'
|
7229
7739
|
});
|
7230
|
-
|
7740
|
+
unshifters.push(unshiftBody);
|
7231
7741
|
return up.layout.anchoredRight().each(function() {
|
7232
|
-
var $element, elementRight, elementRightShift,
|
7742
|
+
var $element, elementRight, elementRightShift, unshifter;
|
7233
7743
|
$element = $(this);
|
7234
7744
|
elementRight = parseInt($element.css('right'));
|
7235
7745
|
elementRightShift = scrollbarWidth + elementRight;
|
7236
|
-
|
7746
|
+
unshifter = u.temporaryCss($element, {
|
7237
7747
|
'right': elementRightShift
|
7238
7748
|
});
|
7239
|
-
return
|
7749
|
+
return unshifters.push(unshifter);
|
7240
7750
|
});
|
7241
7751
|
};
|
7242
|
-
|
7243
|
-
var
|
7244
|
-
|
7245
|
-
|
7246
|
-
|
7247
|
-
$modal.show();
|
7248
|
-
deferred = up.animate($modal, animation, animateOptions);
|
7249
|
-
return deferred.then(function() {
|
7250
|
-
return up.emit('up:modal:opened');
|
7251
|
-
});
|
7752
|
+
unshiftElements = function() {
|
7753
|
+
var results, unshifter;
|
7754
|
+
results = [];
|
7755
|
+
while (unshifter = unshifters.pop()) {
|
7756
|
+
results.push(unshifter());
|
7252
7757
|
}
|
7758
|
+
return results;
|
7759
|
+
};
|
7760
|
+
|
7761
|
+
/**
|
7762
|
+
Returns whether a modal is currently open.
|
7763
|
+
|
7764
|
+
@function up.modal.isOpen
|
7765
|
+
@stable
|
7766
|
+
*/
|
7767
|
+
isOpen = function() {
|
7768
|
+
return $('.up-modal').length > 0;
|
7253
7769
|
};
|
7254
7770
|
|
7255
7771
|
/**
|
@@ -7276,6 +7792,9 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7276
7792
|
@param {Boolean} [options.sticky=false]
|
7277
7793
|
If set to `true`, the modal remains
|
7278
7794
|
open even if the page changes in the background.
|
7795
|
+
@param {String} [options.confirm]
|
7796
|
+
A message that will be displayed in a cancelable confirmation dialog
|
7797
|
+
before the modal is being opened.
|
7279
7798
|
@param {Object} [options.history=true]
|
7280
7799
|
Whether to add a browser history entry for the modal's source URL.
|
7281
7800
|
@param {String} [options.animation]
|
@@ -7287,7 +7806,8 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7287
7806
|
@param {String} [options.easing]
|
7288
7807
|
The timing function that controls the animation's acceleration. [`up.animate`](/up.animate).
|
7289
7808
|
@return {Promise}
|
7290
|
-
A promise that will be resolved when the
|
7809
|
+
A promise that will be resolved when the modal has been loaded and
|
7810
|
+
the opening animation has completed.
|
7291
7811
|
@stable
|
7292
7812
|
*/
|
7293
7813
|
follow = function(linkOrSelector, options) {
|
@@ -7317,7 +7837,8 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7317
7837
|
@param {Object} options
|
7318
7838
|
See options for [`up.modal.follow`](/up.modal.follow).
|
7319
7839
|
@return {Promise}
|
7320
|
-
A promise that will be resolved when the
|
7840
|
+
A promise that will be resolved when the modal has been loaded and the opening
|
7841
|
+
animation has completed.
|
7321
7842
|
@stable
|
7322
7843
|
*/
|
7323
7844
|
visit = function(url, options) {
|
@@ -7331,40 +7852,49 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7331
7852
|
@internal
|
7332
7853
|
*/
|
7333
7854
|
open = function(options) {
|
7334
|
-
var $link, animateOptions,
|
7855
|
+
var $link, animateOptions, target, url;
|
7335
7856
|
options = u.options(options);
|
7336
7857
|
$link = u.option(options.$link, u.nullJQuery());
|
7337
7858
|
url = u.option(options.url, $link.attr('up-href'), $link.attr('href'));
|
7338
|
-
|
7339
|
-
width = u.option(options.width, $link.attr('up-width'), config.width);
|
7340
|
-
maxWidth = u.option(options.maxWidth, $link.attr('up-max-width'), config.maxWidth);
|
7341
|
-
height = u.option(options.height, $link.attr('up-height'), config.height);
|
7342
|
-
animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation);
|
7343
|
-
sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'));
|
7344
|
-
history = up.browser.canPushState() ? u.option(options.history, u.castedAttr($link, 'up-history'), config.history) : false;
|
7859
|
+
target = u.option(options.target, $link.attr('up-modal'), 'body');
|
7860
|
+
options.width = u.option(options.width, $link.attr('up-width'), config.width);
|
7861
|
+
options.maxWidth = u.option(options.maxWidth, $link.attr('up-max-width'), config.maxWidth);
|
7862
|
+
options.height = u.option(options.height, $link.attr('up-height'), config.height);
|
7863
|
+
options.animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation);
|
7864
|
+
options.sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'));
|
7865
|
+
options.history = up.browser.canPushState() ? u.option(options.history, u.castedAttr($link, 'up-history'), config.history) : false;
|
7866
|
+
options.confirm = u.option(options.confirm, $link.attr('up-confirm'));
|
7345
7867
|
animateOptions = up.motion.animateOptions(options, $link);
|
7346
|
-
|
7347
|
-
|
7348
|
-
|
7349
|
-
|
7350
|
-
|
7351
|
-
|
7352
|
-
|
7353
|
-
|
7354
|
-
|
7355
|
-
|
7356
|
-
|
7357
|
-
|
7358
|
-
|
7359
|
-
|
7360
|
-
|
7361
|
-
|
7362
|
-
|
7363
|
-
|
7364
|
-
|
7365
|
-
|
7366
|
-
|
7367
|
-
|
7868
|
+
return up.browser.confirm(options.confirm).then(function() {
|
7869
|
+
var promise, wasOpen;
|
7870
|
+
if (up.bus.nobodyPrevents('up:modal:open', {
|
7871
|
+
url: url
|
7872
|
+
})) {
|
7873
|
+
wasOpen = isOpen();
|
7874
|
+
if (wasOpen) {
|
7875
|
+
close({
|
7876
|
+
animation: false
|
7877
|
+
});
|
7878
|
+
}
|
7879
|
+
options.beforeSwap = function() {
|
7880
|
+
return createFrame(target, options);
|
7881
|
+
};
|
7882
|
+
promise = up.replace(target, url, u.merge(options, {
|
7883
|
+
animation: false
|
7884
|
+
}));
|
7885
|
+
if (!wasOpen) {
|
7886
|
+
promise = promise.then(function() {
|
7887
|
+
return up.animate($('.up-modal'), options.animation, animateOptions);
|
7888
|
+
});
|
7889
|
+
}
|
7890
|
+
promise = promise.then(function() {
|
7891
|
+
return up.emit('up:modal:opened');
|
7892
|
+
});
|
7893
|
+
return promise;
|
7894
|
+
} else {
|
7895
|
+
return u.unresolvablePromise();
|
7896
|
+
}
|
7897
|
+
});
|
7368
7898
|
};
|
7369
7899
|
|
7370
7900
|
/**
|
@@ -7399,7 +7929,7 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7399
7929
|
@stable
|
7400
7930
|
*/
|
7401
7931
|
close = function(options) {
|
7402
|
-
var $modal,
|
7932
|
+
var $modal, promise;
|
7403
7933
|
$modal = $('.up-modal');
|
7404
7934
|
if ($modal.length) {
|
7405
7935
|
if (up.bus.nobodyPrevents('up:modal:close', {
|
@@ -7411,15 +7941,12 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7411
7941
|
title: $modal.attr('up-covered-title')
|
7412
7942
|
});
|
7413
7943
|
currentUrl = void 0;
|
7414
|
-
|
7415
|
-
|
7416
|
-
|
7417
|
-
while (unshifter = unshiftElements.pop()) {
|
7418
|
-
unshifter();
|
7419
|
-
}
|
7944
|
+
promise = up.destroy($modal, options);
|
7945
|
+
promise = promise.then(function() {
|
7946
|
+
unshiftElements();
|
7420
7947
|
return up.emit('up:modal:closed');
|
7421
7948
|
});
|
7422
|
-
return
|
7949
|
+
return promise;
|
7423
7950
|
} else {
|
7424
7951
|
return u.unresolvableDeferred();
|
7425
7952
|
}
|
@@ -7480,20 +8007,26 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7480
8007
|
a modal dialog.
|
7481
8008
|
|
7482
8009
|
@selector a[up-modal]
|
7483
|
-
@param [up-
|
7484
|
-
|
7485
|
-
|
8010
|
+
@param {String} [up-confirm]
|
8011
|
+
A message that will be displayed in a cancelable confirmation dialog
|
8012
|
+
before the modal is opened.
|
8013
|
+
@param {String} [up-sticky]
|
8014
|
+
If set to `"true"`, the modal remains
|
8015
|
+
open even if the page changes in the background.
|
8016
|
+
@param {String} [up-animation]
|
8017
|
+
The animation to use when opening the modal.
|
8018
|
+
@param {String} [up-height]
|
8019
|
+
The width of the dialog in pixels.
|
8020
|
+
By [default](/up.modal.config) the dialog will grow to fit its contents.
|
7486
8021
|
@param [up-width]
|
7487
|
-
|
8022
|
+
The width of the dialog in pixels.
|
8023
|
+
By [default](/up.modal.config) the dialog will grow to fit its contents.
|
8024
|
+
@param [up-history="true"]
|
8025
|
+
Whether to add a browser history entry for the modal's source URL.
|
7488
8026
|
@stable
|
7489
8027
|
*/
|
7490
|
-
up.link.
|
7491
|
-
|
7492
|
-
if ($link.is('.up-current')) {
|
7493
|
-
return close();
|
7494
|
-
} else {
|
7495
|
-
return follow($link);
|
7496
|
-
}
|
8028
|
+
up.link.onAction('[up-modal]', function($link) {
|
8029
|
+
return follow($link);
|
7497
8030
|
});
|
7498
8031
|
up.on('click', 'body', function(event, $body) {
|
7499
8032
|
var $target;
|
@@ -7554,8 +8087,9 @@ To disable this behavior, give the opening link an `up-sticky` attribute:
|
|
7554
8087
|
},
|
7555
8088
|
contains: contains,
|
7556
8089
|
source: function() {
|
7557
|
-
return up.error('up.
|
7558
|
-
}
|
8090
|
+
return up.error('up.modal.source no longer exists. Please use up.popup.url instead.');
|
8091
|
+
},
|
8092
|
+
isOpen: isOpen
|
7559
8093
|
};
|
7560
8094
|
})(jQuery);
|
7561
8095
|
|
@@ -8011,19 +8545,40 @@ Play nice with Rails UJS
|
|
8011
8545
|
|
8012
8546
|
(function() {
|
8013
8547
|
up.rails = (function($) {
|
8014
|
-
var u, willHandle;
|
8548
|
+
var csrfField, isRails, u, willHandle;
|
8015
8549
|
u = up.util;
|
8016
8550
|
willHandle = function($element) {
|
8017
8551
|
return $element.is('[up-follow], [up-target], [up-modal], [up-popup]');
|
8018
8552
|
};
|
8019
|
-
|
8020
|
-
|
8021
|
-
|
8022
|
-
|
8023
|
-
|
8024
|
-
|
8025
|
-
|
8553
|
+
isRails = function() {
|
8554
|
+
return u.isGiven($.rails);
|
8555
|
+
};
|
8556
|
+
u.each(['method', 'confirm'], function(feature) {
|
8557
|
+
var dataAttribute, upAttribute;
|
8558
|
+
dataAttribute = "data-" + feature;
|
8559
|
+
upAttribute = "up-" + feature;
|
8560
|
+
return up.compiler("[" + dataAttribute + "]", function($element) {
|
8561
|
+
var replacement;
|
8562
|
+
if (isRails() && willHandle($element)) {
|
8563
|
+
replacement = {};
|
8564
|
+
replacement[upAttribute] = $element.attr(dataAttribute);
|
8565
|
+
u.setMissingAttrs($element, replacement);
|
8566
|
+
return $element.removeAttr(dataAttribute);
|
8567
|
+
}
|
8568
|
+
});
|
8026
8569
|
});
|
8570
|
+
csrfField = function() {
|
8571
|
+
if (isRails()) {
|
8572
|
+
return {
|
8573
|
+
name: $.rails.csrfParam(),
|
8574
|
+
value: $.rails.csrfToken()
|
8575
|
+
};
|
8576
|
+
}
|
8577
|
+
};
|
8578
|
+
return {
|
8579
|
+
csrfField: csrfField,
|
8580
|
+
isRails: isRails
|
8581
|
+
};
|
8027
8582
|
})(jQuery);
|
8028
8583
|
|
8029
8584
|
}).call(this);
|