Dokonale promyšlené HTML: iframe a automatická výška

Tomáš Herceg       28. 9. 2011       HTTP/HTML, JavaScript       9370 zobrazení

Jeden náš zákazník má web na objednávání vstupenek do divadel a nedávno potřeboval udělat affiliate program, tedy že někdo si na svůj web dá tlačítko “koupit vstupenky na tuhle show na tento den”, a pokud ho někdo použije, tak majitel toho webu dostane nějakou provizi.

Vzhledem k tomu, že ne každému affiliátovi vyhovuje obyčejné tlačítko koupit, ale rád by od nás použil i obrázek a případně kalendář s výběrem vhodného představení, nabízelo se prakticky jediné řešení – použít iframe.

No a teď přijde ta legrace. Hledal jsem snad všude, ale v HTML neexistuje rozumný způsob, jak iframu říct, aby si velikost určil podle toho, co je uvnitř.

Představoval bych si třeba nějaký atribut “autoheight” nebo něco takového, nebo ještě lépe naprosto přirozené chování, že když nezadáte výšku resp. šířku, zabere to tolik místa, kolik potřebuje anebo kolik má k dispozici (což dělá většina dalších elementů, například tabulka, obrázek, odstavec textu, prostě všechno). Až pokud si někdo výšku řekne, pak to teprve platí.

Jenže ne - pokud výšku a šířku nezadáte, dostane iframe výchozí rozměry 300x150. Jak na ta čísla přišli si dovedu představit naprosto jasně – to se takhle někdo ráno vzbudí, protáhne se a řekne “tak co třeba 300x150”, to je takový užitečný rozměr.

Prostředky samotného HTML to tedy nejde, přichází na řadu javascript. Nemám rád, když musím k layoutu a rozložení prvků na stránce používat skripty, když v jiných technologiích se podobné věci dají dělat deklarativně a snadno. No ale když to jinak nejde… Takže vnitřní stránka si zjistí, kolik pixelů potřebuje, a nějak to předá té vnější, která iframu nastaví požadovanou výšku (šířka je naštěstí vždy pevná, takže tu neřešíme).

Typicky člověk dospěje k něčemu jako window.parent.document.getElementById…

Potíž je, že v našem případě obsahuje iframe stránku, která pochází z jiné domény, než ta, jež tento iframe hostuje. A tu přichází další problém – v prohlížečích není mnoho obecně použitelných způsobů, jak si z jednoho iframu poslat do druhého zprávu. Když si zkusíte sáhnout na objekt document iframu z jiné domény, dostanete po čumáku chybovou hláškou “Access denied”. Nejde ani zavolat javascriptovou funkci, vnější stránka ani není schopná zjistit URL té vnitřní, takže si to nelze předat ani přes fragment v URL ani přes window.name, jak na některých fórech ještě najdete. Možná to ve starších prohlížečích funguje, ale v IE9 třeba ne.

Bezpečnostní důvody, které jsou za tím, celkem chápu, na druhou stranu proč tam už od začátku není nějaká možnost komunikace (se kterou by musely počítat obě strany)? Funkci postMessage přináší HTML5, ale tu ještě mnoho prohlížečů neumí, a je na tom opět vidět, že HTML 5 řeší problémy, které bylo potřeba řešit už před minimálně 5 lety – iframy jsou tu přeci jen dost dlouho.

Nakonec jsem na webu a fórech jedno řešení vyštrachal – vnitřní stránka si uvnitř udělá ještě jeden (neviditelný) iframe, a nastaví mu jako URL nějakou speciální stránku (svou výšku jí předá v URL fragmentu), která musí být na stejné doméně, jako ta vnější. Ta nejvnitřnější pak může komunikovat s tou vnější a velikost iframe elementu nastavit podle toho, co najde v URL.

Jak to tedy vypadá na obrázku?

Řešení pomocí vnořených iframe

Pointa je, že nejvnitřnější a vnější rám (tedy červená a modrá) musí být na stejné doméně. Jinak by volání window.parent.document vyhodilo chybu.

Nejvíc mě na tom štve, že tohle celé divadlo by nebylo nutné, kdyby se při návrhu HTML aspoň trochu přemýšlelo a když se iframu rozměry nezadají, uzpůsobilo by ho to podle velikosti obsahu – stejně jako to dělá třeba obrázek nebo tabulka. 

 

hodnocení článku

1 bodů / 1 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

Diskuse: Dokonale promyšlené HTML: iframe a automatická výška

Pěkné řešení. Může se výška obsahu a tedy i iframu měnit dynamicky? Nebo se nastavuje jednou po načtení stránky?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Hmm, blbá otázka. Samozřejmě jen po načtení stránky. Už jsem doufal, že snad někdo našel řešení. Předchozí příspěvek jsem psal já.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ten javascriptový kód se dá vyvolat kdykoliv, klidně by se to mohlo měnit každou sekundu například.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Teoreticky by šlo ve vnější stránce chytat událost, kdy se změnila velikost okna (žádné ptaní se každou sekundu, to je největší pitomost - pokud to jde udělat událostí, tak nikdy timer).

Jakmile tato událost nastane, tak prvnímu iframu změnit URL, ale jen fragment v URL (např. přidat znak, přičíst jedničku nebo tak něco). Vnitřní stránka by se navěsila na událost hashchange a při jejím vyvolání by se změřila a změnila adresu zase ve vnořeném iframu, který to tím skriptem už zpropaguje do první stránky.

Ale nezkoušel jsem to, takže nevím, jestli to funguje. Naštěstí to nepotřebuju.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ano samozřejmě, ta sekunda byl pouze příklad pro ilustraci, že je možné ten kód nechat proběhnout opravdu při každém vývojářově rozmaru :) Mimochodem HashChange nemá zase tak širokou podporu a běžně se časovačem řeší, pokud jej browser nepodporuje, ale jak říkám, tím směrem jsem nemířil.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nejsem zcela zběhlý v programování, jak má vypadat ten zápis scriptu v pomocné stánce helper.html ?

a to červené #výška tam má být napsáno?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nejsem zcela zběhlý v programování, jak má vypadat ten zápis scriptu v pomocné stánce helper.html ?

a to červené #výška tam má být napsáno?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Místo toho #výška se tam dosadí třeba #365, prostě počet pixelů, kolik ten dokument má na výšku.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

A jak má vypadat zápis v helper.html ?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nejsem zcela zběhlý v programování, jak má vypadat ten zápis scriptu v pomocné stánce helper.html ?

a to červené #výška tam má být napsáno?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Teoreticky ano, nepochybně. V praxi ale nelze (resp. nevím jak) spolehlivě získat aktuální výšku dokumentu v případě, že došlo k dynamické změně.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Dokonale promyšlené HTML: iframe a automatická výška

Toto je velice zajimavé řešení, mě by to asi nenapadlo, je pravda, že toto je opravdu hodně špatně řešeno a člověk by prostě tak nějak očekával, že takováto věc již bude v základu, ale ne prostě není, člověk pak musí zdlouhavě googlit různé paskvily a když pak tlačí čas, tak je to dost o nervy, bohužel :-(

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback