Sunday, February 28, 2016

İz Olduk

Arşın kalbinde nur idik ateş olduk ferşe düştük
Yaktık yıktık harabe ettik kıyamet olduk
Sonra kara bir bulut olduk yükseldik dağıldık
Simsiyah yağmur olduk toprağa karıştık
Aslan olduk, ceylan olduk ayaklandık
Kuş olduk, böcek olduk kanatlandık
Ağaç olduk, çiçek olduk kök saldık
Sonra öldük...
Şarkı olduk, söz olduk, şiir olduk anlam bulduk
Alemin hatırında incecik bir iz olduk şereflendik

Jquery ile Boostrap Açık-Kapalı Dikey Akordiyon Menü Oluşturmak - Designing Bootstrap Open-Close Vertical Accordion Menu with Jquery

Bu yazıda daha önce oluşturulan akordiyon menü sola yaslı açınıp kapanabilen bir yapıya dönüştürülecektir. Bu yazı daha önceki yazının devamı niteliğinde olup akordiyon menü anlatımı için bu yazıya bakmak gerekmektedir.

Öncelikle CSS kodlarını tanımlayalım:

<style>
        
        .menuContainerVyy
        {
            position:relative;
            width: 200px;
            height: auto;
            left:0;
            top:0;
            border-right: 3px solid black;
            background-color:Orange;            
        }
        
        .menuSubContainerVyy
        {
            overflow: hidden;
            background-color:White;
            margin-right:10px;
        }
        
        .menuButtonVyy
        {
            position: absolute;
            left: 100%;
            top: 50%;
            margin-left: -3px;
            margin-top: -15px;
        }
        
        .menuContainerVyy .nav
        {
            width: 200px;
        }
        
</style>

Burada önemli noktalardan ilki "position" tanımlamasıdır. Bu niteliği "relative" olan element mevcut konumuna göre göreceli olarak yerleştirilmektedir. Niteliği "absolute" olan element ise ebeveyn elementi "static" olmayan yani pozisyonlanmış elemente göre göreceli yerleştirilmektedir. Yazı içinde sunum maksadıyla taşıyıcı element "relative" olarak pozisyonlanmıştır. Taşıycı elementin bu niteliği "absolute" yapılarak ve kodları uygun yere konularak menü web uygulaması içinde istenilen bir yere konumlandırılabilir.

Burada bir diğer önemli nokta ise "overflow" niteliğidir. Bu nitelik değeri "hidden" yapılarak animasyonun menü kapsayıcı elementi sıkıştırırken iç yapıyı bozmaması sağlanmıştır. Yani sıkıştırma işlemi sırasında iç elementler kapsayıcı elementin içine sığmayarak taşmakta, bu durumda bu taşan kısımlar gizlenerek daha akıcı bir animasyon oluşturulmakta, ayrıca kapanma animasyonu sonunda menünün tamamen gizlenmesi sağlanmaktadır.

Sonraki aşamada javascript kodlarını tanımlayalım:

function toggleMenu(sender) {

            var parentElement = $(sender).parent("div");

            if (parentElement.width() > 0) {
                parentElement.animate({ width: '0px' }, "slow");
            }
            else {
                parentElement.animate({ width: '200px' }, "slow");
            }
        }

Yukarıda fonksiyon menü açma-kapama işlemini yerine getirmektedir. Bunu yaparken kapsayıcı elementin genişlik değerinin sıfır olup olmadığı kontrol edilmekte, durumu göre kapsayıcı element jquery "animate" fonksiyonu kullanılarak animasyonlu genişletilip daraltılmaktadır.

Bir önceki yazıdan farklı olarak menünün DOM içinde bulunmasında aşağıdaki kod yerine sınıf üzerinden arama yapan yeni kod kullanılmıştır:

#VerticalMenu1.nav.nav-pills.nav-stacked > li
.menuContainerVyy .nav.nav-pills.nav-stacked > li

Son olarak Bootstrap menü kodlarını sarmalayan HTML kodlarını ekleyelim:

<div class="menuContainerVyy">
<button class="btn btn-default menuButtonVyy" onclick="toggleMenu(this);" type="button">
<span class="glyphicon glyphicon-menu-hamburger"></span>
</button>
<div class="menuSubContainerVyy">
BURADA MENÜ KODLARI BULUNMAKTA!
</div>
</div>

Yukarıda yer alan kodlar çalıştırıldığında aşağıdaki sonuç elde edilmektedir:

Friday, February 26, 2016

Jquery ile Boostrap Akordiyon Menü Oluşturmak - Designing Bootstrap Accordion Menu with Jquery

Bu yazıda Bootstrap "Pills" kullanılarak akordiyon menü oluşturulacaktır. İlk aşamada "Vertical Pills" yani dikey hapları oluşturacak Bootstrap kodunu yazalım:

<ul id="VerticalMenu1" class="nav nav-pills nav-stacked">
    <li><a data-toggle="tab" href="#">Home <span class="glyphicon glyphicon-chevron-down" style="float: right;"></span></a></li>
    <div class="panel-body" style = "display:none;">
    Section1
    </div>
    <li><a data-toggle="tab" href="#">Menu 1<span class="glyphicon glyphicon-chevron-down" style="float: right;"></span></a></li>
    <div class="panel-body" style = "display:none;">
    Section2
    </div>
    <li><a data-toggle="tab" href="#">Menu 2<span class="glyphicon glyphicon-chevron-down" style="float: right;"></span></a></li>
    <div class="panel-body" style = "display:none;">
    Section3
    </div>
    <li><a data-toggle="tab" href="#">Menu 3<span class="glyphicon glyphicon-chevron-down" style="float: right;"></span></a></li>
    <div class="panel-body" style = "display:none;">
    Section4
    </div>
  </ul>

Burada önemli unsurlardan biri "data-toggle" niteliğidir. Bu nitelik ile ögenin üstüne tıklandığında otomatik olarak "active" sınıfının ögeye eklenmesi sağlanmaktadır. Detay gösteren div'lerin display niteliği "display:none" yapılarak div'ler görünmez hale getirilmektedir.

Akordiyon özelliğini tanımlamak amacıyla aşağıdaki javascript kodlarını oluşturalım:

$(document).ready(function(){

   $("#VerticalMenu1.nav.nav-pills.nav-stacked > li").click(function(){
     
     var parentElement = this;
     var section = $(parentElement).next("div").first();

     if(!$(section).is(":visible"))

       $(section).slideDown({ duration:"fast", complete: function(){
  
            UpdateArrow($(section).is(":visible"), parentElement);
       }});
     else
       $(section).slideUp({ duration:"fast", complete: function(){

            UpdateArrow($(section).is(":visible"), parentElement);
       }});

   });

});

function UpdateArrow(Visible, Obj)
{
   if(Visible)
   {
      $(Obj).find("span").addClass("glyphicon-chevron-up");
      $(Obj).find("span").removeClass("glyphicon-chevron-down");
   }else
   {
      $(Obj).find("span").removeClass("glyphicon-chevron-up");
      $(Obj).find("span").addClass("glyphicon-chevron-down");
   }

}

Burada jquery "slideUp()" fonksiyonuyla detay alanı kapatılmakta, "slideDown()" fonksiyonu ile detay alanı açılmaktadır. Jquery "next()" fonksiyonuyla sonraki çocuk elementler seçilmektedir. Jquery "find()" fonksiyonu ile DOM üzerinde derin arama yapılmaktadır.

Ok, animasyon olay akışı dışında güncellendiği zaman animasyonun iptal edildiği durumlarda yanlış durama geçebilmektedir (Örn. Hızlı çift tıklama veya seri tıklama). Bu sebeple ok durumunu güncelleme işlemi "complete" olayında yapılmaktadır. Bu olay animasyon tamamlandığında tetiklenmektedir. Animasyon tamanlandığında detay div'in görünürlüğü kontrol edilmekte ve ok durumu düzenlenmektedir.

Yukarıda yer alan kodların çalıştırılması ile aşağıdaki sonuç elde edilmektedir:

Thursday, February 25, 2016

Jquery ile Açılıp Kapanabilen Bootstrap Panel Oluşturmak - Designing Open-Close Bootstrap Panel with Jquery

Bu yazıda bootstrap panelin nasıl açılıp kapanabilen bir yapı haline getirilebileceği konusu işlenecektir. Bootstrap panel div elementleri ile oluşturulan, yorum alanları, içerik görüntülemeleri veya kısa gösterimler gibi bir çok alanda kullanılabilen kullanım alanı geniş bir ögedir. Bootstrap panel aşağıdaki kod bloğu ile oluşturulmaktadır:

<div class="panel panel-primary">
<div class="panel-heading">
Panel with panel-primary class <span class="glyphicon glyphicon-circle-arrow-up" style="float: right;"></span></div>
<div class="panel-body">
Panel Content</div>
</div>

Burada "panel panel-primary" ile "primary" tipinde bir bootstrap panel oluşturulacağı belirtilmektedir. "panel-heading" panelin başlık alanını, "panel-body" ise panelin içeriği taşıyacağı esas alanını belirtmektedir. Başlık içine eklenen "glyphicon" içeren "span" elementi ile panelin durumunu gösteren resim panel başlağına eklenmektedir. "float:right" yapılarak ok işaretinin sağ tarafa kayması sağlanmaktadır. "glyphicon-circle-arrow-up" yukarı işaretinin ekleneceğini belirtmektedir.

Panel HTML kodları oluşturulduktan sonra açılıp kapanma özelliğinin panele kazandırılması için aşağıdaki Jquery javascript kodlarının eklenmesi gerekmektedir:

$(document).ready(function(){
    $(".panel-primary").children(".panel-heading").click(function(){
        $(this).parent().children(".panel-body").toggle();
        $(this).children(".glyphicon").toggleClass("glyphicon-circle-arrow-up");
        $(this).children(".glyphicon").toggleClass("glyphicon-circle-arrow-down");
    });
});

Yukarıdaki kod ile başlık ögesinin "click" olayı yakalanmakta ve toggle() fonksiyonu ile panel içeriğinin görünüp kaybolması sağlanmaktadır. "span" elementinin sınıfı da aynı anda değiştirilerek okun durumu güncellenmektedir.

Yukarıda yer alan kodların çalıştırılması ile aşağıdaki sonuç elde edilmektedir:

Panel with panel-primary class
Panel Content
Panel Content2
Panel Content3
Panel Content4

Wednesday, February 24, 2016

Jquery ile Mayın Tarlası Oyunu (2. Bölüm) - Mine Sweeper Game with Jquery (Section 2)

Bu yazıda mayın tarlası oyununda mayın olmayan yere tıklandığında mayınsız bölgenin otomatik açılması işlemini, mayına basıldığında tüm oyunun açılmasını ve gerekli renklendirmeleri yapacağız.

1. Bölümde ekranı oluşturmuş ve mayınları rastgele yerleştirmiştik. Şimdi bir önceki makalede yer alan CSS kodlarını mayın tuşunun durumuna göre aşağıdaki gibi güncelleyelim:

<style>

        .MineGameCanvas {

            width:500px;
            height:500px;

        }

        .MineButton {

            float:left;
            width:25px;
            height:25px;
        }

        .MineButtonPressed {

            float:left;
            width:25px;
            height:25px;
            pointer-events:none;
            background-color:gray;
            border:inset;
            
        }

        .MineButtonT {

            float:left;
            width:25px;
            height:25px;
            background-color:red;
            pointer-events:none;
        }

        .MineButtonT2 {

            float: left;
            width: 25px;
            height: 25px;
            background-color: orange;
            pointer-events:none;
            
        }
</style>

Burada mayına basılması durumu için "MineButtonT" sınıfı, mayına basılıp oyun sonlandığında diğer mayınları göstermek içi "MineButtonT2" ve boş mayın tarlası alanlarını göstermek için "MineButtonPressed" sınıfları eklenmiştir. Bir diğer önemli nokta ise "pointer-events:none" bilgisidir. Bununla tuşun olay yakalayıcıları etkisizleştirilmektedir (tuş disable yapılmaktadır).

Mayın taraması işleminin ve diğer ek fonksiyonların çalıştırılması için javascript kodu aşağıdaki gibi güncellenmiştir:

<script type="text/javascript">

        var mineCount = 50;
        var arr = [];
        var width = 20;
        var height = 20;
        var possibility = mineCount / (width * height);

        var BoomClass = "MineButtonT";
        var BoomClassShow = "MineButtonT2";
        var MinePressed = "MineButtonPressed";

        var MineSweeperWrapper = function () {

            this.HasMine = false,
            this.IsEnabled = true,
            this.IsPressed = false,
            this.IsFlagged = false,
            this.MineButton = null
        }

        function ButtonPressed(sender) {

            var btNumx = $(sender).attr("btNumx");
            var btNumy = $(sender).attr("btNumy");

            var x = parseInt(btNumx);
            var y = parseInt(btNumy);

            if (arr[x][y].HasMine) {

                arr[x][y].IsPressed = true;
                OpenAll();
            } else {

                EvaluateSituation(x, y);
            }
        }

        function PressMine(X, Y) {

            arr[X][Y].IsEnabled = false;
            $(arr[X][Y].MineButton).toggleClass(MinePressed);
        }

        function EvaluateSituation(X, Y) {

            var stack = [];

            var neighborCount = 0;

            if (ControlButtonHasMine(X, Y + 1, stack)) {
                neighborCount++;
            }

            if (ControlButtonHasMine(X, Y - 1, stack)) {
                neighborCount++;
            }

            if (ControlButtonHasMine(X + 1, Y, stack)) {
                neighborCount++;
            }

            if (ControlButtonHasMine(X + 1, Y - 1, stack)) {
                neighborCount++;
            }

            if (ControlButtonHasMine(X + 1, Y + 1, stack)) {
                neighborCount++;
            }

            if (ControlButtonHasMine(X - 1, Y, stack)) {
                neighborCount++;
            }

            if (ControlButtonHasMine(X - 1, Y - 1, stack)) {
                neighborCount++;
            }

            if (ControlButtonHasMine(X - 1, Y + 1, stack)) {
                neighborCount++;
            }

            if (arr[X][Y].IsEnabled)
                PressMine(X, Y);

            if (neighborCount > 0) {

                $(arr[X][Y].MineButton).val(neighborCount);

            } else {

                while (stack.length > 0) {

                    var neighbour = stack.pop();

                    EvaluateSituation(neighbour.X, neighbour.Y);

                }
            }

        }

        function ControlButtonHasMine(X, Y, stack) {

            if (X >= 0 && X < width && Y >= 0 && Y < height) {

                if (arr[X][Y].IsEnabled) {

                    stack.push(arr[X][Y]);

                    if (!arr[X][Y].HasMine) {

                        return false;

                    } else {

                        return true;
                    }
                }
            }
        }

        function OpenAll() {

            for (var x = 0; x < width; x++) {

                for (var y = 0; y < height; y++) {

                    if (arr[x][y].HasMine) {

                        if (!arr[x][y].IsPressed)
                            $(arr[x][y].MineButton).toggleClass(BoomClassShow);
                        else
                            $(arr[x][y].MineButton).toggleClass(BoomClass);
                    } else {

                        if (arr[x][y].IsEnabled) {

                            $(arr[x][y].MineButton).toggleClass(MinePressed);
                            arr[x][y].IsEnabled = false;
                        }
                    }

                    arr[x][y].IsEnabled = false;
                }
            }
        }

        $(document).ready(function () {

            arr = CreateArray(width, height, 0);

            PlantMines();

            GenerateMineField();


        });

        function GenerateMineField() {

            var canvas = $(".MineGameCanvas");

            for (var x = 0; x < width; x++) {

                for (var y = 0; y < height; y++) {

                    var button = $('<input id="Button-' + x + '-' + y + '" type="button" value="" class ="MineButton" btNumx="' + x + '" btNumy="' + y + '" onClick="ButtonPressed(this)"/>');
                    arr[x][y].MineButton = button;
                    arr[x][y].X = x;
                    arr[x][y].Y = y;
                    canvas.append(button);
                }
            }
        }

        function CreateArray(witdh, height, defaultValue) {

            var arr = [];
            for (var x = 0; x < width; x++) {
                arr[x] = [];
                for (var y = 0; y < height; y++) {
                    arr[x][y] = new MineSweeperWrapper();
                }
            }

            return arr;
        }

        function PlantMines() {

            for (var x = 0; x < width; x++) {
                for (var y = 0; y < height; y++) {

                    if (!arr[x][y].HasMine) {

                        var deger = Math.random();

                        if (deger <= possibility) {
                            arr[x][y].HasMine = true;
                            mineCount--;

                            if (mineCount == 0)
                                return;
                        }
                        else {
                            arr[x][y].HasMine = false;;
                        }
                    }
                }
            }

            if (mineCount > 0)
                PlantMines();
        }

    </script>

Bir önceki makalede anlatılmayan ve yeni eklenen fonksiyonların işlevleri şöyledir:

* PressMine fonksiyonu bir tuşa basıldığında tuş ile ilgili gerekli sınıf değişiklikleri ve durum değişikliklerini yapmaktadır.

* EvaluateSituation fonksiyonu mayın olmayan boş bir alana tıklandığında mayınsız alanı tarama ve mayınları sayma işlemlerinin yerine getirildiği recursive fonksiyondur.

* ControlButtonHasMine fonksiyonu tuş üzerinde mayın olup olmadığını ve kontrol edilen tuşun geçerli bir tuş olup olmadığını kontrol eden fonksiyondur. Ayrıca tuş çevresinde yer alan komşu tuşların eğer kontrol edilmemişlerse yığına eklenme işlemi de burada yapılmaktadır. Yığın içinde yer alan komşu tuşlar EvaluateSituation fonsiyonu içinde tekrar çağrılarak değerlendirilmektedir.

* OpenAll fonksiyonu mayına basılıp oyun sonlandığında bütün mayın alanını açık hale getiren fonksiyondur.

Bu makalede önemli noktalardan ilki javascript sınıf tanımlamasıdır:

var MineSweeperWrapper = function () {

            this.HasMine = false,
            this.IsEnabled = true,
            this.IsPressed = false,
            this.IsFlagged = false,
            this.MineButton = null
        }

Yukarıda görüldüğü gibi constructer olarak kullanılan bir fonksiyon üzerinden tanımlama yapılmaktadır. Sınıf ve arr dizisi kullanılarak tarama işleminin hızlı yapılması sağlanmaktadır. Diğer durumda DOM üzerinden işlem yapmak daha zordur.

MineSweeperWrapper sınıfı gerekli algoritmik alanları ve ilgili DOM nesnesine referans içermektedir. Bu alanlardan "HasMine" tuş üzerinde mayın olup olmadığı bilgisini, "IsEnabled" tuşun kullanılabilir olup olmadığı bilgisini, "IsPressed" basılan tuşun işaret bilgisini, "IsFlagged" tuşa bayrak konulup konulmadığı bilgisini (sonraki makalede işlenecektir) ve son olarak "MineButton" DOM nesnesine referans bilgisini sağlamaktadır.

Bu yazıda diğer önemli nokta ise yığın (stack) kullanımıdır. Yığınlara kasik diziler ile aynı şekilde tanımlanırken yığına ekleme için push(), yığında çıkarma için pop() fonksiyonları kullanılmaktadır.

Yukarıdaki kodların çalıştırılması sonucu elde edilen sonuç aşağıdaki gibidir:

Tuesday, February 23, 2016

Jquery ile Mayın Tarlası Oyunu (1. Bölüm) - Mine Sweeper Game with Jquery (Section 1)

Bu yazıda mayın tarlası oyununu genel hatlarıyla oluşturacağız. Bu yazı sonunda mayın tarlası oyunu ekranı oluşturulmuş, mayınlar rastgele dağıtılmış ve tuşlara gerekli olay yakalayıcıları yerleştirilmiş olacaktır. İlk aşamada oyunun yerleşeceği canvas ögesini tanımlayalım:

<div class="MineGameCanvas"></div>

Ekranı oluşturmak için bazı CSS kodları tanımlamamız gerekecektir:

<style>

        .MineGameCanvas {

            width:500px;
            height:500px;
        }

        .MineButton {

            float:left;
            width:25px;
            height:25px;
        }

        .MineButtonT {

            float:left;
            width:25px;
            height:25px;
            background-color:red;
        }

</style>

Burada "MineGameCanvas" sınıfı mayın tarlası oyununun yerleşeceği pencereyi tanımlamakta, "MineButton" sınıfı üzerinde mayın tanımlanmamış tuşu, "MineButtonT" ise üzerinde mayın tanımlanmış tuşu ifade etmektedir. Burada dikkat edilmesi gereken unsur "float:left" belirtimidir. Float ile tuşların canvas içine düzgün yerleştirilmesi sağlanmaktadır. Bir sonraki aşama olarak gerekli javascript kodlarını tanımlayalım:

<script type="text/javascript">

        var mineCount = 50;
        var arr = [];
        var width = 20;
        var height = 20;
        var possibility = mineCount / (width * height);

        function ButtonPressed(sender) {

            var btNumx = $(sender).attr("btNumx");
            var btNumy = $(sender).attr("btNumy");

            alert("Pressed to " + btNumx + "," + btNumy );

            if (arr[btNumx][btNumy] == 1)
                alert('Boom');

        }

        $(document).ready(function () {

            arr = CreateArray(width, height, 0);

            PlantMines();

            GenerateMineField();
        });

        function GenerateMineField() {

            var canvas = $(".MineGameCanvas");

            for (var x = 0; x < width; x++) {

                for (var y = 0; y < height; y++) {

                    if (arr[x][y] == 0) {
                        var button = $('<input id="Button-' + x + '-' + y + '" type="button" value="" class ="MineButton" btNumx="' + x + '" btNumy="' + y + '" onClick="ButtonPressed(this)"/>');

                        canvas.append(button);
                    } else {

                        var button = $('<input id="Button-' + x + '-' + y + '" type="button" value="" class ="MineButtonT" btNumx="' + x + '" btNumy="' + y + '" onClick="ButtonPressed(this)"/>');

                        canvas.append(button);
                    }

                }
            }
        }

        function CreateArray(witdh, height, defaultValue) {

            var arr = [];
            for (var x = 0; x < width; x++) {
                arr[x] = [];
                for (var y = 0; y < height; y++) {
                    arr[x][y] = defaultValue;
                }
            }

            return arr;
        }

        function PlantMines() {

            for (var x = 0; x < width; x++) {
                for (var y = 0; y < height; y++) {

                    if (arr[x][y] != 1) {

                        var deger = Math.random();

                        if (deger <= possibility) {
                            arr[x][y] = 1;
                            mineCount--;

                            if (mineCount == 0)
                                return;
                        }
                        else {
                            arr[x][y] = 0;
                        }
                    }
                }
            }

            if (mineCount > 0)
                PlantMines();
        }

</script>

Yukarıdaki javascript komutlarında yer alan bazı kod parçalarının ve fonksiyonların yaptığı işler şöyledir:

* Bir Jquery fonksiyonu olan ready ile döküman elementlerinin DOM'a yerleştirilmesi tamamlandıktan sonra oyun için gerekli işlemlerin yapılamasını sağlayan fonksiyonlar kullanılmaktadır.

* CreateArray fonksiyonu ile 2 boyutlu bir dizi oluşturulmaktadır. Oluşturacağımız dizi mayın lokasyonlarını içermektedir.

* ButtonPressed fonksiyonu bir tuşa basıldığında yapılması gereken kodları içermektedir.

* GenerateMineField fonksiyonu ile mayın tarlası için gerekli tuşlar dinamik olarak oluşturulmaktadır.

* PlantMines fonksiyonu ile mayınlar rastgele olarak oluşturulmakta ve dizi içine yerleştirilmektedir.

PlantMines fonksiyonu rastgele mayınları oluşturken Math.random fonksiyonunu kullanmaktadır. Mayın bulunma ihtimali her tuş için eşit olduğu için şöyle hesaplanmaktadır:

var possibility = mineCount / (width * height);

Burada toplam mayın sayısı toplam tuş sayısına bölünerek ihtimal eşit olarak dağıtılmış olmaktadır.

PlantMines fonksiyonu eğer tüm mayınları yerleştiremezse recursive olarak kendini tekrar çağırarak tüm mayınların yerleştirilmesini sağlamaktadır.

Tuşlar dinamik olarak Jquery ile aşağıdaki gibi oluşturulmaktadır:

var button = $('<input id="Button-' + x + '-' + y + '" type="button" value="" class ="MineButton" btNumx="' + x + '" btNumy="' + y + '" onClick="ButtonPressed(this)"/>');

Burada görüldüğü üzere Jquery fonksiyonu içinde direk olarak HTML olarak tanımlanan kod kullanılarak HTML elementleri dinamik olarak oluşturulup DOM içine yerleştirilebilmektedir.

Bir diğer önemli unsur ise "custom attribute" kullanımıdır. Jquery "attr" fonksiyonu ile bir DOM nesnesinin attribute değerleri alınabilmektedir.

Yukarıdaki kodların çalıştırılması sonucu elde edilen sonuç aşağıdadır:

Monday, February 22, 2016

Bootstrap Modal Kullanımı (JavaScript Üzerinden) - Using Bootstrap Modal Component (With JavaScript)

Bootstrap Modal iki yöntemle kullanılabilmektedir. Bunlardan ilki attribute üzerinden diğeri ise Js kodları ile tetikleyerektir.

JavaScript kullanarak Modal oluşturmak için aşağıdaki kod bloğu kullanılabilmektedir:


<script type="text/javascript">

function Close()
{
   $('#myModal').modal('hide');
}

function Open()
{
   $('#myModal').modal('show');
}

function Toggle()
{
   $('#myModal').modal('toggle');
}

</script>

Yukarıdaki Javascript kodları modal üzerinde yer alan tuşlara fonksiyonelik kazandırılması amacıyla kullanılmaktadır. Javascript kodları yazıldıktan sonra Bootstrap Modalı tanımlayalım:

<button class="btn btn-info btn-lg" type="button" onclick="Toggle()">Open Modal</button>

<!-- Modal -->
<br />
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
    <br />
<div class="modal-content">
<div class="modal-header">
<button class="close" type="button" onclick="Close()">×</button>
        <br />
<h4 class="modal-title">
Modal Header</h4>
</div>
<div class="modal-body">
Some text in the modal.</div>
<div class="modal-footer">
<button class="btn btn-default" type="button" onclick="Close()">Close</button>
      </div>
</div>
</div>
</div>
Yukarıdaki kodları aşağıdaki tuşa basarak çalıştırabilirsiniz:



Burada javascript "modal" fonksiyonu ile modal yönetilebildiği gösterilmiştir. "toggle" parametresi modalı açıp kapatmaya, "show" parametresi modalı göstermeye ve "hide" parametresi modalı gizlemeye yaramaktadır.

Bootstrap Modal Kullanımı (Attribute Üzerinden) - Using Bootstrap Modal Component (With Attributes)

Bootstrap Modal iki yöntemle kullanılabilmektedir. Bunlardan ilki attribute üzerinden diğeri ise Js kodları ile tetikleyerektir.

Attribute kullanarak Modal oluşturmak için aşağıdaki kod bloğu kullanılabilmektedir:

<button class="btn btn-info btn-lg" data-target="#myModal" data-toggle="modal" type="button">Open Modal</button>

<!-- Modal -->
<br />
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
    <br />
<div class="modal-content">
<div class="modal-header">
<button class="close" data-dismiss="modal" type="button">×</button>
        <br />
<h4 class="modal-title">
Modal Header</h4>
</div>
<div class="modal-body">
Some text in the modal.</div>
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" type="button">Close</button>
      </div>
</div>
</div>
</div>

Yukarıdaki kod bloğunu  aşağıdaki tuşa basarak çalıştırabilirsiniz.



Burada dikkat edilecek en önemli unsurlar "data-dismiss" ve  "data-toggle" özellikleridir. Bunlardan ilki modalı kapatırken, diğeri modalı açıp kapatmaktadır.


Sunday, February 21, 2016

Blogger İçinde Bootstrap Kullanılması - Using Bootstrap in Blogger Template

Blogger içinde Bootstrap özelliklerini kullanmak istiyorsak Bootstrap kurulumunu blog kodlarının içinde yapmamız gerekir. Blogger menüsünden "Şablon" ve daha sonra "HTML'yi Düzenle" kısımlarından aşağıda gösterilen kod bloğuna ulaşınız.



Daha sonra <Head> bloğunun hemen altına aşağıdaki referansları kopyalayınız:

<meta content='width=device-width, initial-scale=1' name='viewport'/>
<link href='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' rel='stylesheet'/>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js'/>
<script src='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js'/>

Referanslardan da anlaşılabileceği gibi Bootstrap için gerekli olan Bootstrap CSS ve Javascript dosyası ile Jquery bloğa referans olarak eklenmektedir. İlgili referanslar web üzerinde yer aldığı için herhangi bir dosya yükleme işlemine gerek yoktur.

Friday, February 19, 2016

Yazı İçinde Yer Alan Türkçe Karakterlerin İngilizce Karakterlere Dönüştürülmesi

Bazı ingilizce kökenli uygulamalarda kullanıcı ismi vb. bilgiler ingilizce karakter kullanılarak oluşturulmaktadır. Örneğin isim kısaltması yapılacaksa Adnan Göktürk olan bir kişinin kullanıcı kodu A-GOKTURK olarak kullanılabilmektedir. Bu ve benzeri durumlarda giriş verisi içinde yer alan tükçe karakterler ingilizce karşılıkları ile değiştirilmesi gerekir. Bu gereksinimi karşılayan C# kodu aşağıdadır.

IsNull fonksiyonu parametrenin null veya DBNull olup olmadığını kontrol etmektedir.
        
public static string GetEnglishLocalizedString(string SearchString)
{
if (!IsNull(SearchString))
{
char[] turkishChars = { 'ı', 'ğ', 'İ', 'Ğ', 'ç', 'Ç', 'ş', 'Ş', 'ö', 'Ö', 'ü', 'Ü' };
char[] englishChars = { 'i', 'g', 'I', 'G', 'c', 'C', 's', 'S', 'o', 'O', 'u', 'U' };
for (int i = 0; i < turkishChars.Length; i++)
{
SearchString = SearchString.Replace(turkishChars[i], englishChars[i]);
}
return SearchString;
}
else
return null;
}

Düzenli İfadeleri Kullanarak Karakter Dizisi İçindeki Örüntüleri Bulma - Finding Patterns in Strings with Using Regular Expressions

Regex (Regular Expression) bir karakterler dizisi içinde düzenli bir parçayı bulmak için kullanılan bir yöntemdir. Düzenli yapının ifadesi Regex tanımlama kuralları kullanarak tanımlanır ve string içindeki bu kurala uyan kısımlar ayrıştırılıp elde edilebilir. Örnek olarak karmaşık bir string içinde yer alan tarih kısmını bulalım:

* Bulmak istediğimiz tarih formatı:

19.02.2016

* Örüntüyü ifade eden RexExp :

(0[1-9]|[12][0-9]|3[01]|[1-9])[- /.](0[1-9]|1[012]|[1-9])[- /.](19|2)\d\d\d

* Test Verisi 1:

dafffas1319.02.2016daq12341515

* Test Verisi 2:

-*daf/fa.*19.2.20169a1341qwca12.1.1

* Çalıştıracağımız C# kodu:

public static DateTime? findDateInString(string SearchString)
{
Regex ex = new Regex(DateInStringRegEx);
var match = ex.Matches(SearchString);
if (match.Count > 0)
return DateTime.Parse(match[0].Value);
else
return null;
}

SONUÇLAR:

* Sonuç 1 (Test Verisi 1):

19.02.2016

* Sonuç 2 (Test Verisi 2):

19.02.2016



Wednesday, February 17, 2016

GUID (Evrensel Eşsiz Tanımlayıcı Nedir) - What is GUID (Globally Unique Identifier) or UUID (Universally Unique Identifier)?

GUID (Globally Unique Identifier) X.667 dökümanında tanımlı, genellikle nesneler için eşsiz tanımlayıcılar kullanılması gerektiği durumlarda tanımlayıcı olarak kullanılan ikili bir sayıdır. UUID (Universally Unique Identifier) ve GUID aynı şeyi ifade etmektedir.

Otomatik artırılan sayılar tablo içinde PK (Primary Key) olarak kullanıldığında tablo içindeki eşsizliği garanti ederken tablolar arasındaki eşsizliği sağlayamaz. Yani 1 değeri Personel tablosunda Ali'yi tanımlarken aynı 1 değeri Şehir tablosunda Ankara'yı belirtebilir. Ayrıca otomatik sayıların kullanılması bir yönetim maliyeti ortaya çıkarır.

GUID'ler yapısı gereği teoride genel olarak eşsizlik sunarlar. Yani bir veritabanı nesnesine atanan GUID sadece o nesnenin tanımlayıcısı olmakta ve veri tabanında başka bir eşi olmamaktadır. Bu durum insanlardaki parmak izinin sağladığı eşsizlikle de benzerdir.

GUID 128 bit (16 oktet - 16 byte) ikili bir sayı olarak tanımlanmaktadır.  Ayrıca GUID URN (Uniform Resource Name) olarak hexadecimal formatta string olarak da aşağıdaki gibi ifade edilebilmektedir.

f81d4fae-7dec-11d0-a765-00a0c91e6bf6

GUID tanımı hexadecimal sayılardan oluştuğu için sadece aşağıdaki karakterleri içerebilmektedir:

A B C D E F a b c d e f 0 1 2 3 4 5 6 7 8 9

GUID aşağıdaki alanlardan oluşmaktadır:

a) "TimeLow" Alanı: 4 oktet;
b) "TimeMid" Alanı: 2 oktet;
c) "VersionAndTimeHigh" Alanı: 2 oktet;
d) "VariantAndClockSeqHigh" Alanı: 2 oktet;
e) "ClockSeqLow" Alanı: 1 oktet;
f) "Node" Alanı: 6 oktet.

Bu alanlar GUID oluşturulurken GUID içinde aşağıda gösterilen formatta yerleştirilmektedir.

 

Node alanı görüldüğü üzere 6 sekizliden yani 48 bitten oluşmaktadır. Genellikle Node olarak MAC (Media Access Control) adresi kullanılmaktadır. Bilindiği üzere MAC adresleri teoride Dünya geneli eşsizlik sağlamaktadır. Genel eşsizlik MAC üzerinden sağlanırken aynı makinenin oluşturduğu sayılar arasındaki eşsizlik ise zaman ve ClockSeq alanları kullanılarak sağlanmaktadır.

GUID içinde yer alan zaman alanı bir başlangıç noktasından itibaren (15 Ekim 1582) 100 nanosaniye aralıklı sayılan şimdiki zamanı ifade etmektedir. Bu değer .NET framework içince "Tick" olarak adlandırılmaktadır.

ClockSeq alanı GUID'lerin birbiriyle çok yakın zamanda oluşturulması, makine zamanının geriye alınması veya node değerinin değişmesi durumunda eşsizliğin sürdürülebilmesi amacıyla kullanılmaktadır. Bu değer eğer makine içinde sıralı tutuluyorsa sıradaki sayı, eğer tutulmuyorsa rastgele bir sayı olarak kullanılabilmektedir.

Versiyon alanı GUID çeşidini belirtmektedir. GUID'ler aşağıdaki versiyonlarda olabilmektedir.

* Zaman Tabanlı
* İsim Tabanlı
* Rastgele Sayı Tabanlı

GUID alanlarının hangi oktetlerde olduğu aşağıdaki tabloda gösterilmektedir:




C# kullanılarak GUID'ler aşağıdaki kod ile oluşturulabilmektedir:

Guid g = Guid.NewGuid()

Monday, February 15, 2016

AJAX (Asynchronous JavaScript and XML) 2

Daha önce AJAX isteklerinin nasıl işlendiğini incelemiştim. Bu yazıda da AJAX isteklerinin asenkron olmasından bahsetmek yararlı olacaktır.  Klasik istek işleme yönteminde aşağıdaki görüntüde de görülebileceği gibi istemci üzerinden bir tetiklemeyle sunucuya istek gönderilmekte ve sunucu tarafından bu istek işlendikten sonra geriye dönen sayfa üzerinden kullanıcı işlemlerine devam edebilmektedir. Arada geçen zaman diliminde kullanıcı aktivitesi kesilmektedir.




Klasik yönteme karşı AJAX fikri kullanıcı etkileşimini kesintiye uğratmadan işlemlerin devamlılığını sağlayan bir mimari ortaya koyar. Bu durumda yapılan istekler esnasında kullanıcı başka etkileşimlerde bulunabilmekte, böylece kullanıcı uygulama ile etkileşimine kesintisiz devam edebilmektedir. Bu duruma göre AJAX ile aynı anda birden fazla istek yapılabilmektedir.





Asenkron etkileşimin etkilerini kod üzerinden incelemek gerekirse daha önce w3schools'da yer alan örneği aşağıdaki gibi değiştirip sonuçlarını gözlemleyelim.





Yukarıda yer alan kod bloğu çalıştırıldığında aşağıdaki sonuçlar gözlemlenecektir:

Function Executing
AJAX Request Starting
Function Executed
AJAX Request Ended

Görüldüğü üzere AJAX istekleri ana iş ipliğini (Thread) çalışmasını engellememektedir. AJAX işlemindeki geçikme nedeniyle öncelikle fonksiyonun çalışması bitirilmekte ve sonra AJAX işleminin sonucu gecikmeyle elde edilmektedir.


Sunday, February 14, 2016

AJAX (Asynchronous JavaScript and XML) 1

AJAX web uygulamalarında sayfaların parçalı olarak çalışmasını sağlayan bir teknolojidir. Klasik yöntemde web sayfası sunucuya tamamen gönderilip sunucudan cevap olarak dönen web sayfasının yeni durumu tarayıcıya tamamen yüklenirken diğer yaklaşımda javascript aracılığıyla DOM (Document Object Model) kullanılarak ilgili değişikliklerin kısmı olarak yapılması sağlanmaktadır. Bu yazıda AJAX sorgularının Jquery ile w3schools'da yer alan örneği kullanarak nasıl çalıştığını açıklamaya çalışacağım. Aşağıdaki örnekte JSON nesnesi olarak name ve city paremetreleri gönderilmekte ve ASP sayfasından bu değerler okunup sonucu döndürülmektedir.



Bir network analiz aracı ile yaptığım analizde sorgunun paket yapısı aşağıdaki gibi gözlemlenmiştir. Görüntüde görüldüğü gibi istek HTTP protokolü ile POST yöntemi kullanılarak yapılmaktadır. Burada önemli noktalardan biri X-Requested-With başlığıdır. Bu başlığa XMLHttpRequest değeri atanarak ilgili isteğin bir AJAX isteği olduğu belirtilmektedir. Normal istekler ile AJAX istekleri arasındaki en önemli fark AJAX isteklerinin "redirect" yapılmamasıdır. Jquery ile gönderilen JSON nesnesinin HTTP protokolü içinde form element olarak taşınması bir diğer önemli noktadır. Görüntüde görüldüğü üzere mesaj yapısı "application/x-www-form-urlencoded" olarak görülmektedir. Mesaj parametre değerlerini içeren key-value ikililerinden oluşmaktadır.



Yapılan AJAX sorgusunda ASP sayfasından ilgili parametrelerin değerlerini de içeren bir yazı (text) döndürülmektedir. Bu durumu gösteren network paketi aşağıdaki gibidir. Görüldüğü üzere dönen mesajın türü text/html dir. Jquery tarafından bu değer "alert" olarak bize bildirilmektedir.



İletişim kurduğumuz ASP sayfasın aşağıdaki kod ile bize text bir değer döndürmektedir. Görüldüğü üzere yapılan istek  x-www-form-urlencoded türünde olduğu için Request.Form kullanılarak gönderilen parametrelere kolaylıkla ulaşılabilmektedir. 

<%
dim fname,city
fname=Request.Form("name")
city=Request.Form("city")
Response.Write("Dear " & fname & ". ")
Response.Write("Hope you live well in " & city & ".")
%>

Saturday, February 13, 2016

Üç Şey

Şu üç şey hakkında dudağını kıpırdatma: Gittiğin yol, paran, bir de mezhebin. Çünkü bu üçünün de düşmanı çoktur.

Mevlana

Thursday, February 11, 2016

İt Sürüsü

Kılıç kınından çıkmadıkça it sürüsü dağılmaz.

2. Mahmud

Ne Günlere Kaldık

Ne günlere kaldık ey Gâzi Hünkâr, Katır mühürdâr oldu, eşek defterdâr! 

Ziya Paşa

Ahbabı Siayet

İkbâl için ahbabı siayet yeni çıktı
Bilmez idik evvel bu dirayet yeni çıktı

Ziya Paşa

Yeni Adet

Sadıkları tahkir ile red kaide oldu
Hırsızlara ikram ü inayet yeni çıktı
Hak söyleyen evvel dahi menfur idi gerçi
Hainlere amma ki riayet yeni çıktı
Milliyeti nisyan ederek her işimizde
Efkâr-ı Frenge tebaiyyet yeni çıktı



Ziya Paşa

Üniforma

Bed-asla necâbet mi verir hiç üniforma
Zer-dûz palan vursan eşek yine eşektir

Ziya Paşa

Monday, February 8, 2016

Ukalâ

Âhir zamanın âdi ukalâsı, kendilerini evvelce gelenlerden üstün görürler.

Mevlana

Sunday, February 7, 2016

Dil

Söz bilmez cahile bir şeyler öğretmek için kendi dilini terk etmek, onun dilince konuşmak gerek. Ancak bu suretle senden bir bilgi, bir fen öğrenebilir.

Mevlana

Friday, February 5, 2016

Cevher

Gül de aynı madenin cevheri, hayvan da insan da
Çöl de aynı madenin cevheri, bağlık da bahçe de

Monday, February 1, 2016

Separation of Concerns (Birbiriyle Yakından İlgili İşlerin Ayrışımı - Kavramların Ayrışımı)

"Separation of concerns" kavramının Türkçe karşılığının tanımlanması konusu biraz sıkıntılı olmakla beraber 'Birbiriyle Yakından İlgili İşlerin Ayrışımı' şeklinde çevrilebilir. Benim tanımıma göre SOLID gibi kavramlar ayrılığını, yani ata binmek isteyeni atla kuşu karıştırıp pegasus'a bindirmeyini ifade eder. Birbirlerinin arasında yakından fonksiyonel ilişki olan işlerin ayrılmasıyla kod anlaşılabilirliği artar dolayısıyla bakım maliyeti düşer. Bunlara en iyi örnekler daha önce SOA yazılarımda örnekleri bulunan katmanlı yapılardır. Bu durum ile ilgili MSDN'den aldığım aşağıdaki katmanlı mimariyi örnek verebilirim.



Mimaride görüldüğü gibi kullanıcı ile etkileşime giren yazılım modülleri esas işlemlerin yapıldığı ticari (Business) katmandan ayrıştırılmıştır. Aynı şekilde veri tabanı ile etkileşime giren modüller de diğer modüllerden ayrıştırılmıştır. Böyle bir mimaride yapılan büyük bir iş parçalara ayrılmış ve birbirinden soyutlanmış olur. En basit anlatımıyla sunum katmanını oluşturan kodlarda hiçbir değişiklik yapmadan ve dikkati lüzumsuz yere gereksiz ayrıntılarla dağıtmadan veri erişim kodları veya ticari kodlar değiştirilebilir. Aynı şekilde veri katmanın ayrıştırılmasıyla veri tabanı yazılımı değiştirildiğinde sadece bu katmanı oluşturan yazılım kodlarının değiştirilmesi yeterli olacaktır.

Entity Framework CRUD İşlemleri - CRUD with Entity Framework

Bir yazılımın en önemli kısımlarından biri CRUD (Create, Read, Update, Delete) işlemleridir. CRUD işlemlerinin kalitesi veri kalitesine doğrudan etki eder. Bu yüzden CRUD uygulamaları özentili ve sert protokolle oluşturulmalıdır. Bu yazıda EF ile ilgili fonksiyonların nasıl olması gerektiği anlatılmıştır. Bu fonksiyonlar şunlardır:

public MyObject SelectObj(Decimal? ID)
     {
         if (ID != null)
         {
             DataBaseContext con = new DataBaseContext();
             return con.MyObjects.Include(r => r.MyObjectRelation).Single(r => r.ID == ID);
         }
         else
             return new MyObject();
     }

     public void InsertObj(MyObject Obj)
     {
         DataBaseContext con = new DataBaseContext();
         var a = con.MyObjects.Attach(Obj);
         con.Entry(a).State = EntityState.Added;
         con.SaveChanges();

     }

     public void UpdateObj(MyObject Obj)
     {
         DataBaseContext con = new DataBaseContext();
         var a = con.MyObjects.Attach(Obj);
         con.Entry(a).State = EntityState.Modified;
         con.SaveChanges();

     }

     public void DeleteObj(MyObject Obj)
     {
         DataBaseContext con = new DataBaseContext();
         var a = con.MyObjects.Attach(Obj);
         con.Entry(a).State = EntityState.Deleted;
         con.SaveChanges();
     }

Burada dikkat edilmesi gereken bir unsur ilişkili tablonun verilerinin "eargerly loading" yaklaşımıyla yapılmasıdır. Bunun direk olarak CRUD kalitesine etkisi olmamakta birlikte tarafımca performans kaygısı sebebiyle bu yöntem kullanılmaktadır.

Aşağıdaki kod satırları nesne durumunu EF'ye tanıtmaktadır.

con.Entry(a).State = EntityState.Added;
con.Entry(a).State = EntityState.Modified;
con.Entry(a).State = EntityState.Deleted;

Bu satırlardan Added nesnenin yeni eklendiğini belirtmekte ve INSERT DML (Data Manipulation Language) komutunu ima etmekte, Modified nesnenin güncellendiğini ve UPDATE DML komutunu ima etmekte, Deleted ise nesnenin silindiğini ve DELETE DML komutunu ima etmektedir.

Direk nesne üzerinden yapılan durum belirtimleri nesnenin tüm propertyleri için geçerlidir. Örneğin Modified durumu sonucu oluşan SQL (Structured Query Language) tüm property'leri içerecektir. Eğer ilgili nesnenin belirli property'leri güncellenmek isteniyorsa aşağıdaki kod satırı kullanılmalıdır:

con.Entry(a).Property(r => r.MyProperty).EntityEntry.State = EntityState.Modified;

veya

con.Entry(a).Property(r => r.MyProperty).IsModified = true;

Burada MyProperty güncellenmiş olarak işaretlenmiş ve güncellemede sadece gösterilen property dikkate alınacaktır. 

Bir diğer husus ise "using" kullanımıdır. "Context" nesneleri yüksek maliyetli nesneler oldukları için kaynakların çabuk bırakılması yararlı olacaktır. Bu yüzden "Context" nesnelerinin "using" bloğu kullanılarak kullanılması yararlı olacaktır.

Son olarak yukarıdaki işlemlerde nesne tanımlayıcısının yani "primary key" alanlarının kesinlikle tam olması şarttır.