Trolleme: Rengarenk mesajlar...

zztri

Yaşayan Forum Efsanesi
9 Tem 2015
10,055
388
Ankara
Geçenlerde elemanın biri rengarenk bir yorum yazınca, ben de benim yorumumu rengarenk yapacak ufak bir kod yazmıştım. Ama sorun şu ki o anda önümde visual studio açıktı, ondan C#'ta yazıldı o kod. Ben bookmarklardan tıklayabileceğim şekilde olmasını istiyorum.

Yani amacımız şu:

1. Javascript browser'da o anda seçili olan yazıyı bulup, her harfi 'color] tag'leri içine alıp yavaş yavaş değişen bir şekilde renklendirecek.
2. Boşluk ve enter karakterlerini (' ','\r','\n') görmezden gelecek.
3. Yazı içindeki bbcode'ları da doğal olarak görmezden gelecek. Yani '[' karakterine rastlarsa, ']' karakterine gelene kadar atlayacak.

Öncelikle ne yapacağız? Kullanıcı bir textarea içinde bir yazıyı seçip seçmemiş mi ona bakacağız. Yani o anda "aktif" olan eleman "textarea" olmalı, bu textarea'da selectionStart, yani seçilmiş yazının başlangıcı selectionEnd ile aynı olmamalı. Çünkü aynı ise iki değer de bize o andaki karetin yerini verir.

Kod:
if (docu ment.activeElement.tagName=='TEXTAREA' && docu ment.activeElement.selectionStart!=docu ment.activeElement.selectionEnd) {
  var hedefTextarea=docu ment.activeElement;
  //Asıl kodumuz burada olacak...
}

Yani dedik ki, dokümanda aktif eleman textarea değilse veya seçim boyutu 0'dan büyük değilse fonksiyonu terket.

E bunlar uyarsa, renklendirmeye başlayabiliriz. Ben R, G ve B değerlerini birer değişkende tutacağım, ayrıca o esnada hangi renge geçtiğimi bilmek için bir de "state" değişkeni tutacağım. Renk değişiminde her adıma geçişte, state'i bir sonrakine geçireceğim. Siz kendi istediğiniz renk değişimini yapabilirsiniz.

Tabii ilk olarak R, G, B değerlerini #?????? şeklinde yazmak için bir byte'ı hex formatında gösteren ufak bir fonksiyona ihtiyacımız var.

Kod:
var hexYap=n=>(n<16?'0':'')+n.toString(16);

Eğer sayımız 16'dan küçükse başına "0" eklemeyi unutmuyoruz, ardından kalan kısmını 16 radix'i ile (sayı tabanı ile) yazdırıyoruz yani...

Benim düşündüğüm renk geçişleri şunlar:

255,0,0
0,255,0
0,0,255
255,0,255
255,255,0
0,255,255
255,255,255

Gereken değişkenleri tanımlayalım, döngümüzü de yazalım.

Kod:
var R=255,G=255,B=255,state=0;
var renklenmisYazi='';
for (var i=hedefTextArea.selectionStart;i<hedefTextArea.selectionEnd;++i) switch (hedefTextArea.value[i]) {
  //Artık burada o anda işlediğimiz karaktere göre olacakları yazacağız.
}

Değişkenleri tanımladık, seçimin başlangıcından bitimine kadar bir döngü koyduk,

Şimdi bazı istisnalarımız vardı. Neydi? İlk olarak boşluk ve enter karakteri renklendirilmeyecekti.

Kod:
  case ' ':
  case '\r':
  case '\n':
    renklenmisYazi+=hedefTextArea.value[i];
    break;

Ardından, bbcode'ları atlayacaktık. Yani [ işaretini görünce, ] gelene kadar renklendirme yapmayacaktık.

Kod:
  case '[':
    for (;hedefTextArea.value[i]!=']';++i) renklenmisYazi+=hedefTextArea.value[i];
    renklenmisYazi+=']';
    break;

Karakter ] olana kadar ilerledik, sonra son olarak ] karakterini de elle koyduk. Bu kısım renklenme kısmından kurtuldu.

Kalan her karakter renklendirilmeli değil mi?

Kod:
  default:
    renklenmisYazi+='[color=#'+hexYap(R)+hexYap(G)+hexYap(B)+']'+hedefTextArea.value[i]+'[/color]';
    ....

Şimdi amele işi kalıyor. Her state için hangi değer artacak, hangisi azalacak, hangisi kontrol edilip gerekirse state atlanacak elle yazmak zorundayız.

Kod:
    switch (state) {
      case 0:
        G-=5;
        B-=5;
        if (G==0) ++state;
        break;
      case 1:
        R-=5;
        G+=5;
        if (R==0) ++state;
        break;
      case 2:
        G-=5;
        B+=5;
        if (G==0) ++state;
        break;
      case 3:
        R+=5;
        if (R==255) ++state;
        break;
      case 4:
        G+=5;
        B-=5;
        if (B==0) ++state;
        break;
      case 5:
        R-=5;
        B+=5;
        if (R==0) ++state;
        break;
      case 6:
        R+=5;
        if (R==255) state=0;
        break;
    }

En son olarak da seçimden önceki kısmı, ürettiğimiz renkli kısmı ve de seçimden sonraki kısmı birleştirip textarea'nın yeni değeri olarak atıyoruz...

Kod:
hedefTextArea.value=hedefTextArea.value.substr(0,hedefTextArea.selectionStart)+renklenmisYazi+hedefTextArea.value.substr(hedefTextArea.selectionEnd);

Bütün kodu tek bir seferde görelim;

Kod:
if (docu ment.activeElement.tagName=='TEXTAREA' && docu ment.activeElement.selectionStart!=docu ment.activeElement.selectionEnd) {
  var hedefTextarea=docu ment.activeElement;
  var hexYap=n=>(n<16?'0':'')+n.toString(16);
  var R=255,G=255,B=255,state=0;
  var renklenmisYazi='';
  for (var i=hedefTextarea.selectionStart;i<hedefTextarea.selectionEnd;++i) switch (hedefTextarea.value[i]) {
    case ' ':
    case '\r':
    case '\n':
      renklenmisYazi+=hedefTextarea.value[i];
      break;
    case '[':
      for (;hedefTextarea.value[i]!=']';++i) renklenmisYazi+=hedefTextarea.value[i];
      renklenmisYazi+=']';
      break;
    default:
      renklenmisYazi+='[color=#'+hexYap(R)+hexYap(G)+hexYap(B)+']'+hedefTextarea.value[i]+'[/color]';
      switch (state) {
        case 0:
          G-=5;
          B-=5;
          if (G==0) ++state;
          break;
        case 1:
          R-=5;
          G+=5;
          if (R==0) ++state;
          break;
        case 2:
          G-=5;
          B+=5;
          if (B==0) ++state;
          break;
        case 3:
          R+=5;
          if (R==255) ++state;
          break;
        case 4:
          G+=5;
          B-=5;
          if (B==0) ++state;
          break;
        case 5:
          R-=5;
          B+=5;
          if (R==0) ++state;
          break;
        case 6:
          R+=5;
          if (R==255) state=0;
          break;
      }
  }
  hedefTextarea.value=hedefTextarea.value.substr(0,hedefTextarea.selectionStart)+renklenmisYazi+hedefTextarea.value.substr(hedefTextarea.selectionEnd);
}

Şimdi de bir "bookmarklet maker" sitesi bulup, bunu bookmarklet haline getirelim.

Edit: Yanlışlıkla yazdığımız ekstra ++i ifadesini kaldırdım.
Edit II: Case 5 düzeltildi.

Sonucu test ediyoruz, üçüncü kez... Sabahın köründe uykum kaçınca yaparsam, böyle saçma hatalar olur işte. Asıl sıkıntı javascript'te debug etmekten nefret etmem. Hızlıca BBCode'ları da kontrol edelim. Bu bir linktir. Bu kalındır. Bu italiktir.

Bütün case'lere girdiğinden emin olmak için birazcık daha uzatmam lazım sanırım. Umarım bu kadar yeterdir. Bu sefer aptallık etmeyip renklendirmeden önce bir yere bu kısmın bir kopyasını alayım.

Tam emin olmak için üçüncü bir paragraf daha yazıyorum. Toplam 7 state olduğuna ve her state içinde 51 karakter boyunca durduğuna göre rahatça yetmeli.

En sonunda başardık. Kendiniz uğraşmak istemezseniz yeni bir bookmark oluşturun, URL yerine https://pastebin.pl/view/d227ae31 adresindeki yazıyı paste edin. Başarılı bir şekilde çalışacaktır.
 
Son düzenleme:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.