Vylepšená náhrada textu obrázkem: acIR

Nemám rád sIFR, proto když mi můj oblíbený (dis)grafik nakreslil nový design pro mojí homepage s použitím moc hezkého, ale nestandradního, fontu, rozhodl jsem se najít jiné řešení pro jeho použití při zachování přístupnosti. Přístupností mám na mysli to, aby byl text v kódu skutečně jako text, byl vidět i při vypnutých obrázcích a šel označit pomocí myši.

Řešení vychází z použití Pixyho náhrady textu obrázkem, které řeší požadavek na text v kódu a funkčnost při vypnutých obrázcích. Zbývalo tedy dořešit problém s označením pomocí myši. Toho jsem dosáhl kouskem JavaScriptu, který při pokusu o označení textu, jenž je ve skutečnosti obrázkem na pozadím elementu opravdový text překrývající, tento překrývající element skryje a po zrušení označení ho opět zobrazí. Malá ukázka (screencast):

Lorem ipsum dolor sit amet,
consectetur adipiscing elit

Accesible Image Replacement neboli acIR, jak jsem toto řešení honosně nazval, vypadá takto:

var acIR = {
 
    FF: /Firefox/i.test(window.navigator.userAgent),
 
    init: function() {
        var element, elements = document.getElementsByTagName('span');
        for (var i = 0; i < elements.length; i++) {
            element = elements[i];
            if (element.parentNode.tagName != 'A') {
                    acIR.enableSelection(element);
            }
        }
    },
 
    enableSelection: function(element) {
 
        acIR.FF && element.parentNode.insertBefore(element, element.parentNode.firstChild)
 
        window.opera || (element.style.cursor = 'text');
        element.onmousedown = function(e) {
 
            // clean-up
            document.body.onmousedown && document.body.onmousedown();
            document.body.onmouseup && document.body.onmouseup();
 
            // Left button is down, enable selection by hiding the picture
            var e = e || window.event;
            if (e.button === 0 || e.button === 1) {
                acIR.start(element);
                document.body.onmouseup = function() {
                    // ..released immediately without moving, cancel the process
                    acIR.end(element);
                    document.body.onmousemove = null;
                }
                document.body.onmousemove = function() {
                    // ...cursor moved, init the re-appear process
                    document.body.onmouseup = null;
                    document.body.onmousemove = null;
 
                    // Down-move-up means 'click' to some browsers, work it around
                    document.body.onmousedown = function () {
                        // The button is down again, we're going to show the pic again soon
                        document.body.onmousemove = function(e) {
                            document.body.onmouseup = null;
                        }
                        document.body.onmouseup = function(e) {
                            // ...clicked, let's show it
                            var e = e || window.event;
                            if (e.button === 0 || e.button === 1) {
                                acIR.end(element);
                                document.body.onclick = null;
                                document.body.onmousedown = null;
                            }
                        }
                    }
                }
            }
        }
    },
 
    start: function(element) {
        if (acIR.FF) {
            element.style.display = 'none';
        } else {
            element.style.visibility = 'hidden';
        }
    },
 
    end: function(element) {
        if (acIR.FF) {
            element.style.display = 'block';
        } else {
            element.style.visibility = 'visible';
        }
    }
 
}

Určitě by stálo za to kód přetvořit do podoby používající nějaký framework nebo alespoň DOM3 events, aby ho bylo možné použít i na stránkách již obsahujující JavaScript, se kterým by acIR v tuto chvíli kvůli způsobu zavěšování posluchačů událostí mohl kolidovat.

acIR bez problému funguje v Opeře, Google Chrome, Konqueroru, IE6, IE7. Ve Firefoxu funguje též, ale je tam menší nedostatek v tom, že po skrytí překrývajícího elementu není text pod ním ihned vybrán – je potřeba pokus o výběr zopakovat výběr začíná od začátku textu nikoliv přesně od místa, kde bylo kliknuto.

V akci lze acIR vidět také na WebKitchen.cz.

Licence pro acIR: Creative Commons License

Aktualizace: tento článek je již staršího data, v současné době samozřejmě @font-face rule them all

Tags: , ,

15 Responses to “Vylepšená náhrada textu obrázkem: acIR”

  1. Filosof Says:

    Zajímavé řešení, rozhodně je pro větší bloky textu přístupnější než samotná pixyho technika.. ale přiznám se, že raději použiju cufón (tj. nemusím vytvářet jednotlivé obrázky, ačkoliv označování textu zatím neumí a asi hned tak umět nebude)..

  2. Martin Says:

    A to ti fakt přijde v praxi použitelné? S tím by mě zákazník vyhodil, jakmile by na to zkusil kliknout. I kdybych se tisíckrát zaklínal nějakou přístupností.
    Navíc říkat chování ve Firefoxu “funguje to” vyžaduje hodně hrubou náturu!

  3. Jakub Says:

    @Martin
    Ano, přijde mi to použitelné. Použitelnější, než klasické řešení. Výsledný efekt samozřejmě závisí na míře podobnosni skrytého textu a textu na obrázku. Tvojí reakci, jakožto uživatele FF, chápu. Ve Firefoxu to skutečně nefunguje nejlépe, ale jeho chování si nedovedu vysvětlit (není k němu důvod) a navíc všechny ostatní důležité prohlížeče fungují podle předpokladu, proto to považuji za bug ve Firefoxu. Asi bude nejlepší tento probhlížeč do momentu, než přijdu na nějaký workaround nebo chybu neopraví, odříznout.

  4. Marek Soldát Says:

    Bohužel musím souhlasit s Martinem. Ono je to sice vtipný řešení, ale má to pár háčků:
    1) ve FF nefunguje (pseudofunguje = nefunguje), což je ovšem jedna z mála věcí, která se možná dá odstranit
    2) při hodně rozdílné šířky jednotlivých znaků u nestandardního a standardního fontu funguje buď nepřesně, nebo nefunguje (testováno na WebKitchen, když zkusím označit Analýzy a Marketing, tak ten Marketing mi tam prostě zmizí), tohle neodstraníme
    3) ať mi nikdo netvrdí, že jdou takhle řešit odkazy (ani kdyby se tohle řešení 1000x upravovalo), což jsou podle mě nejčastější místa, kam se většinou ten “krásný” font dává, potenciální řešení přes nějaký event ala startselect (či jak to je), ale nedávám šanci, že se dá dobrat k fungujícímu výsledku
    4) kdo uhádne, co se stane s vypnutým javascriptem? správně, zůstane jenom obrázek. a v praxi sem viděl víc prohlížečů s vypnutým javascriptem, než s vypnutými obrázky = to taky neodstraníme a pro tuhle skupinu uživatelů bude fungovat select jenom s čistým textem
    5) délka a náročnost kódu (a to už vůbec nemluvím o konstrukci document.body.onmousemove = function(), která tímto způsobem napsaná bude jednak kolidovat s dalšími odvážnějšími javascripty a druhak myslím, že by to šlo vyřešit i úsporněji), to je potenciálně řešitelné
    6) použití textu přes obrázek na pozadí je stále jednodušší, funguje líp a když se dobře udělá, může vypadat i srovnatelně dobře – tady řešitelnost necháme stranou, protože jisté typy klientů se bez toho krásného fontu prostě neobejdou

    Abych jenom nekritizoval, chválím snahu autora, určitě je potřeba, aby někdo hledal originální řešení zapeklitých problémů, ale v tomto konkrétním případě snaha za vývoj 7/10, ovšem výsledná použitelnost zatím tak 1/10 se zavřenýma očima.

  5. Jakub Says:

    @marek
    1) to je bohužel pravda (zvláštní je, že to závisí na délce textu), ještě se tomu podívám na zoubek, nicméně před vynesením soudu si to doporučuji vyzkoušet v jiném prohlížeči, než Firefoxu

    2) je to zamýšleno pro delší textu typu představení na WebKitchen.cz a tam je podstatné to, aby bylo možné označení a případné zkopírování textu, což (kromě Firefoxu) toto řešení umožňuje; problém s přesnou pozicí a velikostí skrytého textu se dá do určité míry řešit, ale ke splnění účelu není nutné, aby to bylo naprosto shodně.

    3) pro odkazy je to nevhodné, protože při kliknutí dojde k probliknutí, ale u odkazů požadavek na označitelnost textu není tak velký

    4) toto je pouze nadstaba, při vypnutém JS se nenastane nic neočekávaného, bude se to chovat jako klasický text nahrazený obrazkem – tj., nejpůjde vybrat pomocí myši

    5) délka a náročnost kódu problém není, protože je to pouze pár bytů a změnit způsob navěšování ovladačů událostí je otázka minut, osobně jsem to zatím nepotřeboval, proto jsem to neuělal

    6) “použití textu přes obrázek na pozadí” je přesně to, co tohle řešení rozšířuje, proto je tenhle argument mimo

    Díky za chválu. Použitelnost v non-FF prohlížečích osobně hodnotím jako 8/10, protože dokonalé to opravdu není, ale reší to přesně ten problém, kvůli kterému script vznikl.

  6. Jadugar Says:

    Nechápu co má autor proti sIFR řešení, je naprosto přístupné, použitelné a jeho nasazení je otázkou pár minut.

    Hlavní je že nejnovější verze funguje ve všech důležitých prohlížečích a text jako takový je přístupný, protože ve zdrojáku je tak jak by ho tam zanechal kodér – nemusím zbytečně přidávat tagy SPAN (nebo jiné), které jsou na WebKitchen.cz. …

    Toto řešení je velice neohrabané a už jenom to, že ve FF nefunguje. A jak řekl Martin Says: S tímhle by mne zákazník vyhodil…

    Nikdy bych toto řešení nepoužil a ani nedoporučil, neshledávám na něm absolutně žádnou výhodu…

  7. Peter Láng Says:

    Dobrý je to, jen to chce ještě trochu doladit, aby to mohli i Martinové s klidem prezentovat svým zákazníkům.

  8. Jakub Says:

    @jadugar sIFR používá flash, takže každý kousek textu, který zpracovává, to flashový objekt. Když si otevřu homepage sIFRU pod linuxem, tak dochází k trvalému vytížení procesoru ze cca 40 %. Když ještě reflex.cz používal sIFR pro nadpisy, tak mi to pravidelně shazovalo prohlížeč. Proto jsem se znažil najít nové, z Pixyho klasické metody vycházející, řešení, kde bych se vyhnul použití pluginů. Pár prázdných spanů nevadí absolutně ničemu.

    @peter díky

  9. Marek Soldát Says:

    Ono by možná pro začátek stačilo vůbec nějakým způsobem dát najevo, že takto zpracované texty jsou označeny (tj obrázek přes nějaké transparence podsvětlit, dát mu rámeček atp.), protože často se kopírují i větší kusy textu a vědět, že se kopírují i nadpisy je pro uživatele užitečná informace. Řešení bych viděl patrně v onselectu, pokud je dobře podporován (snad by mohl být, nezkoušel sem). Ve stejném případě by ovšem taky ty obrázky mohly zmizet, takže možná zbyde i možnost z těch obrázků vybírat jenom části textu. Takové řešení bude stejně vykazovat chyby, ale měly by to být chyby běžné při selectování, na které jsou uživatelé trochu zvyklí.

    Asi bych to osobně stejně nepoužil, ale třeba ten tip autorovi pomůže k vylepšení jeho řešení.

  10. carnero Says:

    @Jakub (8): Chápu správně, že něco co nefunguje ~1% uživatelů (sIFR vs Linux) si nahradil něčím, co nefunguje ~30% uživatelů (acIR vs Firefox)? To nezní příliš rozumně.

  11. Jakub Says:

    @marek – Díky za tip a konstruktivní komentář.

    @carnero – Tady nejde o zásadní funkcionalitu, ale o drobné vylepšení. Pokud se mám rozhodnout, jestli toto poskytnu 70 % uživatelů, nebo všem, ale za cenu toho, že procento z nich bude minimálně zpruzeno a nekterým to shodí prohlížeč, tak pro svojí homepage volím variantu první (už jenom proto, že jí občas navštívím). Asi jsi si nevšiml, ale script jsem upravil tak, že ve Firefoxu funguje, pouze je tam ten nedostatek zmíněný v zápisku.

  12. carnero Says:

    @Jakub – Nechci Ti kazit radost (teď už ne), ale ani po té úpravě to nefunguje. Jen to nefunguje trochu odlišně.

  13. Jakub Says:

    @carnero
    V obou verzích Firefoxu, ve kterých jsi tuhle stránku včera a dneska navštívil (3.0.10 Windows a 3.5b4 Linux), jsem to testoval, ale nefunkčnost jsem nezaznamenal. Nemám tedy ponětí, o čem mluvíš.

  14. Jakub Says:

    @Filosof – Cufón vypadá skutečně zajímavě, díky za tip.

  15. Jakub Hejda Says:

    Snaha vymyslet něco nového se cení! Vedle Cufonu to je ale naprosto k ničemu že :-)

Leave a Reply