Asp.net MVC FileResult Dosyasını JQuery Ajax ile Yakalamak

1 Eyl

Asp.net mvc projelerinde dosya sonuçlarını kullanıcıya dönmek için action sonucunda File() metodu ile dönüş yapılabilmektedir.

Örneğin bir PDF için.

[HttpPos]
public FileContentResult Test(TestViewModel vm)
{
    var stream = new MemoryStream();
    //... add content to the stream.

    return File(stream.GetBuffer(), "application/pdf", "test.pdf");
}

Excel için;

[HttpPost]
public FileContentResult Test(TestViewModel vm)
{
    var stream = new MemoryStream();
    //... add content to the stream.

    return File(stream.GetBuffer(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "File.xlsx");
}

Bu oluşturulan dosyaya javascript tarafından jquery ile request gönderilirken dikkat edilmesi gereken bir husus, jquery’nin dosyayı bozmasıdır. Benzer bir durum burada yaşanmıştır. Dosya indiriliyor fakat bozuk olduğu için excel tarafından açılamıyor.

Bunu düzeltmek için xhrFields alanında responseType olarak arraybufffer değeri verilmelidir.

$.ajax({
    url: '/server/url',
    type: 'POST',
    contentType: "application/json; charset=utf-8",
    xhrFields : {
	   responseType : 'arraybuffer'
    },
    data: JSON.stringify(jsonData),   
    success: function (data) {
        var blob = new Blob([data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
        var downloadUrl = URL.createObjectURL(blob);
        var a = document.createElement("a");
        a.href = downloadUrl;
        a.download = "data.xls";
        a.click();
    },
});

Asp.net MVC web site oluşturma platformu olması dolayısı ile günümüzde çok sık kullanılmasa bile hala günümüzde yaygın olarak kullanılmaktadır. Dosya indirme konusunda internette epeyce aranmış ve çok fazla çözüm gösterilememiş bir konuya açılık getirmek istedim.

JQuery event.stopPropagation() ve event.preventDefault() metodları

23 Ara

JQuery ile event yakalama işlemleri sırasında iç içe geçmiş HTML elementleri sırasında istemeden bazı karışıklıklara neden olabiliriz. Bu karışıklıklardan bir tanesi, bir elementteki event tetiklendiğinde onun üst elementlerinde de olayın tetiklenmesidir.

event.stopPropagation()

Örneğin bir unorderedlist (<ul>) ile çalışırken listedeki bir eleman(<li>) tıklandığında, hemen (<ul>) elementinde de “click” event tetiklenecektir. Çünkü bu ili element iç içe barındırılmaktadır. Eğer (<li>) elementine tıklandığında (<ul>) elementinde bir “click” event gerçekleşmesinin istenmediği durumda event.stopPropagation() metodu kullanılmaktadır.


$("li").click(function(event){
   event.stopPropagation();
   alert("The li element was clicked.");
});

 

event.preventDefault()

Bir diğer durum ise HTML elementlerinin mevcut eylemlerini engelleme isteğidir. Örneğin bir link tıklandığında doğrudan linkin gösterdiği adrese yönlendirme yapılır. Ancak link tıklandığında bu eylemin engellenmesi gerekiyor ise event.preventDefault(); metodu kullanılabilir.


$("a").click(function(event){
   event.preventDefault();
});

Bu durumda link tıklansa da adrese yönlendirme yapılmaz.

Javascript Touch Events

22 Haz

Javascript kullanana uygulamaları kişisel bilgisayarların tarayıcılarında kullanırken yakalanabilen mouse olayları(events)mobil platforlarda mümkün olmamaktadır. Bunun yerinde mobil veya dokunmatik platformlarda touch(dokunma) olayları yakalanabilmektedir.

touchevents
Resim Kaynağı: http://www.girliemac.com/assets/images/articles/2013/04/touchevents.png

 

Mouse hareketlerinde olduğu gibi dokunmatik ekranlarda da javascriptin bizlere sunduğu touch down, touch move, touch end gibi olay yakalama(event handling) seçenekleri vardır.

Olay Açıklama
touchstart Kullanıcı ekrana bir veya daha fazla parmağını ekrana dokunduğunda gerçekleşir.
touchmove Kullanıcı ekranda parmağını dokunarak hareket ettirdiğinde, sürüklediğinde gerçekleşir.
touchend Kullanıcı ekrandan parmağını çektiğinde gerçekleşir.
touchcancel Ekrandaki temas noktası kesintiye uğradığında gerçekleşir.

 

touchstart

function start() {
   // Dokunulacak element referans olarak alınır.
   var touchElement = document.getElementById("touchelement");
 
   // Referans alınan elemente event handler eklenir.
   touchElement.addEventListener("touchstart", touchHandler, false);

   function touchHandler(event) 
   {
       e.preventDefault();

       console.log("I am touch start event");
  } 
} 

touchmove

function start() {
   // Dokunulacak element referans olarak alınır.
   var touchElement = document.getElementById("touchelement");
 
   // Referans alınan elemente event handler eklenir.
   touchElement.addEventListener("touchmove", touchHandler, false);

   function touchHandler(event) 
   {
       e.preventDefault();

       console.log("I am touch move event");
  } 
} 

Bu olayların hepsi bazı tarayıcıda çalışmayabilir. Ancak ilk üç olay(event) genelde tüm tarayıcılarda çalışır.

Olayları Chrome Internet tarayıcısında test etmek için F12 ile geliştirici araçlarında bulunan “Toggle Device Toolbar” seçeneği kullanılabilir. Bu seçenekte değişik mobil cihazların simülasyonu gerçekleştirilmektedir.

Adsız

Burada not olarak belirtmekte fayda var ki touchcancel olayını çalıştırmak için ekranda touchmove hareketini yaparken mouse sağ tuşuna basmanız yeterli olacaktır. Bu durumda ekranda ki temas noktası bozulmaya uğrar ve touchcancel olayı tetiklenecektir.

Angularjs direktif template belirleme ve $templateCache servisi

12 Eyl

Angularjs direktiflerinin görünüm tarafını template özelliği üzerinden belirleyebiliriz. Template özelliğini belirlemenin bazı yöntemleri vardır. Bunlar:

  • Düz metin şeklinde belirleme
  • URL ile dosya yolunu göstererek belirleme
  • $templateCache servisi ile belirleme

Bu işlemleri örnek bir personel kartı tanımlayarak gerçekleştirmeye çalışalım.

Düz Metin Şeklinde Template Belirlemek

Direktiflerin template özelliğini düz metin şeklinde belirlemek aşağıdaki yöntem izlenmelidir.

 

URL ile Dosya Yolunu Göstererek Belirleme

Bu yöntemde templateUrl özelliği olarak bir html dosya yolu verilir. HTML dosya üzerinde istediğimiz gibi düzenlemeleri yaparak yolunu bu şekilde direktife kolayca verebiliriz.

 

$templateCache Servisi ile Belirleme

URL ile template belirlerken yapılan işlem önceden hazırlanmış bir HTML dosyasının yolunu templateUrl özelliğine bildirmektir.

$templateCache servisini kullanırken HTML metinini önceden servise belirtmek gerekmektedir. Servisin kullanımı put() ve get() metodları üzerinden yapılmaktadır.

  • $templateCache.put(“templateAdı”, “template içeiği”)
  • $templateCache.get(“templateAdı”)

Template içeriğini uygulama başlatılırken yani modülün run fonksiyonu çalıştırıldığında gerçekleştirebiliriz.

 

$templateCache içerisindeki veriye templateUrl üzerinden aşağıdaki şekilde erişmek mümkündür.

Not: Angularjs uygulamalarında script şeklinde tanımlanan html içerikleri doğrudan $templateCache içerisine kaydedilir.

Bunu şu şekilde inceleyebiliriz:

Burada html içeriği script olarak tanımlanmıştır ve id değeri olarak card.html verilmiştir. İçeriğe javascript tarafından $templateCache.get(‘card.html’) şeklinde erişilebilmektedir.

Angularjs Proje Yönetimi

8 Eyl

Yazılım projelerinin geliştirilmesi sırasında karşılaşılan bazı genel problemler vardır. Bu problemler yazılımın Frontend veya Backend olmasına bağlı olmayan, sürecin gelişimi sırasında ortaya çıkan problemlerdir.

Projelerde istenen taleplere bağlı olarak yazılımda çok fazla kod olabilir. Kod sayısı arttıkça yazılımın çalışma performansı da düşmeye başlar. Bir süre sonra kodu yönetemez hale gelirsiniz. Artık kod sizi yönetmeye başlar ki bu durumda yeterki  çalışsın mantığıyla bir dizi mantıksız işler yapmaya başlayabilirsiniz. Bu gibi durumlarla başa çıkabilmek için uyguladığınız yöntemlerde kod sayısı artsa bile kodda karmaşıklığın oluşmaması gerekmektedir. Yani bir sene süren bir projede ilk gün nasıl kafa karışıklığı olmadan rahatça kod eklenebiliyorsa, son günde de aynı rahatlıkla kod eklemesi yapılabilmelidir. Modüler yapılar kullanarak bir şekilde kodun karmaşasını azaltabiliriz, bu sefer de modül sayıları artar ve iş süreleri uzamaya başlar.

Bu noktada işlerimizi önemli ölçüde kolaylaştıracak olan araçlar Framework’lerdir. Bizim yapmamız gereken bir takım işleri Framework’lere yüklemek zaman kazanmak açısından önemlidir. Her framework amaca uygun olmayabilir. Bu nedenle Framework seçiminde kolay kullanılabilirlik, sürekli güncellenme, performans ve geniş topluluklar tarafından kullanılıyor olmak önemlidir.

Angularjs bu açıdan bakıldığında yapılabilecek en doğru seçimlerden birisidir. Üretim ve destekleme tarafında Google vardır ve çok yaygın kullanılan bir Framework’dür. Kullanım açısından son derece kolaydır. Model ve View tarafındaki ayrımı yapabilmesi (MVC mimarisi) ve modüler geliştirmeye imkan sağlayan yapısı sayesinde kullanıcı dostu bir yapısı vardır.

Angularjs Yapı Taşları

Angularjs kendine özgü bir mimari üzerine geliştirilmiştir. Belli yapı taşları üzerine oturtulmuş bir düzen söz konusudur. Bunlar:

  • Module
  • Config
  • Route
  • Controller
  • View
  • Directive
  • Filter
  • Service
  • Factory

şeklinde sıralanabilir.

Angularjs Proje Yapılandırması

Angularjs ile yapılandırılacak projeler mimari açıdan önemlidir. Biz geliştiricilere düzgün kod yazabilmek için birçok imkanı sunan bir framewrok ile spagetti kod oluşturmamak lazım. Bu açıdan angularjs ile çalışırken dikkat edilmesi gereken bazı hususları aşağıda başlıklar halinde ele alınmıştır.

Modüler Yapı

Müşterinin her talebi için uygulamayı bölümlendirmek ve her bölüm için farklı bir modül oluşturulmalıdır. Geniş ölçekli bir uygulama geliştirirken her bileşeni tek bir modül altına toplamak yerine iş mantığına göre tasarlanmış birden fazla modül ile çalışmak daha uygun olacaktır. Örnek olarak Email Hizmeti veren bir uygulama için modüller şu şekilde olabilir:

angular.module("Epostalar", []);
angular.module("GelenKutusu", ["Epostalar"]);
angular.module("EpostaServisi", ["GelenKutusu"]);

Model Servisleri

Angularjs tarafından sunulan Dependency Injection yapısı sayesinde soyutlamalar kolayca yapılabilmektedir. Servis yapısı ile modüller arasında izolasyonlar yapılmalıdır. Bu sayede servisler veya modüller arasında kod aktarımı ile iletişim sağlanabilir.

Oluşturulan servisler tek bir görevi yerine getirmelidir. Örneğin HTTP protokolü üzerinden bir dış kaynak ile veri alış verişi yapacak olan bir servis sadece o kaynakla konuşmalıdır. Veriyi almışken servise hadi ekranda listeleme de yapın şeklinde ikinci bir görev verilmemelidir. Aksi taktirde hep karşısında durduğumuz karmaşıklık problemine doğru ilk adımı atmış oluruz.

Kod Yapısı

Mümkün olduğunca az kod satırlarıyla hazırlanmış, gerektiğinde servisler aracılığı ile haberleşebilen modüller oluşturulmalıdır. Servis, Controller ve Template gibi kod birimlerinin içerikleri sade anlaşılır ve kısa tutulmalıdır.

HTML tarafındaki bir DOM elemanları üzerinde Controller veya Service gibi yapılar içinden erişip doğrudan işlem yapmamalısınız.

Controller sınıflarından dış kaynaklara erişilmemelidir. Bu işlemi servisler aracılığı ile gerçekleştirip, ilgili servislere controller tarafından erişim sağlanmalıdır. Veri kümelerinin controller içerisinde depolanması da yanlış bir davranıştır.

Görünüm Yapısı

Görünüm tarafındaki HTML elementlerini depoladığımız yapılara template denir. Template içerisinde sadece HTML kodları ve Angularjs direktifleri olmalıdır. İş kuralları bu kısımda tanımlanmamalıdır. Kurallar template tarafından erişilen controller içerisinde tanımlanmalıdır. Aksi taktirde görünümle alakası olmayan kural belirleme sorumluluğu controller tarafından alınıp görünüm tarafına yüklenmiş olur.

Görünüm tarafında sürekli güncellenmesi gerekmeyen içerikler için TwoWayBinding yerine OneWayBinding tercih edilmelidir.

Proje Dizin Yapısı

Proje yapısı şekillendirilirken dikkat edilmesi gereken bir diğer yapı ise proje dizin yapısının oluşturulmasıdır. Kod birimlerinizi HTML, CSS, JS gibi özelliklerine ve Angularjs yapılarına göre ayırmak ve dizinlere aktarmak sık kullanılan bir yöntemdir.

Dizin
Yanlış Dizin Yapısı

Bütün controller dosyalarını Controllers dizini altında dizini altında toplamak, zamanla dizin içerisinde onlarca belki yüzlerce dosya birikmesine neden olacaktır. Bu durumda aradığımızı bulmak daha fazla zaman alacaktır. Örneğin bir EmailApplication projesi için GelenKutusu modülünün controller kodu Controllers dizininde aranacak ve görünüm için hazırlanan template kod dosyası ise Templates dizininde aranacaktır. Bu şekildeki proje tasnifi “türe göre tasnif” olarak adlandırılır. Türe göre tasnif edilen projeler zamanla projelerin karmaşık bir hal almasına neden olur.

Bunun yerine iş mantığına göre planlanmış bir dizin yapısı oluşturmak daha uygun bir yöntem olacaktır.

Uygun Dizin Yapısı
Uygun Dizin Yapısı

Email hizmeti ile ilgili iş kurallarını ve dosyalarını tabakalandırarak çalışmak daha uygun bir seçim olacaktır. Bu şeklide proje tasnifine ise “özelliğe göre tasnif” denir. Bu durumda Email listemizdeki kişilerle ilgili işlemlerin Contacts dizininde olduğunu özellik bakımından kolayca anlayabiliriz. Hem görünüm hem kullanım açısından sade ve anlaşılır bir yöntemdir.

Kodun organizasyon yapılandırması tamamen ekibinize veya size kalmış bir seçimdir. Bir dayatma söz konusu değildir. Temel nokta, kodun iyi bir şekilde ayrıştırılması ve ayrıştırılan bölümlerin yeni bir karmaşaya yol açmamasıdır.

Bu yazıda angularjs projeleri oluşturulurken dikkat edilmesi gereken önemli hususlardan bahsetmeye çalıştık. Umarım faydalı olmuştur. Bir sonraki yazıda görüşmek dileğiyle.

Javascript Array.prototype.slice.apply(arguments)

2 Tem

Geleneksel programlama dillerine göre bir çok yönden farklılık gösteren Javascript dilinde nesne oluşturma fonksiyonlar yardımıyla yapılır. Javascript dilinde, function tipleri normal programlama dillerindeki class benzeri işlev görür. Bir function tipinden yeni bir nesne oluşturmak için new anahtar sözcüğü kullanılır. function tipine dışarıdan gönderilen argümanlar arguments isimli bir iç değişkende tutulur. Aşağıdaki örnek, bir fonksiyona gönderilen argümanları listeleme işlemini göstermektedir.


function f(){
   return arguments;
}

console.log(new f());      // Ekrana [] yazar.
console.log(new f(1,2));   // Ekrana [1,2] yazar.
console.log(f(1,2));       // Ekrana [1,2] yazar.

Ekrana yazım şekilleri her ne kadar Array tipinde görünse bu diziler Array nesnesinin özelliklerini taşımazlar. Yani:


function f(){
   return arguments;
}

console.log(f(1,2) instanceof Array);    // Ekrana false yazar.

Çünkü oluşturulan nesneler Array tipinin push, pop, slice benzeri prototype özelliklerini taşımazlar. Bir fonksiyonun arguments üyesini Array tipine dönüştürmek için Array.prototype.slice.apply(arguments) şeklinde kullanmak gerekmektedir. Bu şekilde kullandığımızda, nesne içerisindeki argümanlar Array tipine dönüştürülmüş olur. Yani bu yöntem ile Array olmayan fakat ona benzeyen nesneleri Array tipine dönüştürür.


function f(){
   return arguments;
}

console.log(Array.prototype.slice.apply(f(1,2)) instanceof Array)
// Ekrana true yazar.

Bu özellikler Javascript dilinde ileri seviye işlemlerde önem arz etmektedir. Örneğin kütüphaneler oluştururken bizim sınıflarımızı kullanan kullanıcıların gönderdiği parametreleri bu şeklide alıp değerlendirmek durumunda kalabiliriz. Açık kaynak javascript kütüphanelerini inceleyerek dilin daha fazla özelliğini kavramak mümkündür.

Bir sonraki yazıda görüşmek dileğiyle.

 

Javascript Class ve Nesne Oluşturma

1 Tem

Javascript programlama dili, geleneksel programlama dillerindeki gibi gelişmiş özelliklere sahip olmasa da nesneye yönelik programlama açısından son derece esnek bir yapıya sahiptir. Bu yazıda nesneye yönelik programlamada önemli bir yer tutan class yapısını incelemeye çalışacağız.

Javascript dilinde class benzeri tanımlamalar fonksiyonlar yardımıyla yapılmaktadır. Class benzeri diyorum çünkü geleneksel programlama dillerindeki gibi class tanımlamak için özel bir yöntem yoktur. Her fonksiyon bir class olarak değerlendirilebilir ve her fonksiyonun new anahtar sözcüğü ile bir nesnesi oluşturulabilir.

1-Fonksiyon Tanımlamak

Normal bir Javascript fonksiyonu tanımlayarak aşağıdaki gibi bir class oluşturabiliriz.


function Map(name){
    this.name = name;
    this.version = "1.0.0";
    this.zoomLevel = 0;
    this.zoomin = zoomIn;
}

function zoomIn(){
    return this.zoomLevel + 1;
}

Yukarıda tanımlanan bir constructor fonksiyondur. Aynı zamanda class olarak değerlendirilir.  Bu class tipinde bir nesne aşağıdaki gibi oluşturulabilir.


var map = new Map("myMap");
map.version = 1.1.1;
map.zoomin();

2-Anti Pattern

Yukarıda tanımlama da zoomIn metodu Map calss dışında ayrı bir şekilde tanımlandığından  bir anti pattern oluşmaktadır. Kodun çalışması açısından hiç bir sorun yoktur. Ancak dışarıda tanımlanan her metod, global namespace içerisinde yer alacağından başka bir amaçla aynı isimde (zoomIn) bir metod tanımlandığında bu durum bir isim karışıklığına sebep olacaktır. Bu tür kirliliklerin önüne geçmek adına ihtiyaç duyulan metodlar constructor fonksiyonların içerisine tanımlanmalıdır.

function Map(name){
    this.name = name;
    this.version = "1.0.0";
    this.zoomLevel = 0;
    this.zoomin = function(){
           return this.zoomLevel + 1;
    }
}

Bu şekilde bir tanımlama kodda her hangi bir değişikliğe sebep olmayacaktır.

3-Metodların Prototype Şeklinde Tanımlanaması

2. maddede olduğu gibi metodları constructor fonksiyon içerisine tanımlayarak anti pattern oluşumundan kurtulmak mümkündür. Ancak bu durumun karşımıza çıkardığı bir dezavantaj vardır. Her nesne oluşturulduğunda zoomin() metodu yeniden oluşturulacaktır. Bu dezavantajı ortadan kaldırmak için zoomin() metodu prototype olarak tanımlanmalıdır.

function Map(name){
    this.name = name;
    this.version = "1.0.0";
    this.zoomLevel = 0;
}

Map.prototype.zoomin = function(){
    return this.zoomLevel + 1;
}

4-Doğrudan Nesne Tanımlamak

Şu ana kadar olan bölümlerde constructor fonksiyonlar yardımıyla sınıf simülasyonları olşuturduk ve new anahtar sözcüğü ile bu constructor fonksiyonlardan nesneler oluşturduk. Bu bölümde doğrudan nesneler tanımlamayı inceleyeceğiz.

Javascript dilinde doğrudan nesne tanımlamak object literal olarak geçer. Doğrudan oluşturulan  nesnelerden new anahtar sözcüğü ile tekrardan nesneler oluşturulamaz. Doğrudan bir nesne oluşturmak:

  var obj = {};

veya

  var obj = new Object();

şeklinde yapılabilmektedir.

Dizler için doğrudan nesne oluşturmak:

  var arr = [];

veya

  var arr = new Array();

şeklinde yapılır.

Herhangi bir sınıf tanımlamadan Map nesnesini doğrudan oluşturmak mümkündür.

var map = {
    this.name = name,
    this.version: "1.0.0",
    this.zoomLevel: 0,
    this.zoomin: function(){
        return this.zoomLevel + 1;
    }
}

Artık bu nesneyi doğrudan kullanmak mümkündür.

   map.version = 1.1.1;
   map.zoomin();

Bu tür tanımlamalar singleton olarak da geçer.

5-Fonksiyonlar Yardımıyla Singleton Nesne Tanımlamak

var map = new function(name){
    this.name = name;
    this.version = "1.0.0";
    this.zoomLevel = 0;
    this.zoomin = function(){
           return this.zoomLevel + 1;
    }
}

Burada tanımlanan constructor fonksiyonunun önünde new anahtar sözcüğü kullanıldığında doğrudan bir nesne oluşturulmuştur.

Böylece Javascript dilinde class ve doğrudan nesne kavramını ve bu türlerin nasıl tanımlandığını ve kullanıldığını incelemiş olduk. Bir sonraki makalede görüşmek üzere.

Javascript ve HTML Dom element etkileşimleri

8 Ara

Javacsript kodu ile HTML Dom elementler arasındaki etkileşimleri genelde elementin ID değeri üzerinden sağlarız. Javascript kodu ile document.getElementById(“elementId”) şeklinde ID aracılığıyla elementin seçilebilmesi mümkündür. Bu aşamadan sonra ise element üzerindeki bir değerin değiştirilmesi veya bir olayın(event) tetiklenmesi gibi işlemeri yapmak daha kolay hale gelmektedir.

HTML elementleri üzerinde tanımlı mevcut nitelikler(attributes), javascript tarafından elemente erişmemizi sağlarlar. Mevcut elementlerin kullanılabildiği gibi kendi tanımlayacağımız özel elementler üzerinden de bağlantı kurmamız mümkündür. Günümüzde kullanılan birçok Javascript kütüphanesi kendi tanımladığı nitelikler üzerinden işlemlerini yürütmektedir. Örneğin AngularJS ile çelışırken “ng-*” şeklinde veya JQuery ile çalışırken “data-*” şeklinde nitelikleri görürüz.

Şimdi bir senaryo geliştirerek biz de kendi tanımladığımız HTML nitelikler aracılığı ile bir uygulama geliştirmeye çalışalım. Bir buton elementi üzerine ekleyeceğimiz netelikleri(attribute) javascript tarafında kullanmaya çalışalım.

<button type="submit"
         data-get-async="true"
         data-url="/products.txt"
         data-attr-target="#getasyncresult">Getir
 </button>

Buton üzerinde data-get-async, data-url, data-attr-target şeklinde tanımladığımız nitelikleri anlamlandırmamız gerekmektedir.

data-get-async: işlemin asenkron gerçekleştirileceğini,
data-url: talebin gönderileceği adresi,
data-attr-target: talep sonrasında dönen cevabın hengi elementi etkileyeceğini belirtiyoruz.

Javascript dosyasını (deneme.js) ise şu şekilde düzenliyoruz:

<script type="text/javascript">

   $(function() {
       var buttonRequest = function () {
       var $button = $(this);
       var options = {
           url: $button.attr("data-url")
      };

      $.ajax(options).done(function(data) {
        console.log(data);
        var $target = $($button.attr("data-attr-target"));
        $target.html(data);
      });
  };

  $("button[data-get-async='true']").click(buttonRequest);
})
</script>

javascript tarafında gerçekleştirdiğimiz işlemi kısaca özetleyecek olursak, yaptığımız şey data-get-async niteliğini barındıran buton tıklandığında yapılacak işlemi belirlemektir.

$(“button[data-get-async=’true’]”).click(buttonRequest);

Bu örnekte “data-*” şeklinde nitelikler tanımlamamın sebebi yardımcı olarak JQuery kütüphanesini kullanıyor olmamdır.

JQuery ajax sorgusu için gerekli url gibi seçenekleri de yine buton üzerinde tanımlanan niteliklere tanımlıyoruz. Geriye kalan ise javascript işlemleridir.

Bu şekilde bir uygulama ile HTML tarafı ile Javascript kod tarafı birbirinden ayrılmış olmaktadır. Yani ön yüz(front end) geliştirme tarafında, Model ve View şeklinde bir ayrım yapılmış olmaktadır. Javascript MVC geliştirme araçlarının yaptığı işlem de bu şekildedir aslında. Direktifleri HTML nitelikeri(attributes) aracılığı ile alır ve komutları çalıştırırlar.

Bir sonraki yazıda görüşmek dileğiyle.

Yaygın Olarak Kullanılan Javascript MVC Çatıları

25 Eki

Yazılım dünyasında en popüler tasarım şablonlarından olan MVC(Model View Controller) tasarım şablonu, geleneksel programlama dillerinin yanında Javascript tarafında da yaygın olarak kullanılmaya başlamıştır. MVC bir uygulamada yapılması gereken işlerin üç sınıfta birbirinden ayrılmasıdır.

Model: Modellenen verinin tipi olarak düşünülebilir. Örneğin; ürün, kullanıcı, sipariş, v.s

View: Uygulamanın ön yüzü oalrak düşünülebilir. Örneğin; temalar, css, resimler.

Controller: Uygulamadaki eylemleri karşılar. Örneğin; Tıklamalar, istekler, cevaplar.

Javascript dili, kullanıcı(client) taraflı bir dil olduğundan ve internet tarayıcısı(browser) tarafından yorumlandığından bir ön yüz geliştirme aracıdır. MVC tasarım şablonunun ön yüzde yani View tarafında uygulanması biraz ilginç gelebilir. Fakat her ne kadar View tarafında olsak da ortada bir programlama aracı vardır ve bu programlama aracı ile yani javascript ile ön yüzde MVC şablonunu uygulamak mümkündür. Model ve Controller olarak javascript nesnelerini, View olarak ise HTML elemntlerini düşünebiliriz. Bu sayede MVC şablonunu ön yüz geliştirme ortamına uygulayabiliriz.

Neden MVC çatıları kullanılır?

Javascript MVC çatısı altında DOM etkileşimleri yanı sıra Sunucu ve Kullanıcı arası iletişimleri sağlamak mümkündür. Bu iletişim sırasında alınan ve gönderilen veriler üzerinde bazı mantıksal işlemleri uygulamak gerekebilir. MVC çatılarını kullanarak bu mantıksal işlemleri View tarafından ayırabiliriz.

Bir uygulama çatısı geliştirmek çok külfetli ve maliyetli olduğundan sıfırdan kütüphaneler yazmak yerine güven kazanmış açık kaynak kütüphaneleri kullanabiliriz.

Seçerken Dikkat

Bir MVC çatısını seçerken dikkat edilmesi gereken bazı hususlar vardır. Bunlar:

  • İhtiyacımızı gerçekten karşılayacak yapıda olması.
  • Destek alabilecek bir topluluğun olması.
  • Dökümantasyonunun iyi yapılmış olması.
  • Küçük uygulamalarla kullanım kolaylığının test edilmiş olması.

Javascript MVC Çatıları

MVC tasarım şablonunun javascript tarafında rahatça kullanılabilmesi için birçok çatı(framework) geliştirilmiştir.

Benim tecrübe ettiğim javascript MVC araçları Knockout, AngularJS, giriş seviyesinde de Backbone olmuştur. Fakat yaygın olarak kullanılarn Javascript MVC araçlarını şu şekilde listeleyebiliriz:

  • AngularJS
  • BackboneJS
  • KnockoutJS
  • EmberJS
  • AgilityJS
  • CanJS


Bir sonraki yazıda görüşmek dileğiyle.

Javascript ile sunucuya dosya yükleme işlemi

13 Eki

Javascript dili son yıllarda yaygın bir ön yüz(front end) geliştirme aracı haline gelmiştir. Farklı problemlere çözüm üreten kütüphanelerin sayısı gün geçtikçe artmakta ve “front end” geliştiricilerin işi de epeyce kolaylaşmaktadır.  Bazı durumlarda hazır kütüphanelerin dışına çıkıp kontrolü elimize almak istediğimizde Javascript kodları ile birebir haşır neşir olmak durumunda kalırız.

Javascript ile ağırlıklı olarak DOM (Document Object Model) işlemeleri yapılmaktadır. DOM Türkçe olarak “Belge Nesnesi Modeli” şeklinde çevirilebilir. Sunucu tarafından oluşturulup(render) bize gönderilen internet sayfasını bir belge olarak düşünebiliriz. Bu internet sayfasında gördüğümüz yazı, resim, video, form gibi elemanları birer nesne olarak düşünebiliriz. Javascript dili ile bu nesneler üzerinde işlemler yapabilmekteyiz. Bunun yanı sıra Javascript dili bize sunucu ile iletişim kurmamızı da sağlamaktadır. Sunucudaki bir URL üzerinden veri istemek veya sunucuya veri göndermek mümkündür.

Javascript bize, sunucuya düz metin (plain text) verisi göndermenin yanı sıra bir de dosya gönderme imkanı sunmaktadır. Bu yazının konusu da dosyaların sunucuya gönderimi sırasında işlemleri takip etmektir.

Javascript ile arka plandan sunucu ile bilgi alışverişi yapmak istediğimizde XMLHttpRequest nesnesini kullanırız. XMLHttpRequest nesnesi ile;

  • Sayfa yenilemeden bilgi alışverişi yapmak mümkündür.
  • Veri alışverişi arka planda gerçekleşir.
  • Veri alışverişi asenkron veya senkron olarak belirlenebilir.

Sunucuya bir istek göndermek için XMLHttpRequest nesnesinin Open() ve Send() metodları kullanılır.

  • open() Metodu: Gönderilen isteğin(request) türünü(GET, POST), URL adresini ve isteğin asenkron olup olmadığını belirler.
  • send() Metodu: İsteği sunucuya gönderir.

XMLHttpRequest nesnesinin çalışma prensibini incelemek için bir kaç örnek vermeden geçmek olmaz.

Örnek: Senkron çalışan yöntem

Senkron Yöntem
Senkron Yöntem

Senkron yöntemlerde open() metodunun son parametresi false olarak belirlenir ve send() metodu ile istek sunucuya gönderilir. İşlem asenkron olmadığından istek gönderildikten sonra cevap gelene kadar beklenir. Yani send() metodundan sonra gelen kodlar çalışmaz.

Örnek: Asenkron çalışan yöntem

Asenkron Yöntem
Asenkron Yöntem

Asnekron isteklerde open() medodunun son parametresi true olarak belirlenir ve request nesnesinin readystatechange olayına(event) bir metod bağlanır. Sunucudan cevap geldiğinde bu metod tetiklenir. İsteği göndermek için send() metodu çalıştırılır.  İşlem asenkron olduğundan send() metodu çalıştırıldıktan sonra başka kod satırları varsa onlar da çalıştırılır.

Bu örneklerde sunucudan GET metodu ile düz metin sonucu almak için uygulamalar yaptık.

Asıl konumuz, bir dosyanın bir isteğe(request) eklenerek sunucuya gönderilmesi işlemidir. Dosyalar büyük veriler olabildiği için, uzak sunucuya gönderilmeleri sırasında takip grektiren bir durum durum ortaya çıkmaktadır. İsteğin sunucuya ulaşıp ulaşmadığı, dosyanın bir T anında yüzde kaçının yüklendiği ve işlemin tamamlanıp tamamlanmadığı gibi durumların kullanıcıya bildirilerek belirsizliğin ortadan kaldırılması gerekmektedir.

Dosya gönderim işlemleri sırasında XMLHttpRequest nesnesinin upload özelliğinden faydalanırız. upload özelliği üzerindeki olaylar(events) sayesinde yükleme işlemlerini takip edebiliriz.

Upload Javascript Kodu
Upload Javascript Kodu

upload özelliğinin;

  • loadstart olayı: yükleme işlemi başladığında tetiklenir.
  • progress olayı: yükleme işlemi sırasında her giden byte grubu sunucuya aktarıldığında tetiklenir.
  • load olayı: yükleme işlemi başarıyla tamamlandığında tetiklenir.

request.open() metodu çalıştırıldıktan sonra setRequestHeader metodu ile gönderilecek olan isteğe(request) dosya bilgileri eklenir. Dosya bilgileri, file tipindeki input elementinden alınır. send() metodu ile istek POST tipinde sunucuya gönderilir. Burada send netodunun parametre alan çeşidi kullanılmış ve parametre olarak POST edilecek bilgi send metoduna eklenmiştir.

Dosya Upload İşlemi
Dosya Upload İşlemi

Dosya yükleme sırasında işlem takibini konsola yazarak gerçekleştirdim. Siz isterseniz HTML elementlerine yazarak gerçekleştirebilirsiniz. Hatta daha önceki yazılarımdan birinde css aracılığı ile durum çubuğu yapmayı işlemiştim. Dosya upload işlemini bu yöntemle bir durum çubuğuna bağlamak mümkündür.

Bir sonraki yazıda görüşmek üzere.