Gulp’ta Yavaş Çalışan Uglify Derlemesi Nasıl Düzeltilir?

Merhaba arkadaşlar, sizlere gulp’ın kullanımını anlatmıştım. Ancak zamanla kullandıktan sonra yaşadığım bir sorununda çözümünü paylaşmak istiyorum. Büyük front-end projelerinde, javascript tarafındaki kodlar çoğaldıkça fark ettim ki, kullandığım uglify paketi çok yavaş şekide build etmeye başladı dosyaları. Yani öyleki bir js değişikliğinden sonra 8-10 sn arası bekliyordum build etsin diye. Bunun böyle olmayacağını düşünüp araştırmaya başladım ve gulp-fs-cache paketini buldum.

İlgili paketin linki; 
https://www.npmjs.com/package/gulp-fs-cache

Kurulumu ise;

npm install gulp-fs-cache

Kullanım

Benim eski kodlarım şu şekildeydi;

gulp.task('js', () => {
return gulp.src('scripts/*.js')
.pipe(uglify())
.pipe(concat('app.min.js'))
.pipe(gulp.dest('dist/js'));
});

Bu şekilde kodlar çoğaldıkça derleme süresi 8-9 saniyeyi bulmaya başladı. Gif’e gözatın!

Ve bu paketi kullanarak şu hale dönüştürdüm;

gulp.task('js', () => {
let jsFsCache = fsCache('tmp/jscache');
return gulp.src('scripts/*.js')
.pipe(jsFsCache)
.pipe(uglify())
.pipe(jsFsCache.restore)
.pipe(concat('app.min.js'))
.pipe(gulp.dest('dist/js'));
});

Sonuç ise mükemmel 🙂

Kolaylıklar dilerim 🙂

Gulp ile İşlerinizi Kolaylaştırın

Merhaba arkadaşlar, front-end çalışmalarında gulp kullandığım şu dönemde bilmeyenler için bir makale yazmaya karar verdim. Öncelikle ne nedir bundan başlayalım ve neden kullanmamız gerek anlayalım.

Gulp nedir?

Gulp, geliştirme yaparken iş akışımızı yavaşlatan işlemleri otomatik yapmamızı sağlayan bir araçtır.

Gulp hangi durumlarda kullanılır?

CSS, HTML, JavaScript ya da Resim dosyalarınızla ilgili işlemler için kullanılabilir.

Ben kısaca CSS’de SASS ve LESS dosyalarımı çalıştırdım, minify ettim, tek dosya haline getirdim. Görselleri sıkıştırarak daha küçük boyut haline getirdim. HTML’leri herhangi bir template engine sisteminde otomatik çıkarttım. Javascript’te minify edip tüm js dosyalarını tek bir js dosyasına çevirdim. Ve bunları yaparken gulp dosyamı ayarladıktann sonra hiçbir şey yapmadım 🙂

Gulp nasıl kurulur?

Gulp, çalışması için node.js ve npm’in kurulu olması gerek. Öncelikle node.js’i sisteminize kurun. Daha sonra şu komutu çalıştırın;

npm install gulp-cli -g
npm install gulp -D

Burada -D aynı zamanda –save-dev değerine eşittir.

Gulp nasıl kullanılır?

Öncelikle dizininizde gulpfile.js adında bir dosya oluşturun. Gulp ile ilgili işlemleri bu dosya içinde yapacağız. Ancak gulp’ı tek başına kullanmak yetmiyor, başka paketlerde indirmeliyiz. Örneğin;

  • sass compiler için – gulp-sass
  • css minify için – gulp-csso
  • dosyaları birleştirmek için – gulp-concat
  • css’de tarayıcı versiyonuna göre prefix ekletmek için – gulp-autoprefixer
  • resim dosyalarını sıkıştırmak için – gulp-imagemin
  • javascript dosyalarını minify etmek için – gulp-uglify
  • dosyaları silmek için – del
  • html’i sıkıştırmak için – gulp-htmlmin
  • belli bir sırayla taskları başlatmak için – run-seqeuence
  • anlık olarak değişiklikleri görmek için – browser-sync

Bu paketleri tek tek isimleriyle şu şekilde kurabilirsiniz;

npm install --save-dev paket_adi

Burada --save-dev dememizin sebebi, bu paketlere sadece geliştirirken ihtiyacımız var, production’da ihtiyacımız olmadığından bu şekilde kuruyoruz.

Şimdi paketleri kurmadan önce bir tane package.json dosyası oluşturalım. Bunun için şu komutu çalıştıralım;

npm init

Daha sonra enter – enter diyerek sonuna kadar gidelim ve dosyamız oluşmuş olacak. Dosya oluştuktan sonra şunun gibi bir şe yolacak içeriği;

{
  "name": "erbilen-test",
  "version": "1.0.0",
  "description": "",
  "main": "gulpfile.js",
  "dependencies": {
    "gulp": "^3.9.1"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Şimdi bunu neden oluşturduk birazdan anlayacağız. Dilerseniz artık paketleri kurabilirsiniz. Ya da package.json dosyanızı şu şekilde değiştirip;

{
  "name": "frontend",
  "version": "1.0.0",
  "main": "gulpfile.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {},
  "devDependencies": {
    "browser-sync": "^2.26.3",
    "del": "^3.0.0",
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^6.0.0",
    "gulp-concat": "^2.6.1",
    "gulp-csso": "^3.0.1",
    "gulp-htmlmin": "^5.0.1",
    "gulp-imagemin": "^4.1.0",
    "gulp-sass": "^4.0.2",
    "gulp-uglify": "^3.0.1",
    "run-sequence": "^2.2.1"
  }
}

Şu komutu çalıştırırsanız otomatik paketler kurulacaktır;

npm install

Paketlerin kurulması biraz zaman alır, kurulduğunda çalıştığınız dizine node_modules diye bir klasör gelecek. Tüm paketler bunun içinde yer alıyor.

Son olarak çalıştığımız klasör içerisinde dist ve src adında 2 klasör oluşturalım. dist burada projenin son hali, src ise sizin çalıştığınız versiyon olacak. Yani production ürünümüz dist içerisinde yer alacak.

Artık gulp’ı ve diğer paketleri beraberinde kullanmaya hazırız. Öncelikle kullanacağımız paketleri sayfamıza dahil edelim. gulpfile.js dosyamız şu şekilde olacak;

const gulp = require('gulp');
const browserSync = require('browser-sync').create();
const sass = require('gulp-sass');
const minifyCSS = require('gulp-csso');
const minifyImg = require('gulp-imagemin');
const minifyJS = require('gulp-uglify');
const minifyHTML = require('gulp-htmlmin');
const concat = require('gulp-concat');
const autoprefixer = require('gulp-autoprefixer');
const del = require('del');
const runSequence = require('run-sequence');

Ve artık tasklarımızı yazmaya başlayalım. Gulp’ta bir task oluşturmanın yolu şudur;

gulp.task('task_adi', () => {
    // işlemler
});

Bunu baz alarak browser-sync için ilk taskımızı oluşturalım.

gulp.task('browser-sync', () => {
    browserSync.init({
        server: {
            baseDir: "dist"
        }
    });
});

Burada baseDir yolunu dist olarak belirledik. Çünkü projemizin son hali orada yer alacak. Ve browser-sync bu klasörü bize serve ederek src altında herhangi bir html’de değişiklik olduğunda sayfayı reload edecek. Burada dikkat etmemiz gereken şey src/*.html yerine src/**/*.html yazmış olmamız. Bu src altındaki .html ile biten ve src altında herhangi bir klasör içinde .html ile biten tüm html dosyaları için geçerli olsun demek.

Şimdide CSS için taskımızı oluşturalım;

gulp.task('css', () => {
    return gulp.src('src/scss/**/*.scss')
        .pipe(sass({
            outputStyle: 'nested',
            precision: 10,
            includePaths: ['.']
        }).on('error', sass.logError))
        .pipe(minifyCSS())
        .pipe(autoprefixer())
        .pipe(concat('app.min.css'))
        .pipe(gulp.dest('dist/css'))
        .pipe(browserSync.stream());
});

Bu taskta sass’ı kullandık, minify ettik, prefixleri eklettik, concat ile tek dosyada birleştirip adını app.min.css koyduk, dest kısmına dist içindeki css klasörüne eklenecek dedik ve son olarak browser-sync kullandık. Bunuda watch ile işlem yaptığımızda anlayacaksınız.

Şimdide JS için taskımızı oluşturalım;

gulp.task('js', () => {
    return gulp.src('src/js/**/*.js')
        .pipe(concat('app.min.js'))
        .pipe(minifyJS())
        .pipe(gulp.dest('dist/js'))
        .pipe(browserSync.stream());
});

Bu taskta yine javascript dosyalarının yolunu belirttikten sonra concat ile tek dosya haline getirdik, uglify ile minift ettik ve dist içindeki js klasörüne çıkarttık. CSS’te olduğu gibi bunda da browser-sync işlemi yaptık.

Şimdide HTML için taskımızı oluşturalım;

gulp.task('html', () => {
    gulp.src('src/**/*.html')
        .pipe(minifyHTML({
            collapseWhitespace: true,
            removeComments: true
        }))
        .pipe(gulp.dest('dist'))
        .pipe(browserSync.stream());
});

Bu taskta da yine html dosyalarının yolunu belirttik, minify ettik ve dist içerisine çıkarttık. HTML’i minify etmek zorunda değilsiniz tabi, ben öyle can sıkıntısına ettim o ayrı 😀

Şimdide resimler için taskımızı oluşturalım;

gulp.task('img', () => {
    gulp.src('src/img/**/*')
        .pipe(minifyImg())
        .pipe(gulp.dest('dist/img'));
});

Bu taskta da yine resimlerin yolunu belirttik, minify ettik ve dist içindeki img klasörüne çıkarttık.

Şimdi ne olacak?

Şimdi tasklarımızı oluşturduk. Son 3 taskımız kaldı, bunlardan ilki gulp çalıştığında dist altındaki ilgili dosyaları silmesi için. İkincisi watch ile dosyaları izleyip bir değişiklik olduğunda ilgili taskları yeniden çalıştırmak için, ve son olarak runSequence kullanarak tasklarımızı sırayla çalıştırmak için;

gulp.task('delete', () => del(['dist/css', 'dist/js', 'dist/img', 'dist/**/*.html']));

gulp.task('watch', () => {
    gulp.watch("src/scss/**/*.scss", ['css']);
    gulp.watch("src/js/**/*.js", ['js']);
    gulp.watch("src/img/**/*", ['img']);
    gulp.watch("src/**/*.html", ['html']);
});

gulp.task('default', () => {
    runSequence(
        'delete',
        'html',
        'css',
        'js',
        'img',
        'browser-sync',
        'watch'
    );
});

İlk taskta css, js, img ve .html dosyalarını sildik. Burada ben özellikle belirttim hangileri olacağını, bazen font dosyası vs. atıyoruz dist içine oda silinmesin diye.

İkinci taskta gulp’ın watch özelliğini kullandık. Buda ilgili dosyaları izleyip bir değişiklik olduğunda belirlediğimiz taskları çalıştırmamızı sağlıyor. Hatırlarsanız css, js tasklarında browser-sync ile ilgili bir kod yazmıştık. İşte burada watch ile izlenip değişiklik olduğunda o task çalıştığında browser-sync’de sayfayı otomatik yenileyip değişiklikleri görmemizi sağlayacak.

Son taskımızın adı default, normalde gulp’ı çalıştırırken task adı belirtilmez ise otomatik olarak default taskı çalıştırılır. Bu yüzden adını bu şekilde koyduk. Bu taskta ise sırasıyla tasklarımız çalıştırıyoruz, yani önce delete taskı çalışıp dist içindeki herşeyi silecek, sonra html taskı çalışıp dist içine html dosyalarını atacak, daha sonra css, js, img. Ondan sonra browser-sync bize bir sunucu oluşturup dosyaları canlı olarak izlememize olanacak sağlayacak. Ve son olarak watch taskıda değişiklikleri takip edecek. Artık gulp’ı çalıştırmak için şunu yazmamız yeterli;

gulp

Sonuç şöyle olacak;

MacBooks-MacBook-Pro-2:frontend tayfunerbilen$ gulp
[00:18:12] Using gulpfile /Applications/MAMP/htdocs/frontend/gulpfile.js
[00:18:12] Starting 'default'...
[00:18:12] Starting 'delete'...
[00:18:12] Finished 'default' after 7.77 ms
[00:18:12] Finished 'delete' after 37 ms
[00:18:12] Starting 'html'...
[00:18:12] Finished 'html' after 16 ms
[00:18:12] Starting 'css'...
[00:18:12] Finished 'css' after 451 ms
[00:18:12] Starting 'js'...
[00:18:13] Finished 'js' after 1.4 s
[00:18:13] Starting 'img'...
[00:18:13] Finished 'img' after 1.55 ms
[00:18:13] Starting 'browser-sync'...
[00:18:14] Finished 'browser-sync' after 41 ms
[00:18:14] Starting 'watch'...
[00:18:14] Finished 'watch' after 178 ms
[Browsersync] Access URLs:
 -------------------------------------
       Local: http://localhost:3000
    External: http://192.168.1.21:3000
 -------------------------------------
          UI: http://localhost:3001
 UI External: http://localhost:3001
 -------------------------------------
[Browsersync] Serving files from: ./dist/
[00:18:44] gulp-imagemin: Minified 65 images (saved 200 kB - 5.9%)

Şimdi gördüğünüz gibi http://localhost:3000 üzerinden artık projemize ulaşabiliriz. Hatta http://192.168.1.21:3000 üzerinden aynı wifi’ye bağlı diğer cihazlardanda ulaşabiliriz. Böylece bir değişiklik olduğunda tüm cihazlardan aynı anda görebileceğiz.

Son hali

Yazdığım kodların son halini github sayfamda paylaştım. Eğer git kurulu ise;

git clone https://github.com/tayfunerbilen/frontend-gulp.git

diyerek indirebilirsiniz. Ya da şu linkten;
https://github.com/tayfunerbilen/frontend-gulp indirebilirsiniz.

İndirdikten sonra;

npm install
gulp

şeklinde kurup çalıştırabilirsiniz. Hepsi bu kadar 🙂 Kolaylıklar dilerim.

JavaScript localeCompare()

Merhaba, bu yazıda sizlere JavaScript’te bulunan localeCompare() metotundan bahsedeceğim. Öncelikle neden ihtiyaç duyup kullandım;

Bir objemi isme göre sıralamak istedim. Bu obje içerisinde türkçe karakterlerde vardı ve sıralama düzgün şekilde gerçekleşmiyordu. Hemen bir örnek verelim;

var data = [
  {
    'id': 1,
    'name': 'İstanbul'
  },
  {
    'id': 2,
    'name': 'Çanakkale'
  },
  {
    'id': 4,
    'name': 'Ümraniye'
  },
  {
    'id': 3,
    'name': 'Ankara'
  },
  {
    'id': 5,
    'name': 'Van'
  }
];

data = data.sort(function(a,b){
  if(a.name < b.name) return -1;
  if(a.name > b.name) return 1;
  return 0;
});

data.forEach(function(key){
  var node = document.createElement("LI"),
      textnode = document.createTextNode(key.name);
  node.appendChild(textnode);
  document.getElementById('test').appendChild(node);
});

Bu kodların çıktısı şu şekilde oluyordu;

Yukarıdaki kodlarımda, sort fonksiyonu içerisindeki kodumu şu şekilde değiştirirsem;

return a.name.localeCompare(b.name);

O zaman sorunumuz çözülüyor ve aşağıdaki gibi başarılı bir sıralama oluşuyor 🙂

Artık birgün bir yerde işinize yararsa ne ala, benim bugün ihtiyacım oldu yarında sizin olabilir 🙂

Zincirleme (Chain) Metodu

Bir çoğunuz yazılmış sınıfları incelediğinizde şu şekilde bir yazım tarzıyla karşılaşmış olabilirsiniz.

$text = new Text();
echo $text->write('Tayfun Erbilen')->color('red')->fontSize('20px')->show();

Bu örneğe ait sınıfımızı oluşturalım hemen.

class Text {
    
    private $text;
    private $style;

    public function write($text)
    {
        $this->text = $text;
    }

    public function color($color)
    {
        $this->style .= 'color: ' . $color . ';';
    }

    public function fontSize($size)
    {
        $this->style .= 'font-size: ' . $size . ';';
    }

    public function show()
    {
        return '<div style="' . $this->style . '">' . $this->text . '</div>';
    }

}

Ancak bu örnek hata verecektir. Çünkü bu şekilde bir yazım tarzı için yapmanız gereken $this objenizi geriye döndürmek. Yani sınıfımızı şu şekilde düzenlersek eğer;

class Text {
    
    private $text;
    private $style;

    public function write($text)
    {
        $this->text = $text;
        return $this;
    }

    public function color($color)
    {
        $this->style .= 'color: ' . $color . ';';
        return $this;
    }

    public function fontSize($size)
    {
        $this->style .= 'font-size: ' . $size . ';';
        return $this;
    }

    public function show()
    {
        return '<div style="' . $this->style . '">' . $this->text . '</div>';
    }

}

Artık bu şekilde bir kullanımı yapmaya hazırız.

Chain (zincirleme) metodu aynı zamanda jQuery içinde aynı mantıkta çalışır. Muhtemelen her dil için bu mantıktadır. Örneğin jQuery’de bir örnek vermem gerekirse, basit bir eklenti hazırlayalım.

$.fn.Text = function(text){
  $(this).html(text);
};

$('body').Text('Tayfun Erbilen').css({
    'color': 'red',
    'font-size': '20px'
  });

Bu şekilde bir zincirleme kullanımda çalışmayacaktır. Çünkü bir this objesi döndürmedik eklentimizde geriye. Eğer geriye this’i döndürürsek geriye kalan jQuery metodlarını da zincirleme olarak kullanabilirsiniz. O halde buna göre düzelttiğimizde son kod parçamız şöyle olacak;

$.fn.Text = function(text){
  $(this).html(text);
  return this;
};

$('body').Text('Tayfun Erbilen').css({
    'color': 'red',
    'font-size': '20px'
  });

JavaScript Object Length Kullanımı

Bir dizinin boyutunu öğrenmek için length özelliğini kullanabilirsiniz. Örneğin;

var arr= ['Tayfun', 'Murat'];

alert(arr.length); // Output: 2

Ancak bunu bir object için yapmak istediğimizde biraz daha farklı şekilde kullanıyoruz;

var obj = new Object();
obj['name'] = 'Tayfun';
obj['surname'] = 'Erbilen';

alert(Object.keys(obj).length); // Output: 2

Kaynak: http://stackoverflow.com/a/6700

jQuery Autocomplete Kullanımı

Merhaba arkadaşlar, bu videoda sizlere jquery autocomplete (otomatik tamamlama) eklentisinin kullanımını gösterdim.

Video içinde bazı linklere giriş yaptım, bunları aşağıda sizlere vereyim hemen;

jQuery CDN Servisi: https://code.jquery.com/
jQuery UI Autocomplete Demo: https://jqueryui.com/autocomplete/
jQuery UI Autocomplete Api Sayfası: http://api.jqueryui.com/autocomplete/

Video içinde hazırladığım kodların örnekleri aşağıdadır;

api.php

try {
    $db = new PDO('mysql:host=localhost;dbname=demo;charset=utf8', 'root', '');
} catch (PDOException $e ){
    die($e->getMessage());
}

$term = $_GET['term'];

$query = $db->query('SELECT * FROM uye
WHERE uye_adi LIKE "%' . $term . '%"', PDO::FETCH_ASSOC);

if ( $query->rowCount() ){

    $data = array();

    foreach ( $query as $row ){
        $data[] = array(
            'value' => $row['uye_adi'],
            'uye_id' => $row['uye_id'],
            'uye_adi' => $row['uye_adi'],
            'uye_eposta' => $row['uye_eposta'],
            'uye_avatar' => $row['uye_avatar']
        );
    }

    echo json_encode($data);

}

index.html

<!doctype html>
<html lang="en">
<head>

    <meta charset="UTF-8">
    <title>Document</title>
    
    <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
    <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="https://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css"/>
    <script>
        $(function(){

            var $search = $('#search');

            $search.autocomplete({
                source: 'api.php',
                focus: function(event, ui){
                    $search.val(ui.item.uye_eposta);
                },
                select: function(event, ui){
//                    window.location.href = 'https://www.google.com/#q=' + ui.item.uye_adi;
                    $search.val(ui.item.uye_eposta);
                }
            });

            $search.data('ui-autocomplete')._renderItem = function( ul, item ){

                var $li = $('
  • '); $li.html('<a href="#">' + '<img src="' + item.uye_avatar + '" />' + '<span class="username">' + item.uye_adi + '</span>' + '<span class="email">' + item.uye_eposta + '</span>' + '</a>'); return $li.appendTo(ul); }; }); </script> <style> #search { width: 500px; } .ui-autocomplete li a { overflow: hidden; display: block; } .ui-autocomplete li a img { float: left; margin-right: 10px; height: 40px; } .ui-autocomplete li a .username { display: block; font-size: 16px; line-height: 17px; } .ui-autocomplete li a .email { display: block; font-size: 12px; color: #999; } </style> </head> <body> <input id="search" type="text"/> </body> </html>
  • mysql: demo

    -- phpMyAdmin SQL Dump
    -- version 4.1.12
    -- http://www.phpmyadmin.net
    --
    -- Host: 127.0.0.1
    -- Generation Time: May 01, 2015 at 11:43 PM
    -- Server version: 5.6.16
    -- PHP Version: 5.5.11
    
    SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
    SET time_zone = "+00:00";
    
    
    /*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */;
    /*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */;
    /*!40101 SET @[email protected]@COLLATION_CONNECTION */;
    /*!40101 SET NAMES utf8 */;
    
    --
    -- Database: `demo`
    --
    
    -- --------------------------------------------------------
    
    --
    -- Table structure for table `uye`
    --
    
    CREATE TABLE IF NOT EXISTS `uye` (
      `uye_id` int(11) NOT NULL AUTO_INCREMENT,
      `uye_adi` varchar(255) NOT NULL,
      `uye_eposta` varchar(255) NOT NULL,
      `uye_avatar` varchar(255) NOT NULL,
      PRIMARY KEY (`uye_id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
    
    --
    -- Dumping data for table `uye`
    --
    
    INSERT INTO `uye` (`uye_id`, `uye_adi`, `uye_eposta`, `uye_avatar`) VALUES
    (1, 'Tayfun Erbilen', '[email protected]', 'https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpt1/v/t1.0-1/p40x40/11150571_931151590276660_1648829158305262977_n.jpg?oh=4069d5e773b3d14b97ad52573aec18d6&oe=55E30655&__gda__=1440015885_52a5a0b45451bc87bad8e780c41e8f35'),
    (2, 'Mert Osman Başol', '[email protected]', 'https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpf1/v/t1.0-1/p50x50/1964950_10206688116828423_6583006539395380068_n.jpg?oh=a7364b334a368f825451c814b7677eda&oe=55D607BF&__gda__=1439900624_dfaef636f9ea1c6076c155eb71781c8d'),
    (3, 'Murat Miregil', '[email protected]', 'https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xpa1/v/t1.0-1/p50x50/11052443_10205415379451129_1842162222714031022_n.jpg?oh=e7c98bc33a241cb00a27f032e3314cbd&oe=55D5BFCE&__gda__=1439485299_413a895407dfa5889a18c2bed7e3c683'),
    (4, 'Batuhan Aydın', '[email protected]', 'https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xap1/v/t1.0-1/p50x50/10898165_641650965964699_1189819791888549590_n.jpg?oh=d4101d34b89c0bafd5f138fe41eb2329&oe=55D32566&__gda__=1440316752_ab45034618b777f1202a446b41e51e70'),
    (5, 'Tolga Çatalahmetoğlu', '[email protected]', 'https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xfp1/v/t1.0-1/c0.1.50.50/p50x50/10154428_10202845905101633_105216030809094613_n.jpg?oh=6cd6cc5970d17f5070b1edc51117ef17&oe=55A20088&__gda__=1440413345_f47c2827f982db88ecd76c3849067949');
    
    /*!40101 SET [email protected]_CHARACTER_SET_CLIENT */;
    /*!40101 SET [email protected]_CHARACTER_SET_RESULTS */;
    /*!40101 SET [email protected]_COLLATION_CONNECTION */;
    

    Ekstralar

    input’a bir şeyler yazıp json servisinden verileri alırken geçen sürede bir loader eklemek isterseniz .ui-autocomplete-loading classını kullanacaksınız css’de.
    yani;

    .ui-autocomplete-loading {
    	background: #fff url(ajax-loader.gif) no-repeat 97%;
    }

    gibi..

    jQuery Touchswipe Eklentisi ile Parmak Hareketlerini Yakalamak

    Telefon ve Tabletlerde ekrana parmak ile dokunduğumuzda bunu yakalayıp işlem yapmamızı sağlayacak güzel bir eklenti tanıtacağım size.
    Ben bu eklentiyi kullanarak parmak ile kaydırarak açılıp kapanan bir yan menü örneği hazırladım videoda.
    Umarım işinize yarar, zira ben responsive dökümlerde bu eklentisi sıkça kullanıyorum.

    Eklenti Adresi;
    https://github.com/mattbryson/TouchSwipe-Jquery-Plugin

    contenteditable fare imleç pozisyonunu öğrenme

    bir contenteditable içeriğimizde fare imlecinin pozisyonunu öğrenmek istersek window.getSelection() metodunu kullanacağız. Örnek vermek gerekirse.

    <div contenteditable="true" id="test">bu bir deneme yazısıdır..</div>
    
    Fare imleç pozisyonu: <span id="position"></span>

    Şimdi dive tıkladıkça fare pozisyonunu alalım ve ekrana yazdıralım.

    $('#test').on('click', function(){
      var sel = window.getSelection();
      $('#position').text( sel.extentOffset );
    });

    işte bu kadar basit 🙂 bana çoğu zaman lazım oluyor, blogda dursun dedim.

    Demo

    jQuery ile Basit Checkbox ve Radio Özelleştirmesi

    Çok basit şekilde checkbox ve radio inputlarını özelleştirebilirsiniz. İlk olarak radio ve checkbox için html yapılarına göz atalım;

    <label>
        <input type="radio" name="cinsiyet" checked />
        Kadın
    </label>
    <label>
        <input type="radio" name="cinsiyet" />
        Erkek
    </label>

    Bu radio inputu içindi. Gördüğünüz gibi label kullanıyoruz. Sebebi ise labele tıklandığında otomatik olarak radio butonunu kendisi seçeceği için jquery’de ekstra bir şey yapmamıza gerek kalmıyor. Aynı şekilde checkboxiçinse yapı şöyle;

    <label>
        <input type="checkbox" value="1" name="test" checked />
        Kullanım Koşulları'nı okudum, kabul ediyorum.
    </label>


    Şimdi jquery kodlarımızda ilk olarak :radio ve :checkbox seçicilerini kullanarak bir döngüye sokacağız. Eğer checked olan inputlar var ise bunların kapsayıcı nesnesine yani labellere checked classı atayacağız.

    $(':radio, :checkbox').each(function(){
        $(this).after('');
        if ( $(this).is(':checked') ){
            $(this).parent().addClass('checked');
        }
    });

    Evet şimdi label’e tıklandığında radio ise farklı checkbox ise farklı işlemler yapalım.
    Radio inputu ise, onun name’ini alıp diğer radioların labellerindeki classı kaldırıp tıklanana checked classı atayacağız.
    Eğer checkbox inputu ise:checked ile seçili olup olmadığını anlayıp ona göre checked classını ekleyip kaldıracağız.

    $('label').on('click', function(e){
    
        // radio
        if ( $(':radio', this).length ){
            var name = $(':radio', this).attr('name');
            $('input[name=' + name + ']').parent().removeClass('checked');
            $(this).addClass('checked');
        }
    
        // checkbox
        if ( $(':checkbox', this).length ){
            if ( $(':checkbox', this).is(':checked') ){
                $(this).addClass('checked');
            } else {
                $(this).removeClass('checked');
            }
        }
    
    });

    Artık geriye sadece css’den düzenleme yapmak kalıyor.
    Örneğin şöyle bir düzenleme yapabilirsiniz;

    label {
      cursor: pointer;
    }
    label input {
      position: absolute;
      opacity: 0;
    }
    label span {
      display: inline-block;
      width: 10px;
      height: 10px;
      background: #ddd;
      margin-right: 3px;
    }
    label.checked {
      color: green;
    }
    label.checked span {
      background: green;
    }

    AngularJS Notlarım – 5

    Biraz daha direktiflerden bahsetmek istiyorum.. ng-clickng-model ve ng-repeat direktifleri ile devam edebiliriz yazımıza.

    ng-click

    ng-click direktifi elemana tıkladığımızda özel bir davranış belirlememizi sağlar. Örneğin elemana tıklanınca ne yapılması gerektiğini belirleyebiliriz. Ya da bir fonksiyon çalıştırabiliriz gibi..

    <div ng-app ng-init="site='erbilen.net'">
      <a href="#" ng-click="site = 'prototurk.com'">[Siteyi değiştir!]</a>
      {{ site }}
    </div>

    ng-model

    ng-model için küçük bir örnek ile başlayalım. Hiç controller karıştırmadan ng-app dedikten sonra bu kodları çalıştıralım.

    <input type="text" ng-model="kelime" />
    <p>{{ kelime }}</p>

    Evet artık input’a ne yazarsam hemen aşağısında o çıkacak.

    Ya da daha farklı bir örnek vermek gerekirse;

    <div ng-app="app">
      <div ng-controller="myController">
      
        <input type="text" placeholder="Birşeyler yaz.." ng-model="kelime" ng-bind="alert(kelime)">
        
      </div>
    </div>

    Şimdi input’ta yazınca bind ettiğim için controllerımdaki alert metodum çalışacak ve yazılan değer ekranda alert ile gösterilecek.

    var app = angular.module('app', []);
    app.controller('myController', ['$scope', function($scope){
      
      $scope.alert = function(str){
        if ( typeof str != 'undefined' )
          alert(str);
      }
      
    }]);

    ng-repeat

    $http servisi ile bir request yapıyoruz ve gelen datayı ng-repeat ile tekrarlatıyoruz. Yani kısaca döngüye sokuyoruz. Nasıl mı?

    var app = angular.module('app', []);
    var myController = function($scope, $http){
      
      var onComplete = function(response){
        $scope.repos = response.data;
      }
      
      var onError = function(response){
        $scope.error = 'Bir sorun oluştu!';
      }
      
      $http.get('https://api.github.com/users/tayfunerbilen/repos')
      .then(onComplete, onError);
      
    };
    app.controller('myController', ['$scope', '$http', myController]);

    Şimdi html tarafında ise şöyle göstereceğim;

    <div ng-app="app">
      <div ng-controller="myController">
        Tayfun Erbilen - Github Repo
        <ul>
          <li ng-repeat="repo in repos">
            {{ repo.name }}
            <span style="display: block; color: #777;">
              {{ repo.description }}
            </span>
          </li>
        </ul>
      </div>
    </div>