22 Mart 2012 Perşembe

HTML 5 audio tag kullanımı



Html 5 ile gelen yeni elementlerden biride "audio" elementi. Ses dosyalarımızı kolay bir şekilde oynatabilmemizi sağlıyor. Tüm browserlar desktekliyor ama Firefox 11.0 sürümünde hata verebiliyor.

Örnek Kullanım :


<audio controls="controls">
<source src="audiodosyasının-url-pathini-yazıyoruz" />
Kullanmakta olduğunuz browser audio elementini desteklememektedir.
</audio>

Herhangi bir hata oluşması durumunda audio tagının içine yazdığımız uyarı mesajı gösterilecektir.
autoplay="autoplay" özelliği ile ses dosyamızı otomatik olarak başlatabiliriz.
loop="loop" özelliği ile ses dosyamızı tekrarlı olarak oynatabiliriz.

Sonuç:

Read More

HTML 5 output ve range kullanımı


output : Html5 ile gelen yeni bir element. IE deskteklemiyor. Chrome, Firefox, Opera ve Safari browserları destekliyor.
range : Html5 ile input elementine eklenen yeni bir tip. IE ve Firefox desteklemiyor. Chrome, Opera ve Safari browserları destekliyor.
Sözü çok uzatmadan basit bir örnek ile hem kullanımlarını hemde bize ne tür avantajlar sağlayabileceklerini görelim.

Örnek Kullanım :



<form oninput="outElement.value = parseInt(rangeElement.value)">
<div style="width: 150px; text-align: center;">
<output name="outElement" for="rangeElement"></output></br>
</div>
<span>0<input type="range" name="rangeElement" value="50" step="5" />100</span>
</form>

Sonuç :


0100
Read More

HTML 5 optgroup tagının kullanımı


IE dahil birçok browser destekliyor.
Örnek Kullanım:


<select>
<optgroup label="Bilgisayar">
<option value="0">Notebook</option>
<option value="1">Desktop</option>
</optgroup>
<optgroup label="Telefon">
<option value="2">Cep Telefonu</option>
<option value="3">Masaüstü Telefon</option>
<option value="4">Telsiz Telefon</option>
</optgroup>
<optgroup label="Beyaz Eşya">
<option value="5">Buzdolabı</option>
<option value="6">Fırın - Ocak</option>
<option value="7">Çamaşır Makinesi</option>
</optgroup>
</select>

Sonuç:

Read More

HTML 5 ile zorunlu alan kontrolü


IE henüz desteklemiyor olsa da Html 5 ile gelen kullanışlı bir özellik.

Örnek Kullanım:

<form action="html5Required.html">
<div>
<input type="text" placeholder="Adınızı yazın" required="required"/>
<input type="submit" value="Tıkla" />
</div>
</form>

Sonuç:

Read More

HTML-5 in güzel nimetlerinden sadece biri, IE harici birçok browser destekliyor.

Örnek Kullanım:

<input type="text" placeholder="Adınızı yazın" />
<input type="text" placeholder="Soyadınızı yazın"/>

Sonuç:


Read More

9 Mart 2012 Cuma

WPF Drag & Drop İşlemleri


Masaüstünden sürüklenen image dosyalarının uygulamamız içinde gösterimini sağlayacağız. Ufak bir Wpf uygulaması yaparak nasıl yapılabileceğini görelim. Hemen bir Wpf Application oluşturarak başlayalım.

 Öncelikle image ların gösterimi için uygulamamıza bir UserControl ekliyoruz.



UserControlümüze bir Image elementi ekliyoruz. Ben biraz daha derli toplu görünmesi için Image elementini Border içinde kullandım. UserControlümüzün Xaml kodlaması aşağıdaki gibidir.

<UserControl x:Class="DesktopFileDrop.ImageDropUI"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="250" d:DesignWidth="250" MaxHeight="250" MaxWidth="250">
    <Grid>
        <Border x:Name="brdContainer" Margin="20">
            <Image x:Name="imgViewer"></Image>
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF7F9CA2" Offset="1" />
                    <GradientStop Color="#FFE9F0F5" Offset="0" />
                </LinearGradientBrush>
            </Border.Background>
        </Border>
    </Grid>
</UserControl>


İşimizi biraz daha kolaylaştırmak için UserControlümüzün Constructor ında Image elementimizin Source propertysini hemen set edebiliriz. Bunun için UserControlümüzün .cs tarafına geçiriyoruz ve Constructor ını Image elementimizin Source propertysini set etmek için kullanacağımız bir BitmapImage objesi parametre alacak şekilde değiştiriyor ve Image elementimizin Source propertysini bu parametremizle set ediyoruz.


using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace DesktopFileDrop
{
    /// <summary>
    /// Interaction logic for ImageDropUI.xaml
    /// </summary>
    public partial class ImageDropUI : UserControl
    {
        public ImageDropUI(BitmapImage bmpImage)
        {
            InitializeComponent();
            imgViewer.Source = bmpImage;
        }
    }
}

Artık image larımızı göstereceğimiz UserControlümüz kullanıma hazırdır. Şimdi MainWindow umuza geçelim ve hazırladığımız UserControlümüzü eklemek için bir container hazırlayalım. Bunun için ben WrapPanel kullanacağım, siz duruma göre farklı bir panel kullanabilirsiniz. Ayrıca panelimde scrool da çıkmasını istiyorum bunun içinde bir ScrollViewer elementi kullanacağım.
MainWindow umuzun Xaml kodlaması aşağıdaki gibidir.


 <Window x:Class="DesktopFileDrop.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="File Drop" Height="350" Width="550">
    <Grid AllowDrop="True" Drop="DropFile">
        <Label></Label>
        <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
            <WrapPanel x:Name="wrpContainer" FlowDirection="LeftToRight" Orientation="Horizontal" MaxWidth="550"></WrapPanel>
        </ScrollViewer>
    </Grid>
</Window>

Görüldüğü gibi en dıştaki Grid imizin AllowDrop propertysini True olarak set ettik. Formun sadece bir bölümünün üzerine gelindiğinde değilde her yerinde drop işlemine izin vermesini istiyoruz. Grid imiz tüm formu kapladığı için drop işlemini Grid in Drop Eventinde yapacağız. Şimdi MainWindow umuzun .cs tarafına geçelim ve Drop Eventimiz tetiklendiğinde imagelarımızın gösterimini yapacak kodlarımızı yazalım.
Öncelikle drop edilen dosyaların uzantılarını kontrol etmeliyiz. Biz image dosyası bekliyoruz ama kullanıcının farklı dosyalar drop etmeyeceğinden tabiki emin olamayız. Bu yüzden kabul edeceğimiz dosyaların uzantılarını bir yerde tutmamız gerekir.
Bu iş için hızlı bir çözüm olarak Uygulamanın Settings dosyasını kullanabiliriz. Settings dosyasının .cs inde AllowedImagePath isimli string bir property tanımlıyorum ve value suna izin verdiğim dosyların uzantılarını virgülle ayırarak ekliyorum. Bu işlemi Settings arayüzünden de yapabilirsiniz.

        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.DefaultSettingValueAttribute(".jpg,.png,.bmp,.ico")]
        public string AllowedImagePath
        {
            get
            {
                return ((string)(this["AllowedImagePath"]));
            }
            set
            {
                this["AllowedImagePath"] = value;
            }
        }

MainWindow un contstructor ında bunları bir string dizisine alarak dosya uzantılarını buradan kontrol edebiliriz.

  private string[] _currentFileExtensions = null;

        public MainWindow()
        {
            InitializeComponent();
            _currentFileExtensions = DesktopFileDrop.Properties.Settings.Default.AllowedImagePath.Split(',');
        }

Şimdi kullanıcının drop ettiği dosyaların uzantılarını kontrol edecek methodumuzu yazalım. Methodumuz bizden bir FileInfo parametresi alsın ve bize boolean bir sonuç döndürsün.

 private bool CheckFileExtension(FileInfo file)
 {
            return _currentFileExtensions.Where(f => f == file.Extension).FirstOrDefault() == null ? false : true;
 }

Artık kullanıcının uygulamamıza sürüklediği dosya pathlerini alarak birer FileInfo nesnesi oluşturmalı ve biraz önce yazdığımız CheckFileExtension methodumuz ile dosya uzantılarının izin verdiğimiz uzantılar içinde olup olmadığını kontrol etmeliyiz. Sonrasında geçerli dosyaları, Image gösterimi için hazırlamış olduğumuz UserControlümüzü create ederken bizden beklediği BitmapImage nesnesini oluşturmak için kullanacağız ve create ettiğimiz her UserControlü MainWindow umuzdaki WrapPanelimize ekleyeceğiz.
Öncelikle kullanıcının drop ettiği dosyaların pathlerini almalıyız. Bu işlemi Grid imizin Drop eventinde DragEventArgs eventinden faydalanarak yapacağız.

private void DropFile(object sender, DragEventArgs e)
{
            string[] filePaths = e.Data.GetData(DataFormats.FileDrop) as string[];
            if (filePaths == null || filePaths.Count() == 0) { return; }

            CreateDropUserControls(CreateImage(GetFiles(filePaths)));
}

Kullanıcının uygulamamıza sürüklediği dosya pathlerini böylece almış olduk.
Şimdi aldığımız bu dosya pathlerini bizden parametre olarak alıp her biri için bir FileInfo nesnesi oluşturarak bize FileInfo Listesi döndürecek bir methoda ihtiyacımız var. Dosya uzantılarını kontrol etmek için yazdığımızCheckFileExtension methodumuzu da burada kullanacağız. Hemen FileInfo Listemizi oluşturacak methodumuzu yazmaya başlayalım.

private List<FileInfo> GetFiles(string[] filePaths)
{
            List<FileInfo> fileList = new List<FileInfo>();
            foreach (string path in filePaths)
            {
                try
                {
                    FileInfo file = new FileInfo(path);
                    if (file == null || !CheckFileExtension(file)) { continue; }
                    fileList.Add(file);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format("{0} dosyası yüklenemedi.\r\nException Message: {1}", path, ex.Message), "Hata!", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            return fileList;
 }

Sıra Image larımızı oluşturmaya geldi. Bunun içinde bizden parametre olarak FileInfo Listesi alıp geriye Image Listesi dönen bir methoda ihtiyacımız olacak.

private List<BitmapImage> CreateImage(List<FileInfo> fileList)
 {
            List<BitmapImage> imageList = new List<BitmapImage>();
            foreach (FileInfo file in fileList)
            {
                try
                {
                    BitmapImage bmp = new BitmapImage();
                    bmp.BeginInit();
                    bmp.UriSource = new Uri(file.FullName);
                    bmp.EndInit();
                    imageList.Add(bmp);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format("{0} imagı oluşturulamadı.\r\nException Message: {1}", file.Name, ex.Message), "Hata!", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            return imageList;
 }

Image larımızıda oluşturduğumuza göre artık bu Image larımızı göstereceğimiz UserControllemizi create edip, WrapPanelimize ekleyebiliriz.


private void CreateDropUserControls(List<BitmapImage> imageList)
 {
            foreach (BitmapImage image in imageList)
            {
                wrpContainer.Children.Add(new ImageDropUI(image));
            }
 }

CreateDropUserControls methodumuzu Grid imizin Drop eventinde çalıştırarak finali yapıyoruz. Drop eventimizin son hali aşağıdaki gibidir.

private void DropFile(object sender, DragEventArgs e)
 {
            string[] filePaths = e.Data.GetData(DataFormats.FileDrop) as string[];
            if (filePaths == null || filePaths.Count() == 0) { return; }

            CreateDropUserControls(CreateImage(GetFiles(filePaths)));
 }


Uygulamanın kaynak kodlarını buradan indirebilirsiniz




Read More

8 Mart 2012 Perşembe

Custom Jquery Category Autocomplete


Autocomplete arama web sitelerinde artık vazgeçilmez oldu diyebiliriz. Jquery nin Autocomplete eklentisi ise bu konuda gerçekten çok başarılı. Birde bunu istediğimiz gibi customize edibelmemiz işin çekiciliğini artırıyor.
Hazır azda olsa vakit bulmuşken, birazcık da biz oynayalım ve aramada kategorilemizi ve gösterilen sonuçlardaki datalara ait image varsa onlarıda gösterelim. Hatta kullanıcının aramasına göre farklı sayfalara yönledirelim. Mesela kullanıcı bir e-ticaret sitesinde ve autocomplete textbox ımızı kullanarak ürün arıyor, arama sonuçlarından herhangi birini seçmeden enter a basmışsa Ürün Arama sayfamıza, arama sonuçlarında bir kategori üzerindeyken enter tuşana basmışsa seçmiş olduğu kategoriye ait ürünlerimizi göstermek üzere Kategorisayfamıza, ürün seçmiş ise o ürünün detayını göstermek üzere Ürün Detaysayfamıza yönlendirecek şekilde AutoComplete textbox ımızı düzenleyelim. ;)
Bunun için öncelikle projemize JqueryUI templatelerinden istediğimiz birini ve jquery kütüphanesi eklememiz gerekiyor.
http://jqueryui.com/download buradan indirebilirsiniz.
Arama textbox ının projedeki tüm sayfalarda görünmesini istiyorum. Bu yüzden öncelikle projemize bir MasterPage ekleyelim. Diğer tüm sayfalarımızada bu MasterPage i uygulayacağız.



















Css ve Js dosylarımızı MasterPage imize ekleyelim.
<link href="../css/redmond/jquery-ui-1.8.18.custom.css" rel="stylesheet" type="text/css" />  
 <script src="<%=ResolveClientUrl("~/js/jquery-1.7.1.min.js") %>" type="text/javascript"></script>
 <script src="<%=ResolveClientUrl("~/js/jquery-ui-1.8.18.custom.min.js") %>" type="text/javascript"></script>

MasterPage imize bir div ekleyelim. Jquery AutoComplete eklentisinin bu div i kullanabilmesi için div in classını “ui-widget” olarak set etmemiz gerekiyor. Aramada kullanacağımız textbox ımızı ve kullanıcının kategori seçebilmesi için bir select objesini de div imizin içine ekleyelim.  Kategorileri ben html üzerinde elle ekleyeceğim, siz projenizin durumuna göre dinamik olarak yükleyebilirsiniz.

<div class="ui-widget">
            <input name="search" type="text" id="txtSearch" style="width: 500px;" placeholder="aramak için birşeyler yaz..." />
            <select id="cmbCategory">
                <option value="0">Kategori Seçiniz</option>
                <option value="1">BİLGİSAYAR</option>
                <option value="2">OEM</option>
                <option value="3">MONİTÖR</option>
                <option value="4">EKRAN KARTI</option>
                <option value="5">RAM</option>
                <option value="6">ANA KART</option>
            </select>
</div>

Kullanıcının arama sonuçlarında seçtiği item ın tipine göre farklı sayfalara yönlendirme yapacağız, bunun için MasterPage de tüm sayfalardan ulaşabileceğimiz bir javascript değişkeni oluşturuyoruz.

<script type="text/javascript">
        window.SearchType = -1; //Arama tipini bu değişkenden alacağız.
</script>

Arama işlemini yapmak için birde GenericHandler a ihtiyacımız olacak. Hemen projemize bir GenericHandler dosyası ekliyoruz.






















Yapacağımız işlemleri biraz daha kolaylaştırmak için projemize bir ProductEntity class ı ekleyelim. Ben hızlı ve basit olsun diye property ve constructor larını aşağıdaki gibi düzenledim. Birde database kullanmayacağım için hardcoded bazı ürünler girdim. GetDefaultProducts() methodumu da bana girmiş olduğum bu ürünleri Generic List olarak getirecek şekilde düzenledim. Siz bunu daha kapsamlı bir şekilde projenizin yapısına göre ürünlerinizi databaseden gelecek şekilde Business ve Entity katmanlarınızda istediğiniz gibi şekillendirebilirsiniz.
ProductEntity classımızın propertyleri.

    private int _productID;
    public int ProductID
    {
        get { return _productID; }
        set { _productID = value; }
    }

    private string _productName;
    public string ProductName
    {
        get { return _productName; }
        set { _productName = value; }
    }

    private string _productImageUrl;
    public string ProductImageUrl
    {
        get { return _productImageUrl; }
        set { _productImageUrl = value; }
    }

    private int _categoryID;
    public int CategoryID
    {
        get { return _categoryID; }
        set { _categoryID = value; }
    }

    private string _categoryName;
    public string CategoryName
    {
        get { return _categoryName; }
        set { _categoryName = value; }
    }


ProductEntity classımızın constructorları.

    public ProductEntity()
    {
        //
        // TODO: Add constructor logic here
        //
    }

    public ProductEntity(int productID,string productName, string productImageUrl,int categoryID, string categoryName)
    {
        this.ProductID = productID;
        this.ProductName = productName;
        this.ProductImageUrl = productImageUrl;
        this.CategoryID = categoryID;
        this.CategoryName = categoryName;
    }


Hardcoded olarak eklediğimiz ürünlerimizi getirecek  GetDefaultProducts() methodumuz.

    public static List<ProductEntity> GetDefaultProducts()
    {
        return new List<ProductEntity>() {
        new ProductEntity(1,"Packard Bell DOTSE3-V-571TK Intel Atom","../images/Bilgisayar_974893.jpg",1,"BİLGİSAYAR"),
        new ProductEntity(2,"Lenovo Z570 Intel Core i7 2670QM","../images/Bilgisayar_1089542.jpg",1,"BİLGİSAYAR"),
        new ProductEntity(3,"Samsung NP-N150-JP0WTR Intel Atom","../images/samsungnpn150.jpg",1,"BİLGİSAYAR"),
        new ProductEntity(6,"TX Sonic 460W Kırmızı Led Fanlı","../images/txsonic.jpg",2,"BİLGİSAYAR KASALARI"),
        new ProductEntity(7,"Frisby 6905BS P4 350W Kulplu Atx Kasa","../images/frisby6905bs.jpg",2,"BİLGİSAYAR KASALARI"),
        new ProductEntity(8,"Thermaltake Level 10 GT Oyun Kasası","../images/thermaltake10gt.jpg",2,"BİLGİSAYAR KASALARI"),     
        new ProductEntity(11,"Philips 192E2SB2/62 18.5” 5ms Monitör","../images/philipsmonitor1.jpg",3,"MONİTÖR"),
        new ProductEntity(12,"Acer (Gamer Serisi) G195HQVBB 18.5” 5ms Monitör","../images/acermonitor1.jpg",3,"MONİTÖR"),
        new ProductEntity(13,"AOC F22S+ 21.5” 5ms Wide Screen LCD Monitör","../images/aocmonitor1.jpg",3,"MONİTÖR"),
        new ProductEntity(14,"Samsung B1930N 18.5” 5ms Wide Screen LCD Monitör","../images/samsungmonitor1.jpg",3,"MONİTÖR"),
        new ProductEntity(15,"LG E2251S-BN 21.5” 5ms Wide Screen LED Monitör","../images/lgmonitor1.jpg",3,"MONİTÖR"),
        new ProductEntity(16,"Sapphire Ati HD5570 1GB/2.8GB HM 128Bit DDR3 Ekran Kartı","../images/sapphireek1.jpg",4,"EKRAN KARTI"),
        new ProductEntity(17,"Volar Nvidia 9600GT 1GB 256Bit GDDR3 Ekran Kartı","../images/volarek1.jpg",4,"EKRAN KARTI"),
        new ProductEntity(18,"HIS Ati HD 4670 Iceq 1GB (128BIT) GDDR3 Ekran Kartı","../images/hisek1.jpg",4,"EKRAN KARTI"),
        new ProductEntity(19,"MSI N430GT-MD2GD3/OC 2GB 128Bit DDR3 Ekran Kartı","../images/misek1.jpg",4,"EKRAN KARTI"),
        new ProductEntity(20,"Zotac GT430 Synergy 1GB (128 Bit) GDDR3 Ekran Kartı","../images/zotacek1.jpg",4,"EKRAN KARTI"),
        new ProductEntity(21,"Team Xtreem 12GB 2000MHz DDR3 Ram","../images/teamextrem_ram1.jpg",5,"RAM"),
        new ProductEntity(22,"Geil Evo Corsa 16GB (2x8GB) DDR3 Ram","../images/geilevo_ram1.jpg",5,"RAM"),
        new ProductEntity(23,"Team Elite 16GB (2x8GB) DDR3 1333MHz Ram","../images/teamelite_ram1.jpg",5,"RAM"),
        new ProductEntity(24,"Kingston 4GB(2x2GB) 1066MHz DDR2 Hyperx Ram","../images/kingston_ram1.jpg",5,"RAM"),
        new ProductEntity(25,"Corsair XMS3 8GB(2x4GB) DDR3 1333MHz Ram","../images/corsair_ram1.jpg",5,"RAM"),
        new ProductEntity(26,"Gigabyte 990FXA-UD5 AMD AM3+ DDR3 1866MHz Anakart","../images/gigabyteak1.jpg",6,"ANA KART"),
        new ProductEntity(27,"Asus P8H61-M LE 3.0 H61 DDR3 Matx Gigalan Anakart","../images/asusak1.jpg",6,"ANA KART"),
        new ProductEntity(28,"MSI E350IA-E45 AMD Soket AM3 DDR3 Anakart","../images/msiak2.jpg",6,"ANA KART"),
        new ProductEntity(29,"MSI P67A-GD65 (B3) Intel P67 DDR3 2133MHz Anakart","../images/msiak1.jpg",6,"ANA KART"),
        new ProductEntity(30,"ECS MCP61M-M3 (7.1) 2000MT DDR3 1333MHz Anakart","../images/ecsak1.jpg",6,"ANA KART"),
        new ProductEntity(31,"Exper Action DR71D Core i5 2310","../images/experactiondr71d.jpg",1,"BİLGİSAYAR"),
        new ProductEntity(32,"Asus EeePc 1015BX-WHI114S AMD C50","../images/asuseepc1015.jpg",1,"BİLGİSAYAR"),
        new ProductEntity(33,"Samsung NP300E5A-S0BTR Intel Core i3 ","../images/samsungnp300.jpg",1,"BİLGİSAYAR"),
        new ProductEntity(34,"Casper Nirvana CN.HBP950A Intel Core","../images/caspernirvanacnhbp950a.jpg",1,"BİLGİSAYAR"),
        new ProductEntity(35,"Mobee Nett 7” T1200 Tablet","../images/mobeenetttablet.jpg",1,"BİLGİSAYAR"),
        new ProductEntity(36,"3R SYS R460Li LCD Ekranlı 120mm FANLI","../images/3rsysr460.jpg",2,"BİLGİSAYAR KASALARI"),
        new ProductEntity(37,"Aerocool XWarrior Mesh Panel","../images/aerocool1.jpg",2,"BİLGİSAYAR KASALARI"),
        new ProductEntity(38,"Aerocool CyborgX 600W Çift Fanlı","../images/aerocool2.jpg",2,"BİLGİSAYAR KASALARI"),
        new ProductEntity(39,"3R Sys L600 Fan Kontrolcülü 120mm","../images/3rsysr4602.jpg",2,"BİLGİSAYAR KASALARI"),
        new ProductEntity(40,"Gmc K-55 Kasa","../images/gmck55.jpg",2,"BİLGİSAYAR KASALARI")
        };
    }


Artık javascript tarafına geçerek AutoCompletimizi şekillendirmeye başlayabiliriz. Bunun için aramada kullanacağımız textbox ın id sini parametre alan bir javascript fonksiyonu yazabiliriz.

function autoComplete(objID) {
    var handlerUrl = '../Handlers/AutoCompleteSearch.ashx';   //Arama için kullanacağımız Generic Handler ımızın pathi
    var searchKeyword = '';   //Arama yapılan kelime }


Şimdi bu fonksiyonumuza id sini parametre olarak göndereceğimiz textbox ımızı autocomplete arama yapacak şekilde biraz geliştirelim. Jquery kütüphanesi ile ajax çağrısı yapmayı bildiğinizi düşünerek işin o kısımlarıyla ilgili açıklamada bulunmuyorum. Daha önce hiç Jquery kütüphanesi ile ajax kullanmamış olanlar internette bununla ilgili çok sayıda örnek bulabilirler.
Fonksiyonumuza aşağıdaki javascript kodlarını ekleyerek, textbox a girilen değer ve seçilen kategoriye göre arama yapması için eklemiş olduğumuz AutoCompleteSearch.ashx adlı Generic Handler ımıza yönlediriyoruz.

$("#" + objID).catcomplete({
        source: function (request, response) {
            $.ajax({
                url: handlerUrl, //arama işleminin yapılacağı .ashx dosyamızın pathi
                contentType: 'application/json; charset=utf8;',
                data: {
                    keyword: request.term, //arama textbox ımıza girilen değer.
                    categoryID: $('#cmbCategory').val() //dropdownlist imizden seçilen kategori
                },
                success: function (data) {
                    searchKeyword = request.term; //daha sonra kullanmak için arama yapılan kelimeyi bir değişken üzerinde tutuyoruz.
                    response($.map(data, function (item) {
                    /*gelen arama sonuçlarımızdaki datayı kullanmak istediğimiz şekilde mapliyoruz.*/
                        return {
                            label: item.ProductName,
                            value: item.ProductName,
                            productID: item.ProductID,
                            imageUrl: item.ProductImageUrl,
                            category: item.CategoryID,
                            categoryName: item.CategoryName
                        }
                    }));
                },
                error: function (xmlHttpRequest) {
                }
            });
        },        open: function () {
            $(this).removeClass('ui-corner-all').addClass('ui-corner-top');
        },
        close: function () {
            $(this).removeClass('ui-corner-top').addClass('ui-corner-all');
        }
    });


Şimdi AutoCompleteSearch.ashx isimli Generic Handler ımızı düzenlemeye başlayalım. Ürünleri arama işlemini burada yapacağız.
Kullanıcının arama textbox ına girdiği kelimeyi ve seçmiş olduğu kategoriyi javascript fonksiyonumuzdan parametre olarak göndermiştik. AutoCompleteSearch.ashx dosyamızda bulunan ProcessRequest methodunda QueryString den göndermiş olduğumuz bu parametreleri alacağız. ProcessRequest methodumuzun ilk hali aşağıdaki gibidir.
public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "application/json";
        string keyword = context.Request.QueryString["keyword"];
        int categoryID = !String.IsNullOrWhiteSpace(context.Request.QueryString["categoryID"]) ? Convert.ToInt32(context.Request.QueryString["categoryID"]) : 0;
              
        // TODO:  Devam edeceğiz...
    }


şimdi almış olduğumuz bu parametreleri kullanarak aramaya uyan ürünlerimizi getirecek methodumuzu yazalım. Bu methodumuz bizden keyword ve categoryID yi parametre olarak alıp bize bir ürün koleksiyonu döndürsün. Bunun için ben, daha önce yazdığımız ProductEntity classımızdaki GetDefaultProducts() methodundan faydalanarak filtreleme yapacağım. Burada Generic List ve filtreleme işleminde Linq kullanacağım için hemen System.Collections.Genericve System.Linq namespacelerim ekliyorum.

using System.Collections.Generic;
using System.Linq;


ve SearchProduct isimli filtreleme yapacağımız methodumuzu yazıyoruz.

/// <summary>
    /// ProductEntity classımızdaki GetDefaultProducts() methodundan dönen ürün listesi üzerinde girilen keyword ve categoryID parametrelerine göre ürünlerin adında ve kategorilerinde filtreleme yapar. categoryID nin değeri 0 ise bu kategori seçilmemiş demektir. Bu durumda filtrelemeyi sadece ürün adında göre yapar.
    /// </summary>
    /// <param name="keyword">Kullanıcının textbox a girdiği arama kelimesi</param>
    /// <param name="categoryID">Kullanıcının seçmiş olduğu kategori</param>
    /// <returns></returns>

    public List<ProductEntity> SearchProduct(string keyword, int categoryID)
    {
        if (categoryID > 0)
        {
            return ProductEntity.GetDefaultProducts().Where(p => p.ProductName.ToLower().Contains(keyword.ToLower()) && p.CategoryID == categoryID).OrderBy(p => p.CategoryID).ToList();
        }
        else
        {
            return ProductEntity.GetDefaultProducts().Where(p => p.ProductName.ToLower().Contains(keyword.ToLower())).OrderBy(p => p.CategoryID).ToList();
        }
    }


Şimdi de SearchProduct methodumuzdan dönen sonucumuzu json datası olarak serilaze edip ajax çağrımıza yanıt olarak dönelim. Bu işlemide yine ProcessRequest methodumuzda yapacağız. ProcessRequest methodumuza kaldığımız yerden devam edelim.

public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "application/json";
        string keyword = context.Request.QueryString["keyword"];
        int categoryID = !String.IsNullOrWhiteSpace(context.Request.QueryString["categoryID"]) ? Convert.ToInt32(context.Request.QueryString["categoryID"]) : 0;
        System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
      
        context.Response.Write(serializer.Serialize(SearchProduct(keyword, categoryID)));
    }


ProcessRequest methodumuzun son hali yukarıdaki gibidir. Artık AutoCompleteSearch.ashx dosyamızla işimizi tamamlamış olduk.
Sayfa yönlendirmeleri için projeye MasterPage mizi kullanan Default.aspxCategory.aspxProduct.aspxSearchResult.aspxisimlerinde 4 tane WebForm ekliyoruz. Fazla karışıklık olmasın diye sayfaları Pages adında bir folder açıp, bu folder a ekleyebiliriz. Aynı şekilde projemizdeki diğer dosyalarıda uygun şekilde folderlar içine eklememiz daha iyi olacaktır.















Şimdi autocomplete javascript fonksiyonumuzu daha da geliştirmeye başlamadan önce kullanıcının arama şekline göre sayfa yönlendirmesini yapacağımız yeni bir javascript fonksiyonu yazalım. Fonksiyonumuzun ismi de navigateSearch olsun ve bizden parametre olarak kullanıcı kategori seçtiyse seçilmiş kategorinin id sini, ürün seçtiyse seçilmiş ürünün id sini ve kullanıcının arama textbox ına girmiş olduğu arama kelimesini parametre olarak alsın. Bu parametreleri ve en başta MasterPage imizde tanımlamış olmuşduğumuz window.SearchType değişkenin o anki değerini kullanarak kullanıcıyı doğru sayfaya yönlendirsin.
function navigateSearch(categoryID, productID, searchKeyword) {
    if (window.SearchType == 1) {
        /*Kullanıcı autocompletten herhangi bir kategori veya ürün seçmeden enter a basmıştır.*/
        /*
        Öncelikle textbox ın değerinin boş olup olmadığını kontrol edelim. Boş değilse kullanıcı aradığını gelen sonuçlar içinde bulamamış ve seçtiği kategoride detaylı arama yapmak için enter a basmıştır.
        Bu durumda categoryID ve textbox a girmiş olduğu kelime ile arama sayfasına(SearchResult.aspx) yönlendiriyoruz.*/
        if (searchKeyword == '') { return false; }
        else {
            window.location.href = '../Pages/SearchResult.aspx?c=' + categoryID + '&k=' + searchKeyword;
        }
    }
    else {
        /*Kullanıcı autocompletten bir kategori veya ürün seçmiştir.*/
        if (productID == -1) {
            /*productID nin değeri -1 ise kullanıcı kategori seçmiş demektir. Bu durumda seçmiş olduğu kategorinin id si ile Category.aspx sayfamıza yönlendiriyoruz.*/
            window.location.href = '../Pages/Category.aspx?c=' + categoryID;
        }
        else if (productID > 0 && categoryID > 0) {
            /*productID nin değeri 0 dan büyükse kullanıcı ürün seçmiş demektir. Bu durumda seçmiş olduğu ürünü id si ve ürünün categoryID si ile Ürün sayfasına yönlendiriyoruz. Ürün seçilmişse categoryID nin değeri 0 dan büyük gelecektir ama biraz paranoyaklık yapıp onuda kontrol etmekte fayda var...*/
            window.location.href = '../Pages/Product.aspx?c=' + categoryID + '&p=' + productID;
        }
    }
}


navigateSearch fonksiyonumuzun son hali yukarıdaki gibidir. Sayfa yönlendirme işinide büyük ölçüde tamamladığımıza göre artık autocomplete fonksiyonumuzu geliştirmeye devam edebiliriz.
İlk olarak, arama sonuçlarına göre autocomplete mizde ürünleri ve ürün kategorilerini göstereceğimiz için, kullanıcı gösterilen sonuçlardan birini seçmiş ise window.SearchType değişkenimizin değerini olarak set ediyoruz ve sayfa yönlendirmesini yapması için navigateSearch fonksiyonumuzu çağırıyoruz. Bunu autocomplete mizin select option unda yapıyoruz.
select: function (event, ui) {
            window.SearchType = 0; //Search Type = Autocomplete Search
            /*Kullanıcı productID nin değerine göre Category.aspx sayfasına veya Product.aspx sayfasına yönlendirilecek.*/
            navigateSearch(ui.item.category, ui.item.productID, searchKeyword);
            return false;
}


Category.aspx sayfasınamı, yoksa Product.aspx sayfasınamı yönlendirceğimizi ise navigateSearch fonksiyonumuza parametre olarak verdiğimiz productID değişkeninin değeri belirleyecektir. Bu yüzden autocomplete mizde gösterdiğimiz kategoriler için özel bir productID değeri belirlemeliyiz. Şimdi hem bunun için hemde kategorilerin gösterimini render etmek için kullanacağımız bir AutoCompleteCategoryItem nesnesi oluşturalım. Bu nesne üzerinde productID property miz olacak ve değerini -1 olarak set ederek bunun aslında bir ürün değilde kategori olduğunu belirtmiş olacağız. Bunun için projenizin durumuna göre farklı çözüm yollarıda kullanabilirsiniz.

function AutoCompleteCategoryItem(item) {
    var categoryItem =
    {
        label: item.categoryName,
        value: item.categoryName,
        category: item.category,
        categoryName: item.categoryName,
        productID: -1
    }
    return categoryItem;
}



AutoComplete mizdeki kategori itemlerınıda render ederken oluşturduğumuz categoryItem nesnesini kullanacağız.
Peki kullanıcı arama textbox ına birşeyler yazdı ve autocomplete den herhangi bir item seçmeden enter a basarsa ne olacak? Bu durumda kullanıcının texbox a girmiş olduğu değer ve seçmiş olduğu kategorinin id si ile arama sayfamıza (SearchResult.aspx) yönlendireceğiz. Bu işlemi ise autocomplete mizin searchoption ununda yapabiliriz. search option unda sadece window.SearchType değişkenimizin değerini 1 olarak set ediyoruz. Sayfa yönlendirmesini ise arama textbox ımızın keyup yada keydown event inde keyCode u kontrol ederek yapacağız. Şimdilik sadece autocomplete mizin search option ununu yazıyoruz.
search: function (event, ui) {
            window.SearchType = 1; //Search Type = Text Search
            /*Kullanıcı enter a basarsa SearchResult.aspx sayfasını yönlendirelecek.*/
}


Sıra AutoComplete mizin  itemlarını istediğimiz gibi render etmeye geldi.

 $.widget("custom.catcomplete", $.ui.autocomplete, {
    
 });


bu işlem için AutoComplete mizin widget fonksiyonunu kullanacağınız. Önce Ürünleri göstereceğimiz itemları ürün resimlerinide gösterecek şekilde yeniden render ediyoruz.

/*Ürünlerin sadece adlarını değil resimlerinide göstereceğiz. Bu yüzden AutoCompletimizin itemlerını kendimize göre render ediyoruz.*/        
_renderItem: function (ul, item) {
            if (item.productID != '0') {
                return $('<li></li>')
                .data('item.autocomplete', item)
                .append("<a style='line-height: 30px;'><span style='width: 33px; height: 30px; float: left;'><img width='30' height='25' alt='' style='padding-right: 2px;' src='" + item.imageUrl + "'/></span>" + item.label + "</a>")
                .appendTo(ul);
            }
}


Şimdi de kategorilerimizi render edelim.

/*Arama sonuçlarında ürünlerimizi category lerine göre gruplayarak göstereceğiz. Bu yüzden AutoCompletimizin menüsünüde kendimize göre render ediyoruz.*/
_renderMenu: function (ul, items) {
            var self = this,
                currentCategory = '';
            $.each(items, function (index, item) {
            if (item.category != currentCategory) {
                    var categoryItem = AutoCompleteCategoryItem(item);
                    var categoryElement = $('<li></li>')
                                            .data('item.autocomplete', categoryItem)
                                            .append("<a style='text-decoration: underline; font-weight: bold;'>" + categoryItem.categoryName + "</a>");
                    ul.append(categoryElement);
                    currentCategory = item.category;
                }
                self._renderItem(ul, item);
            });
}


autoComplete fonksiyonumuzun son hali aşağıdaki gibidir.

function autoComplete(objID) {
    var handlerUrl = '../Handlers/AutoCompleteSearch.ashx';//Arama için kullanacağımız Generic Handler ımızın pathi
    var searchKeyword = ''; //Arama yapılan kelime
    $.widget("custom.catcomplete", $.ui.autocomplete, {
    /*Ürünlerin sadece adlarını değil resimlerinide göstereceğiz. Bu yüzden AutoCompletimizin itemlerını kendimize göre render ediyoruz.*/
        _renderItem: function (ul, item) {
            if (item.productID != '0') {
                return $('<li></li>')
                .data('item.autocomplete', item)
                .append("<a style='line-height: 30px;'><span style='width: 33px; height: 30px; float: left;'><img width='30' height='25' alt='' style='padding-right: 2px;' src='" + item.imageUrl + "'/></span>" + item.label + "</a>")
                .appendTo(ul);
            }
        },
        _renderMenu: function (ul, items) {
        /*Arama sonuçlarında ürünlerimizi category lerine göre gruplayarak göstereceğiz. Bu yüzden AutoCompletimizin menüsünüde kendimize göre render ediyoruz.*/
            var self = this,
                currentCategory = '';
            $.each(items, function (index, item) {
            if (item.category != currentCategory) {
                    var categoryItem = AutoCompleteCategoryItem(item);
                    var categoryElement = $('<li></li>')
                                            .data('item.autocomplete', categoryItem)
                                            .append("<a style='text-decoration: underline; font-weight: bold;'>" + categoryItem.categoryName + "</a>");
                    ul.append(categoryElement);
                    currentCategory = item.category;
                }
                self._renderItem(ul, item);
            });
        }
    });

    $("#" + objID).catcomplete({
        source: function (request, response) {
            $.ajax({
                url: handlerUrl, //arama işleminin yapılacağı .ashx dosyamızın pathi
                contentType: 'application/json; charset=utf8;',
                data: {
                    keyword: request.term, //arama textbox ımıza girilen değer.
                    categoryID: $('#cmbCategory').val() //dropdownlist imizden seçilen kategori
                },
                success: function (data) {
                    searchKeyword = request.term; //daha sonra kullanmak için arama yapılan kelimeyi bir değişken üzerinde tutuyoruz.
                    response($.map(data, function (item) {
                    /*gelen arama sonuçlarımızdaki datayı kullanmak istediğimiz şekilde mapliyoruz.*/
                        return {
                            label: item.ProductName,
                            value: item.ProductName,
                            productID: item.ProductID,
                            imageUrl: item.ProductImageUrl,
                            category: item.CategoryID,
                            categoryName: item.CategoryName
                        }
                    }));
                },
                error: function (xmlHttpRequest) {
                }
            });
        },
        select: function (event, ui) {
            window.SearchType = 0; //Search Type = Autocomplete Search
            /*Kullanıcı productID nin değerine göre Category.aspx sayfasına veya Product.aspx sayfasına yönlendirilecek.*/
            navigateSearch(ui.item.category, ui.item.productID, searchKeyword);
            return false;
        },
        search: function (event, ui) {
            window.SearchType = 1; //Search Type = Text Search
            /*Kullanıcı enter a basarsa SearchResult.aspx sayfasını yönlendirelecek.*/
        },
        open: function () {
            $(this).removeClass('ui-corner-all').addClass('ui-corner-top');
        },
        close: function () {
            $(this).removeClass('ui-corner-top').addClass('ui-corner-all');
        }
    });
}


Son olarak arama textbox ımızın keydown un da keyCode u kontrol ederek eğer enter a basılmışsa arama sayfa yönlendirme işlemimizi yapacak olan navigateSearch fonksiyonumuzu tetikletiyoruz. Bunun için öncelikle form un submit ini kapatmamız gerekiyor.

<form id="form1" runat="server" onsubmit="return false;">



$('#txtSearch').keydown(function (event) {
                if (event.keyCode == '13') {
                    /*form un submit ini kapatıyoruz ve arama textboxının key enter ında aramamızı yönlendirecek fonksiyonumuzu çalıştırıyoruz.*/
                    navigateSearch($('#cmbCategory').val(), 0, $('#txtSearch').val());
                }
});


Biraz uzun sürsede sonunda bitti, uygulamanın kaynak kodlarını buradan indirebilirsiniz.
Sonuçlar için ekran görüntüleri.







































Read More