coupdoeil 1.0.0.pre.alpha.1 → 1.0.0.pre.alpha.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/app/assets/javascripts/coupdoeil.js +253 -242
- data/app/assets/javascripts/coupdoeil.min.js +1 -1
- data/app/assets/javascripts/coupdoeil.min.js.map +1 -1
- data/app/javascript/coupdoeil/elements/coupdoeil_element.js +1 -1
- data/app/javascript/coupdoeil/events/onclick.js +1 -2
- data/app/javascript/coupdoeil/events/onmouseover.js +8 -5
- data/app/javascript/coupdoeil/events.js +3 -1
- data/app/javascript/coupdoeil/hovercard/actions.js +0 -60
- data/app/javascript/coupdoeil/hovercard/cache.js +5 -1
- data/app/javascript/coupdoeil/hovercard/closing.js +55 -8
- data/app/javascript/coupdoeil/hovercard/controller.js +0 -2
- data/app/javascript/coupdoeil/hovercard/current.js +13 -0
- data/app/javascript/coupdoeil/hovercard/opening.js +78 -73
- data/app/javascript/coupdoeil/hovercard/optionsParser.js +3 -2
- data/app/javascript/coupdoeil/hovercard/positioning.js +6 -5
- data/app/javascript/coupdoeil/hovercard/state_check.js +2 -1
- data/lib/coupdoeil/engine.rb +9 -1
- data/lib/coupdoeil/version.rb +1 -1
- metadata +3 -2
@@ -1,8 +1,8 @@
|
|
1
1
|
import {HovercardController} from '../hovercard/controller'
|
2
2
|
import {openHovercard} from '../hovercard/opening'
|
3
|
-
import {addToCurrents} from "../hovercard/actions";
|
4
3
|
import {HOVERCARD_SELECTOR} from "../hovercard/config";
|
5
4
|
import {closeNow} from "../hovercard/closing";
|
5
|
+
import {addToCurrents} from "../hovercard/current";
|
6
6
|
|
7
7
|
function generateUniqueId() {
|
8
8
|
const array = new Uint32Array(1)
|
@@ -1,8 +1,7 @@
|
|
1
1
|
import {HOVERCARD_SELECTOR} from "../hovercard/config";
|
2
2
|
import {isElementCloseHovercardButton} from "../hovercard/state_check";
|
3
|
-
import {closeAllNow} from "../hovercard/actions";
|
4
3
|
import {noTriggeredOnClick} from "../hovercard/attributes";
|
5
|
-
import {closeChildrenNow, closeNow} from "../hovercard/closing";
|
4
|
+
import {closeAllNow, closeChildrenNow, closeNow} from "../hovercard/closing";
|
6
5
|
|
7
6
|
export const coupdoeilOnClickEvent = ({ target: clickedElement }) => {
|
8
7
|
const coupdoeilElement = clickedElement.closest('coup-doeil')
|
@@ -1,11 +1,13 @@
|
|
1
1
|
import {HOVERCARD_SELECTOR} from "../hovercard/config";
|
2
2
|
import {isAnyHovercardOpened} from "../hovercard/state_check";
|
3
|
+
import {notTriggeredOnHover} from "../hovercard/attributes";
|
3
4
|
import {
|
4
|
-
|
5
|
+
cancelCloseRequest,
|
6
|
+
closeChildrenNow,
|
7
|
+
closeOnHoverChildrenLater,
|
5
8
|
closeTriggeredOnHoverLater, closeTriggeredOnHoverNow
|
6
|
-
} from "../hovercard/
|
7
|
-
import {
|
8
|
-
import {cancelCloseRequest, closeChildrenNow, closeOnHoverChildrenLater} from "../hovercard/closing";
|
9
|
+
} from "../hovercard/closing";
|
10
|
+
import {addToCurrents as addToCurrentHovercards} from "../hovercard/current";
|
9
11
|
|
10
12
|
export const onMouseOver = ({ target: hoveredElement }) => {
|
11
13
|
const coupdoeilElement = hoveredElement.closest('coup-doeil')
|
@@ -32,12 +34,13 @@ function handleMouseOverCoupdoeilWithinHovercard(coupdoeilElement, hovercardElem
|
|
32
34
|
return;
|
33
35
|
|
34
36
|
if (childHovercard.isOpen) {
|
35
|
-
// when mouse goes back from child hovercard to its coupdoeil element within parent hovercard
|
37
|
+
// when the mouse goes back from child hovercard to its coupdoeil element within parent hovercard
|
36
38
|
// it means that this child hovercard was already open
|
37
39
|
closeChildrenNow(childHovercard)
|
38
40
|
} else {
|
39
41
|
// ensures to close other children hovercards before opening the one that current one
|
40
42
|
closeChildrenNow(parentHovercard)
|
43
|
+
// should also close any open hovercard outside of parent
|
41
44
|
coupdoeilElement.openHovercard()
|
42
45
|
}
|
43
46
|
}
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import {coupdoeilOnClickEvent} from "./events/onclick";
|
2
2
|
import {onMouseOver} from "./events/onmouseover";
|
3
|
-
|
3
|
+
|
4
|
+
import {clearHovercardContentCache} from "./hovercard/cache";
|
5
|
+
import {clearAll} from "./hovercard/closing";
|
4
6
|
|
5
7
|
document.addEventListener("DOMContentLoaded", () => {
|
6
8
|
clearHovercardContentCache()
|
@@ -1,60 +0,0 @@
|
|
1
|
-
import {hovercardContentHTMLMap} from "./cache";
|
2
|
-
import {triggeredOnHover} from "./attributes";
|
3
|
-
import {clear as clearHovercard, closeLater, closeNow, cancelCloseRequest} from "./closing";
|
4
|
-
import {cancelOpening} from "./opening";
|
5
|
-
|
6
|
-
const CURRENT_HOVERCARDS_BY_ID = new Map()
|
7
|
-
window.hovercads = CURRENT_HOVERCARDS_BY_ID
|
8
|
-
|
9
|
-
export function clearHovercardContentCache() {
|
10
|
-
hovercardContentHTMLMap.clear()
|
11
|
-
}
|
12
|
-
|
13
|
-
export function currentHovercardsById() {
|
14
|
-
return CURRENT_HOVERCARDS_BY_ID
|
15
|
-
}
|
16
|
-
|
17
|
-
export function addToCurrents(coupdoeilElement) {
|
18
|
-
CURRENT_HOVERCARDS_BY_ID.set(coupdoeilElement.uniqueId, coupdoeilElement)
|
19
|
-
}
|
20
|
-
|
21
|
-
export function closeAllNow() {
|
22
|
-
for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
|
23
|
-
closeNow(coupdoeilElement.hovercardController)
|
24
|
-
removeFromCurrents(coupdoeilElement)
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
|
-
export function clearAll() {
|
29
|
-
for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
|
30
|
-
clearHovercard(coupdoeilElement.hovercardController)
|
31
|
-
removeFromCurrents(coupdoeilElement)
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
export function closeTriggeredOnHoverNow() {
|
36
|
-
for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
|
37
|
-
if (triggeredOnHover(coupdoeilElement.hovercardController)) {
|
38
|
-
closeNow(coupdoeilElement.hovercardController)
|
39
|
-
removeFromCurrents(coupdoeilElement)
|
40
|
-
}
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
|
-
export function closeTriggeredOnHoverLater() {
|
45
|
-
for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
|
46
|
-
if (triggeredOnHover(coupdoeilElement.hovercardController)) {
|
47
|
-
closeLater(coupdoeilElement.hovercardController)
|
48
|
-
removeFromCurrents(coupdoeilElement)
|
49
|
-
}
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
export function removeFromCurrents(coupdoeilElement) {
|
54
|
-
CURRENT_HOVERCARDS_BY_ID.delete(coupdoeilElement.uniqueId)
|
55
|
-
}
|
56
|
-
|
57
|
-
export function cancelOpenCloseActions(controller) {
|
58
|
-
cancelOpening(controller)
|
59
|
-
cancelCloseRequest(controller)
|
60
|
-
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import {getParams, getType, preloadedContentElement} from './attributes'
|
2
2
|
|
3
3
|
export const hovercardContentHTMLMap = new Map()
|
4
4
|
|
@@ -16,3 +16,7 @@ export function getHovercardContentHTML(controller) {
|
|
16
16
|
export function setHovercardContentHTML(controller, value) {
|
17
17
|
hovercardContentHTMLMap.set(cacheMapKey(controller), value)
|
18
18
|
}
|
19
|
+
|
20
|
+
export function clearHovercardContentCache() {
|
21
|
+
hovercardContentHTMLMap.clear()
|
22
|
+
}
|
@@ -1,7 +1,7 @@
|
|
1
|
-
import {triggeredOnHover} from "./attributes"
|
2
|
-
import {defaultConfig} from "./config"
|
3
|
-
import {leave} from "el-transition"
|
4
|
-
import {
|
1
|
+
import {triggeredOnHover} from "./attributes"
|
2
|
+
import {defaultConfig} from "./config"
|
3
|
+
import {leave} from "el-transition"
|
4
|
+
import {addToCurrents, CURRENT_HOVERCARDS_BY_ID, removeFromCurrents} from "./current"
|
5
5
|
|
6
6
|
function detachFromParent(controller) {
|
7
7
|
if (controller.parent) {
|
@@ -10,13 +10,26 @@ function detachFromParent(controller) {
|
|
10
10
|
}
|
11
11
|
}
|
12
12
|
|
13
|
+
export function cancelOpenCloseActions(controller) {
|
14
|
+
cancelOpening(controller)
|
15
|
+
cancelCloseRequest(controller)
|
16
|
+
}
|
17
|
+
|
18
|
+
function cancelOpening(controller) {
|
19
|
+
console.log('deleting openingHovercard: ', controller.coupdoeilElement.uniqueId)
|
20
|
+
delete controller.coupdoeilElement.openingHovercard
|
21
|
+
}
|
22
|
+
|
13
23
|
export function cancelCloseRequest(controller) {
|
14
24
|
clearTimeout(controller.closingRequest)
|
15
25
|
controller.closingRequest = null
|
26
|
+
addToCurrents(controller.coupdoeilElement)
|
16
27
|
}
|
17
28
|
|
18
29
|
export function closeNow(controller, allowAnimation = true) {
|
19
|
-
|
30
|
+
console.log('closing: ', controller.coupdoeilElement.uniqueId)
|
31
|
+
console.log({ closing: controller.closing, isClosed: controller.isClosed && !controller.coupdoeilElement.openingHovercard })
|
32
|
+
if (controller.closing || (controller.isClosed && !controller.coupdoeilElement.openingHovercard)) return
|
20
33
|
|
21
34
|
controller.closing = true
|
22
35
|
|
@@ -28,7 +41,7 @@ export function closeNow(controller, allowAnimation = true) {
|
|
28
41
|
|
29
42
|
detachFromParent(controller)
|
30
43
|
|
31
|
-
if (allowAnimation && controller.card.dataset.animation) {
|
44
|
+
if (allowAnimation && controller.card && controller.card.dataset.animation) {
|
32
45
|
closeWithAnimation(controller)
|
33
46
|
} else {
|
34
47
|
closeWithoutAnimation(controller)
|
@@ -42,8 +55,10 @@ async function closeWithAnimation(controller) {
|
|
42
55
|
}
|
43
56
|
|
44
57
|
function closeWithoutAnimation(controller) {
|
45
|
-
controller.card
|
46
|
-
|
58
|
+
if (controller.card) {
|
59
|
+
controller.card.remove()
|
60
|
+
controller.card = null
|
61
|
+
}
|
47
62
|
delete controller.closing
|
48
63
|
delete controller.coupdoeilElement.dataset.hovercardOpen
|
49
64
|
}
|
@@ -79,3 +94,35 @@ export function closeOnHoverChildrenLater(controller) {
|
|
79
94
|
}
|
80
95
|
})
|
81
96
|
}
|
97
|
+
|
98
|
+
export function closeAllNow() {
|
99
|
+
for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
|
100
|
+
closeNow(coupdoeilElement.hovercardController)
|
101
|
+
removeFromCurrents(coupdoeilElement)
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
export function clearAll() {
|
106
|
+
for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
|
107
|
+
clearHovercard(coupdoeilElement.hovercardController)
|
108
|
+
removeFromCurrents(coupdoeilElement)
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
export function closeTriggeredOnHoverNow() {
|
113
|
+
for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
|
114
|
+
if (triggeredOnHover(coupdoeilElement.hovercardController)) {
|
115
|
+
closeNow(coupdoeilElement.hovercardController)
|
116
|
+
removeFromCurrents(coupdoeilElement)
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
export function closeTriggeredOnHoverLater() {
|
122
|
+
for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
|
123
|
+
if (triggeredOnHover(coupdoeilElement.hovercardController)) {
|
124
|
+
closeLater(coupdoeilElement.hovercardController)
|
125
|
+
removeFromCurrents(coupdoeilElement)
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
@@ -8,8 +8,6 @@ export class HovercardController {
|
|
8
8
|
this.parent = null // can go on hovercardElement
|
9
9
|
|
10
10
|
this.closingRequest = null // can go on coupdoeil element
|
11
|
-
this.openingDelay = null // can go on coupdoeil element
|
12
|
-
this.fetchDelay = null // can go on coupdoeil element
|
13
11
|
}
|
14
12
|
|
15
13
|
get isOpen() {
|
@@ -0,0 +1,13 @@
|
|
1
|
+
export const CURRENT_HOVERCARDS_BY_ID = new Map()
|
2
|
+
|
3
|
+
export function currentHovercardsById() {
|
4
|
+
return CURRENT_HOVERCARDS_BY_ID
|
5
|
+
}
|
6
|
+
|
7
|
+
export function addToCurrents(coupdoeilElement) {
|
8
|
+
CURRENT_HOVERCARDS_BY_ID.set(coupdoeilElement.uniqueId, coupdoeilElement)
|
9
|
+
}
|
10
|
+
|
11
|
+
export function removeFromCurrents(coupdoeilElement) {
|
12
|
+
CURRENT_HOVERCARDS_BY_ID.delete(coupdoeilElement.uniqueId)
|
13
|
+
}
|
@@ -1,60 +1,73 @@
|
|
1
|
-
import {defaultConfig, HOVERCARD_CLASS_NAME} from "./config"
|
2
|
-
import {getParams, getType, preloadedContentElement, triggeredOnClick} from "./attributes"
|
3
|
-
import {getHovercardContentHTML, setHovercardContentHTML} from "./cache"
|
4
|
-
import {
|
5
|
-
import {
|
6
|
-
import {
|
7
|
-
import {
|
8
|
-
import {
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
1
|
+
import {defaultConfig, HOVERCARD_CLASS_NAME} from "./config"
|
2
|
+
import {getParams, getType, preloadedContentElement, triggeredOnClick} from "./attributes"
|
3
|
+
import {getHovercardContentHTML, setHovercardContentHTML} from "./cache"
|
4
|
+
import {extractOptionsFromElement} from "./optionsParser"
|
5
|
+
import {positionHovercard} from "./positioning"
|
6
|
+
import {enter} from "el-transition"
|
7
|
+
import {addToCurrents} from "./current"
|
8
|
+
import {cancelCloseRequest, clear as clearHovercard} from "./closing"
|
9
|
+
|
10
|
+
function fetchHovercardContent(controller) {
|
11
|
+
const type = getType(controller)
|
12
|
+
const params = getParams(controller)
|
13
|
+
const authenticityToken = document.querySelector('meta[name=csrf-token]').content
|
14
|
+
let url = `/coupdoeil/hovercard`
|
15
|
+
const opts = {
|
16
|
+
method: 'POST',
|
17
|
+
headers: {
|
18
|
+
'Content-Type': 'application/json'
|
19
|
+
},
|
20
|
+
body: JSON.stringify({ params, action_name: type, authenticity_token: authenticityToken })
|
21
|
+
}
|
22
|
+
return fetch(url, opts)
|
23
|
+
.then((response) => {
|
24
|
+
if (response.status >= 400) {
|
25
|
+
throw 'error while fetching hovercard content'
|
26
|
+
}
|
27
|
+
return response.text()
|
28
|
+
})
|
29
|
+
}
|
30
|
+
|
31
|
+
async function loadHovercardContentHTML(controller, options, delayOptions) {
|
32
|
+
return new Promise((resolve) => {
|
33
|
+
setTimeout(async () => {
|
34
|
+
if (!controller.coupdoeilElement.openingHovercard) return // opening has been canceled
|
35
|
+
|
36
|
+
if (options.cache === false || (options.cache && !getHovercardContentHTML(controller))) {
|
37
|
+
let html
|
38
|
+
if (options.loading === "preload") {
|
39
|
+
html = preloadedContentElement(controller).innerHTML
|
40
|
+
} else {
|
41
|
+
html = await fetchHovercardContent(controller)
|
42
|
+
}
|
43
|
+
setHovercardContentHTML(controller, html)
|
44
|
+
}
|
45
|
+
resolve()
|
46
|
+
}, delayOptions.fetch)
|
47
|
+
})
|
16
48
|
}
|
17
49
|
|
18
50
|
export async function openHovercard(controller, { parent }) {
|
51
|
+
console.log('opening: ', controller.coupdoeilElement.uniqueId)
|
19
52
|
if (controller.isOpen) {
|
20
|
-
cancelCloseRequest(controller)
|
21
|
-
return addToCurrents(controller.coupdoeilElement)
|
53
|
+
return cancelCloseRequest(controller)
|
22
54
|
}
|
23
55
|
if (parent) {
|
24
56
|
controller.parent = parent
|
25
57
|
parent.children.add(controller)
|
26
58
|
}
|
27
59
|
|
28
|
-
const
|
60
|
+
const delays = getDelayOptionsForController(controller)
|
29
61
|
const options = extractOptionsFromElement(controller.coupdoeilElement)
|
30
|
-
const { cache } = options
|
31
62
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
setTimeout(resolve, delayOptions.actualOpening)
|
37
|
-
}
|
38
|
-
})
|
39
|
-
if (!getHovercardContentHTML(controller) || !cache) {
|
40
|
-
// prevent fetching if the user hovers in and out quickly
|
41
|
-
controller.fetchDelay = new Promise((resolve) => {
|
42
|
-
setTimeout(resolve, delayOptions.fetch)
|
43
|
-
})
|
44
|
-
await controller.fetchDelay
|
45
|
-
if (!controller.fetchDelay) {
|
46
|
-
return
|
47
|
-
}
|
48
|
-
controller.fetchDelay = null
|
49
|
-
const html = preloadedContentElement(controller)?.innerHTML || await fetchHovercardContent(controller)
|
50
|
-
setHovercardContentHTML(controller, html)
|
51
|
-
}
|
52
|
-
// still await the delay even if content is already fetched
|
53
|
-
await controller.openingDelay
|
63
|
+
const openingDelay = new Promise(resolve => setTimeout(resolve, delays.opening))
|
64
|
+
const fetchDelay = loadHovercardContentHTML(controller, options, delays)
|
65
|
+
await Promise.all([fetchDelay, openingDelay])
|
66
|
+
|
54
67
|
const parentIsClosedOrClosing = controller.parent && (controller.parent.isClosed || controller.parent.closingRequest)
|
55
|
-
|
56
|
-
if
|
57
|
-
|
68
|
+
|
69
|
+
// but if opening has been canceled (nullified), the wait still happens, so we need to check again
|
70
|
+
if (controller.coupdoeilElement.openingHovercard && !parentIsClosedOrClosing) {
|
58
71
|
await display(controller, options)
|
59
72
|
}
|
60
73
|
}
|
@@ -72,17 +85,29 @@ async function display(controller, options) {
|
|
72
85
|
}
|
73
86
|
|
74
87
|
requestAnimationFrame(async () => {
|
88
|
+
if (!controller.coupdoeilElement.openingHovercard) {
|
89
|
+
return clearHovercard(controller)
|
90
|
+
}
|
91
|
+
|
75
92
|
controller.card.style.opacity = '0'
|
76
93
|
controller.card.classList.remove('hidden')
|
77
94
|
|
78
95
|
requestAnimationFrame(async () => {
|
79
|
-
|
96
|
+
if (!controller.coupdoeilElement.openingHovercard) {
|
97
|
+
return clearHovercard(controller)
|
98
|
+
}
|
99
|
+
|
100
|
+
await positionHovercard(controller.coupdoeilElement, controller.card, options)
|
80
101
|
|
81
102
|
controller.card.classList.add('hidden')
|
82
103
|
controller.card.style.removeProperty('opacity')
|
83
104
|
|
84
105
|
requestAnimationFrame(async () => {
|
85
|
-
|
106
|
+
if (!controller.coupdoeilElement.openingHovercard) {
|
107
|
+
return clearHovercard(controller)
|
108
|
+
}
|
109
|
+
|
110
|
+
// // adding again the card to make sure it is in the map, could be better
|
86
111
|
addToCurrents(controller.coupdoeilElement)
|
87
112
|
delete controller.coupdoeilElement.openingHovercard
|
88
113
|
controller.coupdoeilElement.dataset.hovercardOpen = true
|
@@ -95,36 +120,16 @@ async function display(controller, options) {
|
|
95
120
|
|
96
121
|
function getDelayOptionsForController(controller) {
|
97
122
|
if (triggeredOnClick(controller)) {
|
98
|
-
return {
|
99
|
-
}
|
100
|
-
return {
|
101
|
-
fetch: defaultConfig.fetchDelay,
|
102
|
-
// the time (ms) to wait if we already have fetched the content
|
103
|
-
reOpening: defaultConfig.fetchDelay + defaultConfig.openingDelay,
|
104
|
-
// the time (ms) to wait if we already have waited to fetch the content
|
105
|
-
actualOpening: defaultConfig.openingDelay - defaultConfig.fetchDelay
|
123
|
+
return { fetch: 0, opening: 0 }
|
106
124
|
}
|
107
|
-
}
|
108
125
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
const opts = {
|
115
|
-
method: 'POST',
|
116
|
-
headers: {
|
117
|
-
'Content-Type': 'application/json'
|
118
|
-
},
|
119
|
-
body: JSON.stringify({ params, action_name: type, authenticity_token: authenticityToken })
|
126
|
+
let fetchDelay
|
127
|
+
if (defaultConfig.openingDelay === 0) {
|
128
|
+
fetchDelay = 0
|
129
|
+
} else {
|
130
|
+
fetchDelay = defaultConfig.openingDelay / 2
|
120
131
|
}
|
121
|
-
return fetch
|
122
|
-
.then((response) => {
|
123
|
-
if (response.status >= 400) {
|
124
|
-
throw 'error while fetching hovercard content'
|
125
|
-
}
|
126
|
-
return response.text()
|
127
|
-
})
|
132
|
+
return { fetch: fetchDelay, opening: defaultConfig.openingDelay }
|
128
133
|
}
|
129
134
|
|
130
135
|
function buildHovercardElement(controller, options) {
|
@@ -25,7 +25,7 @@ const PLACEMENTS = [
|
|
25
25
|
'bottom', 'bottom-start', 'bottom-end',
|
26
26
|
'left', 'left-start', 'left-end'
|
27
27
|
]
|
28
|
-
const LOADINGS = ["
|
28
|
+
const LOADINGS = ["async", "preload", "lazy"]
|
29
29
|
|
30
30
|
function parseCSSSize(value) {
|
31
31
|
if (typeof value === 'number') {
|
@@ -78,7 +78,8 @@ function getCache(optionsInt) {
|
|
78
78
|
}
|
79
79
|
|
80
80
|
function getLoading(optionsInt) {
|
81
|
-
|
81
|
+
// Shift right 1 time to remove trigger bit, mask with 3 (0b11).
|
82
|
+
return LOADINGS[(optionsInt >> 1) & 3]
|
82
83
|
}
|
83
84
|
|
84
85
|
function getTrigger(optionsInt) {
|
@@ -5,11 +5,12 @@ import {
|
|
5
5
|
offset,
|
6
6
|
arrow
|
7
7
|
} from "@floating-ui/dom"
|
8
|
+
import {clear as clearHovercard} from "./closing";
|
8
9
|
|
9
|
-
export async function positionHovercard(
|
10
|
+
export async function positionHovercard(target, card, options) {
|
10
11
|
let { placement: placements, offset: offsetValue } = options
|
11
12
|
const placement = placements[0]
|
12
|
-
const arrowElement =
|
13
|
+
const arrowElement = card.querySelector('[data-hovercard-arrow]')
|
13
14
|
const middleware = [AutoPositioningWithFallbacks(placements)]
|
14
15
|
|
15
16
|
if (arrowElement) {
|
@@ -21,7 +22,7 @@ export async function positionHovercard(controller, options) {
|
|
21
22
|
middleware.push(offset(offsetValue))
|
22
23
|
|
23
24
|
const computedPosition = await computePosition(
|
24
|
-
|
25
|
+
target, card, { placement, middleware }
|
25
26
|
)
|
26
27
|
const { x, y, placement: actualPlacement} = computedPosition
|
27
28
|
|
@@ -29,8 +30,8 @@ export async function positionHovercard(controller, options) {
|
|
29
30
|
positionArrow(arrowElement, computedPosition)
|
30
31
|
}
|
31
32
|
|
32
|
-
|
33
|
-
Object.assign(
|
33
|
+
card.dataset.placement = actualPlacement
|
34
|
+
Object.assign(card.style, { left: `${x}px`, top: `${y}px` })
|
34
35
|
}
|
35
36
|
|
36
37
|
const AutoPositioningWithFallbacks = (placements) => {
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import {HOVERCARD_CLOSE_BTN_SELECTOR} from "./config";
|
2
|
-
|
2
|
+
|
3
|
+
import {currentHovercardsById} from "./current";
|
3
4
|
|
4
5
|
export function isElementCloseHovercardButton(element) {
|
5
6
|
return element.closest(HOVERCARD_CLOSE_BTN_SELECTOR) ||
|
data/lib/coupdoeil/engine.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
module Coupdoeil
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
isolate_namespace Coupdoeil
|
4
|
-
|
4
|
+
config.eager_load_namespaces << Coupdoeil
|
5
5
|
config.coupdoeil = ActiveSupport::OrderedOptions.new
|
6
6
|
|
7
|
+
config.autoload_once_paths = %W(
|
8
|
+
#{root}/app/controllers
|
9
|
+
#{root}/app/controllers/concerns
|
10
|
+
#{root}/app/helpers
|
11
|
+
#{root}/app/models
|
12
|
+
#{root}/app/models/concerns
|
13
|
+
)
|
14
|
+
|
7
15
|
# If you don't want to precompile Coupdoeil's assets (eg. because you're using webpack),
|
8
16
|
# you can do this in an intiailzer:
|
9
17
|
#
|
data/lib/coupdoeil/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coupdoeil
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.alpha.
|
4
|
+
version: 1.0.0.pre.alpha.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PageHey
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-05-
|
10
|
+
date: 2025-05-11 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rails
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- app/javascript/coupdoeil/hovercard/closing.js
|
70
70
|
- app/javascript/coupdoeil/hovercard/config.js
|
71
71
|
- app/javascript/coupdoeil/hovercard/controller.js
|
72
|
+
- app/javascript/coupdoeil/hovercard/current.js
|
72
73
|
- app/javascript/coupdoeil/hovercard/opening.js
|
73
74
|
- app/javascript/coupdoeil/hovercard/optionsParser.js
|
74
75
|
- app/javascript/coupdoeil/hovercard/positioning.js
|