Metody vyskakovacích oken a oken

Vyskakovací okno je jednou z nejstarších metod zobrazení dalšího dokumentu uživateli.

V podstatě stačí spustit:

window.open('https://javascript.info/')

…A otevře se nové okno s danou URL. Většina moderních prohlížečů je nakonfigurována tak, aby otevíraly adresy URL na nových kartách namísto samostatných oken.

Vyskakovací okna existují již od pradávna. Původní myšlenkou bylo zobrazit jiný obsah bez zavření hlavního okna. V tuto chvíli existují i ​​jiné způsoby, jak toho dosáhnout:můžeme obsah načítat dynamicky pomocí funkce načítání a zobrazit jej v dynamicky generovaném <div> . Vyskakovací okna tedy nepoužíváme každý den.

Vyskakovací okna jsou také záludná na mobilních zařízeních, která nezobrazují více oken současně.

Přesto existují úlohy, kde se vyskakovací okna stále používají, např. pro autorizaci OAuth (přihlášení pomocí Google/Facebook/…), protože:

  1. Vyskakovací okno je samostatné okno, které má své vlastní nezávislé prostředí JavaScriptu. Otevření vyskakovacího okna z nedůvěryhodného webu třetí strany je tedy bezpečné.
  2. Otevření vyskakovacího okna je velmi snadné.
  3. Vyskakovací okno může procházet (změnit adresu URL) a odesílat zprávy do otevíracího okna.

Blokování vyskakovacích oken

V minulosti zlé stránky hojně zneužívaly vyskakovací okna. Špatná stránka může otevřít spoustu vyskakovacích oken s reklamami. Nyní se tedy většina prohlížečů snaží blokovat vyskakovací okna a chránit uživatele.

Většina prohlížečů blokuje vyskakovací okna, pokud jsou volána mimo obslužné programy událostí spouštěné uživatelem, jako je onclick .

Například:

// popup blocked
window.open('https://javascript.info');

// popup allowed
button.onclick = () => {
 window.open('https://javascript.info');
};

Tímto způsobem jsou uživatelé do jisté míry chráněni před nechtěnými vyskakovacími okny, ale funkce není zcela zakázána.

Co když se vyskakovací okno otevře z onclick , ale po setTimeout ? To je trochu složité.

Zkuste tento kód:

// open after 3 seconds
setTimeout(() => window.open('http://google.com'), 3000);

Vyskakovací okno se otevře v prohlížeči Chrome, ale ve Firefoxu se zablokuje.

…Pokud zkrátíme zpoždění, vyskakovací okno bude fungovat i ve Firefoxu:

// open after 1 seconds
setTimeout(() => window.open('http://google.com'), 1000);

Rozdíl je v tom, že Firefox považuje časový limit 2000 ms nebo méně za přijatelný, ale po něm – odstraní „důvěru“ za předpokladu, že je nyní „mimo akci uživatele“. Takže první je blokován a druhý ne.

windows.open

Syntaxe pro otevření vyskakovacího okna je:window.open(url, name, params) :

url
Adresa URL, která se má načíst do nového okna.
jméno
Název nového okna. Každé okno má window.name a zde můžeme určit, které okno použít pro vyskakovací okno. Pokud již okno s takovým názvem existuje – otevře se v něm daná adresa URL, jinak se otevře nové okno.
parametry
Konfigurační řetězec pro nové okno. Obsahuje nastavení oddělená čárkou. V parametrech nesmí být žádné mezery, například:width=200,height=100 .

Nastavení pro params :

  • Pozice:
    • left/top (numerické) – souřadnice levého horního rohu okna na obrazovce. Existuje omezení:nové okno nelze umístit mimo obrazovku.
    • width/height (numerické) – šířka a výška nového okna. Minimální šířka/výška je omezena, takže není možné vytvořit neviditelné okno.
  • Funkce okna:
    • menubar (ano/ne) – zobrazí nebo skryje nabídku prohlížeče v novém okně.
    • toolbar (ano/ne) – zobrazí nebo skryje navigační lištu prohlížeče (zpět, vpřed, znovu načíst atd.) v novém okně.
    • location (ano/ne) – zobrazí nebo skryje pole URL v novém okně. FF a IE jej ve výchozím nastavení neumožňují skrýt.
    • status (ano/ne) – zobrazí nebo skryje stavový řádek. Opět platí, že většina prohlížečů jej nutí k zobrazení.
    • resizable (ano/ne) – umožňuje zakázat změnu velikosti nového okna. Nedoporučuje se.
    • scrollbars (ano/ne) – umožňuje zakázat posuvníky pro nové okno. Nedoporučuje se.

Existuje také řada méně podporovaných funkcí specifických pro prohlížeč, které se obvykle nepoužívají. Příklady naleznete v okně window.open v MDN.

Příklad:minimalistické okno

Otevřeme okno s minimální sadou funkcí, abychom viděli, které z nich prohlížeč umožňuje zakázat:

let params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,
width=0,height=0,left=-1000,top=-1000`;

open('/', 'test', params);

Zde je většina „funkcí okna“ deaktivována a okno je umístěno mimo obrazovku. Spusťte to a uvidíte, co se skutečně stane. Většina prohlížečů „opravuje“ podivné věci, jako je nula width/height a mimo obrazovku left/top . Například Chrome otevře takové okno s plnou šířkou/výškou, takže zabere celou obrazovku.

Přidejme normální možnosti umístění a rozumné width , height , left , top souřadnice:

let params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,
width=600,height=300,left=100,top=100`;

open('/', 'test', params);

Většina prohlížečů zobrazuje výše uvedený příklad podle potřeby.

Pravidla pro vynechaná nastavení:

  • Pokud v open není žádný 3. argument volání, nebo je prázdné, pak se použijí výchozí parametry okna.
  • Pokud existuje řetězec parametrů, ale nějaký yes/no vlastnosti jsou vynechány, pak se předpokládá, že vynechané prvky mají no hodnota. Pokud tedy zadáte parametry, ujistěte se, že jste explicitně nastavili všechny požadované funkce na ano.
  • Pokud zde není left/top v parametrech se prohlížeč pokusí otevřít nové okno poblíž naposledy otevřeného okna.
  • Pokud neexistuje width/height , pak bude mít nové okno stejnou velikost jako naposledy otevřené.

Přístup k vyskakovacímu okně z okna

open call vrátí odkaz na nové okno. Může být použit k manipulaci s jeho vlastnostmi, změně umístění a ještě více.

V tomto příkladu generujeme obsah vyskakovacího okna z JavaScriptu:

let newWin = window.open("about:blank", "hello", "width=200,height=200");

newWin.document.write("Hello, world!");

A zde upravíme obsah po načtení:

let newWindow = open('/', 'example', 'width=300,height=300')
newWindow.focus();

alert(newWindow.location.href); // (*) about:blank, loading hasn't started yet

newWindow.onload = function() {
 let html = `<div style="font-size:30px">Welcome!</div>`;
 newWindow.document.body.insertAdjacentHTML('afterbegin', html);
};

Poznámka:bezprostředně za window.open , nové okno ještě není načteno. To dokazuje alert v řádku (*) . Čekáme tedy na onload jej upravit. Můžeme také použít DOMContentLoaded handler pro newWin.document .

Stejná politika původu

Windows mohou volně přistupovat ke svému obsahu pouze v případě, že pocházejí ze stejného původu (stejný protokol://domena:port).

Jinak např. pokud je hlavní okno z site.com a vyskakovací okno z gmail.com , to z bezpečnostních důvodů uživatelů není možné. Podrobnosti viz kapitola Komunikace napříč okny.

Přístup k oknu z vyskakovacího okna

Vyskakovací okno může také otevřít okno „otvírák“ pomocí window.opener odkaz. Je to null pro všechna okna kromě vyskakovacích oken.

Pokud spustíte níže uvedený kód, nahradí obsah otevíracího (aktuálního) okna textem „Test“:

let newWin = window.open("about:blank", "hello", "width=200,height=200");

newWin.document.write(
 "<script>window.opener.document.body.innerHTML = 'Test'<\/script>"
);

Spojení mezi okny je tedy obousměrné:hlavní okno a vyskakovací okno na sebe navzájem odkazují.

Zavření vyskakovacího okna

Zavření okna:win.close() .

Chcete-li zkontrolovat, zda je okno zavřené:win.closed .

Technicky vzato, close() metoda je dostupná pro jakýkoli window , ale window.close() je ignorován většinou prohlížečů, pokud window není vytvořen pomocí window.open() . Bude tedy fungovat pouze ve vyskakovacím okně.

closed vlastnost je true pokud je okno zavřené. To je užitečné pro kontrolu, zda je vyskakovací okno (nebo hlavní okno) stále otevřené nebo ne. Uživatel jej může kdykoli zavřít a náš kód by měl tuto možnost zohlednit.

Tento kód se načte a zavře okno:

let newWindow = open('/', 'example', 'width=300,height=300');

newWindow.onload = function() {
 newWindow.close();
 alert(newWindow.closed); // true
};

Přesouvání a změna velikosti

Existují způsoby, jak přesunout/změnit velikost okna:

win.moveBy(x,y)
Přesuňte okno vzhledem k aktuální pozici x pixelů vpravo a y pixelů dolů. Záporné hodnoty jsou povoleny (pohyb doleva/nahoru).
win.moveTo(x,y)
Přesuňte okno na souřadnice (x,y) na obrazovce.
win.resizeBy(width,height)
Změňte velikost okna o zadanou hodnotu width/height vzhledem k aktuální velikosti. Záporné hodnoty jsou povoleny.
win.resizeTo(width,height)
Změňte velikost okna na danou velikost.

Je zde také window.onresize událost.

Pouze vyskakovací okna

Aby se zabránilo zneužití, prohlížeč tyto metody obvykle blokuje. Spolehlivě fungují pouze u vyskakovacích oken, která jsme otevřeli a která nemají žádné další karty.

Žádná minifikace/maximalizace

JavaScript nemá žádný způsob, jak minimalizovat nebo maximalizovat okno. Tyto funkce na úrovni operačního systému jsou před vývojáři frontendu skryté.

Metody přesunutí/změny velikosti nefungují pro maximalizovaná/minimalizovaná okna.

Posouvání okna

O rolování okna jsme již hovořili v kapitole Velikosti oken a rolování.

win.scrollBy(x,y)
Posuňte okno x pixelů vpravo a y dolů vzhledem k aktuálnímu rolování. Záporné hodnoty jsou povoleny.
win.scrollTo(x,y)
Posuňte okno na zadané souřadnice (x,y) .
elem.scrollIntoView(top = true)
Posuňte okno a vytvořte elem zobrazí se nahoře (výchozí) nebo dole pro elem.scrollIntoView(false) .

Je zde také window.onscroll událost.

Zaostřit/rozostřit okno

Teoreticky existuje window.focus() a window.blur() metody zaostření/rozostření okna. A existují také focus/blur události, které umožňují zachytit okamžik, kdy se návštěvník zaměří na okno a přepne jinam.

I když v praxi jsou značně omezené, protože je v minulosti zlé stránky zneužívaly.

Podívejte se například na tento kód:

window.onblur = () => window.focus();

Když se uživatel pokusí přepnout z okna (window.onblur ), vrátí okno do ohniska. Záměrem je „uzamknout“ uživatele v rámci window .

Prohlížeče tedy musely zavést mnoho omezení, aby takový kód zakázaly a chránily uživatele před reklamami a zlými stránkami. Závisí na prohlížeči.

Například mobilní prohlížeč obvykle ignoruje window.focus() zcela. Zaostření také nefunguje, když se vyskakovací okno otevře na samostatné kartě, nikoli v novém okně.

Přesto existují případy použití, kdy taková volání fungují a mohou být užitečná.

Například:

  • Když otevřeme vyskakovací okno, může být dobrý nápad spustit newWindow.focus() na to. Jen pro případ, u některých kombinací OS/prohlížeče zajišťuje, že uživatel je nyní v novém okně.
  • Pokud chceme sledovat, kdy návštěvník skutečně používá naši webovou aplikaci, můžeme sledovat window.onfocus/onblur . To nám umožňuje pozastavit/obnovit aktivity na stránce, animace atd. Upozorňujeme však, že blur událost znamená, že návštěvník vypadl z okna, ale přesto to může pozorovat. Okno je na pozadí, ale stále může být viditelné.

Shrnutí

Vyskakovací okna se používají zřídka, protože existují alternativy:načítání a zobrazování informací na stránce nebo v prvku iframe.

Pokud se chystáme otevřít vyskakovací okno, je dobré o tom uživatele informovat. Ikona „otevíracího okna“ poblíž odkazu nebo tlačítka by návštěvníkovi umožnila přežít posun zaměření a mít na paměti obě okna.

  • Vyskakovací okno lze otevřít pomocí open(url, name, params) volání. Vrátí odkaz na nově otevřené okno.
  • Prohlížeče blokují open volání z kódu mimo akce uživatele. Obvykle se zobrazí upozornění, aby je uživatel mohl povolit.
  • Prohlížeče ve výchozím nastavení otevírají novou kartu, ale pokud jsou uvedeny velikosti, bude to vyskakovací okno.
  • Vyskakovací okno může otevřít okno otevírání pomocí window.opener vlastnictví.
  • Hlavní okno a vyskakovací okno se mohou navzájem volně číst a upravovat, pokud mají stejný původ. V opačném případě mohou vzájemně měnit polohu a vyměňovat si zprávy.

Chcete-li zavřít vyskakovací okno:použijte close() volání. Uživatel je také může zavřít (stejně jako všechna ostatní okna). window.closed je true poté.

  • Metody focus() a blur() povolit zaostření/rozostření okna. Ale nefungují pořád.
  • Události focus a blur umožňují sledovat zapínání a vypínání okna. Pamatujte však, že po blur může být okno stále viditelné i na pozadí .