Arayüz geliştiricileri (Front-end) dünyası çok hızlı bir şekilde güncelleniyor. Her gün birçok kütüphane ve araç çıkıyor ve bazıları kendilerini sonlandırıyor. Arayüz geliştiriciler için bu yeniliklerin takibi önemli bir konu. Kendini güncel tutmak için yenilikleri takip etmek olmazsa olmaz. Çıkan yenilikleri çalışma hayatımızı kolaylaştıran yenilikler, bunlardan haberdar olmak bizim iş yükümüzü azaltıyor. Aynı şekilde eskiyen ve yayından kalkan kütüphane ve araçları sistemimizden kaldırmak ve güncellemek bizim için bir görev.

npm WARN deprecated [email protected]: ...psst! 
Your project can stop working at any moment because its dependencies can change.
Prevent this by migrating to Yarn:
https://bower.io/blog/2017/how-to-migrate-away-from-bower/

zingat.com‘da middleware olarak nodejs kullanıldığı için client olarak tanımlanan tarafta için iki tane paket yöneticimiz vardı. npm (yarn) ve bower. Bower geliştirmeyi sonlandırdıktan sonra acaba tüm paketleri yarn’a mı geçirsek diye ara sıra konuşuyorduk. Sonra Doğan ile birikte bir gün kaldıralım bu bower’ı ne olacak dedik ve işe giriştik.

Bazı paketlerde sıkıntı yaşasakta bower kaldırma işlemi beklediğimizden daha kolay geçti.

İlk olarak bower.json dosyasındaki bağımlılıkları npm’e taşıdık.

"dependencies": {
"bootstrap": "3.3.1",
"highcharts": "4.1.10",
"jquery": "1.11.2",
"jsUri": "1.3.0",
"bootstrap-select": "1.12.1",
"jquery.tablesorter": "2.18.4",
"lodash": "4.15.0",
"jquery-validation": "1.13.1",
"jquery-mask-plugin": "1.14.0",
"bootbox": "4.4.0",
"moment": "2.9.0",
"numeral": "1.5.3",
"notifyjs": "jpillora/notifyjs#0.3.2",
"jquery.cookie": "1.4.1",
"jquery-ui": "1.11.4",
"jquery-touchswipe": "1.6.18",
"slick-carousel": "1.6.0",
"df-visible": "1.2.0",
"moment-timezone": "0.5.4",
"async": "2.0.1",
"DOMPurify": "dompurify#0.8.4",
"nouislider": "9.2.0",
"Watch.JS": "watch#1.3.1",
"multiple-circular-player":"0.0.2",
"jquery-lazy": "1.7.5"
}

sonra nodejs ile ön tarafta kullandığımız kütüphaneleri bu listeden sildik. lodash, moment, numeral vs.

Sonra bower_component, node_modules klasörü ve .bowerrc ve bower.json dosyalarını sildik. Ayrıca zingat.com yayına alma süreçlerindeki bazı kısımlardan da sildik.

yarn cache clean

ve

yarn

diyerek tüm bağımlılıklarımızı yükledik. Burada bower’dan taşıdığımız bazı kütüphaneler uyarı verdi. Belirttiğimiz sürümlerin yerine daha yeni sürümleri var diye. Bazı bağımlılıkları da bulamadı. yarn’ın bulamadığı kütüphaneleri https://yarnpkg.com/lang/en/ sitesinden aradık. Bazılarının isimleri npm’de farklılık gösterdiği için yükleyememişti. Yeni isimlerini package.json‘a ekledik ve komut satırından yarn komutu çalıştırdık.

Sıra geldi bu kütüphaneleri koda ekleyen grunt-concat yürütücüsünde bower_component geçen yerleri düzelttik.

Sonra kendi bilgisayarımızda projeyi ayağa kaldırdığımız da bazı scriptlerin çalışmadığını gördük. Çalışmayan kütüphaneler ismini değiştirdiğimiz kütüphanelerdi, bunları yeni node_module‘deki karşılıkları ile değiştirdik.

İşlem bitti.

Bunların dışında sitenin yayına çıkma süreçlerinde bazı düzenleme işleri çıktı. Site iyi bir testten geçtikten sonra bower’sız bir şekilde yayına çıktı.

Bower’ı o kadar kullandık ama artık zamanı geçti. Ne diyelim “Toprağı bol olsun” diyelim. :)

Kaynaklar

DOM (Belge Nesnesi Modeli) HTML ile javascript’i birbirine bağlar. DOM, HTML dokümanındaki tüm elamanları ağaç yapısı mantığıyla nesneye çevirir ve javascript’in erişebileceği hale getirir. Böylelikle dinamik olarak HTML elemanına ekleme, çıkarma ve biçimini değiştirme imkanı elde etmiş oluruz.

HTML’in yapısını etiketler (tag), attribute (öznitelik) ve elemanlar oluşturur.

Bir HTML belgesinin temel yapısı, içeriğini saran ve ona bir anlam katan etiketlerden oluşur. Örneğin <body> bir etikettir. Etiketler ek bilgi parçaları olan özniteliklere (attribute) sahip olabilirler. Örneğin <body id="anasayfa"> Öznitelikler iki bölümden oluşur. Öznitelik adı ve değeri. Elemanlar web sayfasını oluşturan bölümlerdir.

Bu temel bilgileri verdikten sonra asıl konumuza gelelim.

Biz bu makalede HTML öznteliklerini ve tarayıcıların yorumlaması sonucu oluşan DOM özelliklerine değineceğiz.

HTML Öznitelikleri (attributes) ve DOM özellikleri (property)

Tarayıcılar HTML dokümanını tararken DOM nesneleri oluşturur. HTML öznitelikleri bu nesnelerin özellikleri olur. Örneğin <body id="Haydaa"> tanımının DOM’daki karşılığı document.body.id dır.

HTML dokümanındaki tüm elemanlar, etiketler ve öznitelikler bu şekilde DOM nesnelerine çevrilir.

Standart öznitelikler bu şekilde DOM özelliklerine çevrilir. HTML’de standart dışı öznitelikler de tanımlanabilir. Örneğin <body id="Haydaa" sampiyon="Trabzon"> gibi bir tanım yapmak mümkündür. Ancak bu öznitelikler tarayıcı tarafından DOM özelliklerine dönüştürülmez.

document.body.sampiyon;

gibi bir kod bize undefined sonucu dönecektir.

Bir etiket için standart olan öznitelik başka bir etiket için standart olmayabilir. Örneğin <input type="text"> input için type standart iken body etiketine atanan type standart değildir.

Peki standart dışı özniteliklere javascript’ten nasıl erişeceğiz?

Bunun için hazır metotlar mevcut.

  • elem.hasAttribute(name) – varlığını kontrol et.
  • elem.getAttribute(name) – değerini al.
  • elem.setAttribute(name, value) – değer tanımla.
  • elem.removeAttribute(name) – özniteliği sil.

Örneğin yukarıdaki sampiyon tanımına erişmek için;

document.body.getAttribute('sampiyon');

bize Trabzon sonucu dönecektir.

Ayrıca elem.attributes ile de erişebiliriz. elem.attributes kodu bize tüm öznitelikleri adı ve değeri olan bir nesne koleksiyonu olarak dönecektir.

DOM Özelliği - HTML Özniteliği senkrenizasyonu

Standart bir HTML özniteliği değiştiğinde, ilgili DOM özelliği otomatik olarak güncellenir. Burada bazı istisnalar var. Sırası gelince değineceğiz.

Aşağıdaki örnekte, id bir HTML özniteliği değiştirilmiştir ve DOM özelliği de değişmiştir. Benzer şekilde DOM özelliği değiştirildiğinde HTML özniteliği değişti.

<input>

<script>
var input = document.querySelector('input');

input.setAttribute('id', '123');
alert(input.id); // 123 (güncellendi)

input.id = '456';
alert(input.getAttribute('id')); // 456 (güncellendi)
</script>

Ancak, farklı durumlar vardır, örneğin input.value HTML özniteliği değiştirildiğinde DOM özelliği değişir, ancak DOM özelliği değiştirildiğinde HTML öznteliği güncellenmez.

var input = document.querySelector('input');

input.setAttribute('value', 'çay');
alert(input.value); // çay

// Burada değişmez
input.value = 'kahve';
alert(input.getAttribute('value')); // çay (güncellenmedi!)

Bu dikkat edilmesi gereken bir durum.

Başka bir durum, HTML özniteliği göreceli bir URL veya yalnızca #hash içerse bile, href DOM özelliği her zaman tam bir URL döner.

Örneğin:

<a id="siteLink" href="#merhaba">link</a>
<script>
// HTML özniteliği
alert(a.getAttribute('href')); // #merhaba

// DOM özelliği
alert(a.href ); // tam URL http://site.com/page#merhaba
</script>

Sonuç

jQuery’den kurtulmak için giriştiğim yolda bu tip farklılıkların olduğunu öğreniyorum. Eskiden jQuery’de sadece attr() metodu vardı. Sonra prop() metodu da eklendi. jQuery topluluğu ilk önce prop‘un attr‘nin yerini aldığını söyledi. Ancak yukarıdaki fark sebebi ile hatalarını anlayıp her iki metodu da koruma yoluna gittiler. Yukarıda anlattığım farkı jQuery ile biz attr() ve prop() metodu ile uyguluyoruz.

Ben bu ve benzer durumlarda jQuery’nin javascript gerçeklerini tam anlamama engel olduğunu düşünüyorum. Bu durum da hatalar ile karşılaştığımızda saatlerce hatta günlerce zaman kaybetmemize neden oluyor. Bu bile tek başına jQuery’den vazgeçme sebebi olur.

Kalın sağlıcakla.

Kaynaklar

Ardalan resimler için uyguladığımız background-size ve background-position özelliklerine benzer bir kullanımı <img> ve <video> etiketleri içine uygulamamızı sağlayan özellikler.

Bu özelliğe ihtiyacımız çok eksilere dayanır. Görsel içeriğin kullanıcı tarafından girildiği sitelerde gelen resim boyutlarını istenen tasarımdaki içerik kutusuna sığdırma isteklerini karşılamak için bu özellikleri kullanırız. Bu özellik yaygınlaşmadan önce bu gibi ihtiyaçları karşılamak için resimleri ardalan resmine çevirip, background-size ve background-position ile halletmeye çalışırdım. Şimdi tarayıcı desktek oranları bayağı arttı ve artık kullanabiliriz.

object-fit

Yapısı : object-fit: [ deger ]
Aldığı Değerler : fill | contain | cover | none | scale-down
Başlangıç değeri: fill
Uygulanabilen elementler: yerine konabilir elementler
Kalıtsallık: Yok

object-fit özelliği, bir öğenin içerik kutusunun yüksekliğine ve genişliğine nasıl tepki verdiğini tanımlar. object-position özelliği ile birlikte resimler, videolar vd. medya formatları için tasarlanmıştır. object-fit içerik kutusuna nesneyi en/boy oranını koruyarak, mümkün olduğunca uzatarak veya mümkün olduğunca fazla yer kaplayacak şekilde yerleştirmeyi sağlar.

Aldığı değerler

  • fill: En/boy oranına bakılmaksızın görüntüyü içerik kutusuna uyacak şekilde uzatan varsayılan değerdir.
  • contain: En/boy oranını korurken kutuya doldurmak için duruma göre resmin boyutunu artırır veya azaltır.
  • cover: Resim, en/boy oranını koruyarak ancak işlem sırasında resmi kırparak kutunun yüksekliğini ve genişliğini dolduracaktır.
  • scale-down: Resim, en küçük somut nesne boyutunu bulmak için none ve contains arasındaki farkı karşılaştıracaktır ve uygun olanı uygulayacaktır.
  • none: Resim orijinal halindeki boyutlarını korur ve içerik kutusu içine sığmaya çalışmaz. İçerik kutusundan taşan kısımlar kırpılır.

Örnek ile daha iyi anlayacağız.

object-position

object-position özelliği bir objenin içerik kutusundaki yerini ayarlamamızı sağlar.

Yapısı : object-position: [ deger ]
Aldığı Değerler : left | center | right | top | bottom | uzunluk değerleri | yüzde değerleri
Başlangıç değeri: 50% 50%
Uygulanabilen elementler: yerine konabilir elementler
Kalıtsallık: Var

Örneğin üye resmi, adı ve soyadının olduğu bir alanımız var.

Görüldüğü gibi normal şartlarda resimler büzülmüş görünecektir. object-fit: cover; tanımı yaptığımızda en/boy oranı korunduğu için büzülme düzelcektir, ancak şimdide resimlerin üste çok yakın olması sorunu vardır. Bunu da halletmek için object-position: 50% 15%; tanımı yaparsak isteidiğimize yakın bir sonuç elde etmiş oluruz.

Bu gibi bir çok durum için kullanışlı özellikler.

Tarayıcı desteği

Can I Use object-fit? Data on support for the object-fit feature across the major browsers from caniuse.com.

Kalın sağlıcakla.

## Kaynaklar

DOM ilişkili seçiciler

İlk yazımda genel seçicilerden bahsetmiştim bu yazımda ise DOM üzerinden ilişkilendirilen seçicilerden bahsedeceğim. DOM’daki elementler bir ağaç yapısı ile aile bağlarına benzer bir şekilde bir birlerine bağlıdır. Bu ilişkiden yararlanılarak oluşturulan seçicilere DOM ilişkili seçiciler denir.

Örnek bir HTML kodu verelim;

<div>
<h1>HTML <em>Hiyerarşisi </em></h1>
<div><strong>Sitemize</strong> hoş geldiniz <strong class="es-gec">Merhaba</strong> biz <em>sizler için</em> <a href=""> bazı önemli konular!</a> hazırladık.</div>
</div>

Yukarıdaki koddaki HTML elemanlarının arasında bir aile yapısına benzer bir yapı vardır. Örneğin h1, em elementinin ebeveyni, diğer bir tanım ile em; h1‘in çocuk elementidir.

Ebevey (parent) seçicisi

Örneğin em elementinin ebeveynini

jQuery ile

$('em').parent();

Javascript ile

document.querySelector('em').parentNode;

h1 sonucu bize verecektir.

Çocuk (children) seçicisi

Alt eleman olarak da tanımladığımız çocuk seçicileri yaklamak için;

jQuery ile

$('h1').children();

Javascript ile

document.getElementsByTagName('h1').childNodes;

text ve em‘i yakalarız.

document.getElementsByTagName('h1').children;

ile sadece em‘i yakalarız.

Torun (Descendants) seçicisi

Bir elemanın alt eleman kümesindeki belirlenen tanıma uygun elemanları yakalamak için kullanılır. Yine CSS’den aşina olduğumuz bir kullanım.

jQuery ile

$('div em');

Javascript ile

document.querySelectorAll('div em');

Bu seçici bize her iki em elemanını verecektir.

En yakın ebeveyn (closest) seçicisi

jQuery kullanırken en yakın ebeveyni yakalamak için closest metodunu kullandığımız oluyor. jQuery’de bunun için bir metot var. Örnek verelim.

jQuery ile

$('a').closest('div');

ile kodumuz içindeki bağlantının en yakın div ebeveyni yakalanmış olur. Javascript’e de yeni gelen bu özellik ile aynı kolaylıkta elemanı yakalayabiliriz.

document.getElementsByTagName('a').closest('div');

Bu yeni bir özellik olmasına rağmen şu an Türkiye’deki desteği %83 seviyesinde. Desteklmeyen tarayıcılar için https://github.com/cferdinandi/getClosest kullanılabilir.

Can I Use element-closest? Data on support for the element-closest feature across the major browsers from caniuse.com.

Kardeş (siblings) seçicisi

Aynı ebeveyne sahip elemanlara kardeş seçiciler denir. Kardeş seçicileri ikiye ayırırız. Bitişik kardeş seçicileri birbiri ardına gelen seçiciler ve genel kardeş seçicileri. jQuery API’sindeki siblings metodu ise bunlardan biraz daha farklıdır. Tanımlanan elemanın seviyesindeki tüm elemanları (kendisi hariç) yakalar. Javascript’te bu durumu direk karşılayan bir metot yoktur. Basit bir fonksiyon ile bu isteği karşılabiliriz.

CSS’deki kardeş seçici mantığı ile ilk kardeşi yakalayıp sonrakileri seçerek jQuery siblings metodunu karşılayabiliriz.

Bu tip javascript’te olmayan metotları kodumuza kazandırdığımız kodları genel erişilebilir bir yerde tutabiliriz.

Genel bir fonksiyon tanımlayıp siblings dizisini oluşturalım. Belirlediğimiz elemanın ebeveyni ve oradanda bu ebeveynin ilk elemanını yakalarız. Sonra bir döngü içinde nextSibling yardımı ile sonraki elemanları yakalayıp bir diziye atarak çözümü oluşturabiliriz.

var getSiblings = function (elem) {
var siblings = [];
var sibling = elem.parentNode.firstChild;

for (; sibling; sibling = sibling.nextSibling) {
// kod gelecek
}
};

Siblings içinde belirlediğmiz elamanın olmaması lazım. Bunun için bir if kontrolü koymalıyız.

var getSiblings = function (elem) {
var siblings = [];
var sibling = elem.parentNode.firstChild;

for (; sibling; sibling = sibling.nextSibling) {
if (sibling.nodeType !== 1 || sibling === elem) continue;
siblings.push(sibling);
}
return siblings;
};

Son olarakta döngü bittiğinde sonuçları geri göndereceğiz.

jQuery ile

$('div.icerik .es-gec').siblings();

Javascript ile

let elem = document.querySelector('div.icerik .es-gec');
let siblings = getSiblings(elem);

jQuery basitliğinde değil ancak çokta zor olmayan bir yardımcı fonksiyon ile işimizi halletik.

Elemanları hariç tutmak (not)

Bazı elemanları seçimden hariç tutmak için

jQuery ile

$('p strong').not('.es-gec');

Javascript ile

document.querySelectorAll('p strong:not(.es-gec)');

Bu seçim sonrası sadece ilk strong elemnaı seçilmiş olur.

Çoklu eleman seçimi

Birden fazla eleman seçmek istediğimizde

jQuery ile

$('h1, .es-gec, a');

Javascript ile

document.querySelectorAll('h1, .es-gec, a');

yukarıdaki kodlar h1, .es-gec ve link elemanını verecektir.

Sonuç

Bu iki yazılık javascript seçicileri yazımızda gördük ki jQuery’nin en büyük avanatajlarından birisi olan seçiciler konusunda javascript’te yeterli seviyede.

jQuery’nin DOM üzerindeki hakimiyetinin çok fazla olması ve bu hakimiyeti oluşturmak için ürettiği metotlar(nextUntil, nextAll, offsetParent, parentsUntil, prevUntil, prevAll) çoğu zaman kırılgan ve anlışlmaz yapıların çıkmasına neden oluyor. Kırılganlığı önlemek ve daha esnek kodlar yazmak için DOM ilişkili seçicilerin kullanımına dikkat etmeliyiz.

Bazı durumlar için siblings ve closest örneklerinde gördüğümüz gibi yardımcı fonksiyonlar ile kolay çözümlerde oluşturabiliriz.

Kalın sağlıcakla.

Kaynaklar

Daha önce bu özelliği kullanacaktım ancak Chrome desteğini kaldırdığı için kullanım oranı çok düşüktü. Chrome 56’dan itibaren tekrar desteklemeye başladığı için artık kullanabiliriz.

position:sticky tanımlanan eleman kaydırma çubuğu gelene kadar position:relative gibi davranır, kaydırma çubuğu geldikten sonra position:fixed gibi davranır.

Örnek ile daha iyi anlayacağız.

Daha önce bu tip ihtiyaçları position:fixed ile yapıp kaydırma çubuğu gelene kadarki kısmı javascript yardımı ile çözüyorduk. Çünkü postion:fixed olan eleman position:absolute gibi davranıp her halükarda kendini aynı yerde sabitliyor.

Sticky kullanımlarında kaydırma çubuğu, elemana gelene kadar sabit kalsın ama kaydırma çubuğu gelince fixed olsun gibi istekler ile karşılaşıyorduk. Bu istekleri karşılamak için javascript çözümlerine başvuruyorduk. position:sticky güzel ve tek satrılık çözümü süper oldu.

Elemanın sticky olması için dikeydeki kaydırmalarda top / bottom değeri, yataydaki kaydırmalarda left / right değeri tanımlamak gerekiyor.

Desteklemeyen tarayıcılar için çözüm

Bu yazıyı yazdığımda Türkiye için destek %82 idi. Desteği olmayan tarayıcılar için iki seçenek var. Javascript ile destek sağlamak veya desteklemeyenlerde position:relative olarak tanımlamak.

Javascript ile çözüm

Javascript ile çözüm oluşturmak için aşağıdaki çözümlerden biri tercih edilebilir.

CSS ile çözüm

İkinci çözüm desteği olmayanlar için position:relative olarak bırakmak.

.sticky-element{
position: relative;
}

@supports(position:sticky){
.sticky-element{
position: sticky;
top: 0px;
}
}

Sonuç

Kullanıcı ihtiyacı olan bir özellik. Standartlaşması süper. W3C kullanıcı ihtiyaçlarını karşılamada çok yavaş kalıyor. Bu nedenle birçok şeyi olması gerektiği gibi değil çakma çözümler ile yapıyoruz. Umarım zamanla bu değişir.

Tarayıcı desteği

Can I Use css-sticky? Data on support for the css-sticky feature across the major browsers from caniuse.com.

Kaynaklar