• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Podpinanie jednej funkcji z argumentem pod addEventListener

0 głosów
238 wizyt
pytanie zadane 20 lipca 2017 w JavaScript, jQuery, AJAX przez plkpiotr Stary wyjadacz (12,520 p.)
edycja 20 lipca 2017 przez plkpiotr

Piszę stronę z formularzem rejestracji w HTML/PHP. Chciałbym, aby po kliknięciu na kolejne elementy formularza (input-text, input-password, date, select) pojawiała się poniżej każdego z nich informacja jak poprawnie wypełnić to pole...

Chciałbym zapytać, czy istnieje możliwość podpięcia jednej funkcji (wyświetlającej podpowiedź) z argumentem, będącym liczbą/obiektem, coś na wzór mojej funkcji, czy może każdy element formularza trzeba podpiąć do odpowiadającej mu funkcji?

Niedziałający skrypt:

var allFormElements = document.querySelectorAll('.field');

var allInformation = document.querySelectorAll('.info');
len = allInformation.length;
for (var i = 0 ; i < len; i++)
    allInformation[i].innerHTML = "&#8203;";

function displayInfo(number) {
    switch(number) {
        case 0:
            allInformation[0].innerHTML = "tip first";
            break;
        case 1:
            allInformation[1].innerHTML = "info first";
            break;
        case 2:
            allInformation[2].innerHTML = "next info";
            break;
        case 3:
            allInformation[3].innerHTML = "next tip";
            break;
        case 4:
            allInformation[4].innerHTML = "next tip";
            break;
        case 5:
            allInformation[5].innerHTML = "next tip";
            break;
        case 6:
            allInformation[6].innerHTML = "next tip";
            break;
        case 7:
            allInformation[7].innerHTML = "next tip";
            break;
        case 8:
            allInformation[8].innerHTML = "next tip";
            break;
    }
}

allFormElements[0].addEventListener('click', displayInfo(0));
allFormElements[1].addEventListener('click', displayInfo(1));
allFormElements[2].addEventListener('click', displayInfo(2));
allFormElements[3].addEventListener('click', displayInfo(3));
allFormElements[4].addEventListener('click', displayInfo(4));
allFormElements[5].addEventListener('click', displayInfo(5));
allFormElements[6].addEventListener('click', displayInfo(6));
allFormElements[7].addEventListener('click', displayInfo(7));

Struktura strony:

<!DOCTYPE HTML>
<html lang="en-GB">
<head>
    <meta charset="utf-8">
    <meta name="description" content="Registration form web application's for group of squash players">
    <meta name="keywords" content="squash, team, games, matches, players, society, app, registration, sign, in">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Join | Squash Court</title>
    <link rel="icon" href="img/ball.png">
    <link rel="stylesheet" href="css/style.css">
    <link href="https://fonts.googleapis.com/css?family=Titillium+Web:400,700&amp;subset=latin-ext" rel="stylesheet">
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
          integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
    <script src="js/jquery-3.2.1.min.js"></script>
    <script src="js/samePositionBackAndReload.js"></script>
</head>
<body>
    <header>
        <div class="bar">
            <a href="get-to-know-squash-court-better">Home</a>
        </div>
    </header>
    <main>
        <div class="container">
            <header>
                <h1>
                    Join
                </h1>
            </header>
            <article>
                <form method="post">
                    <input type="text" name="name" placeholder="name" id="cursor" class="field">
                    <div class="info"></div>
                    <input type="text" name="surname" placeholder="surname" class="field">
                    <div class="info"></div>
                    <input type="text" name="nick" placeholder="nick" class="field">
                    <div class="info"></div>
                    <input type="password" name="password_first" placeholder="password" class="field">
                    <div class="info"></div>
                    <input type="password" name="password_second" placeholder="confirm password" class="field">
                    <div class="info"></div>
                    <input type="text" name="team" placeholder="team" class="field">
                    <div class="info"></div>
                    <input type="text" name="birthday" min="1901-01-01" max="2013-12-31" placeholder="birth"
                           onfocus="(this.type='date')" class="field">
<!--                    change in js-->
                    <div class="info"></div>
                    <select name="sex" class="field">
                        <option value="" disabled selected>woman/men</option>
                        <option value="woman">woman</option>
                        <option value="man">man</option>
                    </select>
                    <div class="info"></div>

                </form>
            </article>
        </div>
    </main>
    <script src="js/setInfoOnJoinPage.js"></script>
    <aside>
        <div class="socials">
            <span class="tile1">
                <a href="https://github.com/plkpiotr">
                    <i class="fa fa-github-alt" aria-hidden="true"></i>
                </a>
            </span>
            <span class="tile2">
                <a href="https://forum.pasja-informatyki.pl/user/Za%C4%87wilichowski">
                    <i class="fa fa-code" aria-hidden="true"></i>
                </a>
            </span>
            <span class="tile1">
                <a href="https://plus.google.com/u/0/100065018101140624093">
                    <i class="fa fa-google" aria-hidden="true"></i>
                </a>
            </span>
        </div>
    </aside>
    <footer>
        <p class="signature">All rights reserved &nbsp;|&nbsp; SquashCourt &nbsp;|&nbsp; 07/2017</p>
    </footer>
</body>

 

1 odpowiedź

+2 głosów
odpowiedź 20 lipca 2017 przez JSHolic Szeryf (78,620 p.)
wybrane 21 lipca 2017 przez plkpiotr
 
Najlepsza
allFormElements[0].addEventListener('click', displayInfo(0));

Jako drugi parametr powinieneś przekazać referencję do funkcji, która zostanie dopiero wywołana z przekazaniem jej jako parametr obiekt zdarzenia.

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

target.addEventListener(type, listener[, options]);

listener

    The object which receives a notification (an object that implements the Event interface) when an           event of the specified type occurs. This must be an object implementing the EventListenerinterface,     or a JavaScript function.

Jeśli chcesz przekazać własne parametry, to przekaż funkcję anonimową, w której dopiero wywołasz swoją funkcję:

element.addEventListener( 'click', function() {
    myFunction( parameter );
} );

Sposób, w który przekazałeś drugi parametr zadziałałby, gdyby wywołana funkcja zwracała jakąś funkcję - wtedy ona została by wywołana jako callback i do niej trafiłby obiekt zdarzenia, przykład:

function getEventHandler( dummyArg ) {
    return function( event ) {
       /** ta funkcja zostanie wywołana przez EventListener */
    }
}

element.addEventListener( 'click', getEventHandler( 'dummyParameter' ) );

Funkcje w JavaScript to obiekty, których kod możesz wywołać (nazywają się konkretnie First Class Function) - do tego służą dwa okrągłe nawiasy na końcu, często z przekazaniem tam parametrów. Jako, że są to obiekty, możesz je po prostu przekazać jako parametr - co spowoduje że będą one mogły zostać wywołane ze środka jako callback. Jeśli przekazujesz funkcję, którą od razy wywołujesz, to de facto przekazujesz wynik wykonania danej funkcji.

Całość natomiast, żeby się nie powtarzać 8 razy - umieść w pętli albo zastosuj event delegation - podłączasz EventListener na wspólnym rodzicu wszystkim pól formularza i tam za pośrednictwem event.target wykrywasz, w które pole kliknąłeś i co ma się dziać.

1
komentarz 20 lipca 2017 przez JSHolic Szeryf (78,620 p.)
edycja 20 lipca 2017 przez JSHolic

Przykład, dlaczego funkcje są obiektami - możesz im przypisywać normalnie propertisy, jak zwykłym obiektom:

function foo( arg ) {
    console.log('foo invoked');
}
foo.prop = 'Test prop';

console.log(foo);
foo();

/** Rezultat wyswietlenia funkcji w konsoli i wywolania jej kodu */
//
//  function foo( arg )
//  prop: "Test prop"
//  arguments: null
//  caller: null
//  length: 1
//  name: "foo"
//  prototype: Object
//  __proto__: function ()
//  [[FunctionLocation]]: VM2236:1
//  [[Scopes]]: Scopes[1]
//    
//  foo invoked

Użycie console.dir() wyświetla zmienne w postaci obiektów (można zobaczyć ich propertisy, co console.log nie zawsze robi).

komentarz 21 lipca 2017 przez plkpiotr Stary wyjadacz (12,520 p.)
edycja 21 lipca 2017 przez plkpiotr

Dziękuję za pomoc! Wszystko wyjaśnione na różne sposoby i w dodatku z przykładami - bardzo pomocne dla kogoś kto dopiero raczkuje w JS.
Kod po refaktoryzacji i zastosowaniu porad wygląda znacznie lepiej:

var fields = document.querySelectorAll('.field');

var information = document.querySelectorAll('.info');
len = information.length;
for (var i = 0 ; i < len; i++) {
    information[i].innerHTML = "&#8203;";
    fields[i].addEventListener('focus', getEventHandler(i));
}

function getEventHandler(number) {
    return function(event) {
        switch(number) {
            case 0:
                information[0].innerHTML = "Name should have from 3 to 15 characters";
                break;
            case 1:
                information[1].innerHTML = "Surname should have from 3 to 20 characters";
                break;
            case 2:
                information[2].innerHTML = "Nick should have from 6 to 10 characters";
                break;
            case 3:
                information[3].innerHTML = "Password should from 6 to 15 characters";
                break;
            case 4:
                information[4].innerHTML = "Confirm your password, please...";
                break;
            case 5:
                information[5].innerHTML = "Enter name of team to meet your friends (from 6 to 20 characters)";
                break;
            case 6:
                information[6].innerHTML = "Enter your date of birth and ";
                break;
            // other options later...
        }
    }
}

 

1
komentarz 21 lipca 2017 przez JSHolic Szeryf (78,620 p.)

Spróbuj jeszcze przerobić kod, aby wykorzystać Event Delegation.

Dodatkowo - poczytaj czym są domknięcia, ponieważ skorzystałeś w switch z parametru number, który został "zapamiętany" przez zwróconą funkcję anonimową przyjmującą event. Warto wiedzieć, dlaczego kod działa tak a nie inaczej, aby wraz z nabywanym doświadczeniem, bardziej świadomie go pisać.

Podobne pytania

0 głosów
3 odpowiedzi 98 wizyt
pytanie zadane 25 marca 2018 w PHP, Symfony, Zend przez Mebya Użytkownik (700 p.)
0 głosów
2 odpowiedzi 89 wizyt
0 głosów
1 odpowiedź 51 wizyt
Porady nie od parady
Forum posiada swój własny chat IRC, dzięki któremu będziesz mógł po prostu pogadać z innymi Pasjonatami lub zapytać o jakiś problem. Podstrona z chatem znajduje się w menu pod ikoną człowieka w dymku.IRC

64,846 zapytań

111,307 odpowiedzi

234,118 komentarzy

46,718 pasjonatów

Przeglądających: 181
Pasjonatów: 9 Gości: 172

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...