cx 24.3.1 → 24.3.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/dist/charts.css +5 -0
- package/dist/charts.js +130 -0
- package/dist/manifest.js +750 -746
- package/dist/util.js +4 -2
- package/dist/widgets.js +23 -9
- package/package.json +1 -1
- package/src/charts/Swimlanes.d.ts +41 -0
- package/src/charts/Swimlanes.js +112 -0
- package/src/charts/Swimlanes.scss +14 -0
- package/src/charts/axis/Axis.d.ts +96 -96
- package/src/charts/axis/Axis.js +252 -252
- package/src/charts/index.d.ts +24 -23
- package/src/charts/index.js +1 -0
- package/src/charts/index.scss +17 -17
- package/src/charts/variables.scss +19 -13
- package/src/data/StringTemplate.spec.js +105 -105
- package/src/ui/Controller.d.ts +182 -182
- package/src/ui/FocusManager.js +171 -171
- package/src/ui/Instance.d.ts +72 -72
- package/src/util/getParentFrameBoundingClientRect.js +6 -4
- package/src/widgets/form/Label.js +88 -88
- package/src/widgets/form/UploadButton.d.ts +34 -34
- package/src/widgets/grid/Grid.js +27 -15
- package/src/widgets/overlay/captureMouse.js +124 -124
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
import { Widget, VDOM } from "../../ui/Widget";
|
|
2
|
-
import { HtmlElement } from "../HtmlElement";
|
|
3
|
-
import { FocusManager } from "../../ui/FocusManager";
|
|
4
|
-
import { isArray } from "../../util/isArray";
|
|
5
|
-
import { coalesce } from "../../util/coalesce";
|
|
6
|
-
|
|
7
|
-
export class Label extends HtmlElement {
|
|
8
|
-
declareData() {
|
|
9
|
-
super.declareData(...arguments, {
|
|
10
|
-
required: undefined,
|
|
11
|
-
disabled: undefined,
|
|
12
|
-
htmlFor: undefined,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
prepareData(context, instance) {
|
|
17
|
-
let { data } = instance;
|
|
18
|
-
data.stateMods = {
|
|
19
|
-
...data.stateMods,
|
|
20
|
-
disabled: data.disabled,
|
|
21
|
-
};
|
|
22
|
-
data._disabled = data.disabled;
|
|
23
|
-
super.prepareData(context, instance);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
explore(context, instance) {
|
|
27
|
-
let { data } = instance;
|
|
28
|
-
|
|
29
|
-
if (!data.htmlFor) data.htmlFor = context.lastFieldId;
|
|
30
|
-
|
|
31
|
-
data.disabled = data.stateMods.disabled = coalesce(
|
|
32
|
-
context.parentStrict ? context.parentDisabled : null,
|
|
33
|
-
data._disabled,
|
|
34
|
-
context.parentDisabled
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
data.asterisk = context.parentAsterisk || this.asterisk;
|
|
38
|
-
|
|
39
|
-
if (instance.cache("disabled", data.disabled) || instance.cache("asterisk", data.asterisk)) {
|
|
40
|
-
instance.markShouldUpdate(context);
|
|
41
|
-
this.prepareCSS(context, instance);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
super.explore(context, instance);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
isValidHtmlAttribute(attrName) {
|
|
48
|
-
switch (attrName) {
|
|
49
|
-
case "asterisk":
|
|
50
|
-
case "required":
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
return super.isValidHtmlAttribute(attrName);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
attachProps(context, instance, props) {
|
|
57
|
-
super.attachProps(context, instance, props);
|
|
58
|
-
|
|
59
|
-
let { data } = instance;
|
|
60
|
-
|
|
61
|
-
if (data.htmlFor) {
|
|
62
|
-
props.htmlFor = data.htmlFor;
|
|
63
|
-
|
|
64
|
-
if (!props.onClick)
|
|
65
|
-
props.onClick = () => {
|
|
66
|
-
//additional focus for LookupFields which are not input based
|
|
67
|
-
let el = document.getElementById(instance.data.htmlFor);
|
|
68
|
-
if (el) FocusManager.focusFirst(el);
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (!props.id && data.htmlFor) props.id = `${data.htmlFor}-label`;
|
|
73
|
-
|
|
74
|
-
if (data.required && data.asterisk) {
|
|
75
|
-
if (!isArray(props.children)) props.children = [props.children];
|
|
76
|
-
props.children.push(" ");
|
|
77
|
-
props.children.push(
|
|
78
|
-
<span key="asterisk" className={this.CSS.element(this.baseClass, "asterisk")}>
|
|
79
|
-
*
|
|
80
|
-
</span>
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
Label.prototype.baseClass = "label";
|
|
87
|
-
Label.prototype.tag = "label";
|
|
88
|
-
Label.prototype.asterisk = false;
|
|
1
|
+
import { Widget, VDOM } from "../../ui/Widget";
|
|
2
|
+
import { HtmlElement } from "../HtmlElement";
|
|
3
|
+
import { FocusManager } from "../../ui/FocusManager";
|
|
4
|
+
import { isArray } from "../../util/isArray";
|
|
5
|
+
import { coalesce } from "../../util/coalesce";
|
|
6
|
+
|
|
7
|
+
export class Label extends HtmlElement {
|
|
8
|
+
declareData() {
|
|
9
|
+
super.declareData(...arguments, {
|
|
10
|
+
required: undefined,
|
|
11
|
+
disabled: undefined,
|
|
12
|
+
htmlFor: undefined,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
prepareData(context, instance) {
|
|
17
|
+
let { data } = instance;
|
|
18
|
+
data.stateMods = {
|
|
19
|
+
...data.stateMods,
|
|
20
|
+
disabled: data.disabled,
|
|
21
|
+
};
|
|
22
|
+
data._disabled = data.disabled;
|
|
23
|
+
super.prepareData(context, instance);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
explore(context, instance) {
|
|
27
|
+
let { data } = instance;
|
|
28
|
+
|
|
29
|
+
if (!data.htmlFor) data.htmlFor = context.lastFieldId;
|
|
30
|
+
|
|
31
|
+
data.disabled = data.stateMods.disabled = coalesce(
|
|
32
|
+
context.parentStrict ? context.parentDisabled : null,
|
|
33
|
+
data._disabled,
|
|
34
|
+
context.parentDisabled
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
data.asterisk = context.parentAsterisk || this.asterisk;
|
|
38
|
+
|
|
39
|
+
if (instance.cache("disabled", data.disabled) || instance.cache("asterisk", data.asterisk)) {
|
|
40
|
+
instance.markShouldUpdate(context);
|
|
41
|
+
this.prepareCSS(context, instance);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
super.explore(context, instance);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
isValidHtmlAttribute(attrName) {
|
|
48
|
+
switch (attrName) {
|
|
49
|
+
case "asterisk":
|
|
50
|
+
case "required":
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
return super.isValidHtmlAttribute(attrName);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
attachProps(context, instance, props) {
|
|
57
|
+
super.attachProps(context, instance, props);
|
|
58
|
+
|
|
59
|
+
let { data } = instance;
|
|
60
|
+
|
|
61
|
+
if (data.htmlFor) {
|
|
62
|
+
props.htmlFor = data.htmlFor;
|
|
63
|
+
|
|
64
|
+
if (!props.onClick)
|
|
65
|
+
props.onClick = () => {
|
|
66
|
+
//additional focus for LookupFields which are not input based
|
|
67
|
+
let el = document.getElementById(instance.data.htmlFor);
|
|
68
|
+
if (el) FocusManager.focusFirst(el);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!props.id && data.htmlFor) props.id = `${data.htmlFor}-label`;
|
|
73
|
+
|
|
74
|
+
if (data.required && data.asterisk) {
|
|
75
|
+
if (!isArray(props.children)) props.children = [props.children];
|
|
76
|
+
props.children.push(" ");
|
|
77
|
+
props.children.push(
|
|
78
|
+
<span key="asterisk" className={this.CSS.element(this.baseClass, "asterisk")}>
|
|
79
|
+
*
|
|
80
|
+
</span>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Label.prototype.baseClass = "label";
|
|
87
|
+
Label.prototype.tag = "label";
|
|
88
|
+
Label.prototype.asterisk = false;
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import * as Cx from "../../core";
|
|
2
|
-
import { FieldProps } from "./Field";
|
|
3
|
-
|
|
4
|
-
interface UploadButtonProps extends FieldProps {
|
|
5
|
-
/** Text description. */
|
|
6
|
-
text?: Cx.StringProp;
|
|
7
|
-
|
|
8
|
-
url?: Cx.StringProp;
|
|
9
|
-
|
|
10
|
-
/** Base CSS class to be applied to the element. Default is 'uploadbutton'. */
|
|
11
|
-
baseClass?: string;
|
|
12
|
-
|
|
13
|
-
/** Defaults to `false`. Set to `true` to enable multiple selection. */
|
|
14
|
-
multiple?: boolean;
|
|
15
|
-
|
|
16
|
-
method?: string;
|
|
17
|
-
uploadInProgressText?: string;
|
|
18
|
-
|
|
19
|
-
/** Defaults to `false`. Set to `true` to abort uploads if the button is destroyed (unmounted). */
|
|
20
|
-
abortOnDestroy?: boolean;
|
|
21
|
-
|
|
22
|
-
/** Defines file types that are accepted for upload. */
|
|
23
|
-
accept?: Cx.StringProp;
|
|
24
|
-
|
|
25
|
-
/** Name of the icon to be put on the left side of the button. */
|
|
26
|
-
icon?: Cx.StringProp;
|
|
27
|
-
|
|
28
|
-
onUploadStarting?: ((xhr: XMLHttpRequest, instance: any, file: File, formData: FormData) => boolean) | string;
|
|
29
|
-
onUploadComplete?: ((xhr: XMLHttpRequest, instance: any, file: File, formData: FormData) => void) | string;
|
|
30
|
-
onUploadProgress?: ((event: ProgressEvent, instance: any, file: File, formData: FormData) => void) | string;
|
|
31
|
-
onUploadError?: ((event: ProgressEvent, instance: any, file: File, formData: FormData) => void) | string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class UploadButton extends Cx.Widget<UploadButtonProps> {}
|
|
1
|
+
import * as Cx from "../../core";
|
|
2
|
+
import { FieldProps } from "./Field";
|
|
3
|
+
|
|
4
|
+
interface UploadButtonProps extends FieldProps {
|
|
5
|
+
/** Text description. */
|
|
6
|
+
text?: Cx.StringProp;
|
|
7
|
+
|
|
8
|
+
url?: Cx.StringProp;
|
|
9
|
+
|
|
10
|
+
/** Base CSS class to be applied to the element. Default is 'uploadbutton'. */
|
|
11
|
+
baseClass?: string;
|
|
12
|
+
|
|
13
|
+
/** Defaults to `false`. Set to `true` to enable multiple selection. */
|
|
14
|
+
multiple?: boolean;
|
|
15
|
+
|
|
16
|
+
method?: string;
|
|
17
|
+
uploadInProgressText?: string;
|
|
18
|
+
|
|
19
|
+
/** Defaults to `false`. Set to `true` to abort uploads if the button is destroyed (unmounted). */
|
|
20
|
+
abortOnDestroy?: boolean;
|
|
21
|
+
|
|
22
|
+
/** Defines file types that are accepted for upload. */
|
|
23
|
+
accept?: Cx.StringProp;
|
|
24
|
+
|
|
25
|
+
/** Name of the icon to be put on the left side of the button. */
|
|
26
|
+
icon?: Cx.StringProp;
|
|
27
|
+
|
|
28
|
+
onUploadStarting?: ((xhr: XMLHttpRequest, instance: any, file: File, formData: FormData) => boolean) | string;
|
|
29
|
+
onUploadComplete?: ((xhr: XMLHttpRequest, instance: any, file: File, formData: FormData) => void) | string;
|
|
30
|
+
onUploadProgress?: ((event: ProgressEvent, instance: any, file: File, formData: FormData) => void) | string;
|
|
31
|
+
onUploadError?: ((event: ProgressEvent, instance: any, file: File, formData: FormData) => void) | string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class UploadButton extends Cx.Widget<UploadButtonProps> {}
|
package/src/widgets/grid/Grid.js
CHANGED
|
@@ -157,15 +157,15 @@ export class Grid extends Container {
|
|
|
157
157
|
)
|
|
158
158
|
row.hasResizableColumns = true;
|
|
159
159
|
|
|
160
|
-
if (c.aggregate && (c.aggregateField || isDefined(c.aggregateValue))) {
|
|
160
|
+
if (c.aggregate && c.aggregateAlias && (c.aggregateField || isDefined(c.aggregateValue))) {
|
|
161
161
|
aggregates[c.aggregateAlias] = {
|
|
162
162
|
value: isDefined(c.aggregateValue)
|
|
163
163
|
? c.aggregateValue
|
|
164
164
|
: isDefined(c.value)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
? c.value
|
|
166
|
+
: c.aggregateField
|
|
167
|
+
? { bind: this.recordName + "." + c.aggregateField }
|
|
168
|
+
: null,
|
|
169
169
|
weight:
|
|
170
170
|
c.weight != null
|
|
171
171
|
? c.weight
|
|
@@ -881,15 +881,22 @@ export class Grid extends Container {
|
|
|
881
881
|
let v,
|
|
882
882
|
c = ci.widget,
|
|
883
883
|
colSpan,
|
|
884
|
-
pad
|
|
884
|
+
pad,
|
|
885
|
+
cls = "",
|
|
886
|
+
style = null;
|
|
885
887
|
if (c.caption) {
|
|
886
888
|
if (c.caption.children)
|
|
887
889
|
v = <Cx widget={c.caption.children} store={store} parentInstance={instance} subscribe />;
|
|
888
|
-
else
|
|
890
|
+
else {
|
|
891
|
+
v = c.caption.value(data);
|
|
892
|
+
let fmt = c.caption.format(data);
|
|
893
|
+
if (fmt) v = Format.value(v, fmt);
|
|
894
|
+
}
|
|
889
895
|
pad = c.caption.pad;
|
|
890
896
|
colSpan = c.caption.colSpan;
|
|
891
897
|
empty = false;
|
|
892
|
-
|
|
898
|
+
cls = CSS.expand(c.caption.class(data)) || "";
|
|
899
|
+
style = parseStyle(c.caption.style(data));
|
|
893
900
|
if (c.caption.expand) {
|
|
894
901
|
colSpan = 1;
|
|
895
902
|
for (
|
|
@@ -903,19 +910,19 @@ export class Grid extends Container {
|
|
|
903
910
|
}
|
|
904
911
|
|
|
905
912
|
if (colSpan > 1) skip = colSpan - 1;
|
|
906
|
-
} else if (c.aggregate && c.
|
|
913
|
+
} else if (c.aggregate && c.aggregateAlias && c.caption !== false) {
|
|
907
914
|
empty = false;
|
|
908
|
-
v = group[c.
|
|
915
|
+
v = group[c.aggregateAlias];
|
|
909
916
|
if (isString(ci.data.format)) v = Format.value(v, ci.data.format);
|
|
910
917
|
}
|
|
911
918
|
|
|
912
|
-
|
|
919
|
+
if (cls) cls += " ";
|
|
913
920
|
if (c.align) cls += CSS.state("aligned-" + c.align);
|
|
914
921
|
|
|
915
922
|
if (pad !== false) cls += (cls ? " " : "") + CSS.state("pad");
|
|
916
923
|
|
|
917
924
|
return (
|
|
918
|
-
<td key={i} className={cls} colSpan={colSpan}>
|
|
925
|
+
<td key={i} className={cls} colSpan={colSpan} style={style}>
|
|
919
926
|
{v}
|
|
920
927
|
</td>
|
|
921
928
|
);
|
|
@@ -986,9 +993,9 @@ export class Grid extends Container {
|
|
|
986
993
|
}
|
|
987
994
|
|
|
988
995
|
if (colSpan > 1) skip = colSpan - 1;
|
|
989
|
-
} else if (c.aggregate && c.
|
|
996
|
+
} else if (c.aggregate && c.aggregateAlias && c.footer !== false) {
|
|
990
997
|
empty = false;
|
|
991
|
-
v = group[c.
|
|
998
|
+
v = group[c.aggregateAlias];
|
|
992
999
|
if (isString(ci.data.format)) v = Format.value(v, ci.data.format);
|
|
993
1000
|
}
|
|
994
1001
|
|
|
@@ -3089,7 +3096,12 @@ class GridColumnHeader extends Widget {
|
|
|
3089
3096
|
if (children) {
|
|
3090
3097
|
delete this.caption.items;
|
|
3091
3098
|
this.caption.children = Widget.create(children);
|
|
3092
|
-
} else
|
|
3099
|
+
} else {
|
|
3100
|
+
this.caption.value = getSelector(this.caption.value);
|
|
3101
|
+
this.caption.class = getSelector(this.caption.class);
|
|
3102
|
+
this.caption.style = getSelector(this.caption.style);
|
|
3103
|
+
this.caption.format = getSelector(this.caption.format);
|
|
3104
|
+
}
|
|
3093
3105
|
}
|
|
3094
3106
|
|
|
3095
3107
|
super.init();
|
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
import { batchUpdates } from "../../ui/batchUpdates";
|
|
2
|
-
import { getParentFrameBoundingClientRect } from "../../util/getParentFrameBoundingClientRect";
|
|
3
|
-
|
|
4
|
-
export function captureMouse2(e, { onMouseMove, onMouseUp, onDblClick, captureData, cursor }) {
|
|
5
|
-
let surface = document.createElement("div");
|
|
6
|
-
surface.className = "cxb-mousecapture";
|
|
7
|
-
surface.style.cursor = cursor || getComputedStyle(e.currentTarget).cursor;
|
|
8
|
-
|
|
9
|
-
document.body.appendChild(surface);
|
|
10
|
-
|
|
11
|
-
// In case when the event originates from an iframe,
|
|
12
|
-
// we use that document as events do not bubble up. //
|
|
13
|
-
let parentDocument = e.target.ownerDocument;
|
|
14
|
-
let options = { capture: true };
|
|
15
|
-
|
|
16
|
-
let active = true;
|
|
17
|
-
parentDocument.addEventListener("mousemove", move, options);
|
|
18
|
-
parentDocument.addEventListener("mouseup", end, options);
|
|
19
|
-
if (onDblClick) parentDocument.addEventListener("dblclick", doubleClick), options;
|
|
20
|
-
|
|
21
|
-
function tear() {
|
|
22
|
-
if (surface == null) return;
|
|
23
|
-
parentDocument.removeEventListener("mousemove", move, options);
|
|
24
|
-
parentDocument.removeEventListener("mouseup", end, options);
|
|
25
|
-
if (onDblClick) parentDocument.removeEventListener("dblclick", onDblClick, options);
|
|
26
|
-
document.body.removeChild(surface);
|
|
27
|
-
surface = null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function doubleClick(e) {
|
|
31
|
-
try {
|
|
32
|
-
onDblClick(e);
|
|
33
|
-
} finally {
|
|
34
|
-
tear();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
e.stopPropagation();
|
|
39
|
-
|
|
40
|
-
function move(e) {
|
|
41
|
-
if (!active) {
|
|
42
|
-
tear();
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
//if mouse moves double clicking is off
|
|
47
|
-
onDblClick = null;
|
|
48
|
-
|
|
49
|
-
batchUpdates(() => {
|
|
50
|
-
if (onMouseMove) onMouseMove(e, captureData);
|
|
51
|
-
e.stopPropagation();
|
|
52
|
-
e.preventDefault(); //disable text selection
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function end(e) {
|
|
57
|
-
active = false;
|
|
58
|
-
batchUpdates(() => {
|
|
59
|
-
// if (surface.releaseCapture)
|
|
60
|
-
// surface.releaseCapture();
|
|
61
|
-
|
|
62
|
-
if (!onDblClick) surface.style.display = "none";
|
|
63
|
-
try {
|
|
64
|
-
if (onMouseUp) onMouseUp(e, captureData);
|
|
65
|
-
} finally {
|
|
66
|
-
if (onDblClick) {
|
|
67
|
-
//keep the surface a little longer to detect double clicks
|
|
68
|
-
setTimeout(tear, 1500);
|
|
69
|
-
} else tear();
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function captureMouseOrTouch2(e, { onMouseMove, onMouseUp, onDblClick, captureData, cursor }) {
|
|
76
|
-
if (e.type.indexOf("touch") == 0) {
|
|
77
|
-
let el = e.currentTarget;
|
|
78
|
-
|
|
79
|
-
let move = (e) => {
|
|
80
|
-
batchUpdates(() => {
|
|
81
|
-
if (onMouseMove) onMouseMove(e, captureData);
|
|
82
|
-
e.preventDefault();
|
|
83
|
-
});
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
let end = (e) => {
|
|
87
|
-
batchUpdates(() => {
|
|
88
|
-
el.removeEventListener("touchmove", move);
|
|
89
|
-
el.removeEventListener("touchend", end);
|
|
90
|
-
|
|
91
|
-
if (onMouseUp) onMouseUp(e);
|
|
92
|
-
|
|
93
|
-
e.preventDefault();
|
|
94
|
-
});
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
el.addEventListener("touchmove", move);
|
|
98
|
-
el.addEventListener("touchend", end);
|
|
99
|
-
|
|
100
|
-
e.stopPropagation();
|
|
101
|
-
} else captureMouse2(e, { onMouseMove, onMouseUp, captureData, onDblClick, cursor });
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function captureMouse(e, onMouseMove, onMouseUp, captureData, cursor) {
|
|
105
|
-
captureMouse2(e, {
|
|
106
|
-
onMouseMove,
|
|
107
|
-
onMouseUp,
|
|
108
|
-
captureData,
|
|
109
|
-
cursor,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function captureMouseOrTouch(e, onMouseMove, onMouseUp, captureData, cursor) {
|
|
114
|
-
captureMouseOrTouch2(e, { onMouseMove, onMouseUp, captureData, cursor });
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function getCursorPos(e) {
|
|
118
|
-
let p = (e.touches && e.touches[0]) || e;
|
|
119
|
-
let offset = getParentFrameBoundingClientRect(e.target);
|
|
120
|
-
return {
|
|
121
|
-
clientX: p.clientX + offset.left,
|
|
122
|
-
clientY: p.clientY + offset.top,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
1
|
+
import { batchUpdates } from "../../ui/batchUpdates";
|
|
2
|
+
import { getParentFrameBoundingClientRect } from "../../util/getParentFrameBoundingClientRect";
|
|
3
|
+
|
|
4
|
+
export function captureMouse2(e, { onMouseMove, onMouseUp, onDblClick, captureData, cursor }) {
|
|
5
|
+
let surface = document.createElement("div");
|
|
6
|
+
surface.className = "cxb-mousecapture";
|
|
7
|
+
surface.style.cursor = cursor || getComputedStyle(e.currentTarget).cursor;
|
|
8
|
+
|
|
9
|
+
document.body.appendChild(surface);
|
|
10
|
+
|
|
11
|
+
// In case when the event originates from an iframe,
|
|
12
|
+
// we use that document as events do not bubble up. //
|
|
13
|
+
let parentDocument = e.target.ownerDocument;
|
|
14
|
+
let options = { capture: true };
|
|
15
|
+
|
|
16
|
+
let active = true;
|
|
17
|
+
parentDocument.addEventListener("mousemove", move, options);
|
|
18
|
+
parentDocument.addEventListener("mouseup", end, options);
|
|
19
|
+
if (onDblClick) parentDocument.addEventListener("dblclick", doubleClick), options;
|
|
20
|
+
|
|
21
|
+
function tear() {
|
|
22
|
+
if (surface == null) return;
|
|
23
|
+
parentDocument.removeEventListener("mousemove", move, options);
|
|
24
|
+
parentDocument.removeEventListener("mouseup", end, options);
|
|
25
|
+
if (onDblClick) parentDocument.removeEventListener("dblclick", onDblClick, options);
|
|
26
|
+
document.body.removeChild(surface);
|
|
27
|
+
surface = null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function doubleClick(e) {
|
|
31
|
+
try {
|
|
32
|
+
onDblClick(e);
|
|
33
|
+
} finally {
|
|
34
|
+
tear();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
e.stopPropagation();
|
|
39
|
+
|
|
40
|
+
function move(e) {
|
|
41
|
+
if (!active) {
|
|
42
|
+
tear();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//if mouse moves double clicking is off
|
|
47
|
+
onDblClick = null;
|
|
48
|
+
|
|
49
|
+
batchUpdates(() => {
|
|
50
|
+
if (onMouseMove) onMouseMove(e, captureData);
|
|
51
|
+
e.stopPropagation();
|
|
52
|
+
e.preventDefault(); //disable text selection
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function end(e) {
|
|
57
|
+
active = false;
|
|
58
|
+
batchUpdates(() => {
|
|
59
|
+
// if (surface.releaseCapture)
|
|
60
|
+
// surface.releaseCapture();
|
|
61
|
+
|
|
62
|
+
if (!onDblClick) surface.style.display = "none";
|
|
63
|
+
try {
|
|
64
|
+
if (onMouseUp) onMouseUp(e, captureData);
|
|
65
|
+
} finally {
|
|
66
|
+
if (onDblClick) {
|
|
67
|
+
//keep the surface a little longer to detect double clicks
|
|
68
|
+
setTimeout(tear, 1500);
|
|
69
|
+
} else tear();
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function captureMouseOrTouch2(e, { onMouseMove, onMouseUp, onDblClick, captureData, cursor }) {
|
|
76
|
+
if (e.type.indexOf("touch") == 0) {
|
|
77
|
+
let el = e.currentTarget;
|
|
78
|
+
|
|
79
|
+
let move = (e) => {
|
|
80
|
+
batchUpdates(() => {
|
|
81
|
+
if (onMouseMove) onMouseMove(e, captureData);
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
let end = (e) => {
|
|
87
|
+
batchUpdates(() => {
|
|
88
|
+
el.removeEventListener("touchmove", move);
|
|
89
|
+
el.removeEventListener("touchend", end);
|
|
90
|
+
|
|
91
|
+
if (onMouseUp) onMouseUp(e);
|
|
92
|
+
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
el.addEventListener("touchmove", move);
|
|
98
|
+
el.addEventListener("touchend", end);
|
|
99
|
+
|
|
100
|
+
e.stopPropagation();
|
|
101
|
+
} else captureMouse2(e, { onMouseMove, onMouseUp, captureData, onDblClick, cursor });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function captureMouse(e, onMouseMove, onMouseUp, captureData, cursor) {
|
|
105
|
+
captureMouse2(e, {
|
|
106
|
+
onMouseMove,
|
|
107
|
+
onMouseUp,
|
|
108
|
+
captureData,
|
|
109
|
+
cursor,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function captureMouseOrTouch(e, onMouseMove, onMouseUp, captureData, cursor) {
|
|
114
|
+
captureMouseOrTouch2(e, { onMouseMove, onMouseUp, captureData, cursor });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function getCursorPos(e) {
|
|
118
|
+
let p = (e.touches && e.touches[0]) || e;
|
|
119
|
+
let offset = getParentFrameBoundingClientRect(e.target);
|
|
120
|
+
return {
|
|
121
|
+
clientX: p.clientX + offset.left,
|
|
122
|
+
clientY: p.clientY + offset.top,
|
|
123
|
+
};
|
|
124
|
+
}
|