Begint JS voor zichzelf?
Vooral waarom de ene keer als ik op een input veld klik de popup onder dat veld verschijnt en de andere keer niet. Het lijkt erop dat JS voor zichzelf begint en dat zou heel bijzonder zijn.
In het attach label laadt JS twee keer een input veld.
Dat heb ik JS verteld, dus dat doet ie dan ook braaf.
JS laadt twee objecten, voor elk input veld een, in het array instances.
Met het statement 'let inst = tp.instances[id]', krijgt 'inst' het laatst geladen object.
'inst.target.addEventListener('click', () => { tp.show(inst) })' is een klik op het laatst geladen object en dat krijg ik dan ook te zien. Niks bijzonders precies zoals ik dat verwacht.
Wat ik niet begrijp is dat een klik op het eerst geladen object soms(!) ook werkt.
Hoe kan JS weten dat ik op dat input veld heb geklikt?
Magic, of doet JS soms gewoon wat hij wil?
Of, en dat is waarschijnlijker, begrijp ik gewoon niet wat er gebeurd.
Kan, wil iemand hier wat licht over laten schijnen?
Als het helpt, maak ik even een fiddleltje.
HTML
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>
<head>
<title>Javascript Test Popup</title>
<!-- (A) LOAD CSS & JS -->
<link href="test-popup.css" rel="stylesheet">
<script src="test-popup.js"></script>
</head>
<style>
.test-popup-wrapper {width: 700px;display: flex;justify-content: space-evenly;}
.test-popup {position:relative;top: 170px;left: 180px;}
#popup-one:focus {background-color: coral;}
#popup-two:focus {background-color:chartreuse;}
.test-input {height: 60px;border: 2px solid red;}
.test-input input[type=text] {font-size: 3.0em;;}
</style>
<body>
<!-- (B) HTML FIELD -->
<div class="test-popup-wrapper">
<div class="test-popup">
<label for="popup-one">Popup one:</label>
<input class="test-input" type="text" id="popup-one"/>
</div>
<div class="test-popup">
<label for="popup-two">Popup two:</label>
<input class="test-input" type="text" id="popup-two"/>
</div>
</div>
<!-- (C) ATTACH -->
<script>
tp.attach({ target: document.getElementById("popup-one")});
tp.attach({ target: document.getElementById("popup-two")});
</script>
</body>
</html>
<html>
<head>
<title>Javascript Test Popup</title>
<!-- (A) LOAD CSS & JS -->
<link href="test-popup.css" rel="stylesheet">
<script src="test-popup.js"></script>
</head>
<style>
.test-popup-wrapper {width: 700px;display: flex;justify-content: space-evenly;}
.test-popup {position:relative;top: 170px;left: 180px;}
#popup-one:focus {background-color: coral;}
#popup-two:focus {background-color:chartreuse;}
.test-input {height: 60px;border: 2px solid red;}
.test-input input[type=text] {font-size: 3.0em;;}
</style>
<body>
<!-- (B) HTML FIELD -->
<div class="test-popup-wrapper">
<div class="test-popup">
<label for="popup-one">Popup one:</label>
<input class="test-input" type="text" id="popup-one"/>
</div>
<div class="test-popup">
<label for="popup-two">Popup two:</label>
<input class="test-input" type="text" id="popup-two"/>
</div>
</div>
<!-- (C) ATTACH -->
<script>
tp.attach({ target: document.getElementById("popup-one")});
tp.attach({ target: document.getElementById("popup-two")});
</script>
</body>
</html>
JS
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
let tp = {
init: () => {
tp.tPop = document.createElement('div')
tp.tPop.classList.add('popup-wrapper')
document.body.appendChild(tp.tPop)
// ADD TEST POPUP INNERHTML
tp.tPop.innerHTML =
`
<h1>Here we can do all kinds of stuff.</h1>
<br>
<button id="tp-set" onclick="tp.set()">Kies</button>
`
}, // init: ------------------------------
instances: [],
attach: (opt) => {
console.log("opt: ", opt)
// output:
// Object
// bottom: 282
// left: 548
// sPos: "top: 282px; left: 199px;"
// target: <input id="popup-one"></input>
// and again for <input id="popup-two"></input>
opt.target.readOnly = true;
opt.target.setAttribute("autocomplete", "off")
const targetElem = opt.target.getBoundingClientRect()
opt.target.left = Math.floor(targetElem.x)
opt.target.bottom = Math.floor(targetElem.bottom)
console.log("opt.target: ", opt.target)
// attach is executed twice; for each call on attach.
// output:
// <input class="test-input" type="text" id="popup-one" readonly autocomplete="off">
// <input class="test-input" type="text" id="popup-two" readonly autocomplete="off">
let id = tp.instances.length
// HERE WE PUSH THE OPT OBJECTS TO INSTANCES ARRAY
tp.instances.push(opt)
// WHEN WE HAVE TWO INPUT FIELDS, INST CONTAINS THOSE
// TWO OBJECTS.
// 'ID' POINTS TO THE LAST OBJECT LOADED.
let inst = tp.instances[id]
// GET LEFT & BOTTOM POSITION OF THIS INSTANCE
inst.left = opt.target.left + 10
inst.bottom = opt.target.bottom + 10
tPos = 'top: ' + inst.bottom + 'px;'
lPos = 'left: ' + inst.left + 'px;'
inst.sPos = tPos + ' ' + lPos
// ON CLICK ON THIS INSTANCES TARGET FIELD, SHOW POPUP
inst.target.addEventListener('click', () => { tp.show(inst) })
}, // attach: ------------------------------------
show: (inst) => {
// POSITION THIS INSTANCES TARGET FIELD
tp.tPop.setAttribute('style', inst.sPos)
tp.tPop.classList.add('show')
}, // show: ---------------------------------------
// SET SELECTED STUFF AND CLOSE POPUP
set: () => {
tp.tPop.classList.remove('show')
},
} // tp ---------------------------------------------
document.addEventListener("DOMContentLoaded", tp.init)
init: () => {
tp.tPop = document.createElement('div')
tp.tPop.classList.add('popup-wrapper')
document.body.appendChild(tp.tPop)
// ADD TEST POPUP INNERHTML
tp.tPop.innerHTML =
`
<h1>Here we can do all kinds of stuff.</h1>
<br>
<button id="tp-set" onclick="tp.set()">Kies</button>
`
}, // init: ------------------------------
instances: [],
attach: (opt) => {
console.log("opt: ", opt)
// output:
// Object
// bottom: 282
// left: 548
// sPos: "top: 282px; left: 199px;"
// target: <input id="popup-one"></input>
// and again for <input id="popup-two"></input>
opt.target.readOnly = true;
opt.target.setAttribute("autocomplete", "off")
const targetElem = opt.target.getBoundingClientRect()
opt.target.left = Math.floor(targetElem.x)
opt.target.bottom = Math.floor(targetElem.bottom)
console.log("opt.target: ", opt.target)
// attach is executed twice; for each call on attach.
// output:
// <input class="test-input" type="text" id="popup-one" readonly autocomplete="off">
// <input class="test-input" type="text" id="popup-two" readonly autocomplete="off">
let id = tp.instances.length
// HERE WE PUSH THE OPT OBJECTS TO INSTANCES ARRAY
tp.instances.push(opt)
// WHEN WE HAVE TWO INPUT FIELDS, INST CONTAINS THOSE
// TWO OBJECTS.
// 'ID' POINTS TO THE LAST OBJECT LOADED.
let inst = tp.instances[id]
// GET LEFT & BOTTOM POSITION OF THIS INSTANCE
inst.left = opt.target.left + 10
inst.bottom = opt.target.bottom + 10
tPos = 'top: ' + inst.bottom + 'px;'
lPos = 'left: ' + inst.left + 'px;'
inst.sPos = tPos + ' ' + lPos
// ON CLICK ON THIS INSTANCES TARGET FIELD, SHOW POPUP
inst.target.addEventListener('click', () => { tp.show(inst) })
}, // attach: ------------------------------------
show: (inst) => {
// POSITION THIS INSTANCES TARGET FIELD
tp.tPop.setAttribute('style', inst.sPos)
tp.tPop.classList.add('show')
}, // show: ---------------------------------------
// SET SELECTED STUFF AND CLOSE POPUP
set: () => {
tp.tPop.classList.remove('show')
},
} // tp ---------------------------------------------
document.addEventListener("DOMContentLoaded", tp.init)
Ik heb even deze css verzonnen voor de test:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
body {
font: 16px Verdana;
}
.popup-wrapper {
position: absolute;
display: none;
border: 3px solid orange;
}
.popup-wrapper.show {
display: block;
}
font: 16px Verdana;
}
.popup-wrapper {
position: absolute;
display: none;
border: 3px solid orange;
}
.popup-wrapper.show {
display: block;
}
Gewijzigd op 23/09/2022 20:58:18 door Jan Koehoorn
Inmiddels heb ik een test versie die goed werkt; EN die de dubbele verwerking voorkomt.
HTML
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>
<head>
<title>Javascript Test Popup</title>
<!-- (A) LOAD CSS & JS -->
<link href="test-popup.css" rel="stylesheet">
<script src="test-popup.js"></script>
</head>
<style>
.test-popup-wrapper {width: 700px;display: flex;justify-content: space-evenly;}
.test-popup {position:relative;top: 170px;left: 180px;}
#popup-one:focus {background-color: coral;}
#popup-two:focus {background-color:chartreuse;}
.test-input {height: 60px;border: 2px solid red;}
.test-input input[type=text] {font-size: 3.0em;;}
</style>
<body>
<!-- (B) HTML FIELD -->
<div class="test-popup-wrapper">
<div class="test-popup">
<label for="popup-one">Popup one:</label>
<input class="test-input" type="text" id="popup-one" onfocus="pOne(this)"/>
</div>
<div class="test-popup">
<label for="popup-two">Popup two:</label>
<input class="test-input" type="text" id="popup-two" onfocus="pTwo(this)"/>
</div>
</div>
<!-- (C) ATTACH -->
<script>
pOne = (x) => {tp.attach({ target: document.getElementById("popup-one")})}
pTwo = (x) => {tp.attach({ target: document.getElementById("popup-two")})}
</script>
</body>
</html>
<html>
<head>
<title>Javascript Test Popup</title>
<!-- (A) LOAD CSS & JS -->
<link href="test-popup.css" rel="stylesheet">
<script src="test-popup.js"></script>
</head>
<style>
.test-popup-wrapper {width: 700px;display: flex;justify-content: space-evenly;}
.test-popup {position:relative;top: 170px;left: 180px;}
#popup-one:focus {background-color: coral;}
#popup-two:focus {background-color:chartreuse;}
.test-input {height: 60px;border: 2px solid red;}
.test-input input[type=text] {font-size: 3.0em;;}
</style>
<body>
<!-- (B) HTML FIELD -->
<div class="test-popup-wrapper">
<div class="test-popup">
<label for="popup-one">Popup one:</label>
<input class="test-input" type="text" id="popup-one" onfocus="pOne(this)"/>
</div>
<div class="test-popup">
<label for="popup-two">Popup two:</label>
<input class="test-input" type="text" id="popup-two" onfocus="pTwo(this)"/>
</div>
</div>
<!-- (C) ATTACH -->
<script>
pOne = (x) => {tp.attach({ target: document.getElementById("popup-one")})}
pTwo = (x) => {tp.attach({ target: document.getElementById("popup-two")})}
</script>
</body>
</html>
JAVASCRIPT
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
let tp = {
init: () => {
tp.tPop = document.createElement('div')
tp.tPop.classList.add('popup-wrapper')
document.body.appendChild(tp.tPop)
// ADD TEST POPUP INNERHTML
tp.tPop.innerHTML =
`
<h1>Here we can do all kinds of stuff.</h1>
<br>
<button id="tp-set" onclick="tp.set()">Kies</button>
`
}, // init: ------------------------------
attach: (opt) => {
// ADD ATTRIBUTES TO THE INPUT ELEMENT: WHY?
opt.target.readOnly = true;
opt.target.setAttribute("autocomplete", "off")
// // GET INPUT FIELDS BOUNDING RECT
const inputFieldRect = opt.target.getBoundingClientRect()
// // SET SCREEN POSITION OF POPUP
popLeft = Math.floor(inputFieldRect.x) + 20
popTop = Math.floor(inputFieldRect.bottom) + 20
// LEFT & TOP POSITION FOR THE POPUP ASSOCIATED WITH
// CLICKED INPUT FIELD OBJECT
tOne = 'top: ' + popTop + 'px;'
lOne = 'left: ' + popLeft + 'px;'
popup = {
target: opt.target,
scrPos: tOne + ' ' + lOne,
}
// A CLICK ON THE TARGETED INPUT FIELD, TRIGGERS SHOW POPUP.
popup.target.addEventListener('click', (e) => {
tp.show(popup)
})
}, // attach: ------------------------------------
show: (popup) => {
// FORCE THE SCREEN POSITION OF THE POPUP. WE ONLY
// CHANGE THE SCREEN POSITION OF TP.TPOP DEPENDING ON
// THE POSITION OF THE INPUT FIELD CLICKED.
tp.tPop.setAttribute('style', popup.scrPos)
tp.tPop.classList.add('show')
}, // show: ---------------------------------------
// SET SELECTED STUFF AND CLOSE POPUP
set: () => {
tp.tPop.classList.remove('show')
},
} // tp ---------------------------------------------
document.addEventListener("DOMContentLoaded", tp.init)
init: () => {
tp.tPop = document.createElement('div')
tp.tPop.classList.add('popup-wrapper')
document.body.appendChild(tp.tPop)
// ADD TEST POPUP INNERHTML
tp.tPop.innerHTML =
`
<h1>Here we can do all kinds of stuff.</h1>
<br>
<button id="tp-set" onclick="tp.set()">Kies</button>
`
}, // init: ------------------------------
attach: (opt) => {
// ADD ATTRIBUTES TO THE INPUT ELEMENT: WHY?
opt.target.readOnly = true;
opt.target.setAttribute("autocomplete", "off")
// // GET INPUT FIELDS BOUNDING RECT
const inputFieldRect = opt.target.getBoundingClientRect()
// // SET SCREEN POSITION OF POPUP
popLeft = Math.floor(inputFieldRect.x) + 20
popTop = Math.floor(inputFieldRect.bottom) + 20
// LEFT & TOP POSITION FOR THE POPUP ASSOCIATED WITH
// CLICKED INPUT FIELD OBJECT
tOne = 'top: ' + popTop + 'px;'
lOne = 'left: ' + popLeft + 'px;'
popup = {
target: opt.target,
scrPos: tOne + ' ' + lOne,
}
// A CLICK ON THE TARGETED INPUT FIELD, TRIGGERS SHOW POPUP.
popup.target.addEventListener('click', (e) => {
tp.show(popup)
})
}, // attach: ------------------------------------
show: (popup) => {
// FORCE THE SCREEN POSITION OF THE POPUP. WE ONLY
// CHANGE THE SCREEN POSITION OF TP.TPOP DEPENDING ON
// THE POSITION OF THE INPUT FIELD CLICKED.
tp.tPop.setAttribute('style', popup.scrPos)
tp.tPop.classList.add('show')
}, // show: ---------------------------------------
// SET SELECTED STUFF AND CLOSE POPUP
set: () => {
tp.tPop.classList.remove('show')
},
} // tp ---------------------------------------------
document.addEventListener("DOMContentLoaded", tp.init)
Dit was lastig om het uit te pluizen, maar zeer leerzaam.
.