avatar

Paylaşım Menüsü
Sayfalarımızda işaretlenen alanlar için paylaşım menüsü açan bir jQuery Plugin yazalım...

31/07/2014
Hakan Özakar

Daha önce jQuery eklentisi yazmak konusunda bir giriş yapmıştım. Bu defa açık kaynak olarak yayınlamak istediğim bir eklentiyi birlikte yazalım. Hazır yazmışken belki bir işe de yarar.

Eklenti bu sayfada çalışır durumdadır. Sayfa içeriğinde istediğiniz bir metni işaretleyerek sonuçları gözlemleyebilirsiniz.

Bu çalışmayı https://github.com/hozakar/sharemenu adresinden indirebilirsiniz.

 

Paylaşım menüsü

Sayfalarımızda kullanıcının işaretlediği alan ile ilgili işlemleri barındıran bir menü oluşturmayı amaçlıyorum. Görüntüsü şöyle olsun:

ShareMenu

 

Kullanım

<!-- CSS Dosyası -->
<link href="css/sharemenu.css" rel="stylesheet">

<!-- Font Awesome -->
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome.css" rel="stylesheet">

<!-- jQuery -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

<!-- js Dosyası -->
<script src="js/sharemenu.min.js"></script>

<!-- Aktivasyon -->
<script>
  $(function() {
    $('.sharemenu').sharemenu();
  });
</script>

 

Parametreler

twitter Menüde Tweetle seçeneği bulunsun mu? (Değerler: 0, 1) (Varsayılan: 1)
facesharer Menüde Facebook'ta Paylaş (sharer.php) seçeneği bulunsun mu? (Değerler: 0, 1) (Varsayılan: 1)
google Menüde Google'da Ara seçeneği bulunsun mu? (Değerler: 0, 1) (Varsayılan: 1)
facebook Menüde Facebook'ta Paylaş (dialog feed) seçeneği bulunsun mu? (Değer: nesne)

app_id Facebook Application Id
redirect_uri İşlem sonunda dönülecek sayfanın adresi
extra Menüye eklenecek kullanıcı tanımlı satırlar. Dizi değişkendir. Her bir elemanı bir nesnedir.

name Menü satırında görüntülenecek yazı.
link Bağlantı adresi "[selection]" anahtar kelimesi ile seçili metin alınabilir.
target Bağlantının açılacağı ekran (Varsayılan: _self)
fa Menü ikonu için font-awesome ismi. (Örn: "fa-search" için "search")

Not: İşin kodlama kısmına ilgi duymuyorsanız bundan sonrasını pas geçin.

 

Senaryo

İşaretleme işlemi bir context menü tetiklesin. Bu menü işaretli metinle ilgili işlevleri içersin.

İşlev

  • İşaretlenmiş metni Tweet atabilmeli,
  • İşaretlenmiş metni (mümkünse) içeren Facebook paylaşımı oluşturabilmeli,
  • İşaretlenmiş metin için Google araması başlatabilmeli,
  • Kullanıcı isteği doğrultusunda menü satır(lar)ı eklenebilmeli,
  • Aynı sayfada, farklı konfigürasyonlarda, birden çok menü aktive edilebilmeli.

 

CSS

Öncelikle açılır menümüzün görüntüsünü CSS ile düzenleyelim. CSS dosyasını "scss" kullanarak oluşturalım. Menümüz için bir class seçmeliyiz. Mümkün olduğunca sayfa içinde kullanılabilecek başka class isimleriyle çakışmamasını sağlamak için kontrolümüze özel bir isim belirleyelim: "_sharemenu_menu_list_".

/* Variables */
$menuWidth:      160px;
$fontSize:       14px;
$bgColor:        #fff;
$borderColor:    #eee;
$borderRadius:   4px;
$boxShadow:      0 6px 12px rgba(0,0,0,.175);
$menuItem-color: #333;
$menuItem-bg:    #f6f6f6;

/* Share Menu */
._sharemenu_menu_list_ {
  position: absolute;
  z-index: 999;
  display: none;
  float: left;
  min-width: $menuWidth;
  font-size: $fontSize;
  padding: .4em 0;
  margin: .15em 0 0;
  text-align: left;
  list-style: none;
  background-color: $bgColor;
  background-clip: padding-box;
  background-clip: padding-box;
  border: 1px solid $borderColor;
  border-radius: $borderRadius;
  box-shadow: $boxShadow;
  user-select: none;

  li {
    a {
      display: block;
      padding: .25em 1.5em .25em .75em;
      clear: both;
      font-weight: 400;
      line-height: 1.6;
      color: $menuItem-color;
      white-space: nowrap;
      text-decoration: none;
		
      &:hover {
        background-color: $menuItem-bg;
        text-decoration: none;
      }

      i {
        display: inline-block;
        width: 1.25em;
      }
    }
  }
}

Not: Sass, less ve js dosyalarınız için önerebileceğim çok güzel bir araç, Prepros.

 

JavaScript

Javascript dosyamızı yazmaya başlamadan önce nasıl kurgulayacağımıza karar verelim:

  • jQuery Plugin olarak yazalım,
  • Aynı sayfada birden fazla menüyü (instance) birlikte çalıştırmak isteyebileceğimize göre her bir instance'ı kendi özellik ve metodlarını içinde barındıran bir nesne olarak tasarlamak yerinde olur.

 

Kullanıcı parametrelerini ne şekilde alabileceğimize bakalım:

Twitter, facebook ve google arama işlemlerini ana işlevler olarak belirlemiştik. Facebook paylaşımlarında artık "sharer.php" tercih edilmiyor (deprecated). Bu sebeple dialog feed tercih etmeliyiz. Ancak bunun için kullanıcının Facebook app_id'sini ve redirect_uri'sini belirtmesi gerekli. Aksi taktirde "sharer.php" kullanmak dışında bir seçeneğimiz yok. Ayrıca kullanıcı kendi isteği doğrultusunda menü satırları ekleyebilmeli demiştik. Kulanıcının bu verileri parametre olarak göndermesi için aşağıdaki gibi bir yapı oluşturabiliriz:

/* Varsayılan parametreler aşağıdaki gibi olsun...
** Bu değerler, "$(element).sharemenu();"
** kullanımının eşleniğidir ve
** Tweet işlevini, "sharer.php" yardımıyla
** Facebook paylaşımı işlevini ve
** Google araması işlevini kullanacağımız anlamına
** gelir. */
{
  twitter: 1,
  facesharer: 1,
  google: 1
}

/* Eğer Facebook paylaşımı dialog feed
** kullanılacaksa app_id ve redirect_uri
** bilgisini aşağıdaki gibi alabiliriz.
** "app_id" Facebook'tan edinilen aplikasyon
** id'si, "redirect_uri" ise paylaşım işlemi
** tamamlandığında dönülecek olan sayfanın
** adresidir. */
{
  facebook: {
    app_id: 'facebook_app_id',
    redirect_uri: 'donus_adresi'
  }
}

/* Kullanıcı tarafından eklenen özel satırlar için
** ise (herbir satır için) nesnelerden
** oluşan bir dizi değişkeni oluşturalım.
** burada bir anahtar kelime belirleyelim, bu ifade ile
** seçilen metni alalım. Bu ifade "[selection]" olsun.
** Menü ikonlarını font-awesome ile kullanalım. */
}
  extra: [
    {
      name: 'Menü Satırı İsmi',
      link: 'http://adres.com/[selection].html',
      target: '_blank',
      fa: 'search'
    }
  ]
}

/* Örnek Kullanım:
** Bu kullanımda menümüzde Tweet işlevi,
** dialog feed ile Facebook paylaşımı işlevi,
** Google araması işlevi ve biri site içi arama
** diğeri "Ana Sayfa" linki olmak üzere
** iki özel işlev bulunuyor... */
$('.sharemenu').sharemenu({
  facebook: {
    app_id: '145634995501895',
    redirect_uri: 'https://facebook.com/'
  },
  extra: [
    {
      name: 'Sitede Ara',
      link: '/ara/[selection]',
      target: '_blank',
      fa: 'search'
    },
    {
      name: 'Ana Sayfaya Dön',
      link: 'http://beltslib.net/',
      fa: 'home'
    }
  ]
});

 

Plug-in ana fonksiyonumuzu oluşturalım:

(function ($) {
  "use strict";

  /* Aynı sayfa içinde birden çok menü aktive
  ** edilebilsin demiştik. Her bir menüyü bir
  ** nesne olarak tanımlayıp kullanabilmek
  ** için bir dizi değişkeni tanımlayalım. */
  var allmenus = new Array();
  
  $(function () {
    /* Sayfanın herhangi bir noktasına
    ** clicklendiğinde o sırada açık olan
    ** menü(ler)in kapanmasını sağlayalım. */
    $('body').mousedown(function () {
      $("._sharemenu_menu_list_").css('display', 'none');
    });
  });

  /* Plug-in ana fonksiyonumuzu oluşturalım. */
  $.fn.sharemenu = function (param) {
    /* Varsayılan değerlerimizi belirleyelim */
    var values = $.extend({
      twitter: 1,
      facesharer: 1,
      google: 1
    }, param);

    /* Facebook paylaşımı için sharer.php kullanımı
    ** artık önerilmiyor (deprecated) ancak kullanıcının
    ** facebook app_id si yoksa yine de kullanmak
    ** durumundayız. Eğer app_id varsa dialog feed
    ** tercih edebiliriz. */
    if (values.facebook) { // Facebook verisi gelmiş mi?
      if (typeof values.facebook == 'object') {
        //Gelen veri nesne ise dialog feed kullan
        values.facefeed = 1;
        values.facesharer = 0;
      } else {
        //Gelen veri nesne değilse "sharer.php" kullan
        values.facefeed = 0;
        values.facesharer = 1;
      }
    }

    /* Menüler için oluşturduğumuz dizi değişkenine
    ** aktive etmekte olduğumuz menüyü taşımak üzere
    ** bir nesne ekleyelim. */
    allmenus.push(new Object());

    /* Oluşturduğumuz yeni nesnenin dizi içindeki
    ** id sini bulalım ve ilgili DOM element(ler)ine
    ** data özelliği yardımıyla bilgi olarak ekleyelim.
    ** Bu bilgiye fonksiyonlarımızı yazarken ihtiyaç
    ** duyacağız. */
    var id = allmenus.length - 1;
    this.data('sharemenuid', id);

    /* Artık oluşturduğumuz yeni nesnemizi
    ** gerekli düzenlemeleri yapacağımız başlatma
    ** (initialization) fonksiyonuna derlediğimiz
    ** verilerle birlikte gönderelim.
    ** Bu fonksiyonu birazdan yazacağız. */
    init(this, id, values);

    /* Zincirleme kullanım sağlayabilmek için
    ** jQuery instance ını geri gönderelim. */
    return this;
  }
})(jQuery);

Açıklama: Plug-in'imiz için gerekli ana fonksiyonu oluşturduk. Bu fonksiyonda gerekli parametreleri derledik. Paylaşım menüsü olarak kullanmak üzere yeni bir nesne oluşturarak bu nesneyi tüm menülerimizi taşıyacak olan dizi değişkenine ekledik. Şimdi bu nesneyi, ihtiyaç duyacağımız işlevleri ekleyerek düzenlemeliyiz.

 

"init" fonksiyonu:

function init(el, id, param) {
  /* DEĞERLER
  ** el    -> Menümüzü üzerinde aktive etmek istediğimiz
  **          DOM elementlerinden oluşan jQuery instance.
  ** id    -> Düzenlemekte olduğumuz nesnenin id si.
  ** param -> Parametreler.
  */
  
  /* Aşağıda:
  ** Menü olarak açacağımız DOM elementini oluşturacağız.
  ** Bu elementin üzerinde mouse butonuna basıldığında,
  ** bırakıldığında ve clicklendiğinde yapılacak işlemleri
  ** düzenleyeceğiz. */
  el.append('<ul class="_sharemenu_menu_list_"></ul>');
  
  $('._sharemenu_menu_list_')
    .off()
    .on('mousedown', function (e) {
      e = e || window.event;
      e.stopPropagation();
    })
    .on('click', function () {
      $("._sharemenu_menu_list_").css('display', 'none');
    });

  el.mouseup(function (e) {
    var sm = allmenus[$(this).data('sharemenuid')];

    e = e || window.event;
    if (e.button !== 0) return;
    e.preventDefault();

    sm.selisleri(e, this);
  });

  /* Nesnemizi düzenleyelim ve gerekli
  ** fonksiyonları ekleyelim. */
  allmenus[id] = {
    id: id,
    param: param,

    /* Seçili metin ile ilgili işlemler. */
    selisleri: function (e, el) {
      var hoy = getSelection().toString();
      hoy = hoy
        .replace(/\n+/igm, " ")
        .replace(/\s+/igm, " ")
        .replace(/^\s+|\s+$/g, "");

      this.openShareMenu(hoy, e, el);
    },

    /* Menüyü aç. */
    openShareMenu: function (hoy, e, el) {
      var $menu = $(el).find("._sharemenu_menu_list_");
      if ($menu.css('display') != 'none') {
        /* Menü açık değilse açılmadan önce seçili metni
        ** menünün data özelliğine yaz. Seçili metin yoksa
        ** menüyü hiç açma. */
        if (!hoy) {
          $menu.data('sel', hoy);
          $menu.css('display', 'none');
        } else if ($menu.data('sel') == hoy) return;
      }

      if (!hoy) return;

      var x = e.pageX;
      var y = e.pageY;
      $menu.data('sel', hoy);
      $menu.css({ left: x + 'px', top: y + 'px' });

      /* Tweetlenecek metni belirle. */
      var twittext = hoy + ' ' + location.href;

      /* Tweet için gerekli uri satırını oluştur. */
      var twit = 'https://twitter.com/intent/tweet?text=' + twittext;

      /* Google araması için uri satırını oluştur. */
      var goog = 'https://www.google.com/?#q=' + hoy;

      var menu = '';

      var current = allmenus[$(el).data('sharemenuid')];

      /* Menü satırlarını ve linkleri oluştur. */
      if (current.param.twitter) // Tweet
        menu += '<li><a href="' + twit + '" target="_blank">' +
          '<i class="fa fa-twitter"></i>&nbsp;Tweet (' + 
          twittext.length + ' Karakter)</a></li>';

      if (current.param.facesharer) // Facebook sharer.php
        menu += '<li><a href="' +
          'https://www.facebook.com/sharer/sharer.php?u=' +
          location.href + '" target="_blank">' +
          '<i class="fa fa-facebook"></i>' +
          '&nbsp;Facebook</a></li>';

      if (current.param.facefeed) // Facebook dialog feed
        menu += '<li><a href="https://www.facebook.com/dialog/feed?app_id=' +
          current.param.facebook.app_id + '&caption=' + hoy +
          '&redirect_uri=' + current.param.facebook.redirect_uri +
          '&link=' + location.href + '" target="_blank">' +
          '<i class="fa fa-facebook"></i>&nbsp;Facebook</a></li>';

      if (current.param.google) // Google araması
        menu += '<li><a href="' + goog +
        '" target="_blank"><i class="fa fa-google">' +
        '</i>&nbsp;Google\'da Ara</a></li>';

      if (current.param.extra)
        if (current.param.extra.length) { // Kullanıcı tanımlı işlemler
          for (var i = 0; i < current.param.extra.length; i++)
            menu += '<li><a href="' +
              current.param.extra[i].link.split('[selection]').join(hoy) +
              '" target="' +
              (current.param.extra[i].target ? current.param.extra[i].target : '') +
              '"><i class="fa fa-' +
              (current.param.extra[i].fa ? current.param.extra[i].fa : 'circle') +
              '"></i>&nbsp;' + current.param.extra[i].name + '</a></li>';
        }

      $menu.html(menu);
      $menu.css('display', 'block');
    }
  }
}

 

Hepsi bu kadar. İşinize yarayacağını umarım.

 

Yorumlar Yorum Yap