Begint JS voor zichzelf?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Jan Kila

Jan Kila

23/09/2022 14:14:34
Quote Anchor link
Kan, wil iemand mij vertellen hoe dit werkt?
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)
PHP script in nieuw venster Selecteer het PHP script
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
<!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>


JS
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
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)
 
PHP hulp

PHP hulp

05/10/2022 00:25:47
 
Jan Koehoorn

Jan Koehoorn

23/09/2022 20:54:44
Quote Anchor link
Niks aan het handje hier. Werkt prima.

Ik heb even deze css verzonnen voor de test:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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;
}
Gewijzigd op 23/09/2022 20:58:18 door Jan Koehoorn
 
Jan Kila

Jan Kila

27/09/2022 13:09:41
Quote Anchor link
Dank Jan.
Inmiddels heb ik een test versie die goed werkt; EN die de dubbele verwerking voorkomt.
HTML
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<!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>

JAVASCRIPT
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
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)

Dit was lastig om het uit te pluizen, maar zeer leerzaam.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.