<< 1. „Przezroczyste” okienko rozmowyNote: Zanim zaczniesz eksperymentować, przeczytaj post do końca.
Przydługi ten post, ale chciałem dokładnie wytłumaczyć jak dodawać nowe rzeczy do DOM okna rozmowy, żeby potem już się nie rozdrabniać.
2. Dodatkowe elementy w oknie rozmowy
Tworząc styl czasem żałujemy, że z powodu sztywnego szablonu div okna rozmowy nie da się zrobić tego czy tamtego. „Jeden dodatkowy div i by było po sprawie” - ile razy tak mówiliśmy? Dzięki expressions można dodać sobie dowolną ilość elementów.
2.1 Teoria - this
W expression zmienna
this określa element określony przez selektor CSS. W tym przykładzie:
CODE
div.send {
-ieh: expression(this.style.color = 'red');
}
odwołuje się do każdego elementu div.send na stronie, po kolei idąc w pętli. Ten kod ustawi czerwony kolor każdemu <div class="send">
2.2 Teoria - createElement, className, id
Aby dodać element do DOM należy najpierw go stworzyć.
CODE
document.createElement('nazwa')
Możemy przyporządkować taki pływający w próżni element (dajmy na to div) do zmiennej.
CODE
temp = document.createElement('div')
Następnie musimy określić klasę bądź identyfikator, aby za pomocą kolejnych reguł CSS jakoś się do niego odwołać. Klasa przyda się, gdy mamy wiele podobnych elementów w oknie rozmowy, identyfikator jeśli jeden.
Klasa:
CODE
temp.className = 'klasa'
Identyfikator:
CODE
temp.id = 'identyfikator'
Okej, jest element, jest do niego uchwyt za pomocą class/id - ale to nie wszystko. Należy go teraz podczepić do dokumentu.
2.3 Teoria - appendChild, insertBefore
Istnieją dwie szeroko używane metody:
CODE
element.appendChild(nowyElement)
element.parentNode.insertBefore(nowyElement, element)
Pierwsza - appendChild - służy do doczepiania nowego elementu wewnątrz jakiegoś, dodając go na sam koniec. Gdybyśmy wykonali appendChild(temp) na div.send dostaniemy coś takiego:
CODE
<div class="send">
<div class="header">…</div>
<div class="body">…</div>
<div class="klasa"></div>
</div>
Druga - insertBefore - pozwala wstawiać element przed dany. Przy małej pomocy może też wstawić element za dany.
Najpierw musimy pobrać element nadrzędny dla danego. Robimy to przez parentNode. Z niego wywołujemy metodę insertBefore. Jej parametry to element do wstawienia oraz element przed który to coś nowe chcemy wstawić - cel. Cel musi być dzieckiem (zawierać się w) naszego parentNode.
Przykładowo, wykonując insertBefore na div.send z naszym temp musimy napisać coś takiego
CODE
this.parentNode.insertBefore(temp, this)
Otrzymamy:
CODE
<div class="klasa"></div>
<div class="send">
…
</div>
2.4 Praktyka - this.parsed
Aby zacząć dostawiać elementy do okna rozmowy, należy upewnić się, że nie wpadniemy w nieskończoną pętlę dodającą setki, tysiące elementów dla danej reguły CSS - zawiesi nam to okno rozmowy -> Konnekta.
CODE
div.send {
-ieh: expression(
this.parsed ? 0 : (
[tutaj wstawiamy nowe rzeczy]
this.parsed = 1
)
);
}
2.5 Praktyka - zaokrąglenie rogów
Aby zaokrąglić rogi, potrzebujemy 4 elementów. Najpierw musimy stworzyć dwa, jeden przed i drugi po. A w nich stworzyć po jednym i odpowiednio wypozycjonować.
Zróbmy to na powiadomieniu o statusie:
CODE
div.status {
-ieh: expression(
this.parsed ? 0 : (
temp = document.createElement('div'),
temp.className = 'statusTop',
temp2 = document.createElement('div'),
temp2.className = 'statusBot',
[c.d.n.]
this.parsed = 1
)
);
}
Mamy już po dwa elementy stworzone, teraz należy je doczepić. Niektóre style swoją kontrukcją pozwolą dodać div przed za pomocą insertBefore (div.statusTop będzie poza div.status) a za przy pomocy appendChild (div.statusBot będzie na końcu, w środku div.status). Wybierzmy jednak metodę najlepszą, ale i najtrudniejszą. Wstawmy div.statusBot naprawdę za div.status.
CODE
div.status {
-ieh: expression(
this.parsed ? 0 : (
temp = document.createElement('div'),
temp.className = 'statusTop',
temp2 = document.createElement('div'),
temp2.className = 'statusBot',
this.parentNode.insertBefore(temp, this),
this.parentNode.insertBefore(temp2, this.nextSibling),
this.parsed = 1
)
);
}
Powstało tutaj magicznie "insertAfter" - wstawiliśmy temp2 (div.statusBot) przed następny element za div.status. Czyli za div.status, prawda? Musimy jednak się zabezpieczyć - musimy zawsze mieć element, który będzie za div.status, żeby się go uchwycić.
Należy przed tą linijką wstawić jakiś zbędny element do elementu nadrzędnego div.status.
CODE
div.status {
-ieh: expression(
this.parsed ? 0 : (
temp = document.createElement('div'),
temp.className = 'statusTop',
temp2 = document.createElement('div'),
temp2.className = 'statusBot',
this.parentNode.insertBefore(temp, this),
this.parentNode.appendChild(document.createElement('fake')),
this.parentNode.insertBefore(temp2, this.nextSibling),
this.parsed = 1
)
);
}
fake { display: none }
Stworzyłem tutaj element o mojej własnej nazwie - fake. Potem odwołałem się do niego w CSS i ukryłem go na 100% za pomocą display: none.
Teraz jesteśmy pewni, że będzie zawsze ten "fake" stał za div.status, żebyśmy się mogli go złapać i wstawić przed niego div.statusBot.
Wystarczy teraz wstawić dodatkowe 2 elementy do naszych div.statusTop i div.statusBot:
CODE
div.statusTop, div.statusBot {
-ieh: expression(
this.parsed ? 0 : (
temp = document.createElement('div'),
temp.className = 'statusRight',
this.appendChild(temp),
this.parsed = 1
)
);
}
Dostajemy teraz po jednym div.statusRight w każdym div.statusTop i div.statusBot. Wystarczy je teraz tylko ostylować wg własnego widzimisię i voila.
2.6 Praktyka - problemy z CSS
- Aby ustawić małą wysokość diva, na przykład 2px, należy dodać overflow: hidden, aby tekst nie rozpychał go w pionie.
- Aby uniezależnić się od szerokości ekranu / okna rozmowy tworząc obrazki teł po parę tysięcy pikseli, można wstawić 2 dodatkowe elementy do div.statusTop i div.statusBot. Wtedy pojemniki mogą dostać tło powtarzane w poziomie, a te 2 same zaokrąglenia.
- Gdyby zdarzyło się, że jakiś element zacznie zanikać w miarę jak ruszamy nad nim myszką albo przewijamy - dodajmy zoom: 1 do div.status (kontenera dodatkowe rzeczy)
Tak może wyglądać proof-of-concept z bardzo prostym stylowaniem (float, background-color).