Skip to content

Instantly share code, notes, and snippets.

@bganicky
Created December 13, 2010 12:38
Show Gist options
  • Select an option

  • Save bganicky/738951 to your computer and use it in GitHub Desktop.

Select an option

Save bganicky/738951 to your computer and use it in GitHub Desktop.
Ukazka struktury jQuery pluginu.
/*
* Cely plugin je zabaleny do anonymni funkce, ktera se hned
* pusti. Vsechen kod uvnitr bezi tim padem ve svem scope.
* Navic se ubezpecujeme, aby "$" vzdy bylo jQuery.
*/
(function($) {
/*
* Zde mame prostor pro definici privatnich funkci ci promennych.
* Kod uvedeny zde probehne jen jednou(!) pri samotnem nacteni
* skriptu. Proto je zde vhodne definovat pomocne funkce, ktere
* nechceme mit verejne pristupne. Zde je take dobre misto pro
* konstanty, pokud nejake potrebujeme.
*/
/*
* Zde zacina vlastni plugin. Plugin neni nic jineho nez nova
* metoda jQuery navesena pres jQuery.fn, coz je vlastne jen
* alias pro Object.prototype. Zaroven ocekavame "options"
* s pripadnym nastavenim pluginu uzivatelem/implementatorem.
*/
$.fn.mySelect = function(options) {
// Tady si jen ukladam namespace pluginu pro kratsi kod
var MS = $.fn.mySelect;
// Mergnem vychozi nastaveni pluginu s uzivatelskym.
var settings = $.extend({}, MS.defaultOptions, options);
/*
* Dulezite! Uvnitr deklarace pluginu je "this" nikoliv
* nativni seznam DOM elementu, ale jiz hotovy jQuery objekt.
* Ten my cely vracime pres "return" jako navratovou hodnotu
* pluginu, abychom zachovali retezeni a bylo tak mozne udelat
* toto: $('select').mySelect().css(...);
* My navic "this" filtrujeme tak, abychom skutecne pracovali
* pouze se <select>y, kdyby nekdo plugin omylem volal na
* elementy jineho typu. Pres metodu .each() pak projdeme
* dotycne elementy a provedeme s nimi, co potrebujeme.
*/
return this.filter('select').each(function() {
/*
* Jsme uvnitr iteratoru .each(). V "this" je nyni v kazde
* iteraci prave jeden <select> jakozto nativni DOM element.
* Nejdrive si nadefinujeme promenne, ktere se nam budou
* hodit pozdeji.
*/
// Samotny select si zabalime do jQuery a rovnou schovame.
var $select = $(this).hide(),
// Options se nam taky budou hodit.
$options = $select.children(),
// Toto je obalovaci div pro cely "widget".
$wrapper = $('<div class="mySelect_wrapper"></div>'),
/*
* Toto je "falesne" tlacitko suplujici select.
* Dulezite je, ze samotne HTML bereme z nastaveni
* pluginu a uzivatel ma tim padem moznost ovlivnit
* jeho HTML podobu. Dame mu pomocnou tridu a vlozime
* do obalovaciho divu.
*/
$trigger = $(settings.triggerTpl)
.addClass('mySelect_trigger')
.appendTo($wrapper),
/*
* Zde si vytvarime vyskakovaci nabidku, resp. jeji
* obalovaci prvek (by default je to <ul>), pomoci
* public metody renderMenu(), jejiz definice je nize
* a opet pridavame pomocnou tridu a schovame.
*/
$selectmenu = MS.renderMenu()
.addClass('mySelect_menu')
.hide();
/*
* Musime si nejak svazat hodnoty z orig. <option>s s
* novou ("falesnou") nabidkou. Tim padem opet pouzijeme
* iterator .each() a pro kazdou <option> si pripravime
* jeji obraz v nove nabidce.
*/
$options.each(function() {
// "this" je zase <option> jakozto DOM element
// ulozime si ho jako jQuery
var $option = $(this),
// vezmeme puvodni textovou hodnotu
text = $option.text(),
// vezmeme puvodni strojovou hodnotu
value = $option.val();
// a vygenerujeme novou polozku podobne jako renderMenu vyse
var $item = MS.renderItem(text);
// Novou polozku vlozime do menu.
$item
.appendTo($selectmenu)
// Zde urcime, co se ma dit po kliknuti na polozku.
.bind('click', function() {
/*
* Zmenime strojovou hodnotu puvodniho select
* na vybranou novou a tim padem zachovame
* puvodni funkcinalitu pro pripad odesilani
* formulare.
*/
$select.val(value);
// Zmenime text tlacitka na novy text.
$trigger.text(text);
// Schovame nabidku.
$selectmenu.hide('fast');
/*
* Zavolame callback funkci "onSelect"
* nastavenou v moznostech pluginu.
* Tim padem ma uzivatel moznost zavesit si
* svoji dalsi funkcionalitu na udalost zmeny
* hodnoty selectu. Pouzivame JS funkci call()
* ktera nam umoznuje podstrcit volane funkci
* hodnotu pro "this" uvnitr volani. V tomto
* pripade mi prislo nejvhodnejsi, aby v onom
* callbacku byl dostupny aktualni <select>,
* a to ve forme nativniho DOM elementu.
*/
settings.onSelect.call($select[0]);
});
});
// Nove sestavene menu vlozime do obalovaciho divu a ten
// zase cely vlozime za odpovidajici (skryty) <select>
$wrapper
.append($selectmenu)
.insertAfter($select);
// Nakonec resime click udalost na tlacitku.
$trigger.bind('click', function() {
/*
* Tady vlastne narazime na tvuj puvodni problem.
* Vime, ze vsechny obalovaci divy maji danou tridu
* a chceme schovat menu v kazdem z nich, krome
* toho, se kterym ted pracujeme.Ten mame ulozeny
* v promenne $wrapper. Pouzijeme tedy metdou .not(),
* ktera nam ho z dane selekce vylouci.
*/
$('.mySelect_wrapper')
.not($wrapper)
/*
* V tuhle chvili mame tedy jen vsechny ostatni.
* Pres .find() v nich najdeme otevrena menu pres
* filter :visible...
*/
.find('.mySelect_menu:visible')
// ...a schovame je.
.hide('fast');
// Naopak aktualni menu bud zavreme nebo otevreme.
$selectmenu.toggle('fast');
});
});
};
/*
* Tady mame definovane vychozi moznosti pluginu.
* Tento objekt je verejne pristupny, takze si clovek muze
* vychozi nastaveni zmenit globalne pro vsechna volani pluginu:
* $.fn.mySelect.defaultOptions = {
* triggerTpl: '<button>Click for options</button>',
* onSelect: function() {}
* }
* Porad ale zustava moznost zmenit nastaveni i pri kazdem volani
* pluginu:
* $('select').mySelect({
* onSelect: function() {
* console.log(this);
* }
* });
*/
$.fn.mySelect.defaultOptions = {
triggerTpl: '<div>Select</div>',
onSelect: function() {}
};
/*
* Definice public funkce na vytvoreni vnejsiho prvku menu.
* Public ji davam z toho duvodu, aby si uzivatel mohl zmenit
* HTML dle sveho, pokud potrebuje. Toto nastaveni pak plati
* pro vsechna volani pluginu!
* $.fn.mySelect.renderMenu = function() {
* return $('<div class="wrapper"></div>');
* };
* Jeste poznamka: tyto funkce by teoreticky mohly byt definovany
* kdekoliv, ale slusnosti je mit je v "namespace" sveho pluginu a
* nestrasit s nimi v namespace jQuery ci nedej boze v globalnim.
*/
$.fn.mySelect.renderMenu = function() {
return $('<ul></ul>');
};
/*
* Zde plati to same jako u renderMenu vyse. Tady je navic akorat
* parametr "text".
* $.fn.mySelect.renderItem = function() {
* return $('<span class="item">'+text+'</span>');
* };
*/
$.fn.mySelect.renderItem = function(txt) {
return $('<li/>').text(txt);
};
})(jQuery);
$(function() {
$('select').mySelect({
onSelect: function() {
$('#log').append('<p>Selected: ' + $(this).val() + '</p>');
}
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment