bigpipe-util 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -13,3 +13,29 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip
13
13
 
14
14
  ### Added
15
15
  - Dialogs support.
16
+
17
+ ## v0.1.3 - 2022-04-27
18
+
19
+ ### Added
20
+ - Method to close only current dialog
21
+
22
+ ### Fixed
23
+ - Dialog z-index
24
+
25
+ ## v0.1.4 - 2022-05-06
26
+
27
+ ### Added
28
+ - Async requests counter
29
+ - Support for extra arguments in dialog controller
30
+
31
+ ### Fixed
32
+ - Arguments for non-method require calls
33
+
34
+ ## v0.2.0 - 2022-05-17
35
+
36
+ ### Added
37
+ - Shield to prevent "JSON Hijacking"
38
+ - Invalid node checking for AsyncDOM
39
+
40
+ ### Fixed
41
+ - Backdrop for 2+ opened dialogs
package/README.md CHANGED
@@ -106,10 +106,6 @@ if (OH_NOES_WE_NEED_TO_CANCEL_RIGHT_NOW_OR_ELSE) {
106
106
  rel="dialog">Open Modal</a>
107
107
  ```
108
108
 
109
- ## Credits
110
-
111
- - [Richard Dobroň][link-author]
112
-
113
109
  ## Inspiration
114
110
 
115
111
  BigPipe is inspired by the concept behind Facebook's BigPipe. For more details
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.1.2",
4
+ "version": "0.2.0",
5
5
  "keywords": [
6
6
  "bigpipe",
7
7
  "xhr",
package/src/ServerJS.js CHANGED
@@ -29,8 +29,6 @@ export default class ServerJS {
29
29
 
30
30
  context[method].apply(context, marker || []);
31
31
  } else {
32
- marker = method;
33
-
34
32
  if (marker) {
35
33
  replaceTransportMarkers(this._relativeTo, marker);
36
34
  }
@@ -15,6 +15,11 @@ export default class AsyncDOM {
15
15
  node = (node || document.documentElement).querySelector(selector);
16
16
  }
17
17
 
18
+ if (!node) {
19
+ console.error(`Selector '${selector}' does not match anything!`)
20
+ continue;
21
+ }
22
+
18
23
  switch (type) {
19
24
  case "eval":
20
25
  (new Function(content)).apply(node);
@@ -1,6 +1,8 @@
1
1
  import emptyFunction from "fbjs/lib/emptyFunction";
2
2
  import AsyncResponse from "./AsyncResponse";
3
3
 
4
+ let requests = 0;
5
+
4
6
  function serialize(obj, prefix) {
5
7
  const str = [];
6
8
  for(const p in obj) {
@@ -119,6 +121,17 @@ AsyncRequest.prototype.abort = function () {
119
121
  }
120
122
  };
121
123
 
124
+ AsyncRequest.prototype._unshieldResponseText = function (text) {
125
+ const shield = "for (;;);";
126
+ const shieldLength = shield.length;
127
+
128
+ if (text.length <= shieldLength) {
129
+ throw new Error("Response too short on async to " + this.getURI());
130
+ }
131
+
132
+ return text.substring(shieldLength);
133
+ };
134
+
122
135
  AsyncRequest.prototype.send = function () {
123
136
  const {uri, method} = this;
124
137
  let { data } = this;
@@ -138,7 +151,8 @@ AsyncRequest.prototype.send = function () {
138
151
  if (this.status >= 200 && this.status < 400) {
139
152
  let response;
140
153
  try {
141
- response = eval("(" + this.responseText + ")");
154
+ const safeJson = self._unshieldResponseText(this.responseText);
155
+ response = eval("(" + safeJson + ")");
142
156
  } catch (e) {
143
157
  throw new Error("Failed to handle response: " + e.message + "\n" + this.responseText);
144
158
  }
@@ -152,7 +166,13 @@ AsyncRequest.prototype.send = function () {
152
166
  };
153
167
 
154
168
  request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
155
- if (!(this.data instanceof FormData)) {
169
+
170
+ requests++;
171
+
172
+ if (this.data instanceof FormData) {
173
+ this.data.append('__req', requests);
174
+ } else {
175
+ data.__req = requests;
156
176
  data = serialize(data);
157
177
 
158
178
  if (method === "POST") {
@@ -1,9 +1,11 @@
1
1
  import Modal from "modal-vanilla/lib/modal";
2
2
  import DOM from "./DOM";
3
3
 
4
+ const DEFAULT_Z_INDEX = 1040;
5
+
4
6
  const stack = [];
5
7
  let modalId = 1;
6
- let zIndex = 1040;
8
+ let zIndex;
7
9
  let originalBodyPad = null;
8
10
 
9
11
  export default class Dialog {
@@ -11,7 +13,15 @@ export default class Dialog {
11
13
  stack.forEach((dialog) => dialog.hide())
12
14
  }
13
15
 
14
- render(options) {
16
+ closeCurrent() {
17
+ const dialog = stack[stack.length - 1];
18
+
19
+ if (dialog) {
20
+ dialog.hide();
21
+ }
22
+ }
23
+
24
+ render(options, args) {
15
25
  DOM.appendContent(document.body, this._makeDialog(options.content));
16
26
 
17
27
  modalId++;
@@ -22,12 +32,12 @@ export default class Dialog {
22
32
  backdrop: options.backdrop ?? true,
23
33
  transition: options.transition ?? 0,
24
34
  backdropTransition: options.backdropTransition ?? 0,
25
- }, options.controller);
35
+ }, options.controller, args);
26
36
 
27
37
  stack.push(_dialog);
28
38
  }
29
39
 
30
- showFromModel(model) {
40
+ showFromModel(model, args) {
31
41
  const _dialog = this._show({
32
42
  title: model.title || '',
33
43
  content: model.body,
@@ -36,12 +46,12 @@ export default class Dialog {
36
46
  backdrop: model.backdrop ?? true,
37
47
  transition: model.transition ?? 0,
38
48
  backdropTransition: model.backdropTransition ?? 0,
39
- }, model.controller);
49
+ }, model.controller, args);
40
50
 
41
51
  stack.push(_dialog);
42
52
  }
43
53
 
44
- _show(options, controller) {
54
+ _show(options, controller, args) {
45
55
  if (originalBodyPad === null) {
46
56
  originalBodyPad = document.body.style.paddingRight;
47
57
  }
@@ -49,13 +59,13 @@ export default class Dialog {
49
59
  const _modal = new Modal(options);
50
60
 
51
61
  if (controller) {
52
- (new (window.require(controller))(_modal));
62
+ (new (window.require(controller))(_modal, ...args));
53
63
  }
54
64
 
55
65
  const self = this;
56
66
 
57
67
  return _modal.on('shown', function ({el}) {
58
- zIndex = 10 * stack.length;
68
+ zIndex = DEFAULT_Z_INDEX + (10 * stack.length);
59
69
  el.style.zIndex = zIndex;
60
70
  setTimeout(() => document.querySelector('.modal-backdrop').style.zIndex = zIndex - 1);
61
71
  }).on('showBackdrop', this._fixBackdrop).on('hidden', function ({el}) {
@@ -73,15 +83,17 @@ export default class Dialog {
73
83
  }).show();
74
84
  }
75
85
 
76
- _fixBackdrop(content) {
86
+ _fixBackdrop() {
77
87
  const backdrops = document.querySelectorAll('.modal-backdrop');
88
+ let shown = false;
78
89
 
79
90
  backdrops.forEach((backdrop, index) => {
80
- if (index > 0 && index === backdrops.length - 1) {
91
+ if (shown || index > 0 && index === backdrops.length - 1) {
81
92
  backdrop.style.display = 'none';
82
93
  } else {
83
94
  backdrop.style.zIndex = zIndex - 1;
84
95
  backdrop.style.display = '';
96
+ shown = true;
85
97
  }
86
98
  });
87
99
  }