- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639

- Rejestracja:ponad 10 lat
- Ostatnio:prawie 3 lata
- 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:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
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:ponad 10 lat
- Ostatnio:prawie 3 lata
- Lokalizacja:Warszawa
Kod powinien być podobny, tak. Trzeba by najprawdopodobniej:
- zapisywać tablicę z indeksami opowiedzi w
sessionStorage
wtedy, gdy wpislastQuestionIndex
wsessionStorage
ma wartośćnull
; - odczytywać ją (tzn. przypisywać ją zmiennej
variants
) wtedy, gdy wpislastQuestionIndex
wsessionStorage
nie ma wartościnull
.

if (sessionStorage.getItem('lastQuestIndex') === null) { sessionStorage.setItem('lastQuestIndex', answersIndices); } else if (sessionStorage.getItem('lastQuestIndex') !== null) { variants = sessionStorage.getItem('lastQuestIndex'); }
sprawdź czy wszystko jest ok ewentualnie co powinienem popawić. Nie dawaj mi gotowego kodu!!!!


- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
Napisałem ten kod ale dostaje coś takiego https://jsfiddle.net/14nxbL7s/


- Rejestracja:ponad 10 lat
- Ostatnio:prawie 3 lata
- 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).
js if (sessionStorage.getItem('lastQuestIndex') === null) { var variants = getRandomVariants(displayQuestQizIndex); sessionStorage.setItem('lastQuestIndex', variants); }

let variants = [];
powinna być przed instrukcjami if
, a w instrukcji if
powinno być samo przypisanie do zmiennej variants
.
- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
Teraz pojawia się pętla nieskończona https://jsfiddle.net/zb231to0/

- Rejestracja:ponad 10 lat
- Ostatnio:prawie 3 lata
- 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:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
Ok nie ma już tej pętli nieskończonej. Teraz jest to https://jsfiddle.net/8vdeajtr/2/

- Rejestracja:ponad 10 lat
- Ostatnio:prawie 3 lata
- Lokalizacja:Warszawa
- Wcześniej pisałem, że obie instrukcje
if
mogł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
sessionStore
są konwertowane do typustring
przed zapisaniem. A w przypadku odczytu wartości zmiennejlastAnswersIndices
potrzebna nam jest tablica, a nie ciąg znaków. W związku z tym trzeba zrobić dwie rzeczy:
2.1. teraz wartość zmiennejlastAnswersIndices
jest zapisywana bezpośrednio dosessionStorage
; natomiast powinna być konwertowana przed tym zapisem do ciągu znaków za pomocą metodyJSON.stringify
;
2.2. teraz wartość wpisulastAnswersIndices
jest przypisywana bezpośrednio do zmiennejvariants
; natomiast powinna być przed tym przypisaniem parsowana za pomocą metodyJSON.parse
.
- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639

- Rejestracja:ponad 10 lat
- Ostatnio:prawie 3 lata
- Lokalizacja:Warszawa
- Nadal są dwie instrukcje
if
. - Metoda
JSON.stringify
jest użyta w dobrym miejscu, ale metodaJSON.parse
już 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ą
variants
pustą tablicą w momencie deklaracji.
- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
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:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
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:ponad 10 lat
- Ostatnio:prawie 3 lata
- 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:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
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:ponad 10 lat
- Ostatnio:prawie 3 lata
- 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
sessionStorage
obiektuWindow
(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 interfejsStorage
przechowuje pary klucz-wartość. (Nie pytaj mnie, czemu razStorage
nazywany 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
if
instrukcjiif
powinny być zawarte następujące instrukcje:
4.1. przypisanie zmiennejdisplayQuestQizIndex
losowego indeksu pytania, używając funkcjigetRandomQuestion
;
4.2. przypisanie zmiennejvariants
tablicy z indeksami odpowiedzi pytania o wylosowanym indeksie, używając funkcjigetRandomVariants
;
4.3. ustawienie wartości hasłalastQuestIndex
obiektusessionStorage
na wylosowany indeks;
4.4. ustawienie wartości hasłalastAnswersIndices
obiektusessionStorage
na tablicę z indeksami odpowiedzi pytania o wylosowanym indeksie, używając metodystringify
obiektuJSON
. -
W bloku
else
instrukcjiif
powinny być zawarte następujące instrukcje:
5.1. przypisanie zmiennejdisplayQuestQizIndex
wartości hasłalastQuestIndex
obiektusessionStorage
;
5.2. przypisanie zmiennejvariants
wartości hasłalastAnswersIndices
obiektusessionStorage
, używając metodyparse
obiektuJSON
.
(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:około 6 lat
- Ostatnio:ponad rok
Ten kod nie przeszedłby review w żadnej poważnej firmie.
- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
Coś nie działa https://jsfiddle.net/4edrnj2t/. Możesz sprawdzić czy wszystko napisałem zgodnie z twoimi wytycznymi?

- Rejestracja:ponad 10 lat
- Ostatnio:prawie 3 lata
- Lokalizacja:Warszawa
- Nadal są dwie instrukcje
if
. Powinna być jedna. - Metoda
JSON.parse
nadal parsuje nie to, co powinna.



- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
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:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
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:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
Ok
- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
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:ponad 10 lat
- Ostatnio:prawie 3 lata
- 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.

answersIndices
– w tej pętli while
, co jest w kodzie (musisz mieć otwartą konsolę, bo jak się pętla rozpocznie, to być może nie będziesz mógł jej już otworzyć w tej karcie). Zmienna answersIndices
zawierała wszystkie indeksy (nie była "czyszczona" po każdym użyciu), więc warunek w pętli while
nie miał szans na bycie niespełnionym (zawsze był spełniony, więc zawsze następowała kolejna iteracja w pętli).

answersIndices
zawierała wszystkie indeksy po pewnym czasie, po iluś wywołaniach tej metody, w której jest pętla, więc w sumie program zawieszał się losowo. :) To bardzo trudny bug do wykrycia, gdyby nasz kod nie był taki prosty.

- Rejestracja:ponad 7 lat
- Ostatnio:2 miesiące
- Postów:639
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:ponad 10 lat
- Ostatnio:prawie 3 lata
- 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?)



szatkus