Výběr a přetahování objektů
Snad každý zná přetahování vybraných objektů na jiné místo, například souborů mezi různými adresáři. Něco takového můžeme celkem oprávněně chtít také ve webové aplikaci. Problém ale je, že jQuery UI k tomu neposkytuje přímé prostředky, tak jako je poskytuje pro přetahování jednotlivých objektů. Je potřeba část práce udělat ručně.
Existují pluginy, které to usnadňují, ale k těm se dostaneme později. Teď je důležité, o co je vlastně potřeba se postarat. Jsou to v zásadě tři věci:
- vykreslování přesouvaných objektů na správných místech,
- ponechání pozice objektů po skončení přetahování,
- zpracování upuštění objektů.
Implementace
Celé to bude fungovat vlastně tak, že základem bude obyčejné přetahování jednoho objektu, které se bude „promítat“ do ostatních objektů. S výhodou k tomu lze využít událostí, které v procesu nastávají. Pokud bude přetahován nevybraný objekt, všechno se bude chovat „jako obvykle“. Při přetahování některého z vybraných objektů však bude chování jiné.
Asi bude nejlepší začít příkladem – nejdřív jen pro obyčejné přetahování, bez reakce na upuštění někam (předpokládejme, že přetahovatelnými objekty budou všechny elementy div
uvnitř kontejneru s identifikátorem cont
):
function updateMultidragOffsets(jq) { var oldpos = jq.data('oldpos'); if (typeof oldpos != 'undefined') { var pos = jq.offset(); var diff = { left: pos.left - oldpos.left, top: pos.top - oldpos.top }; var sel = $('.multidrag'); for (var i = 0; i < sel.length; i++) { var o = $(sel.get(i)); var op = o.data('oldpos'); o.offset({ left: op.left + diff.left, top: op.top + diff.top }); } } } $(document).ready(function() { var opts = { start: function() { if ($(this).hasClass('ui-selected')) { $('.ui-selected').not(this).addClass('multidrag'); $('.ui-selected').each(function() { $(this).data('oldpos', $(this).offset()); }); } }, drag: function() { updateMultidragOffsets($(this)); } stop: function() { updateMultidragOffsets($(this)); $('.multidrag').removeClass('multidrag').removeData('oldpos'); $(this).removeData('oldpos'); }, }; $('#cont div').draggable(opts); $('#cont').selectable(); });
Vezměme to od konce. Metody selectable()
a draggable()
připravují widgety pro výběr, resp. přetahování. Pro přetahování je potřeba připravit reakce na již zmíněné události. Na událost start (začátek tažení) se reaguje tím, že se vybraným objektům (kromě aktuálního) nastaví třída multidrag
ke snazší identifikaci a všem vybraným objektům se uloží původní pozice pro výpočet pozice nové.
Pokud se přesouvá nevybraný objekt, nestane se nic, jak je z kódu zřejmé.
Při události drag
se volá funkce aktualizující pozice objektů (viz dále), při události stop
se aktualizuje pozice (což je nutné, protože při probíhajícím přetahování události obecně nenastávají tak často, aby se pozice aktualizovala vždy přesně), odebere se třída multidrag
a odstraní uložené pozice.
Funkce updateMultidragOffsets()
vypočítává rozdíl v pozici přímo přetahovaného objektu a podle něj vypočítá pozice všech ostatních objektů (přetahovaných prostřednictvím výběru). Pokud se přetahuje jen nevybraný objekt, funkce nedělá nic.
Reakce na upuštění objektů
Ještě zbývá vyřešit reakci na upuštění přetahovaných vybraných objektů někam. Klíčem je samozřejmě reakce na upuštění přímo přetahovaného objektu, ty ostatní vybrané se s ním „svezou“. Tady je krátký příklad, jak to může vypadat:
opts = { drop: function(e, ui) { ui.draggable.removeClass('ui-selected'); $('.multidrag').removeClass('ui-selected'); $(this).append(ui.draggable.detach()); $(this).append($('.multidrag').detach()); } }; $('#target').droppable(opts);
Objekt s identifikátorem target
je cílem, kam se budou přetahované objekty pouštět. V tomto případě bude reakcí na upuštění to, že se objekty přesunou do cíle. Je potřeba je „odvybrat“ (protože už jsou jinde a pracujeme s nimi tedy jinak) a následně provést jejich přesun v DOM.
Zde se počítá s tím, že cílový objekt ty přetahované vždy přijme. Pokud by tomu tak nebylo (byl by použit filtr), mohli bychom požadovat třeba návrat objektů na původní místo. Pak by se přepsala obsluha události stop
tak, že se by v případě neakceptace nastavily zpět původní pozice, případně by to šlo také animovat.
Konkrétní widgety
Tímto dílem seriálu končí pasáž zabývající se interakcí s uživatelem a příště už se podíváme na konkrétní widgety, které jQuery UI poskytuje. Jako první přijdou na řadu tlačítka různého druhu.