Tuesday, October 25, 2016

Kader Ağacı

Söz ki ok olur yüreğe saplanır,
Söz ki leş olur toprağa gömülür.
Dinle ki belki kader ağacının dallarından tohumlar toplarsın,
Dinle ki belki bu ilâhi tohumlardan gül bahçeleri yaparsın.

Wednesday, August 31, 2016

Jquery ile Blogger Üzerinde Facebook Benzeri Odaklanma Uygulaması - Focusing Application like on Facebook with Jquery on Blogger

Bu yazıda yenice facebook'ta karşılaştığım odaklanma uygulamasını blog sayfama nasıl uyguladığımı anlatacağım. Facebook üzerinde durum güncellemesi amacıyla ilgili yazı alanına tıkladığınızda yorum yazılacak yerin dışında kalan kısımların karardığını göreceksiniz. Bu uygulamanın odaklanmada pozitif etkisi olduğu, bu yüzden de bir blog sitesi için de gayet yararlı olacağını düşündüğüm için uygulamayı gerçekleştirme kararı aldım. Öncelikle bir CSS sınıfı tanımlaması yapmamız gerekiyor:

.onFocusMeContainer
{
     background-color:#000000;
     opacity:0.7;
     z-index:12;
     width:100%;
     height:100%;
     position:fixed;  
     top:0;
     left:0;
     display:none;
}

Bu uygulamada bize lazım olan en öncekli element siyah, saydam ve ekranı kaplayan siyah bir elementtir. Bu element bütün ekranı kaplayacak ve odaklama yapacağımız ögenin arkasında, diğer bütün sayfanın üzerinde yer alacaktır. Tabi kırmızı uçan kartalımızın üzerine siyah bir örtü örtmek istemeyeceğimizden dolayı kartalı taşıyan ögenin "z-index" CSS değerini artırdım. "onFocusMeContainer" CSS sınıfında "opacity" değeri ile elemente saydamlık kazandırdık. Elementin "display" özelliğini kullanarak elementi görünmez yapıp, bütün ekranı kaplaması ve pencereyi kaydırdığımız zaman kaymaması için "position" özelliğini "fixed" olarak belirledik. Elementin "z-index" değerini blog için uygun bir değer seçmemiz gerektiği için "12" olarak belirledik, çünkü sitemizin diğer ögelerinin "z-index" değeri 12'den küçüktür. Bu CSS sınıfını oluşturduktan sonra bu sınıfı içeren bir "div" elementini  "body" içine aşağıdaki kod ile ekliyoruz.

<div class="onFocusMeContainer"></div>

Bir sonraki aşamada gerekli fonksiyonaliteyi sağlamak amacıyla bazı javascript kodları tanımlamız gerekiyor.

$(".post-outer").click(function (event) {

   if (lastClicked == null) {

          if (!$(event.target).is("a")) {

               lastClicked = $(event.target);

               while (!$(lastClicked).hasClass("post-outer")) {

                   lastClicked = $(lastClicked).parent();
               }

               $(lastClicked).css("position", "relative");
               $(lastClicked).css("z-index", 5000);
               $(".onFocusMeContainer").show("fast");
          }
    } 
});

$(".onFocusMeContainer").click(function (event) {
   
   $(lastClicked).css("position", "relative");
   $(lastClicked).css("z-index", 0);
   $(".onFocusMeContainer").hide("fast");
   lastClicked = null;
});

Blogger'da yazdığımız makaleler "post-outer" sınıfını içeren bir taşıyıcı kontrol içinde sunulduğu için bu ögenin "click" olayını tanımlamamız gerekiyor. Burada bir döngü aralığıyla "post-outer" sınıfını içeren taşıyıcıya ulaşana kadar "parent" fonksiyonu aracılığıyla DOM üzerine yukarı doğru çıkıyoruz. Bunun sebebi daha önceki bir yazımda bahsettiğim "Event Bubbling" yani olayın yukarı doğru iletilmesi sebebiyledir. Kısaca olayı özetlemek gerekirse, bir taşıyıcı içindeki bir kontrole tıklandığında tıklama olayı en yukarıdaki taşıyıcı elemente kadar iletilmektedir.  Taşıyıcı elementi bulduktan sonra "z-index" özelliğinin çalışması için bu elementin "position" özelliğini "relative" yapmamız gerekiyor. Daha sonra "z-index" değerini büyük bir sayı yaparak elementin yukarıda kalmasını sağlıyoruz. Son aşamada siyah saydam kontrolümüzü görünür hale getiriyoruz. Link ("a") elementlerine tıklandığında ilgili özelliğimiz çalışmaması için "is" fonksiyonunu kullanarak üzerine tıklanan elementin bir "a" elementi olup olmadığını da kontrol etmemiz gerekiyor.

Siyah saydam kontrolümüzün tıklama olayı üzerinde tanımlı fonksiyon aracılığıylada yukarıda yaptığımız düzenlemeleri geri alıyoruz. "lastClicked" değişkeni global olarak tanımlanmıştır ve en son odaklanmış elementi göstermektedir.

Uygulama blog üzerinde şuan aktif olduğu için yazı üzerine tıklayarak uygulamayı deneyimleyebilirsiniz.


Saturday, August 13, 2016

Bir Kez Gönül Yıktın ise

Bir kez gönül yıktın ise
Bu kıldığın namaz değil
Yetmiş iki millet dahi
Elin yüzün yumaz değil

Bir gönülü yaptın ise
Er eteğin tuttun ise
Bir kez hayır ettin ise
Binde bir ise az değil

Yol odur ki doğru vara
Göz odur ki Hak'kı göre
Er odur alçakta dura
Yüceden bakan göz değil

Erden sana nazar ola
İçin dışın pür nur ola
Beli kurtulmuştan ola
Şol kişi kim gammaz değil

Yunus bu sözleri çatar
Sanki balı yağa katar
Halka matahların satar
Yükü gevherdir tuz değil
Yunus Emre

Sunday, July 17, 2016

İki Yalnız Kelebek

Yazık olmuş, kahr olmuş, zamansız ölmüş iki yalnız kelebek,
Kimi kelebekler suçlu demiş, kimi demiş ilahi gerçek.

Saturday, June 25, 2016

Ağaç

Şu büyük ağaç mütevazılıkta önder imiş,
Şanı asaleti gök kubbede aşikar imiş.

Monday, June 13, 2016

Varlık - Yokluk

Bir şeyin varlığı bir şeyler ifade ettiği gibi yokluğu da bir şeyler ifade eder.

Monday, May 30, 2016

Melamet Hırkası (Haydar Haydar)

Ben melamet hırkasını
Kendim giydim eğnime
Ar ü namus şişesini
Taşa çaldım kime ne
Haydar haydar taşa çaldım kime ne

Sofular haram demişler
Aşkımın şarabına
Ben doldurur ben içerim
Günah benim kime ne
Haydar haydar günah benim kime ne

Gah çıkarım gökyüzüne
Seyrederim alemi
Gah inerim yeryüzüne
Seyreder alem beni
Haydar haydar seyreder alem beni

Gah giderim medreseye
Ders okurum hak için
Gah giderim meygedeye
Dem çekerim aşk için
Haydar haydar dem çekerim aşk için

Nesimi'yi sorsalar kim
Yarin ile hoş musun
Hoş olam ya olmayayım
O yar benim kime ne
Haydar haydar o yar benim kime ne

Nesimi

Sunday, May 29, 2016

Hafif

Akılsız kişileri her türlü yel kapıp gider, çünkü onların kuvvetleri sağlam değildir.

Mevlana

Tuesday, March 29, 2016

Angularjs ve ASP.NET MVC ile Javascript Diziler Kullanılarak Dinamik Çoklu Veri Gönderimi - Sending Dynamic Multi Post Data Using Javascript Arrays With Angularjs and ASP.NET MVC

Bu yazıda ASP.NET MVC üzerinde angularjs kullanılarak kullanıcıdan alınan çoklu veri girişlerinin bir dizi içinde tutularak AJAX ile sunucuya gönderilmesi ve sunucuda işlenmesi sağlanacaktır. Bu amaçla oluşturacağımız giriş kontrolünün CSS kodlarını tanımlayalım.

<style>

    .mainContainerAngularExample {

        width:300px;
        margin:10px;
    }

    .detailAngularExample {

        margin-top:10px;
    }

    .detailAngularExample input:focus {

        background-color:lightblue;
    }

    .footerAngularExample {

        margin-top:10px;
        text-align:right;
    }

    .arrayContainerAngularExample {

        margin-top:10px;
        color:coral    
    }

</style>

Sonraki aşamada DOM elementleri ve veri katmanı arasındaki bağlantıyı tanımlamak için angularjs kodlarını yazalım. Aşağıdaki kodlarda "myApp" modulü altında "MainCtrl" kontrolcüsü tanımlanmaktadır. Scope (Kapsam) içinde yer alan "addItem" fonksiyonu ile diziye elemen eklenmekte ve "removeItem" ile diziden eleman silinmektedir. Bu amaçla diziler üzerinde tanımlı "splice" fonksiyonu kullanılmıştır. Scope içinde yer alan "id" değişkeni ile dizi elemanlarının isimlendirilmesi yapılmaktadır. Ayrıca eğer gerekli olursa (dizi içinde yer alan elemanların tekrar ekmesi durumunda) "id" eşsiz anahtar olarak da kullanılabilir. Burada en önemli nokda dizi içinde nesne(object) kullanılmasıdır. "np-repeat" işlemi gerçekleştirirken kendi scope (kavramı) nesnesini yaratmaktadır. Bu sırada javascript prototype yapısından dolayı "primitive (ilkel)" değişkenlerin değeri programlama dillerindeki fonksiyonlara parametre gönderilirken ki durumla benzer olarak kopyalanmaktadır. Bu sebeple dizi içindeki değişikliğin "parentScope" üzerinde geçerli olabilmesi için dizi içinde referans olarak JSON nesnesi kullanılmıştır.

var app = angular.module('myApp', []);

app.controller('MainCtrl', ['$scope','$http',function ($scope, $http) {

    $scope.pages = [
        { val: 'Item 1' }
    ];

    $scope.id = 1;

    $scope.addItem = function (index) {

        $scope.id++;
        $scope.pages.splice(index + 1, 0, { val: 'Item ' + $scope.id });
    }

    $scope.removeItem = function (index) {

        if (index != 0)
            $scope.pages.splice(index, 1);
    }

    $scope.saveData = function () {

        $http.post("./Home/SaveData", $scope.pages).success(function () {

            alert("Veriler Başarıyla Kaydedildi.");

        }).error(function () {
            
            alert("Veriler Kaydedilirken Bir Hata Oluştu!");
        });
    }
}]);

Sonraki aşamada HTML kodlarını tanımlayalım. Aşağıdaki kodlarda "ng-model" niteliği kullanılarak giriş elementiyle dizi elemanı arasındaki ilişki tanımlanmıştır. "ng-click" kullanılarak kontrolcü içinde yer alan ilgili fonksiyonların tıklanma durumunda çalıştırılması sağlanmaktadır. "ng-hide" ile ilk elemandaki sil tuşunun görünmemesi sağlanmaktadır. "saveData" fonksiyonu kullanılarak üzerinde çalıştığımız dizi AJAX POST isteğiyle sunucuya gönderilmektedir.

<div class="mainContainerAngularExample" ng-app="myApp" ng-controller="MainCtrl">
<div class="detailAngularExample" ng-repeat="page in pages">
<input ng-model="page.val" type="text" />
        <button class="btn btn-default btn-xs" ng-click="addItem($index)" type="button"><span class="glyphicon glyphicon-plus"></span>EKLE</button>
        <button class="btn btn-default btn-xs" ng-click="removeItem($index)" ng-hide="$index === 0" type="button"><span class="glyphicon glyphicon-minus"></span>SİL</button>
    </div>
<div class="footerAngularExample">
<button class="btn btn-success" ng-click="saveData()" type="button"><span class="glyphicon glyphicon-save"></span>KAYDET</button>
    </div>
<div class="arrayContainerAngularExample">
CurrentArray = {{pages}}
    </div>
</div>

Sunucu tarafında "postTemplate" ile gelen verinin bağlanacağı yapı tanımlanmaktadır. Son olarak "SaveData" fonksiyonu ile aşağıdaki gibi AJAX ile gönderilen dizi işlenebilmektedir.

public struct postTemplate
{
     public string val { get; set; }
}

[HttpPost]
public ActionResult SaveData(List<postTemplate> Datas)
{
    return Json("OK");
}

Yukarıdaki kodların çalıştırılması sonucunda aşağıdaki sonuç elde edilmektedir:

CurrentArray = {{pages}}

Friday, March 25, 2016

C# ile Zip Formatında Dosya Sıkıştırma - Zip Formatted File Compression with C#

Bu yazıda .NET framework 4.5 ve üzeri için nasıl zip sıkıştırması yapılacağı anlatılacaktır. Bu yazı kapsamında zip dosyasının içinde yer alan sıkıştırılacak dosya ve zip dosyası hafızada oluşturulacaktır. Elde edilen byte dizisi "File" sınıfı kullanılarak dosya sistemine yazılacaktır. Örnek olarak bir text dosyası oluşturulacak ve bu dosya ziplenecektir.

Zip dosyasının oluşturulması için "ZipArchive" sınıfı kullanılacaktır. Bu sınıfın kullanılabilmesi için  "System.IO.Compression" ve "System.IO.Compression.FileSystem" dll dosyalarına referans verilmelidir. Ayrıca "System.IO.Compression" dll dosyasının versiyonunun eski olmamasına dikkat edilmelidir. Referanslar eklendikten sonra aşağıdaki tanımlama kod sayfasına eklenmelidir.

using System.IO.Compression;

Text dosyasının oluşturulması amacıyla "StringBuilder" sınıfını kullanarak aşağıdaki gibi yazı içeriği oluşturalım:

StringBuilder builder = new StringBuilder();  
builder.AppendLine("Veli");
builder.AppendLine("Yigit");
builder.AppendLine("Yolcu");

Aşağıda yer alan ZipThat fonksiyonuyla zip dosyasının byte dizisi elde edilmektedir. Fonksiyon kullanılarak bir zip arşivi oluşturulmakta ve daha önce hazırladığımız yazı içeriği "ZipArchiveEntry" olarak zip arşivine eklenmektedir. Bu fonksiyon zip verisini "MemoryStream" içinde biriktirmekte ve işlem tamamlandığında sıkıştırılmış içeriği byte dizisi olarak döndürmektedir.

byte[] ZipThat(string FileName, byte[] TxtData)
{
    using (MemoryStream mst = new MemoryStream())
    {
        using (ZipArchive arc = new ZipArchive(mst, ZipArchiveMode.Create))
        {
            var zipEntry = arc.CreateEntry(FileName);

            using (Stream st = zipEntry.Open())
            {
                st.Write(TxtData, 0, TxtData.Length);
            }
        }

        return mst.ToArray();
    }
}

"Encoding" sınıfı kullanılarak StringBuilder" içinde yer alan yazının byte dizisi elde edilebilmektedir:

byte[] txtData = Encoding.Default.GetBytes(builder.ToString());

Son olarak oluşturulan zip verisi "File" sınıfı kullanılarak dosya sistemine yazılmaktadır.

File.WriteAllBytes(string.Format(@"C:\Deneme\{0}.zip", "ZipFile"), ZipThat("FileThatInZipArchive.txt"));

Wednesday, March 23, 2016

Jquery ile Yukarı Çık Uygulaması (Uçan Kartal) - Go Up Component with Jquery (Flying Eagle)

Bu yazıda bloğa yeni eklediğim yukarı çık uygulamasının nasıl oluşturulduğu üzerinde duracağım. Bu uygulama ile kullanıcı sayfanın aşağı taraflarına doğru indiğinde sağ alt köşede görünen bileşen yardımıyla en üstüne çıkabilmektedir. Bu yazı aynı zamanda jquery ile "scroll" işlemlerinin nasıl yapıldığı anlatılmaktadır.

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

<style>

        .FlyingEagle {

            position:fixed;
            background-image:url('Images/eagle5.png');
            width:150px;
            height:150px;
            background-size:150px 150px;
            display:none;
            top:100%;
            left:100%;
            margin-top:-180px;
            margin-left:-180px;
            opacity:0.7;
        }

</style>

Yukarıdaki CSS kodlarında önemli noktalardan ilki "position:fixed" tanımlamasıdır. Bu tanımlama ile sınıfın üyesi olan elementin tarayıcı penceresine (window) göre pozisyon alması sağlanmaktadır. Yine "margin" değerleri kullanılarak elementin pozisyondan istediğimiz bir miktarda sapması (disposition) sağlanmaktadır. Elementin saydamlığı "opacity" niteliği kullanılarak azaltılmaktadır. Görüntünün taşıcıyı içine düzgün bir şekilde yerleştirilmesi amacıyla "background-size" niteliği kullanılmıştır. Bu nitelik ile görüntü elementin içine esnetilerek veya daraltılarak yerleştirilmektedir.

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

$(document).ready(function () {

            $(".FlyingEagle").click(function () {

                $("html, body").animate({ scrollTop: 0 }, 500);
            });

            $(window).scroll(function () {

                if ($(window).scrollTop() > 50) {

                    $(".FlyingEagle").show("fast");
                } else {

                    $(".FlyingEagle").hide("fast");
                }
            });
        });

Jquery "scroll" olayı yakalanarak kartal animasyonunun yönetimi yapılmaktadır. Jquery "show" fonksiyonu ile kartal gösterilmekte, "hide" fonksiyonu ile de saklanmaktadır. Jquery scrollTop fonksiyonu ekranın üstüne kaç piksellik kısımın kaydığını döndürmektedir. Bu yüzden sıfır değeri hiç kayma olmadığını göstermektedir. Bu kapsamda sayfa en fazla $(document).height() - $(window).height() kadar kaydırılabilir. Jquery "animation" fonksiyonu ile yukarı yumuşak bir biçimde çıkılması sağlanmaktadır. Son olarak da CSS sınıfı "FlyingEagle" olan bir "div" elementi sayfaya eklenir.

Sunday, March 20, 2016

Angularjs ve ASP.NET MVC ile Döviz Kurları Uygulaması - Exchange Rates Application With Angularjs and ASP.NET MVC

Bu yazıda TCMB (Türkiye Cumhuriyeti Merkez Bankası) tarafından yayınlanan ve kur bilgilerini içeren XML dosyasını kullanarak döviz kurlarını gösteren bir uygulama geliştireceğiz. Bu uygulama içinde gerekli TCMB verileri sunucu üzerinde çekilip AJAX ile tarayıcıya gönderilecektir. Neden direk tarayıcı üzerinden verileri çekmiyoruz diyen arkadaşlar varsa eğer öncelikle "same-origin policy" adı verilen kuralı incelemeleri gerekir. Bu kurala göre bir tarayıcı üzerinden değişik bir kaynaktaki (domaindeki) veriye ulaşım güvenlik endişesiyle engellenmektedir. Bu durum sadece AJAX için değil "iframe" için de geçerlidir.

Öncelikle TCMB kaynağından veriyi alacak sunucu kodunu tanımlayalım:

[HttpGet]
public ActionResult GetData()
{
     XDocument doc = XDocument.Load("http://www.tcmb.gov.tr/kurlar/today.xml");
     var dox = doc.Descendants()
         .Where(r => r.Name == "Currency")
         .Select(r => new {
             Isim = r.Element("Isim").Value,
             Kod = r.Attribute("Kod").Value,
             AlisKur = r.Element("BanknoteBuying").Value,
             SatisKur = r.Element("BanknoteSelling").Value
          });

      return Json(dox, JsonRequestBehavior.AllowGet);
}

Kod yukarıdan aşağıya incelendiğinde öncelikle dikkat çeken nokta [HttpGet] tanımlamasıdır. Bu tanımlama ile "GetData" fonksiyonuna ulaşılırken "Get" isteği kullanılması gerektiği belirtilmektedir. Yani fonksiyon "Post" veya "Delete" isteklerine cevap vermeyecektir.

Bir diğer önemli nokta ise "XDocument" sınıfıdır. Bu sınıf, XML verisini üzerinde LINQ sorgularının çalıştırılmasına olanak sağlayacak bir biçimde kullanmaktadır. Bilindiği üzere aynı işlemi yapan bir diğer sınıf da "XmlDocument" sınıfıdır. Bu sınıf XML verisini eski usül XML DOM olarak kullanmakta ve veri içindeki aramaları "XPath" ile yapmaktadır. LINQ arayüzünün daha basit olması sebebiyle bu uygulamada "XDocument" sınıfını kullandım.

Son aşamada "Json" fonksiyonu kullanılarak bir önceki LINQ işleminden dönen ön tanımsız nesneler JSON formatına dönüştürülüp istemciye gönderilmektedir. "JsonRequestBehavior.AllowGet" kullanılarak fonksiyonun "GET" isteklerine müsaade etmesi sağlanmıştır. Aksi durumda dönüşümü yapmayacaktır.

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

var currencyapp = angular.module('currencyapp', []);

currencyapp.controller('currencyListController', ['$scope', '$http',

  function ($scope, $http) {

      $http.get('./Home/GetData').success(function (data) {
          $scope.kurs = data;
      });

  }]);

Yukarıdaki kodlarda öncelikle "root scope" yani genel tanımlama amacıyla "currencyapp" modülü tanımlanmaktadır. Bu modülün altında "currencyListController" adında "$scope" ve "$http" servislerine bağımlı bir kontrolcü tanımlanmaktadır. Bu nesne aracılığıyla AJAX sorgusu gerçekleştirilmekte ve döviz verisi kapsam (scope) içine alınmaktadır. AJAX işlemi için "$http" servisinin "get()" fonksiyonu kullanılmaktadır.

AngularJs ile veri modeli oluşturduktan sonra son olarak bunu görüntü (View) ile ilişkilendirelim:

<div ng-app="currencyapp">
    <table ng-controller="currencyListController" class="table table-striped table-condensed">

        <thead>
            <tr>
                <th>Döviz Adı</th>
                <th>Döviz Kodu</th>
                <th>Alış</th>
                <th>Satış</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="kur in kurs">
                <td>{{kur.Isim}}</td>
                <td>{{kur.Kod}}</td>
                <td>{{kur.AlisKur}}</td>
                <td>{{kur.SatisKur}}</td>
            </tr>
    </table>
</div>

Burada "ng-app" niteliği ile ilgili DOM nesnesinin altında yer alan ögelerin "currencyapp" uygulamasına dahil olduğu belirtilmektedir. "Table" nesnesi "ng-controller" niteliği ile "currencyListController" kontrolcüsü ile ilişkilendirilmektedir. Bu kontrolcünün kapsamı dahilinde yer alan "kurs" listesinin içindeki "kur" JSON nesneleri kullanılarak tablo oluşturulmaktadır. "{{kur.Isim}}" tanımlaması ile kur nesnesinin "Isim" değeri ilgili tablo kısmına yazılmaktadır. "tr" etiketinde "ng-repeat" niteliği kullanılarak ilgili listedeki tüm nesneler için tablo satırlarının oluşturulması sağlanmaktadır. Yani listede yer alan her bir nesne için bir tablo satırı oluşturulmaktadır.

Uygulama sonunda aşağıda gösterilen tablo elde edilmektedir:




Wednesday, March 16, 2016

Jquery AJAX ile Dinamik Görüntü Yükleme - Dynamically Loading Images with Jquery AJAX

Bu yazıda AJAX kullanılarak görüntülerin tarayıcıya dinamik olarak yüklenmesi sağlanacaktır. Bilindiği üzere HTTP protokolü yazı (text) temelli çalışan bir protokoldür. Bu sebeple AJAX ile bilgi alışverişi yazı (text) olarak yapılmaktadır. Bir görüntünün sunucudan tarayıcıya HTTP protokolüyle yüklenmesi için görüntünün yazıya dönüştürülmesi gerekir. Bu amaçla daha önce anlatılan Base64 kodlama kullanılacaktır. Öncelikle AJAX işlemini gerçekleştirecek javascript kodlarını tanımlayalım:

      
$.ajax({
          type: "POST",
          url: "./WebForm3.aspx/GetImage",
          data: '{"FotoId": "10" }',
          contentType: "application/json; charset=utf-8",
          dataType: "json",
          success: function (msg) {
                    
                 var imageSrc = "data:image/jpg;base64," + msg.d;
                 $("#Base64Image").attr("src", imageSrc);
             },
             error: function (msg) {

                 alert("Hata Oluştu.");
             }
       });

Burada önemli nokta HTML img nesnesinin src niteliğine elde ettiğimiz değerin nasıl ekleneceğidir. Aşağıdaki gibi resmin Base64 biçimi src niteliğine atanarak tarayıcının otomatik olarak görüntüyü çözümleyip göstermesi sağlanmaktadır.

data:image/jpg;base64,...

Burada src içinde kodlu verinin jpg görüntüsü olduğu ve Base64 olarak kodlandığı belirtilmektedir. Son olarak görüntüyü kodlayıp tarayıcıya gönderen sunucu taraflı kodu yazalım:

        
[WebMethod]
public static string GetImage(string FotoId)
{
    byte[] arr = File.ReadAllBytes("IMAGE_PATH");

    string base64 = Convert.ToBase64String(arr);

    return base64;
}

Burada "Convert" nesnesinin "ToBase64String" fonksiyonu kullanılarak byte dizisi biçimindeki görüntü Base64 olarak kodlanıp tarayıcıya gönderilmiştir.

Tuesday, March 15, 2016

Base64 (Taban 64) Kodlama - Base64 Encoding

Base64 kodlamanın RFC 4648'de kullanım amaçları anlatılmaktadır. Burada bahsedildiği gibi Base64 kodlamanın asıl kullanım amacı byte dizisi şeklindeki verinin yazı (text) biçiminde veri iletim ortamında değiştirilmeden iletilmesi veya ilgili protokollerle uyumlu bir şekilde iletilmesidir. Ayrıca iletim ortamında veri iletiminin ortak bir standarta dayalı yapılmasıyla verinin üzerinden geçtiği cihazlar tarafından aynı şekilde yorumlanması sağlanmaktadır. Base64 kodlamada byte dizisi ASCII kodlarıyla uyumlu 64 tabanında yazıya dönüştürülmektedir. Genellikle yazı tabanlı HTTP, SMTP veya XML gibi yapılarda kullanılır. Base64 kodlama yapılırken sayıların karakter karşılıklarıyla eşleştirilmesi için aşağıdaki tablo (Karakter Set - Character Set) kullanılır:

    Value Encoding  Value Encoding  Value Encoding  Value Encoding
         0 A            17 R            34 i            51 z
         1 B            18 S            35 j            52 0
         2 C            19 T            36 k            53 1
         3 D            20 U            37 l            54 2
         4 E            21 V            38 m            55 3
         5 F            22 W            39 n            56 4
         6 G            23 X            40 o            57 5
         7 H            24 Y            41 p            58 6
         8 I            25 Z            42 q            59 7
         9 J            26 a            43 r            60 8
        10 K            27 b            44 s            61 9
        11 L            28 c            45 t            62 +
        12 M            29 d            46 u            63 /
        13 N            30 e            47 v
        14 O            31 f            48 w         (pad) =
        15 P            32 g            49 x
        16 Q            33 h            50 y

Kodlama yapılırken wikipedia'da gösterildiği gibi byte dizisi 6'lılar şeklinde ayrılarak tablodaki karşılıkları bulunur. 24 bit bloklar kullanılarak kodlama yapılır. 24 bitlik blok içinde karşılığı olmayan kısımlar "pad" karakteri (=) ile gösterilir:

Text contentM
ASCII77 (0x4d)0 (0x00)0 (0x00)
Bit pattern010011010000000000000000
Index191600
Base64-encodedTQ==

Yukarıdaki örnekte ASCII kodlanmış yazının dönüştürülmesi gösterilmesine rağmen ilgili işlem diğer kodlamalar içinde aynıdır (UTF-8, UTF-16 vb.). Fakat herhangi bir yazı bu şekilde gönderilecek ise yazının nasıl kodlandığı da ayrıca verinin yanında gönderilmelidir. Base64 kodlamanın yanında 40 bitlik bloklar ile kodlama yapan Base32 kodlama insan tarafından daha okunabilir bir çıktı üretmesine rağmen Base64 kodlama daha yaygın olarak kullanılmaktadır.

Javascript'te btoa(str) fonksiyonu kullanılarak Base64 kodlama ile kodlanmış yazı elde edilirken atop(enc) ile tekrar orjinal veri elde edilebilmekedir (ie > 9).

function Base64ExampleFunction() {

            var str = "M";
            var enc = window.btoa(str);
            var dec = window.atob(enc);

            var res = "Encoded String: " + enc + "
" + "Decoded String: " + dec;
            document.getElementById("base64Div").innerHTML = res;
        }

Yukarıdaki örnek çalıştırıldığında aşağıdaki sonuç elde edilmektedir:


Thursday, March 10, 2016

Jquery ile Yılan Oyununun Gerçeklenmesi - Implementing Snake Game with Jquery

Bu yazıda telefonlarda eskiden sıklıkla oynanan yılan oyununu javascript ve jquery ile oluşturacağız. Yılan oyununun ana fikri yılanı oluşturan parçalarının tren katarları gibi birbirini izlemesidir. Yem alındıkça puan güncellenmeli ve yılan büyümelidir. Yılan kendine veya duvarlara çarptığında oyun bitecektir. İlk olarak CSS kodlarımızı oluşturalım:

<style>

    .SGContainer
    {
        width:204px;
        height:auto; 
    }

    .SGCanvas
    {
        background-color:lightblue;
        width:204px;
        height:204px;
        position:relative;
       
    }

    .SGCanvas:focus
    {
        border:solid;
        border-width:2px;
        border-color:darkgreen;
    }

    .SGSnakePart
    {
        background-color:black;
        position:absolute;
        width:5px;
        height:5px;
    }

    .SGSnakeFood
    {
        background-color:darkred;
        position:absolute;
        width:5px;
        height:5px;
    }

    .SGFinish
    {
        font-weight:bold;
        background-color:brown;
        color:white;
        z-index:1;
        position:absolute;
        top:50%;
        left:50%;
        margin-top:-25px;
        margin-left:-50px;
        width:100px;
        height:50px;
        justify-content: center;
        align-items: center;   
        display:flex;   
    }
</style>

Yukarıdaki CSS kodlarında önemli nokta flex kutusu (flex box) kullanımıdır. Flex kutusu klasik kutuya göre daha esnek özellikler sunmaktadır. Burada "align-items" ile flex kutusunun içeriği dikey olarak, "justify-content" ile de yatay olarak konumlandırılmıştır. Sonraki aşamada javascript kodlarını tanımlayalım:

var Snake = [];
var Food = [];

var Direction = "Right";
var MoveNumber = 5
var Canvas = null;
var Interval = null;
var IsGameStarted = false;
var Score = 0;

var SnakePart = function () {

    this.X = -1;
    this.Y = -1;
    this.DomObject = null;
}

function StartGame() {

    IsGameStarted = false;
    Canvas = $(".SGCanvas");
    $(Canvas).children().remove();
    Snake = [];
    Food = [];
    Direction = "Right";
    Score = 0;

    StopAnimation();

    for (var i = 10; i > -1; i--) {

        var part = new SnakePart();
        part.X = i * 5;
        part.Y = 100;

        var domPart = $('<div class="SGSnakePart"></div>');
        part.DomObject = domPart;

        part.DomObject.css({ top: part.Y, left: part.X });

        Snake.push(part);

        AddPartToCanvas(part.DomObject)
    }

    $(Canvas).focus();

    $(Canvas).keydown(function (event) {

        event.preventDefault();
        SGUpdateDirection(event.keyCode);
    });

    $(Canvas).focusout(function () {

        if (IsGameStarted)
            StopAnimation();
    });

    $(Canvas).focusin(function () {

        if (IsGameStarted)
            StartAnimation();
    });
    
    GenerateFood();

    StartAnimation();
    IsGameStarted = true;
}

function StartAnimation() {

    if (Interval == null)
        Interval = setInterval(SGUpdate, 50);
}

function StopAnimation() {

    if (Interval != null)
        clearInterval(Interval);
    Interval = null;
}

function AddPartToCanvas(part)
{
    $(Canvas).append(part);
}

function GenerateFood() {

    var x = parseInt((Math.random() * 100) % 40) * 5;
    var y = parseInt((Math.random() * 100) % 40) * 5;

    var part = new SnakePart();
    part.X = x;
    part.Y = y;

    var domPart = $('<div class="SGSnakeFood"></div>');
    part.DomObject = domPart;
    part.DomObject.css({ top: part.Y, left: part.X });

    Food.push(part);

    AddPartToCanvas(part.DomObject);
}

function EatFood() {

    if(Snake[0].Y == Food[0].Y && Snake[0].X == Food[0].X)
    {
        Score++;
        Snake.push(Food.pop());
        GenerateFood();
    } 
}

function SGUpdateDirection(key) {
  
    if (key == 39 && Direction != "Left") {

        Direction = "Right";
    }

    if (key == 37 && Direction != "Right") {

        Direction = "Left";
    }

    if (key == 38 && Direction != "Down") {

        Direction = "Up";
    }

    if (key == 40 && Direction != "Up") {

        Direction = "Down";
    }
}

function SGUpdate() {


    for (var i = Snake.length - 1; i > 0; i--) {

        Snake[i].X = Snake[i - 1].X;
        Snake[i].Y = Snake[i - 1].Y;
    }

    if (Direction == "Right") {

        Snake[0].X += MoveNumber;
    }

    if (Direction == "Left") {

        Snake[0].X -= MoveNumber;
    }

    if (Direction == "Up") {

        Snake[0].Y -= MoveNumber;
    }

    if (Direction == "Down") {

        Snake[0].Y += MoveNumber;
    }

    if (SGIsGameOver())
    {
        SGGameOver();
        return;
    }

    EatFood();
    UpdateScore();
    SGUpdateCanvas();
}

function SGUpdateCanvas()
{
    for (var i = Snake.length - 1; i > -1; i--) {

        $(Snake[i].DomObject).css({ top: Snake[i].Y, left: Snake[i].X });
    }
}

function SGIsGameOver() {

    for (var i = Snake.length - 1; i > 0; i--) {

        if (Snake[0].X == Snake[i].X && Snake[0].Y == Snake[i].Y)
            return true;
        if (Snake[0].X == 200 || Snake[0].X < 0 || Snake[0].Y == 200 || Snake[0].Y < 0)
            return true;
    }

    return false;
}

function UpdateScore() {

    $("#SGPuan").text(Score);
}

function SGGameOver() {

    IsGameStarted = false;
    StopAnimation();
    $(Canvas).append($('<div class="SGFinish">OYUN BİTTİ!</div>'));
}

Yukarda yer alan fonksiyonların açıklamaları şöyledir:

* StartGame(): Oyunun sıfırlanmasını ve başlamasını sağlayan fonksiyondur. Burada başlangıç olarak 10 parça yılan oluşturulmakta, canvasla ilgili klavye olaylarına jquery ile fonksiyon atanmakta ve ilgili fonksiyonlar aracılığıyla animasyon başlatılmaktadır. Jquery keydown olayı bir klavye tuşuna basıldığında tetiklenmektedir. Bu fonksiyon içinde kullanılan "event.preventDefault()" ile ok tuşlarının ekranı oynatması engellenmekte yani tuşun ön tanımlı özelliği pasivize edilmektedir. Jquery focus() fonksiyonu ile herhangi bir elemente focus (odaklanma) yapılması sağlanmaktadır. Bu fonksiyonun düzgün çalışması için odaklanılacak elementin "tabindex" niteliği -1 olmalıdır. Jquery focusin() odaklanma olduğunda, focusout() ise odaklanma kaybedildiğinde tetiklenmektedir. İlgili olaylar tetiklendiğinde animasyon durdurulmakta veya devam ettirilmektedir.

* StartAnimation(): Oyun animasyonunun başlatılmasını sağlayan fonksiyondur. Javascript setInterval(çağrılacakfonksiyon, süre) fonksiyonu ile animasyon oynatılmaktadır. Bu fonksiyon ile parametre olarak gönderilen çağrılacak fonksiyon her süre dolduğunda çalıştırılmaktadır. Bu fonksiyon setTimeout() fonksiyondan farklı olarak devamlı olarak çağrıma devam etmektedir. Javascript setTimeout() fonksiyonu süre dolduğunda çağrılacak fonksiyonu çalıştırır ve bir daha çalıştırmaz. Süre parametresi millisecond (ms) olarak ifade edilmektedir. 1000 ms = 1 sec olarak kullanılır.

* StopAnimation(): Javascript clearInterval(interval) fonksiyonu ile animasyonun durdurulması sağlanmaktadır. Parametre olarak setInterval() fonksiyonu tarafından döndürülen değer kullanılmaktadır.

* AddPartToCanvas(): Jquery ile oluşturulan DOM nesnelerinin DOM'a eklenmesini sağlamaktadır.

* GenerateFood(): Rastgele bir pozisyona yem yerleştirilmesini sağlamaktadır. Bunu sağlarken Math.Random() fonskiyonunu kullanmaktadır. Bu fonksiyon 0 ile 1 arasında [0,1) bir reel sayı üretmektedir. Koordinatlar üretilirken kanvas uzunluğumuzun 200px ve aralıkların 5 px olduğu göz önünde bulundurularak elde edilen sayı 100 ile çarpılmakta ve 2 basamaklı rastgele bir sayı elde edilmektedir. Bu sayının 40'a göre modu alınarak rastgele 40'tan küçük bir sayı elde edilmiş olmaktadır. Elde edilen son değer 5 ile çarpılarak koordinat hesaplanmış olmaktadır. Yukarıdaki matematiksel işlemler incelendiğinde elde edilen rastgele sayının [0,200) aralığında olduğu görülebilmektedir.

* EatFood(): Bu fonksiyon ile yılanın baş parçasının konumunun yem konumuyla aynı olup olmadığı kontrol edilmekte ve aynı ise puan artırılmakta, yeni bir yem oluşturulmakta ve yılan büyütülmektedir.

* SGUpdateDirection(key): Okunan klavye tuşunun koduna göre yılanın yönünü belirleyen fonksiyondur.

* SGUpdate(): Diğer bütün fonksiyonların yönetimini sağlayan ve yılanın hareketinin mantıksal hesaplamasını yapan ana animasyon fonksiyonudur.

* SGUpdateCanvas(): SGUpdate() fonksiyonunda belirlenen oyunun yeni durumuna göre kanvası güncelleyen fonksiyondur.

* SGIsGameOver(): Yılanın kanvas dışına çıkıp çıkmadığına veya zaten işgal ettiği bir koordinata yeniden girmesine veya girmemesine göre oyunun bitip bitmediğinin anlaşılmasını sağlayan fonksiyondur.

* UpdateScore(): Kanvasın sağ üstünde bulunan mavi puan sayısını güncelleyen fonksiyondur.

* SGGameOver(): Oyun bittiğinde gerekli işlemlerin yapıldığı fonksiyondur. Oyun bittiğinde animasyon durdurulmakta ve "OYUN BİTTİ!" yazısını taşıyan flex kutusu kanvasa eklenmektedir.

Son aşama olarak HTML kodlarını tanımlayalım:

<div class="SGContainer">
    <div style="margin-bottom:10px">
        <input id="Button1" class="btn btn-success" type="button" value="BAŞLA" onclick="StartGame()"/>
        <span id="SGPuan" class="label label-info" style="float:right; font-size:large">0</span>
    </div>
    <div class="SGCanvas" tabindex="-1">

    </div>
</div>

Yukarıda yer alan kodların çalıştırılması ile aşağıdaki sonuç elde edilmektedir:
(Oyun ok tuşlarıyla oynanmaktadır)


0

Saturday, March 5, 2016

Jquery ile Bulmaca Oyunu - Jquery Puzzle Game

Bu yazı daha önceki yazıların devamı olarak görülmelidir, bu sebeple bu yazıda öncekilerde anlatılan konular anlatılmayacaktır. Bu yazıda karışık olarak yer alan resim parçalarının doğru bir şekilde bir araya getirilerek çözülecek bir bulmaca oyunu tasarladık. Burada önceki yazılarda yer alan script ve css kodlarına (Jquery, Bootstrap) ek olarak sayfaya JqueryUI eklenmesi gereklidir. Bu amaçla JqueryUI CDN kodunu sayfaya ekleyelim:

<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js" type="text/javascript"></script>

JqueryUI sayfada kullanıcı etkileşimlerini veya animasyon efektlerini yönetmek amacıyla kullanılabilecek fonksiyonları içeren bir kütüphanedir. Bulmaca uygulamasında resimler üzerinde sürükle-bırak (drag-drop) yapılmasını sağlamak amacıyla kullanılmıştır.

Uygulamayı oluştururken ilk olarak CSS kodlarını tanımlayalım:

<style>
        .PuzzleContainer
        {
            width: 545px;
            height: 545px;
        }
        
        .PuzzleBoard
        {
            width: 545px;
            height: 545px;
        }
        
        .PuzzleBox
        {
            width: 50px;
            height: 50px;
            float: left;
            margin: 2px;
            border: solid;
            border-width: 1px;
        }
        
        .PuzzlePartContainerDiv
        {
            width: 50px;
            height: 50px;
            background: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijeyFxpSRzHq2d4NyPPy8bA9ybJECYVC1wmPTxj3yI5ih7711-T5Lfmqf44OT_4vx6TQVVko_cOMxGZoWW6CaZOpdRVr6LeMA88Go6S2nvsE8zktavDbEe9c2TBT6pwDvJd0dNUcvzKlo/s1600/puzzle1.jpg);
            background-size: 500px 500px;
            float: left;
            margin: 2px;
        }
        
        .PuzzlePartContainerDiv:hover
        {
            padding: 2px;
            background-clip: content-box;
        }
        
        .PuzzlePartContainerDiv:active
        {
            border: solid;
            border-width: 2px;
            border-color: red;
        }
        
        .PuzzleBoxHover
        {
            border: solid;
            border-color: red;
        }
        
        .PuzzleBoxActive
        {
            background-color: lightblue;
        }
        
        .PuzzleContainerActive
        {
            background-color: lightgray;
        }
</style>

Yukarıdaki CSS kodlarında "PuzzleContainer" karışık halde resim parçalarını içeren kanvasın sınıfını, "PuzzleBoard" resimlerin yerleştirileceği kanvasın sınıfını, "PuzzleBox" resimlerin yerleştirileceği kanvasın içinde yer alan resimlerin içine oturacağı kare alanların sınıfını, "PuzzlePartContainerDiv" "PuzzleBox" içine yerleştirilecek "PuzzleContainer" içinde yer alan resim parçalarının sınıfını, "PuzzlePartContainerDiv:hover" "PuzzleContainer" içinde yer alan resim parçalarının üzerine fareyle gelindiğinde uygulanacak CSS niteliklerini içeren sınıfı, "PuzzlePartContainerDiv:active" "PuzzleContainer"içinde yer alan resim parçalarının üzerine tıklandığında uygulanacak CSS niteliklerini içeren sınıfı, "PuzzleBoxHover" resim parçalarının "PuzzleBox" üstüne getirildiğinde uygulanacak nitelikleri içeren sınıfı, "PuzzleBoxActive" sürükleme esnasında "PuzzleBox" sınıfının üyelerine uygulanacak CSS niteliklerini içeren sınıfı ve son olarak "PuzzleContainerActive" sürükleme esnasında resim parçalarını içeren kanvasa uygulanacak nitelikleri içeren sınıfı ifade etmektedir.

Yukarıdaki önemli noktalardan ilki "background-size: 500px 500px;" belirtimidir. Bu nitelik ile arka plan olarak ayarlanan görüntünün arka planda 500px-500px olarak yeniden boyutlanması sağlanmaktadır. Bir diğer önemli nokta ise "background-clip: content-box;" niteliğidir. Bu nitelik ile arka plan resminin içerik kutusuna yani padding ile kısıtlanmış alana çizilmesi sağlanmaktadır. Yukarıda yer almayan fakat bootstrap ile eklenen ve bu uygulama için kritik olan bir diğer nitelik ise "box-sizing: border-box" belirtimidir. Bu nitelik "border-box" yapılarak margin dışındaki diğer belirtimlerin yani padding, border ve content değerlerinin, belirtilen width (genişlik) ve height (yükseklik) değerlerinin içinde olduğu belirtilmektedir. Yani bir ögeye border kalınlığı 2 olan bir border tanımlasak bile genişlik ve yükseklik değeri daha önce belirttiğimiz değer üzerinde sabit kalacaktır.

Bir sonraki aşama olarak javascript kodlarını tanımlayalım:

<script>

        var PuzzleArray = [];
        var PuzzleTmpArray = [];

        $(document).ready(function () {

            CreateMyWorld(true);
        });

        var PuzzleWrapper = function () {

            this.ActualX = -1,
            this.ActualY = -1,
            this.CurrentX = -1,
            this.CurrentY = -1
        }

        function CreateMyWorld(Shuffle) {

            $(".PuzzleContainer").children().remove();
            $(".PuzzleBoard").children().remove();

            PuzzleArray = CreateArray(10, 10);

            SliceImageAndCreatePuzzle();
            ShuffleImages(Shuffle);
            ConfigurePuzzle();
        }

        function CreateButtonClick() {

            var isShuffle = $("#CBShuffle").is(":Checked");
            CreateMyWorld(isShuffle);
        }

        function ConfigurePuzzle() {

            $(".PuzzlePartContainerDiv").draggable({ snap: ".PuzzleBox", snapMode: "inner", helper: "clone" });

            $(".PuzzleContainer").droppable({

                activeClass: "PuzzleContainerActive",
                drop: function (event, ui) {

                    var parentBox = $(ui.draggable).parent();

                    if ($(parentBox).is(".PuzzleBox")) {

                        var x = parseInt($(parentBox).attr("pX"));
                        var y = parseInt($(parentBox).attr("pY"));

                        PuzzleArray[x][y].CurrentX = -1;
                        PuzzleArray[x][y].CurrentY = -1;
                    }

                    $(parentBox).css("border", "solid");
                    $(parentBox).css("border-width", "1px");
                    $(ui.draggable).css("margin", "2px");
                    $(ui.draggable).appendTo(event.target);
                }
            });

            $(".PuzzleBox").droppable({

                activeClass: "PuzzleBoxActive",
                hoverClass: "PuzzleBoxHover",
                drop: function (event, ui) {

                    var x2 = parseInt($(event.target).attr("pX"));
                    var y2 = parseInt($(event.target).attr("pY"));

                    var container = $(ui.draggable).parent();

                    if ($(event.target).children().length > 0)
                        return false;

                    if ($(container).is(".PuzzleBox")) {

                        $(container).css("border", "solid");
                        $(container).css("border-width", "1px");
                    }

                    $(ui.draggable).css("margin", "0px");
                    $(event.target).css("border", "none");
                    $(ui.draggable).appendTo(event.target);

                    var x = parseInt($(ui.draggable).attr("pX"));
                    var y = parseInt($(ui.draggable).attr("pY"));

                    PuzzleArray[x2][y2].CurrentX = x;
                    PuzzleArray[x2][y2].CurrentY = y;

                    if (IsGameFinished()) {

                        $(".PuzzleBox").animate({ duration: "slow", margin: 0 });
                    }
                }
            });

        }

        function IsGameFinished() {

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

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

                    if (PuzzleArray[x][y].ActualX != PuzzleArray[x][y].CurrentX || PuzzleArray[x][y].ActualY != PuzzleArray[x][y].CurrentY)
                        return false;
                }
            }

            return true;
        }

        function SliceImageAndCreatePuzzle() {

            var ContainerDiv = $(".PuzzleContainer");
            var puzzleBoard = $(".PuzzleBoard");

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

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

                    var item = $('<div class="PuzzlePartContainerDiv" pX=' + x + ' pY=' + y + ' style="background-position:-' + x * 50 + 'px -' + y * 50 + 'px"></div>');
                    var itemBox = $('<div class="PuzzleBox" pX=' + x + ' pY=' + y + '></div>');

                    PuzzleArray[x][y].ActualX = x;
                    PuzzleArray[x][y].ActualY = y;

                    PuzzleTmpArray.push(item);
                    puzzleBoard.append(itemBox);
                }
            }
        }

        function ShuffleImages(Shuffle) {

            var containerDiv = $(".PuzzleContainer");

            if (Shuffle) {

                while (PuzzleTmpArray.length > 0) {

                    var rnd = Math.random();

                    var a = PuzzleTmpArray.shift();

                    if (rnd < 0.3) {
                        $(containerDiv).append(a);
                    } else
                        PuzzleTmpArray.push(a);
                }
            } else {

                while (PuzzleTmpArray.length > 0) {

                    var a = PuzzleTmpArray.shift();

                    $(containerDiv).append(a);
                }
            }
        }

        function CreateArray(width, height) {

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

            return arr;
        }

</script>


Yukarıdaki javascript kodları içinde yer alan fonksiyonların açıklamaları şöyledir:

* CreateMyWorld(Shuffle): İçine görüntülerin karıştırılıp karıştırmayacağını belirleyen bir boolean parametre alarak oyunu kuran ana fonksiyondur.

* CreateButtonClick(): Oyun üzerinde yer alan ve Shuffle paremetresini yanındaki CheckBox'dan alan yeşil "Oyunu Oluştur" tuşuna basıldığında çalışan fonksiyondur.

* ConfigurePuzzle(): Resim parçalarına sürüklenebilirlik (draggable) özelliğini kazandırıldığı ve resim parçalarını içeren ve bu parçaların yerleştirildiği alanlara düşürülebilirlik (droppable) özelliğinin kazandırıldığı fonksiyondur.

* IsGameFinished(): Oyunun tamamlanıp tamamlanmadığının sonucunu döndüren fonksiyondur.

* SliceImageAndCreatePuzzle(): Resimlerin parçalandığı, ve resimlerin yerleştirileceği kutuların oluşturulduğu fonksiyondur. Bu fonksiyon sonlandığında kutular DOM'a yerleştirilmiş olurken resim parçaları bir dizi içinde saklanmış olmaktadır.

* ShuffleImages(Shuffle): Resim parçalarının karıştırılıp karıştırılmayacağını belirleyen parametreye göre bu parçalara gerekli işlemleri yapıp DOM'a yerleştiren fonksiyondur.

Son olarak da oyun için gerekli HTML kodlarını ekleyelim:

<div>
<div>
<div class="checkbox-inline">
<label>
<input checked="checked" id="CBShuffle" type="checkbox" />Görüntüleri Karıştır</label>
</div>
<button class="btn btn-success" onclick="CreateButtonClick()" type="button">
OYUNU OLUŞTUR</button>
</div>
<br />
<div class="PuzzleBoard">
</div>
<div class="PuzzleContainer">
</div>
</div>


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



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: