bigpipe-util 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/package.json +1 -1
- package/src/async/AsyncRequest.js +135 -120
- package/src/core/Dialog.js +21 -11
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<img src="bigpipe.svg">
|
|
1
|
+
<img src="bigpipe.svg" alt="BigPipe logo">
|
|
2
2
|
|
|
3
3
|
This library currently implements small part of [Facebook BigPipe][blog] so far, but the advantage is to efficiently insert/replace content and work with the DOM. It is also possible to easily call JavaScript modules from PHP.
|
|
4
4
|
|
|
@@ -8,7 +8,6 @@ Try the app with [live demo](http://bigpipe.xf.cz).
|
|
|
8
8
|
|
|
9
9
|
## Requirements
|
|
10
10
|
* PHP 7.1 or higher
|
|
11
|
-
* Node 8, 10+.
|
|
12
11
|
* Webpack
|
|
13
12
|
|
|
14
13
|
## Installation
|
|
@@ -73,6 +72,9 @@ const request = (new AsyncRequest('/ajax/remove.php'))
|
|
|
73
72
|
.setErrorHandler((xhr) => {
|
|
74
73
|
// A function to be called if the request fails
|
|
75
74
|
})
|
|
75
|
+
.setFinallyHandler((xhr) => {
|
|
76
|
+
// after request callback function
|
|
77
|
+
})
|
|
76
78
|
.send();
|
|
77
79
|
|
|
78
80
|
if (OH_NOES_WE_NEED_TO_CANCEL_RIGHT_NOW_OR_ELSE) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bigpipe-util",
|
|
3
3
|
"description": "This library currently implements small part of Facebook BigPipe so far, but the advantage is to efficiently insert/replace content and work with the DOM. It is also possible to easily call JavaScript modules from PHP.",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bigpipe",
|
|
7
7
|
"xhr",
|
|
@@ -26,166 +26,181 @@ function validateResponseHandler(handler) {
|
|
|
26
26
|
return valid;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export default
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
export default class AsyncRequest {
|
|
30
|
+
constructor(uri) {
|
|
31
|
+
this.method = "POST";
|
|
32
|
+
this.uri = "";
|
|
33
|
+
this.relative = null;
|
|
34
|
+
this.data = {};
|
|
35
|
+
this.headers = {};
|
|
36
|
+
this.initialHandler = emptyFunction;
|
|
37
|
+
this.handler = null;
|
|
38
|
+
this.finallyHandler = emptyFunction;
|
|
39
|
+
this.errorHandler = emptyFunction;
|
|
40
|
+
|
|
41
|
+
if (uri !== undefined) {
|
|
42
|
+
this.setURI(uri);
|
|
43
|
+
}
|
|
41
44
|
}
|
|
42
|
-
}
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
46
|
+
setMethod(method) {
|
|
47
|
+
this.method = method.toString().toUpperCase();
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
51
|
+
getMethod() {
|
|
52
|
+
return this.method;
|
|
53
|
+
}
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
55
|
+
setRelative(relative) {
|
|
56
|
+
this.relative = relative;
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
60
|
+
getRelative() {
|
|
61
|
+
return this.relative;
|
|
62
|
+
}
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
64
|
+
setData(obj) {
|
|
65
|
+
this.data = obj;
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
69
|
+
getData() {
|
|
70
|
+
return this.data;
|
|
71
|
+
}
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
73
|
+
setRequestHeader(name, value) {
|
|
74
|
+
this.headers[name] = value;
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
setURI(uri) {
|
|
79
|
+
this.uri = uri;
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
getURI() {
|
|
84
|
+
return this.uri;
|
|
85
|
+
}
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
87
|
+
setInitialHandler(fn) {
|
|
88
|
+
this.initialHandler = fn;
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
92
|
+
getInitialHandler() {
|
|
93
|
+
return this.initialHandler || emptyFunction;
|
|
94
|
+
}
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
setHandler(fn) {
|
|
97
|
+
if (validateResponseHandler(fn)) {
|
|
98
|
+
this.handler = fn;
|
|
99
|
+
}
|
|
100
|
+
return this;
|
|
97
101
|
}
|
|
98
|
-
return this;
|
|
99
|
-
};
|
|
100
102
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
setFinallyHandler(fn) {
|
|
104
|
+
this.finallyHandler = fn;
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
104
107
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.errorHandler = fn;
|
|
108
|
+
getFinallyHandler() {
|
|
109
|
+
return this.finallyHandler || emptyFunction;
|
|
108
110
|
}
|
|
109
|
-
return this;
|
|
110
|
-
};
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
112
|
+
getHandler() {
|
|
113
|
+
return this.handler || emptyFunction;
|
|
114
|
+
}
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
setErrorHandler(fn) {
|
|
117
|
+
if (validateResponseHandler(fn)) {
|
|
118
|
+
this.errorHandler = fn;
|
|
119
|
+
}
|
|
120
|
+
return this;
|
|
121
|
+
}
|
|
118
122
|
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
getErrorHandler() {
|
|
124
|
+
return this.errorHandler || emptyFunction;
|
|
121
125
|
}
|
|
122
|
-
};
|
|
123
126
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const shieldLength = shield.length;
|
|
127
|
+
abort() {
|
|
128
|
+
const transport = this.transport;
|
|
127
129
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
if (transport) {
|
|
131
|
+
transport.abort();
|
|
132
|
+
}
|
|
130
133
|
}
|
|
131
134
|
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
_unshieldResponseText(text) {
|
|
136
|
+
const shield = "for (;;);";
|
|
137
|
+
const shieldLength = shield.length;
|
|
134
138
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
if (text.length <= shieldLength) {
|
|
140
|
+
throw new Error("Response too short on async to " + this.getURI());
|
|
141
|
+
}
|
|
138
142
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const initialHandler = this.getInitialHandler();
|
|
143
|
+
return text.substring(shieldLength);
|
|
144
|
+
}
|
|
142
145
|
|
|
143
|
-
|
|
146
|
+
send() {
|
|
147
|
+
const {uri, method} = this;
|
|
148
|
+
let { data } = this;
|
|
144
149
|
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
const handler = this.getHandler();
|
|
151
|
+
const errorHandler = this.getErrorHandler();
|
|
152
|
+
const initialHandler = this.getInitialHandler();
|
|
153
|
+
const getFinallyHandler = this.getFinallyHandler();
|
|
147
154
|
|
|
148
|
-
|
|
155
|
+
initialHandler();
|
|
149
156
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
let response;
|
|
153
|
-
try {
|
|
154
|
-
const safeJson = self._unshieldResponseText(this.responseText);
|
|
155
|
-
response = eval("(" + safeJson + ")");
|
|
156
|
-
} catch (e) {
|
|
157
|
-
throw new Error("Failed to handle response: " + e.message + "\n" + this.responseText);
|
|
158
|
-
}
|
|
157
|
+
const request = new XMLHttpRequest();
|
|
158
|
+
const self = this;
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
request.open(method, uri, true);
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
request.onload = function () {
|
|
163
|
+
if (this.status >= 200 && this.status < 400) {
|
|
164
|
+
let response;
|
|
165
|
+
try {
|
|
166
|
+
const safeJson = self._unshieldResponseText(this.responseText);
|
|
167
|
+
response = eval("(" + safeJson + ")");
|
|
168
|
+
} catch (e) {
|
|
169
|
+
throw new Error("Failed to handle response: " + e.message + "\n" + this.responseText);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
(new AsyncResponse).handle(response, self.relative);
|
|
173
|
+
|
|
174
|
+
handler(response);
|
|
175
|
+
} else {
|
|
176
|
+
errorHandler(this);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getFinallyHandler(this);
|
|
165
180
|
}
|
|
166
|
-
};
|
|
167
181
|
|
|
168
|
-
|
|
182
|
+
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
|
169
183
|
|
|
170
|
-
|
|
184
|
+
requests++;
|
|
171
185
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
186
|
+
if (data instanceof FormData) {
|
|
187
|
+
data.append('__req', requests);
|
|
188
|
+
} else {
|
|
189
|
+
data.__req = requests;
|
|
190
|
+
data = serialize(data);
|
|
177
191
|
|
|
178
|
-
|
|
179
|
-
|
|
192
|
+
if (method === "POST") {
|
|
193
|
+
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
|
194
|
+
}
|
|
180
195
|
}
|
|
181
|
-
}
|
|
182
196
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
197
|
+
Object.keys(this.headers).forEach((name) => {
|
|
198
|
+
request.setRequestHeader(name, this.headers[name]);
|
|
199
|
+
});
|
|
186
200
|
|
|
187
|
-
|
|
188
|
-
|
|
201
|
+
request.onerror = errorHandler;
|
|
202
|
+
request.send(data);
|
|
189
203
|
|
|
190
|
-
|
|
204
|
+
return request;
|
|
205
|
+
}
|
|
191
206
|
};
|
package/src/core/Dialog.js
CHANGED
|
@@ -4,15 +4,15 @@ import DOM from "./DOM";
|
|
|
4
4
|
const DEFAULT_Z_INDEX = 1040;
|
|
5
5
|
|
|
6
6
|
let stack = [];
|
|
7
|
-
let
|
|
7
|
+
let dialogId = 1;
|
|
8
8
|
let zIndex;
|
|
9
9
|
let originalBodyPad = null;
|
|
10
10
|
|
|
11
|
-
Modal.prototype._handleKeydownEvent = function(
|
|
12
|
-
if (
|
|
11
|
+
Modal.prototype._handleKeydownEvent = function(event) {
|
|
12
|
+
if (event.which === 27 && this._options.keyboard) {
|
|
13
13
|
const currentModal = stack[stack.length - 1];
|
|
14
14
|
if (currentModal.el.isEqualNode(this.el)) {
|
|
15
|
-
this.emit('dismiss', this,
|
|
15
|
+
this.emit('dismiss', this, event, null);
|
|
16
16
|
this.hide();
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -34,9 +34,9 @@ export default class Dialog {
|
|
|
34
34
|
render(options, args) {
|
|
35
35
|
DOM.appendContent(document.body, this._makeDialog(options.content));
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
dialogId++;
|
|
38
38
|
|
|
39
|
-
const
|
|
39
|
+
const dialog = this._show({
|
|
40
40
|
el: document.getElementById(this.id),
|
|
41
41
|
animate: false,
|
|
42
42
|
keyboard: options.keyboard ?? true,
|
|
@@ -45,11 +45,13 @@ export default class Dialog {
|
|
|
45
45
|
backdropTransition: options.backdropTransition ?? 0,
|
|
46
46
|
}, options.controller, args);
|
|
47
47
|
|
|
48
|
-
stack.push(
|
|
48
|
+
stack.push(dialog);
|
|
49
|
+
|
|
50
|
+
return dialog;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
showFromModel(model, args) {
|
|
52
|
-
const
|
|
54
|
+
const dialog = this._show({
|
|
53
55
|
title: model.title || '',
|
|
54
56
|
content: model.body,
|
|
55
57
|
footer: model.footer || false,
|
|
@@ -60,7 +62,9 @@ export default class Dialog {
|
|
|
60
62
|
backdropTransition: model.backdropTransition ?? 0,
|
|
61
63
|
}, model.controller, args);
|
|
62
64
|
|
|
63
|
-
stack.push(
|
|
65
|
+
stack.push(dialog);
|
|
66
|
+
|
|
67
|
+
return dialog;
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
_show(options, controller, args) {
|
|
@@ -71,7 +75,13 @@ export default class Dialog {
|
|
|
71
75
|
const _modal = new Modal(options);
|
|
72
76
|
|
|
73
77
|
if (controller) {
|
|
74
|
-
(
|
|
78
|
+
if (typeof controller === 'string') {
|
|
79
|
+
controller = new (window.require(controller));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (typeof controller === 'function') {
|
|
83
|
+
controller(_modal, ...args);
|
|
84
|
+
}
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
const self = this;
|
|
@@ -113,7 +123,7 @@ export default class Dialog {
|
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
_makeDialog(content) {
|
|
116
|
-
this.id = `js_${
|
|
126
|
+
this.id = `js_${dialogId.toString(16)}`;
|
|
117
127
|
return `<div id="${this.id}" class="modal fade" tabindex="-1" role="dialog">
|
|
118
128
|
${content}
|
|
119
129
|
</div>`;
|