bigpipe-util 0.2.7 â 0.2.10
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/CHANGELOG.md +12 -1
- package/README.md +20 -30
- package/package.json +1 -1
- package/src/Primer.js +1 -1
- package/src/async/AsyncDOM.js +1 -5
- package/src/core/Dialog.js +32 -33
- package/src/core/onAfterLoad.js +13 -0
- package/src/core/waitForLoad.js +57 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,10 +4,21 @@ All notable changes to `bigpipe-util` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
|
|
6
6
|
|
|
7
|
+
## v0.2.10 - 2025-05-15
|
|
8
|
+
- Added `onAfterLoad.js`, `waitForLoad.js`
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Added `timeout` to open dialog with a delay in method `showFromModel`
|
|
12
|
+
|
|
13
|
+
## v0.2.8 - 2025-05-02
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Added `timeout` to open dialog with a delay in method `showFromModel`
|
|
17
|
+
|
|
7
18
|
## v0.2.7 - 2025-03-22
|
|
8
19
|
|
|
9
20
|
### Added
|
|
10
|
-
- Added `timeout` to open dialog with a delay
|
|
21
|
+
- Added `timeout` to open dialog with a delay in method `render`
|
|
11
22
|
|
|
12
23
|
## v0.2.6 - 2025-01-16
|
|
13
24
|
|
package/README.md
CHANGED
|
@@ -3,30 +3,30 @@
|
|
|
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
|
|
|
5
5
|
|
|
6
|
-
## Demo App
|
|
6
|
+
## đ Demo App
|
|
7
7
|
Try the app with [live demo](http://bigpipe.xf.cz).
|
|
8
8
|
|
|
9
|
-
## Full documentation
|
|
9
|
+
## đ Full documentation
|
|
10
10
|
https://richarddobron.github.io/bigpipe-php/
|
|
11
11
|
|
|
12
|
-
## Requirements
|
|
12
|
+
## âšī¸ Requirements
|
|
13
13
|
* PHP 7.1 or higher
|
|
14
14
|
* Webpack
|
|
15
15
|
|
|
16
|
-
## Installation
|
|
16
|
+
## đĻ Installation
|
|
17
|
+
Follow these steps to install and set up:
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
1. Install composer package:
|
|
19
|
+
### 1. Install composer package:
|
|
20
20
|
```shell
|
|
21
21
|
$ composer require richarddobron/bigpipe
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
2. Install npm package:
|
|
24
|
+
### 2. Install npm package:
|
|
25
25
|
```shell
|
|
26
26
|
$ npm install bigpipe-util
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
3. Add
|
|
29
|
+
### 3. Add the following to /path/to/resources/js/app.js:
|
|
30
30
|
```javascript
|
|
31
31
|
import Primer from 'bigpipe-util/src/Primer';
|
|
32
32
|
|
|
@@ -39,19 +39,10 @@ window.require = (modulePath) => {
|
|
|
39
39
|
};
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
4.
|
|
43
|
-
- this step is optional, but if you skip it, use this in next step:
|
|
44
|
-
```require("bigpipe-util/ServerJS")```
|
|
45
|
-
```javascript
|
|
46
|
-
import ServerJSImpl from 'bigpipe-util/src/ServerJS';
|
|
47
|
-
export default class ServerJS extends ServerJSImpl {
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
5. Add this lines to page footer:
|
|
42
|
+
### 4. Add these lines to the page footer:
|
|
52
43
|
```html
|
|
53
44
|
<script>
|
|
54
|
-
(new (require("ServerJS"))).handle(<?=json_encode(\dobron\BigPipe\BigPipe::jsmods())?>);
|
|
45
|
+
(new (require("bigpipe-util/ServerJS"))).handle(<?=json_encode(\dobron\BigPipe\BigPipe::jsmods())?>);
|
|
55
46
|
</script>
|
|
56
47
|
```
|
|
57
48
|
|
|
@@ -85,16 +76,16 @@ if (OH_NOES_WE_NEED_TO_CANCEL_RIGHT_NOW_OR_ELSE) {
|
|
|
85
76
|
}
|
|
86
77
|
```
|
|
87
78
|
|
|
88
|
-
# What all can be Ajaxifed?
|
|
79
|
+
# âĄī¸ What all can be Ajaxifed?
|
|
89
80
|
|
|
90
|
-
## Links
|
|
81
|
+
## đ Links
|
|
91
82
|
```html
|
|
92
83
|
<a href="#"
|
|
93
84
|
ajaxify="/ajax/remove.php"
|
|
94
85
|
rel="async">Remove Item</a>
|
|
95
86
|
```
|
|
96
87
|
|
|
97
|
-
## Forms
|
|
88
|
+
## đ Forms
|
|
98
89
|
```html
|
|
99
90
|
<form action="/submit.php"
|
|
100
91
|
method="POST"
|
|
@@ -104,31 +95,30 @@ if (OH_NOES_WE_NEED_TO_CANCEL_RIGHT_NOW_OR_ELSE) {
|
|
|
104
95
|
</form>
|
|
105
96
|
```
|
|
106
97
|
|
|
107
|
-
## Dialogs
|
|
98
|
+
## đŦ Dialogs
|
|
108
99
|
```html
|
|
109
100
|
<a href="#"
|
|
110
101
|
ajaxify="/ajax/modal.php"
|
|
111
102
|
rel="dialog">Open Modal</a>
|
|
112
103
|
```
|
|
113
104
|
|
|
114
|
-
## Inspiration
|
|
105
|
+
## đ Inspiration
|
|
115
106
|
|
|
116
|
-
BigPipe is inspired by
|
|
107
|
+
BigPipe is inspired by Facebook's BigPipe. For more details
|
|
117
108
|
read their blog post: [Pipelining web pages for high performance][blog].
|
|
118
109
|
|
|
119
|
-
## Motivation
|
|
110
|
+
## đĄ Motivation
|
|
120
111
|
|
|
121
112
|
There is a large number of PHP projects for which moving to modern frameworks like Laravel Livewire, React, Vue.js (and many more!) could be very challenging.
|
|
122
113
|
|
|
123
114
|
The purpose of this library is to rapidly reduce the continuously repetitive code to work with the DOM and improve the communication barrier between PHP and JavaScript.
|
|
124
115
|
|
|
125
|
-
##
|
|
116
|
+
## đ¤ Contributing
|
|
126
117
|
|
|
127
|
-
|
|
118
|
+
We welcome contributions! If you'd like to help improve this project, feel free to open an issue or submit a pull request.
|
|
128
119
|
|
|
129
|
-
## License
|
|
120
|
+
## đ License
|
|
130
121
|
|
|
131
122
|
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
|
|
132
123
|
|
|
133
|
-
[link-author]: https://github.com/richardDobron
|
|
134
124
|
[blog]: https://www.facebook.com/notes/facebook-engineering/bigpipe-pipelining-web-pages-for-high-performance/389414033919
|
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.10",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bigpipe",
|
|
7
7
|
"xhr",
|
package/src/Primer.js
CHANGED
package/src/async/AsyncDOM.js
CHANGED
|
@@ -3,11 +3,7 @@ import DOM from "../core/DOM";
|
|
|
3
3
|
export default class AsyncDOM {
|
|
4
4
|
invoke(domOps, element) {
|
|
5
5
|
for (let i = 0; i < domOps.length; ++i) {
|
|
6
|
-
let
|
|
7
|
-
type = domOp[0],
|
|
8
|
-
selector = domOp[1],
|
|
9
|
-
enableTarget = domOp[2],
|
|
10
|
-
content = domOp[3];
|
|
6
|
+
let [type, selector, enableTarget, content] = domOps[i];
|
|
11
7
|
|
|
12
8
|
let node = enableTarget && element || null;
|
|
13
9
|
|
package/src/core/Dialog.js
CHANGED
|
@@ -8,7 +8,7 @@ let dialogId = 1;
|
|
|
8
8
|
let zIndex;
|
|
9
9
|
let originalBodyPad = null;
|
|
10
10
|
|
|
11
|
-
Modal.prototype._handleKeydownEvent = function(event) {
|
|
11
|
+
Modal.prototype._handleKeydownEvent = function (event) {
|
|
12
12
|
if (event.which === 27 && this._options.keyboard) {
|
|
13
13
|
const currentModal = stack[stack.length - 1];
|
|
14
14
|
if (currentModal.el.isEqualNode(this.el)) {
|
|
@@ -42,43 +42,40 @@ export default class Dialog {
|
|
|
42
42
|
|
|
43
43
|
dialogId++;
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}, options.controller, args);
|
|
54
|
-
|
|
55
|
-
stack.push(dialog);
|
|
56
|
-
|
|
57
|
-
return dialog;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
if (options.timeout && typeof options.timeout === 'number') {
|
|
61
|
-
return new Promise(resolve => setTimeout(() => resolve(renderDialog()), options.timeout));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return renderDialog();
|
|
45
|
+
return this._maybeWithTimeout(options.timeout, () => this._show({
|
|
46
|
+
el: document.getElementById(this.id),
|
|
47
|
+
animate: this._getOption(options, 'animate', false),
|
|
48
|
+
keyboard: this._getOption(options, 'keyboard', true),
|
|
49
|
+
backdrop: this._getOption(options, 'backdrop', true),
|
|
50
|
+
transition: this._getOption(options, 'transition', 0),
|
|
51
|
+
backdropTransition: this._getOption(options, 'backdropTransition', 0)
|
|
52
|
+
}, options.controller, args));
|
|
65
53
|
}
|
|
66
54
|
|
|
67
55
|
showFromModel(model, args) {
|
|
68
|
-
|
|
56
|
+
return this._maybeWithTimeout(model.timeout, () => this._show({
|
|
69
57
|
title: model.title || '',
|
|
70
58
|
content: model.body,
|
|
71
59
|
footer: model.footer || false,
|
|
72
|
-
animate:
|
|
73
|
-
keyboard:
|
|
74
|
-
backdrop:
|
|
75
|
-
transition:
|
|
76
|
-
backdropTransition:
|
|
77
|
-
}, model.controller, args);
|
|
60
|
+
animate: this._getOption(model, 'animate', false),
|
|
61
|
+
keyboard: this._getOption(model, 'keyboard', true),
|
|
62
|
+
backdrop: this._getOption(model, 'backdrop', true),
|
|
63
|
+
transition: this._getOption(model, 'transition', 0),
|
|
64
|
+
backdropTransition: this._getOption(model, 'backdropTransition', 0)
|
|
65
|
+
}, model.controller, args));
|
|
66
|
+
}
|
|
78
67
|
|
|
79
|
-
|
|
68
|
+
_maybeWithTimeout(timeout, callback) {
|
|
69
|
+
if (typeof timeout === 'number') {
|
|
70
|
+
return new Promise(resolve => setTimeout(() => resolve(callback()), timeout));
|
|
71
|
+
}
|
|
72
|
+
return callback();
|
|
73
|
+
}
|
|
80
74
|
|
|
81
|
-
|
|
75
|
+
_getOption(obj, key, defaultVal) {
|
|
76
|
+
return obj[key] !== null && obj[key] !== undefined
|
|
77
|
+
? obj[key]
|
|
78
|
+
: defaultVal;
|
|
82
79
|
}
|
|
83
80
|
|
|
84
81
|
_show(options, controller, args) {
|
|
@@ -87,6 +84,7 @@ export default class Dialog {
|
|
|
87
84
|
}
|
|
88
85
|
|
|
89
86
|
const _modal = new Modal(options);
|
|
87
|
+
stack.push(_modal);
|
|
90
88
|
|
|
91
89
|
if (controller) {
|
|
92
90
|
if (typeof controller === 'string') {
|
|
@@ -124,7 +122,7 @@ export default class Dialog {
|
|
|
124
122
|
let shown = false;
|
|
125
123
|
|
|
126
124
|
backdrops.forEach((backdrop, index) => {
|
|
127
|
-
if (shown || index > 0 && index === backdrops.length - 1) {
|
|
125
|
+
if (shown || (index > 0 && index === backdrops.length - 1)) {
|
|
128
126
|
backdrop.style.display = 'none';
|
|
129
127
|
} else {
|
|
130
128
|
backdrop.style.zIndex = zIndex - 1;
|
|
@@ -134,9 +132,10 @@ export default class Dialog {
|
|
|
134
132
|
});
|
|
135
133
|
}
|
|
136
134
|
|
|
137
|
-
_makeDialog(content,
|
|
135
|
+
_makeDialog(content, className = '') {
|
|
138
136
|
this.id = `js_${dialogId.toString(16)}`;
|
|
139
|
-
return
|
|
137
|
+
return `
|
|
138
|
+
<div id="${this.id}" class="modal fade ${className}" tabindex="-1" role="dialog">
|
|
140
139
|
${content}
|
|
141
140
|
</div>`;
|
|
142
141
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import EventListener from 'fbjs/lib/EventListener';
|
|
2
|
+
|
|
3
|
+
export default function onAfterLoad(callback) {
|
|
4
|
+
if (document.readyState === 'complete') {
|
|
5
|
+
setTimeout(callback, 0);
|
|
6
|
+
} else {
|
|
7
|
+
const event = EventListener.capture(window, 'load', () => {
|
|
8
|
+
event.remove();
|
|
9
|
+
|
|
10
|
+
callback();
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import onAfterLoad from "./onAfterLoad";
|
|
2
|
+
|
|
3
|
+
let loadingCounter = 0;
|
|
4
|
+
let originalCursor = '';
|
|
5
|
+
|
|
6
|
+
export default function waitForLoad(elementOnClicked, event, callback = () => {
|
|
7
|
+
}) {
|
|
8
|
+
const boundCallback = callback.bind(elementOnClicked, event);
|
|
9
|
+
const body = document.body;
|
|
10
|
+
|
|
11
|
+
if (document.readyState === 'complete') {
|
|
12
|
+
return boundCallback();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const type = (event || window.event).type;
|
|
16
|
+
loadingCounter++;
|
|
17
|
+
|
|
18
|
+
if (loadingCounter === 1) {
|
|
19
|
+
originalCursor = body.style.cursor;
|
|
20
|
+
body.style.cursor = 'progress';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
switch (type) {
|
|
24
|
+
case 'load':
|
|
25
|
+
case 'focus':
|
|
26
|
+
onAfterLoad(boundCallback);
|
|
27
|
+
return;
|
|
28
|
+
|
|
29
|
+
case 'click':
|
|
30
|
+
elementOnClicked.style.cursor = 'progress';
|
|
31
|
+
|
|
32
|
+
onAfterLoad(() => {
|
|
33
|
+
loadingCounter--;
|
|
34
|
+
|
|
35
|
+
if (loadingCounter === 0) {
|
|
36
|
+
body.style.cursor = originalCursor;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
elementOnClicked.style.cursor = '';
|
|
40
|
+
|
|
41
|
+
const result = boundCallback();
|
|
42
|
+
const href = elementOnClicked.getAttribute('href');
|
|
43
|
+
|
|
44
|
+
if (
|
|
45
|
+
elementOnClicked.tagName.toLowerCase() === 'a' &&
|
|
46
|
+
result !== false &&
|
|
47
|
+
href
|
|
48
|
+
) {
|
|
49
|
+
window.location.href = href;
|
|
50
|
+
} else {
|
|
51
|
+
elementOnClicked.click();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return false;
|
|
57
|
+
}
|