Okna przeglądarki
Za pomocą JavaScript możemy otwierać nowe okna, formatować ich wygląd, przesyłać między nimi informacje itp.
Przez kilka ostatnich lat sporo się pozmieniało w materii otwierania nowych okien. Po pierwsze większość przeglądarek blokuje otwieranie nowych okien na stronach. Po drugie użytkownicy nie lubią gdy próbuje im się narzucić nowe okna. Po trzecie wreszcie - otwieranie okien na urządzeniach mobilnych mija się z celem. Co najwyżej możemy otworzyć stronę w nowej karcie.
Wszystkie te punkty powodują, że nie zalecam otwierania nowych okien, a zamiast ich zalecam używać wszelakiej maści popupów czy modali - najlepiej korzystając z gotowych rozwiązań (1, 2, 3)
Otwieranie nowego okna
Standardowa konstrukcja otwierająca okno ma postać:
const win = window.open(url, name, options)
url | ścieżka do otwieranej strony lub pusty ciąg, jeżeli okno generujemy dynamicznie |
---|---|
name | nazwa okna, do której możemy się odwoływać atrybutem target w linkach i formularzach. Możemy też tutaj podać target="_blank" jeżeli chcemy otworzyć okno jako nową kartę |
options | Dodatkowe opcje otwieranego okna, opisane poniżej |
Wszystkie możliwe ustawienia znajdziesz na stronie https://developer.mozilla.org/pl/docs/Web/API/Window/open, poniżej zamieszczam te najczęściej używane. Tutaj mała uwaga. Przeglądarki są bardzo wybredne jeżeli chodzi o otwierane okna, dlatego nie wszystkie poniższe właściwości będą wszędzie działać.
left | pozycja względem lewej strony ekranu |
---|---|
top | pozycja okna względem góry ekranu |
height | ustawia wysokość okna |
width | ustawia szerokość okna |
menubar | (yes/no) pokazuje lub ukrywa menu przeglądarki |
toolbar | (yes/no) pokazuje lub ukrywa standardowy pasek narzędzi |
location | (yes/no) pokazuje lub ukrywa pasek adresowy |
directories | (yes/no) pokazuje lub ukrywa przyciski katalogów |
status | (yes/no) pokazuje lub ukrywa pasek statusu |
resizable | (yes/no) określa czy okno może zmienić rozmiar |
scrollbars | (yes/no) pokazuje lub ukrywa paski przewijania |
dialog | (yes/no) Usuwa z okna wszystkie menu, statusy itp, zostawiając tylko przycisk zamykania |
noopener | Zapobiega używaniu zmiennej opener w otwieranych oknach. Patrz poniżej |
noreferrer | Zapobiega wysyłaniu informacji o adresie, z której została otwarta strona w oknie. Dodatkowe informacje możesz zobaczyć tutaj |
minizable | (yes/no) używane wraz z dialog. Jeżeli ustawimy na yes, dialog dodatkowo będzie można zminimalizować |
//otwieram jako nowe okno
const myWin = window.open("http://google.pl", "myWindow", "tolbar=no,scrollbars=no,menubar=no,width=500,height=500");
//otwieram jako nową zakładkę
const newTab = window.open("http://mypage.pl", "target=_blank");
Przykładowa funkcja, która otworzy okno na środku ekranu może mieć postać:
const myWindow = function(url, width, height) {
const centerH = window.screen.height / 2;
const centerW = window.screen.width / 2;
const posX = centerW-width/2;
const posY = centerH-height/2;
window.open(url, "tytul-okna", `dialog=yes,width=${width},height=${height},left=${posX},top=${posY}`);
};
const btn = document.querySelector("#testWindow");
btn.addEventListener("click", () => {
myWindow("http://google.pl", 600, 400);
});
Modyfikacja okna
Dzięki przypisaniu nowego okna pod zmienną, możemy nim w łatwy sposób manipulować. Zasady są identyczne jakie stosowaliśmy w rozdziale o DOM - jedyna różnica polega na odwołaniu, gdzie musimy użyć zmiennej, pod którą podstawimy otwarte okno:
const win = document.open(...);
const p = win.document.querySelectorAll("p");
for (const el of p) {
p.style.color = "red";
p.innerHTML = "Lubie koty i psy";
}
win.document.body.addEventListener("click", () => {
console.log("Kliknąłeś body");
});
Właściwość opener
Jedną z ciekawszych ale i niebezpiecznych właściwości otwartych okien/zakładek jest właściwość opener. Dzięki niej możemy się odwoływać do okna, z którego utworzyliśmy nowe okno.
opener.document.body.style.background = "yellow";
Sprawdźmy to:
const btn = document.querySelector("#windowOpenerTest");
btn.addEventListener("click", () => {
const win = window.open("window-test-opener.html", "target='_blank'");
})
Jak zauważysz korzystając z właściwości opener, mogę nieźle namieszać na stronie, która otworzyła takie okno.
Może to być początek groźnego ataku. Wyobraź sobie, że zamiast otwierać małe okienko, otworzę stronę w nowej zakładce. Równocześnie mogę np. przekierować stronę, która otworzyła nowe okno za pomocą kodu:
opener.window.location = "https://www.mbąnk.pl/logoutpage.html?type=t"
Ty wracasz na swoją stronę i widzisz, że zostałeś niechcący wylogowany ze swojego konta. Logujesz się i... Właśnie przejąłem twoje hasła do twojego konta, ponieważ zalogowałeś się na fejkową stronę na domenie mbąnk. Jasne - nie każdy z nas ma konto w mBanku. I pewnie większość wzmocni swoją uwagę, gdyby zaistniała powyższa sytuacja.
Ale nie oszukujmy się - przecież wśród nas jest pełno osób, które bardzo łatwo nabierają się na wnuczków policjantów, blokady komputera nakładane przez FBI, lecznicze kołdry itp. A przecież mówimy powyżej o prostym przekierowaniu. Podobne ataki mogą być bardziej wymyślne, bo mogą zmieniać zdarzenia przypisane do elementów, ich html, ustawiać niewidzialne elementy itp.
Z tego też powodu przy otwieraniu nowych okien, powinieneś używać właściwości noopener.
const win = window.open("window-test-opener.html", "target="_blank"", "noopener,....");
Jeszcze w czasach IE11 podobne zabezpieczenie powinieneś stosować w linkach, gdzie otwierasz stronę w nowej zakładce za pomocą target="_blank"
. Służy do tego atrybut
rel="noopener"
:
<a href="..." target="_blank" rel="noopener"> klik </a>
W dzisiejszych czasach dla linków możesz je pominąć.
Trening czyni mistrza
Jeżeli chcesz sobie potrenować zdobytą wiedzę, zadania znajdują się w repozytorium pod adresem: https://github.com/kartofelek007/zadania