upjs-rails 0.17.0 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|