Przypsianie kilku zmiennym wartości z tablicy
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
Mój błąd. Niepotrzebny jest wpis w sessionStorage o kluczu selected, ponieważ kod powinien inaczej działać, niż myślałem. Powinien działać tak, że za każdym odświeżeniem strony powinno wyświetlać się to samo pytanie. Nic więcej, nic mniej. W związku z tym potrzebny jest jedynie jeden wpis w sessionStorage, czyli lastQuestionIndex. Żeby to osiągnąć, dwie rzeczy:
(1) Handler zdarzenia click przycisku "Wyślij" powinien tak wyglądać:
btnSubmit.addEventListener('click', function() {
if (validateIfChecked() === true) {
sessionStorage.removeItem('lastQuestionIndex');
for (let i = 0; i < input.length; i++) {
input[i].checked = false;
}
showRandomQuestion();
} else {
alert('Zaznacz coś');
}
});
(2) Cały kod z if-em na początku funkcji showRandomQuestion powinien tak wyglądać (czyli usuwasz ten if, co jest, i wstawiasz ten kod):
if (sessionStorage.getItem('lastQuestionIndex') === null) {
displayQuestQizIndex = getRandomQuestion();
sessionStorage.setItem('lastQuestionIndex', displayQuestQizIndex);
} else {
displayQuestQizIndex = sessionStorage.getItem('lastQuestionIndex');
}
U mnie wydaje się działać. Jeśli czegoś nie rozumiesz, pytaj. Zachęcam Cię, byś próbował zrozumieć działanie całego kodu, który ja Ci daję. Jak widać, też mogę popełniać błędy, więc będziesz mieć przynajmniej szansę je wyłapać sam.
PS Atrybut autocomplete w kodzie HTML wydaje się nie działać w zamierzony sposób – najlepiej go usunąć.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
A gdybym chciał zrobić podobny myk z pytaniami żeby po odświeżeniu strony nie zmieniała się kolejność pytań to rozumiem że muszę zastosować podobny kod?
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
Kod powinien być podobny, tak. Trzeba by najprawdopodobniej:
- zapisywać tablicę z indeksami opowiedzi w
sessionStoragewtedy, gdy wpislastQuestionIndexwsessionStoragema wartośćnull; - odczytywać ją (tzn. przypisywać ją zmiennej
variants) wtedy, gdy wpislastQuestionIndexwsessionStoragenie ma wartościnull.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Napisałem ten kod ale dostaje coś takiego https://jsfiddle.net/14nxbL7s/
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
Ciężko pomóc tutaj bez dawania kodu, ale spróbuję. W funkcji showRandomQuestion:
(1) Wynik funkcji getRandomVariants powinnien być przypisywany do zmiennej variants wyłącznie wtedy, kiedy wpis lastQuestIndex ma wartość null. Natomiast u Ciebie dzieje się to zawsze, niezależnie jaką wartość ma ten wpis (linia let variants = getRandomVariants(displayQuestQizIndex);).
(2) Na wartość answersIndices powinieneś ustawiać nowy, oddzielny wpis lastAnswersIndices (taka nazwa jest najlepsza moim zdaniem). Natomiast Ty ustawiasz na nią wpis lastQuestIndex, przez co nadpisujesz go, a nie powinieneś (linia sessionStorage.setItem('lastQuestIndex', answersIndices);). Podobnie z pobieraniem: powinieneś pobierać wartość tego nowego wpisu, a nie wpisu lastQuestIndex (linia variants = sessionStorage.getItem('lastQuestIndex');).
(3) To nie błąd, ale rzecz utrudniająca kod: niepotrzebnie dodałeś drugą instrukcję if. Już jest jedna wyżej, można ją wykorzystać (zwróć uwagę, że warunki w obu tych instrukcjach są takie same).
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Teraz pojawia się pętla nieskończona https://jsfiddle.net/zb231to0/
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
Nie widzę pętli nieskończonej. O czym dokładnie mówisz?
Natomiast kod tak czy siak jest nie do końca dobry. W drugiej instrukcji if w warunku jest sprawdzenie, czy wpis lastAnswersIndices ma wartość null, a powinno być sprawdzenie, czy wpis lastQuestIndex ma wartość null. (To różnica, ponieważ, zauważ, wpis lastQuestIndex jest usuwany w handlerze kliknięcia na przycisk Submit, a wpis lastAnswersIndices nie jest).
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Ok nie ma już tej pętli nieskończonej. Teraz jest to https://jsfiddle.net/8vdeajtr/2/
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
- Wcześniej pisałem, że obie instrukcje
ifmogłyby być razem, ale teraz zmienię zdanie i napiszę, że muszą być razem (czyli musi być tylko jedna instrukcjaif, w której będzie kod obu instrukcji). Inaczej w pierwszej instrukcji, tak jak teraz jest, będzie zmieniać się kod, który jest sprawdzany w warunku drugiej instrukcji, a to niepoprawnie (błąd w logice kodu). - Całkiem zapomniałem, że wartości kluczy
sessionStoresą konwertowane do typustringprzed zapisaniem. A w przypadku odczytu wartości zmiennejlastAnswersIndicespotrzebna nam jest tablica, a nie ciąg znaków. W związku z tym trzeba zrobić dwie rzeczy:
2.1. teraz wartość zmiennejlastAnswersIndicesjest zapisywana bezpośrednio dosessionStorage; natomiast powinna być konwertowana przed tym zapisem do ciągu znaków za pomocą metodyJSON.stringify;
2.2. teraz wartość wpisulastAnswersIndicesjest przypisywana bezpośrednio do zmiennejvariants; natomiast powinna być przed tym przypisaniem parsowana za pomocą metodyJSON.parse.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
- Nadal są dwie instrukcje
if. - Metoda
JSON.stringifyjest użyta w dobrym miejscu, ale metodaJSON.parsejuż nie. Ta ostatnia powinna być umieszczona po pobraniu wartości zsessionStorage, a teraz jest umieszczona przed tym. - To nie błąd, ale dobrze byłoby inicjalizować zmienną
variantspustą tablicą w momencie deklaracji.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Napisałeś wcześniej że '''obie instrukcje if mogłyby być razem, ale teraz zmienię zdanie i napiszę, że muszą być razem (czyli musi być tylko jedna instrukcja if, w której będzie kod obu instrukcji)''' no to jest jedna:
let variants = [];
if (sessionStorage.getItem('lastQuestIndex') === null) {
variants = getRandomVariants(displayQuestQizIndex);
variants = sessionStorage.getItem(JSON.parse('lastAnswersIndices'));
sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
}
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Chodzi o coś takiego?
if (condition) {
if (sessionStorage.getItem('lastQuestIndex') === null) {
variants = getRandomVariants(displayQuestQizIndex);
variants = sessionStorage.getItem(JSON.parse('lastAnswersIndices'));
sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
}
}
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
W sumie nie zauważyłem wcześniej, że usunąłeś blok else. Nie, nie chodzi o usunięcie bloku else. Pisząc, że powinna być jednak instrukcja if, miałem na myśli, że w jednej instrukcji powinny być ustawiane zarówno zmienna displayQuestQizIndex, jak i zmienna variants; natomiast w kodzie pod linkiem do JSFiddle, który zamieściłeś ostatnio, są dwie instrukcje if. I w tej jednej instrukcji if nadal powinien być blok else (w którym będą pobierane wartości kluczów wpisów lastQuestIndex oraz lastAnswersIndices).
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
O to chodzi?
let variants = [];
if (sessionStorage.getItem('lastQuestIndex') === null) {
sessionStorage.setItem('lastQuestIndex', variants);
sessionStorage.setItem('lastQuestIndex', displayQuestQizIndex);
} else {
variants = sessionStorage.getItem(JSON.parse('lastQuestIndex'));
sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
}
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
Może wyjaśnię bliżej, o co mi chodziło, gdy napisałem, że "powinny być ustawiane zmienne".
- Przez "ustawienie zmiennej" rozumiem każdą z następujących instrukcji:
zmienna = coś; // Ustawienie zmiennej
var zmienna = coś; // Również ustawienie zmiennej
let zmienna = coś; // Również ustawienie zmiennej
- Przez "ustawienie stałej" rozumiem następującą instrukcję:
const zmienna = coś; // Ustawienie stałej
Mała uwaga: może byłem wcześniej nieprecyzyjny. Zgodnie z dokumentacją MDN -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const instrukcja zawierająca słowo kluczowe const jest "stałą", a nie "zmienną" (jak mogłem wcześniej nieprecyzyjnie pisać).
Ponadto:
- My korzystamy z właściwości
sessionStorageobiektuWindow(piszesz samosessionStorage, ale mógłbyśWindow.sessionStorage). Ona daje nam dostęp do tzw. obiektuStorage. Zgodnie z dokumentacją MDN -> https://developer.mozilla.org/en-US/docs/Web/API/Storage interfejsStorageprzechowuje pary klucz-wartość. (Nie pytaj mnie, czemu razStoragenazywany jest "obiektem", a kiedy indziej "interfejsem"; nie wiem; @szatkus , @LukeJL , @Freja Draco , wiecie?).
Ja nazywam poszczególne elementy obiektu Storage "wpisami"; trochę odmiennie od dokumentacji MDN, przyznam. Robię tak na podobieństwo terminologii używanej w przypadku typu Object, gdzie jest np. metoda entries() obiektu Object (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries). "Entry" tłumaczę jako "wpis". W interfejsach webowych te moje "wpisy" nazywane są "items"; dlatego też wywoływane w naszym kodzie metody getItem i setItem właśnie tak się nazywają. "Item" może być tłumaczone jako "element".
Ale teraz myślę, że terminologia, której używam, jest cokolwiek niepoprawna: jak teraz zauważyłem, "entry" może być tłumaczone jako "hasło". Poniżej będę już pisać "hasło" zamiast "wpis".
W związku z tym wszystkim, co powyżej:
-
W bloku
ifinstrukcjiifpowinny być zawarte następujące instrukcje:
4.1. przypisanie zmiennejdisplayQuestQizIndexlosowego indeksu pytania, używając funkcjigetRandomQuestion;
4.2. przypisanie zmiennejvariantstablicy z indeksami odpowiedzi pytania o wylosowanym indeksie, używając funkcjigetRandomVariants;
4.3. ustawienie wartości hasłalastQuestIndexobiektusessionStoragena wylosowany indeks;
4.4. ustawienie wartości hasłalastAnswersIndicesobiektusessionStoragena tablicę z indeksami odpowiedzi pytania o wylosowanym indeksie, używając metodystringifyobiektuJSON. -
W bloku
elseinstrukcjiifpowinny być zawarte następujące instrukcje:
5.1. przypisanie zmiennejdisplayQuestQizIndexwartości hasłalastQuestIndexobiektusessionStorage;
5.2. przypisanie zmiennejvariantswartości hasłalastAnswersIndicesobiektusessionStorage, używając metodyparseobiektuJSON.
(No, mam nadzieję, że nigdzie nie zrobiłem błędu).
PS Jak gdzieś widzisz w moich postach jakąś nieścisłość, czy wyraźny błąd, od razu mi pisz, zachęcam. Chciałbym najlepiej Ci pomagać, ale czasem popełnię jakąś literówkę czy błąd logiczny.
- Rejestracja: dni
- Ostatnio: dni
Ten kod nie przeszedłby review w żadnej poważnej firmie.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Coś nie działa https://jsfiddle.net/4edrnj2t/. Możesz sprawdzić czy wszystko napisałem zgodnie z twoimi wytycznymi?
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
- Nadal są dwie instrukcje
if. Powinna być jedna. - Metoda
JSON.parsenadal parsuje nie to, co powinna.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Teraz to wygląda tak
let displayQuestQizIndex = -1;
let variants = [];
if (sessionStorage.getItem('lastQuestIndex') === null) {
displayQuestQizIndex = getRandomQuestion();
variants = getRandomVariants(displayQuestQizIndex);
sessionStorage.setItem('lastQuestIndex', displayQuestQizIndex);
sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
} else {
displayQuestQizIndex = sessionStorage.getItem('lastQuestIndex');
variants = sessionStorage.getItem(JSON.parse('lastAnswersIndices'));
}
wstawiam tak tylko dla uwagi
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
To jest druga instrukcja if (zgodnie z ostatnim kodem), i właśnie tę powinieneś zostawić.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Czyli to co mam tutaj
let displayQuestQizIndex = -1;
let variants = [];
if (sessionStorage.getItem('lastQuestIndex') === null) {
displayQuestQizIndex = getRandomQuestion();
variants = getRandomVariants(displayQuestQizIndex);
sessionStorage.setItem('lastQuestIndex', displayQuestQizIndex);
sessionStorage.setItem(JSON.stringify('lastAnswersIndices'), variants);
} else {
displayQuestQizIndex = sessionStorage.getItem('lastQuestIndex');
variants = sessionStorage.getItem(JSON.parse('lastAnswersIndices'));
}
powinienem zostawić?
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
Tak, właśnie tak.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Ok
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Teraz mam proble z tym JSON.parse. Testuje różne opcje i nie działa mam taki błąd JSON.parse: unexpected character at line 1 column 1 of the JSON data
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
Pokaż kod.
Powinno być tak: najpierw pobierasz wartość hasła lastAnswersIndices z sessionStorage, a następnie tę pobraną wartość parsujesz za pomocą metody JSON.parse.
PS Żeby zrozumieć, po co w ogóle jest to parsowanie, to możesz roboczo wyświetlić sobie tę pobraną wartość, np. za pomocą metody console.log. My potrzebujemy tablicy, a pobrana wartość jest ciągiem znaków.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 640
Gdybym chciał zrobić dodatkowo jeszcze licznik który by zliczał ilość punktów to musiałbym na początku zdefiniować zmienną z wartością 0 która by przechowywała ilość punktów, sprawdzanie poprawności odpowiedzi(czyli na ile pytań użytkownik udzielił poprawnej odpowiedzi, a na ile złej), ustalenie po jakiej ilości pytań zakończyć gre(chodzi o to żeby użytkownik odpowiedział na cztery pytania ale żeby każde pytanie było unikatowe a nie występowało po sobie). Wydaje mi się że musze zaimplementować tą funkcjonalność gdyż pytania wyświetlają mi się w losowej kolejności a nie odgórnie ustalonej. Czy jeszcze coś można dodać do takiego licznika?
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Warszawa
Gdybym chciał zrobić dodatkowo jeszcze licznik który by zliczał ilość punktów to musiałbym na początku zdefiniować zmienną z wartością 0 która by przechowywała ilość punktów (…)
Tak, między innymi taka zmienna będzie potrzebna.
(…) sprawdzanie poprawności odpowiedzi(czyli na ile pytań użytkownik udzielił poprawnej odpowiedzi, a na ile złej) (…)
To raczej nie jest już część licznika.
(…) ustalenie po jakiej ilości pytań zakończyć gre(chodzi o to żeby użytkownik odpowiedział na cztery pytania ale żeby każde pytanie było unikatowe a nie występowało po sobie).
Tego nie rozumiem. Także raczej nie jest to część wspomnianego licznika. Czy chodzi Ci o to, że użytkownik ma określać liczbę pytań, zanim rozpocznie grę?
Przed jakąkolwiek zmianą proponowałbym trochę ulepszyć istniejący kod. :) (Jeśli mam coś zaproponować, to prosiłbym o pokazanie kodu po ostatnich zmianach).
PS
Wydaje mi się że musze zaimplementować tą funkcjonalność gdyż pytania wyświetlają mi się w losowej kolejności a nie odgórnie ustalonej.
Tego też nie rozumiem.
Czy jeszcze coś można dodać do takiego licznika?
Ja bym to ogólnie widział tak, że licznik odpowiedzi powinien liczyć odpowiedzi, i nic więcej nie robić. Jeśli chodzi o inne dodatkowe funkcjonalności, to można by dodawać je ogólnie do programu (jako odrębne od licznika). Przy okazji możesz zerknąć na ten artykuł -> https://pl.wikipedia.org/wiki/Zasada_jednej_odpowiedzialno%C5%9Bci (I przy okazji miałbym pytanie: czy wolisz, żebym dawał artykuły po polsku, czy po angielsku?)