@jx3box/jx3box-editor 3.2.1 → 3.2.2
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/package.json +1 -1
- package/src/assets/js/jx3_element.js +186 -32
package/package.json
CHANGED
|
@@ -3,62 +3,216 @@ import $ from "jquery";
|
|
|
3
3
|
function renderItem(vm, selector = ".w-jx3-element") {
|
|
4
4
|
let outer, inner;
|
|
5
5
|
const pop_class = ".w-jx3-element-pop";
|
|
6
|
+
const scopeEl = vm && vm.$el ? vm.$el : document;
|
|
7
|
+
const $scope = $(scopeEl);
|
|
8
|
+
const uid = vm && vm._uid ? vm._uid : "default";
|
|
9
|
+
const ns = `.jx3boxElement_${uid}`;
|
|
10
|
+
let lastTappedElement = null;
|
|
11
|
+
const debugPop = false;
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
13
|
+
const isMobile = () => {
|
|
14
|
+
if (typeof window === "undefined") return false;
|
|
15
|
+
|
|
16
|
+
const coarsePointer =
|
|
17
|
+
typeof window.matchMedia === "function" &&
|
|
18
|
+
window.matchMedia("(hover: none) and (pointer: coarse)").matches;
|
|
19
|
+
const hasTouchEvent = "ontouchstart" in window;
|
|
20
|
+
const mobileUA =
|
|
21
|
+
typeof navigator !== "undefined" &&
|
|
22
|
+
/Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent || "");
|
|
23
|
+
|
|
24
|
+
return coarsePointer || (hasTouchEvent && mobileUA);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const cachedPop =
|
|
28
|
+
vm &&
|
|
29
|
+
vm.__jx3ElementPop &&
|
|
30
|
+
vm.__jx3ElementPop.length &&
|
|
31
|
+
document.documentElement.contains(vm.__jx3ElementPop[0])
|
|
32
|
+
? vm.__jx3ElementPop
|
|
33
|
+
: null;
|
|
34
|
+
const $pop = cachedPop || $scope.find(pop_class).first();
|
|
35
|
+
|
|
36
|
+
if (!$pop.length) return;
|
|
37
|
+
if (isMobile() && vm) {
|
|
38
|
+
vm.__jx3ElementPop = $pop;
|
|
39
|
+
if ($pop.parent()[0] !== document.body) {
|
|
40
|
+
$pop.appendTo(document.body);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const getCurrentTarget = (el, e) => {
|
|
45
|
+
const $self = $(el).closest(selector);
|
|
46
|
+
if ($self.length) return $self;
|
|
47
|
+
return $(e.currentTarget || e.target).closest(selector);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const getDataTarget = ($target, e) => {
|
|
51
|
+
const $eventTarget = $(e?.target);
|
|
52
|
+
const $fromEvent = $eventTarget.closest("[data-type]");
|
|
53
|
+
if ($fromEvent.length && $target.has($fromEvent).length) return $fromEvent;
|
|
54
|
+
if ($target.attr("data-type")) return $target;
|
|
55
|
+
|
|
56
|
+
return $target.find("[data-type]").first();
|
|
57
|
+
};
|
|
10
58
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
59
|
+
const getHrefTarget = ($target) => {
|
|
60
|
+
if ($target.is("a[href]")) return $target;
|
|
61
|
+
return $target.closest("a[href]");
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const syncElementData = ($dataTarget, $targetForFallback = null) => {
|
|
65
|
+
let type = $dataTarget.attr("data-type");
|
|
66
|
+
if (!type && $targetForFallback && $targetForFallback.length) {
|
|
67
|
+
const $fallback = $targetForFallback.attr("data-type")
|
|
68
|
+
? $targetForFallback
|
|
69
|
+
: $targetForFallback.find("[data-type]").first();
|
|
70
|
+
type = $fallback.attr("data-type");
|
|
71
|
+
if ($fallback.length) $dataTarget = $fallback;
|
|
72
|
+
}
|
|
73
|
+
if (!type) return "";
|
|
74
|
+
|
|
75
|
+
if (type === "item") {
|
|
76
|
+
vm.item.id = $dataTarget.attr("data-id");
|
|
77
|
+
vm.item.client = $dataTarget.attr("data-client") == "origin" ? 2 : 1;
|
|
16
78
|
} else if (type === "author") {
|
|
17
|
-
vm.author.id = $
|
|
79
|
+
vm.author.id = $dataTarget.attr("data-id");
|
|
18
80
|
} else if (type === "emotion") {
|
|
19
|
-
vm.emotion.id = $
|
|
20
|
-
} else {
|
|
21
|
-
vm[type].client = $
|
|
22
|
-
vm[type].id = $
|
|
23
|
-
vm[type].level = $
|
|
81
|
+
vm.emotion.id = $dataTarget.attr("data-id");
|
|
82
|
+
} else if (vm[type]) {
|
|
83
|
+
vm[type].client = $dataTarget.attr("data-client");
|
|
84
|
+
vm[type].id = $dataTarget.attr("data-id");
|
|
85
|
+
vm[type].level = $dataTarget.attr("data-level");
|
|
24
86
|
}
|
|
25
87
|
|
|
26
|
-
// 显示浮层
|
|
27
|
-
$(pop_class).fadeIn();
|
|
28
88
|
vm.jx3_element.type = type;
|
|
89
|
+
return type;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const showPop = ($dataTarget, point = {}, $targetForRect = null) => {
|
|
93
|
+
clearTimeout(outer);
|
|
94
|
+
clearTimeout(inner);
|
|
95
|
+
|
|
96
|
+
const type = syncElementData($dataTarget, $targetForRect);
|
|
97
|
+
if (!type) return;
|
|
98
|
+
|
|
99
|
+
const fallbackRect = $targetForRect && $targetForRect.length ? $targetForRect[0].getBoundingClientRect() : null;
|
|
100
|
+
const fallbackX = fallbackRect ? fallbackRect.left + fallbackRect.width / 2 : 0;
|
|
101
|
+
const fallbackY = fallbackRect ? fallbackRect.top + fallbackRect.height / 2 : 0;
|
|
102
|
+
const clientX = Number(point.clientX ?? fallbackX ?? 0);
|
|
103
|
+
const clientY = Number(point.clientY ?? fallbackY ?? 0);
|
|
104
|
+
|
|
105
|
+
vm.jx3_element.style.display = "block";
|
|
106
|
+
vm.jx3_element.style.position = "fixed";
|
|
107
|
+
vm.jx3_element.style.zIndex = "99999";
|
|
108
|
+
$pop.stop(true, true).fadeIn(120);
|
|
29
109
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
let
|
|
34
|
-
let will_stay_y = e.clientY + 10;
|
|
110
|
+
const selfHeight = $pop.height();
|
|
111
|
+
const winHeight = window.innerHeight;
|
|
112
|
+
const currentY = clientY;
|
|
113
|
+
let willStayY = clientY + 10;
|
|
35
114
|
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
current_y - (self_height - (win_height - current_y)) - 100;
|
|
115
|
+
if (selfHeight && winHeight - currentY < selfHeight) {
|
|
116
|
+
willStayY = currentY - (selfHeight - (winHeight - currentY)) - 100;
|
|
39
117
|
}
|
|
40
|
-
|
|
41
|
-
|
|
118
|
+
|
|
119
|
+
const maxLeft = Math.max(0, window.innerWidth - ($pop.outerWidth() || 0) - 12);
|
|
120
|
+
vm.jx3_element.style.left = Math.max(0, Math.min(clientX + 10, maxLeft)) + "px";
|
|
121
|
+
vm.jx3_element.style.top = Math.max(0, willStayY) + "px";
|
|
122
|
+
|
|
123
|
+
if (debugPop && isMobile()) {
|
|
124
|
+
vm.jx3_element.style.left = "50%";
|
|
125
|
+
vm.jx3_element.style.top = "52%";
|
|
126
|
+
vm.jx3_element.style.transform = "translate(-50%, -50%)";
|
|
127
|
+
vm.jx3_element.style.zIndex = "99999";
|
|
128
|
+
vm.jx3_element.style.background = "rgba(0,0,0,0.88)";
|
|
129
|
+
vm.jx3_element.style.outline = "2px solid #00e5ff";
|
|
130
|
+
vm.jx3_element.style.maxHeight = "72vh";
|
|
131
|
+
vm.jx3_element.style.overflow = "auto";
|
|
132
|
+
} else {
|
|
133
|
+
vm.jx3_element.style.transform = "";
|
|
134
|
+
vm.jx3_element.style.background = "";
|
|
135
|
+
vm.jx3_element.style.outline = "";
|
|
136
|
+
vm.jx3_element.style.maxHeight = "";
|
|
137
|
+
vm.jx3_element.style.overflow = "";
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const hidePop = () => {
|
|
142
|
+
vm.jx3_element.style.display = "none";
|
|
143
|
+
$pop.stop(true, true).fadeOut(120);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// 触发时
|
|
147
|
+
$scope.off(ns);
|
|
148
|
+
$pop.off(ns);
|
|
149
|
+
$(document).off(ns);
|
|
150
|
+
|
|
151
|
+
$scope.on(`mouseenter${ns}`, selector, function (e) {
|
|
152
|
+
if (isMobile()) return;
|
|
153
|
+
const $target = getCurrentTarget(this, e);
|
|
154
|
+
const $dataTarget = getDataTarget($target, e);
|
|
155
|
+
showPop($dataTarget, e, $target);
|
|
42
156
|
});
|
|
43
157
|
|
|
44
158
|
// 移除时
|
|
45
|
-
$
|
|
159
|
+
$scope.on(`mouseleave${ns}`, selector, function () {
|
|
160
|
+
if (isMobile()) return;
|
|
46
161
|
outer = setTimeout(() => {
|
|
47
|
-
|
|
162
|
+
hidePop();
|
|
48
163
|
}, 380);
|
|
49
164
|
});
|
|
50
165
|
|
|
166
|
+
$scope.on(`click${ns}`, selector, function (e) {
|
|
167
|
+
if (!isMobile()) return;
|
|
168
|
+
|
|
169
|
+
const $target = getCurrentTarget(this, e);
|
|
170
|
+
const $dataTarget = getDataTarget($target, e);
|
|
171
|
+
if (!$dataTarget.length) return;
|
|
172
|
+
|
|
173
|
+
const $hrefTarget = getHrefTarget($target);
|
|
174
|
+
const href = String($hrefTarget.attr("href") || "");
|
|
175
|
+
const touch = e.originalEvent?.touches?.[0] || e.originalEvent?.changedTouches?.[0];
|
|
176
|
+
const point = touch || e;
|
|
177
|
+
const tappedElement = $target.get(0);
|
|
178
|
+
|
|
179
|
+
if (href && lastTappedElement === tappedElement) {
|
|
180
|
+
lastTappedElement = null;
|
|
181
|
+
hidePop();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
e.preventDefault();
|
|
186
|
+
lastTappedElement = tappedElement;
|
|
187
|
+
showPop($dataTarget, point, $target);
|
|
188
|
+
});
|
|
189
|
+
|
|
51
190
|
// POP内停留
|
|
52
|
-
$
|
|
191
|
+
$pop.on(`mouseenter${ns}`, function () {
|
|
192
|
+
if (isMobile()) return;
|
|
53
193
|
clearTimeout(outer);
|
|
54
|
-
|
|
194
|
+
vm.jx3_element.style.display = "block";
|
|
195
|
+
$pop.stop(true, true).fadeIn(120);
|
|
55
196
|
});
|
|
56
|
-
$
|
|
197
|
+
$pop.on(`mouseleave${ns}`, function () {
|
|
198
|
+
if (isMobile()) return;
|
|
57
199
|
clearTimeout(inner);
|
|
58
200
|
inner = setTimeout(() => {
|
|
59
|
-
|
|
201
|
+
hidePop();
|
|
60
202
|
}, 280);
|
|
61
203
|
});
|
|
204
|
+
|
|
205
|
+
$(document).on(`click${ns}`, function (e) {
|
|
206
|
+
if (!isMobile()) return;
|
|
207
|
+
const $target = $(e.target);
|
|
208
|
+
const $trigger = $target.closest(selector);
|
|
209
|
+
const isCurrentTrigger = $trigger.length && ($trigger[0] === scopeEl || $scope.has($trigger[0]).length);
|
|
210
|
+
|
|
211
|
+
if (isCurrentTrigger || $target.closest(pop_class).length) return;
|
|
212
|
+
|
|
213
|
+
lastTappedElement = null;
|
|
214
|
+
hidePop();
|
|
215
|
+
});
|
|
62
216
|
}
|
|
63
217
|
|
|
64
218
|
export default renderItem;
|