Belarusian (беларуская мова) translation by Alex Grigorovich (you can also view the original English article)
Адной з новых функцый у HTML5 з'яўляецца ўбудаваны функцыянал "Перацягні і Кінь". Дзіўна, але Internet Explorer падтрымлівае убудаваную функцыю "Перацягні і Кінь" пачынаючы з версіі 5.5; Фактычна HTML5 заснаваны на падтрымцы IE. У сённяшнім ўроку мы разгледзім, як рэалізаваць уласны функцыянал "Перацягні і Кінь", для выкарыстання ў інтэрфейсе кошыка пакупніка.
Крок 0. Што мы збіраемся зрабіць
Вось што мы збіраемся стварыць: прасты кошык пакупніка з панэллю тавараў і панэллю для кошыка. Каб "купіць" прадукт, вы можаце перацягнуць яго з панэлі на значок кошыкі; мы будзем адсочваць колькасць пакупак і выдаляць тавары з панэлі, калі іх няма ў наяўнасці.
Звярніце ўвагу, што мы на самай справе не ствараем поўнафункцыянальную кошык пакупніка; сёння мы не будзем працаваць з сервернай часткай. Гэта будзе толькі інтэрфейс; наша мэта - функцыянал "Перацягні і Кінь" з дапамогай HTML5.
Крок 1. HTML
Вядома, мы пачнем з HTML кода; вось наш каркас:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Drag and Drop Shopping Cart</title> <link rel="stylesheet" href="default.css" /> </head> <body> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script src="jquery.ndd.js"></script> <script src="dragdrop.js"></script> </body> </html>
Усё даволі проста: мы дадаем спасылкі на табліцу стыляў і jQuery; мы будзем выкарыстоўваць jQuery толькі для зручнай апрацоўкі падзей і маніпуляцый з DOM; функцыянал "Перацягні і Кінь" будзе натыўны. Аднак мы можам сутыкнуцца з цяжкасцямі, таму што функцыянал "Перацягні і Кінь" у HTML5 дадае некалькі уласцівасцяў да аб'екта падзеі. А так як JQuery не выкарыстоўвае аб'ект падзеі па-змаўчанні; ён стварае свой уласны эквівалент. І з-за гэтага мы не можам атрымаць доступ да спецыяльных ўласцівасцях з дапамогай jQuery. Але не турбуйцеся; для гэтага ёсць адмысловая ўбудова; мы падлучальны убудова Native Drag and Drop, каб усё гэта працавала. І, нарэшце, мы падлучальны наш скрыпт: dragdrop.js
.
Цяпер мы гатовыя дадаць наш спіс тавараў; у якасці малюнкаў тавараў я выкарыстоўваю значкі з Apple Icon Superpack, створаныя SvenVath (Я пераназваў значкі спрасціўшы імёны і змяніў іх памер да 180 пікселяў.)
Дадайце ul#products
ў якасці першага ўзроўню ўнутры тэга body. Як толькі вы гэта зробіце, мы разгледзім першы элемент спісу:
<li><a class="item" href="#" id="imac" draggable="true"> <img src="http://tutsplus.s3.amazonaws.com/tutspremium/web-development/064_drag_drop_html5/images/imac.png" /> <div> <p><strong>iMac</strong></p> <p><strong>Price</strong>: <span>$1199.00</span></p> <p><strong>Quantity</strong>: <span>10</span></p> </div> </a></li>
Мы завяршаем элемент спісу якарам ўнутры; звярніце ўвагу, што кожны элемент мае клас item
(гэта будзе важна, калі мы пяройдзем да CSS) і карыстацкі ідэнтыфікатар (гэта будзе важна, калі мы пяройдзем да JavaScript). Таксама, якар мае атрыбут draggable = "true"
; гэта ўсё, што нам трэба, каб зрабіць элемент перацягваць (мы хутка выявім некалькі папярэджанняў). Так як мы выкарыстоўваем тэг якара, вы павінны зрабіць што-то для браўзэраў без убудаванай падтрымкі перацягвання (хоць мы і не будзем гэтага рабіць тут). Затым у нас ёсць выява прадукту і пласт з інфармацыяй аб прадукце. І так, неабходна аформіць цану і значэнне колькасці з дапамогай тэга span
Вось астатнія складнікі спісаў:
<li><a class="item" href="#" id="iphone" draggable="true"> <img src="http://tutsplus.s3.amazonaws.com/tutspremium/web-development/064_drag_drop_html5/images/iphone.png" /> <div> <p><strong>iPhone</strong></p> <p><strong>Price</strong>: <span>$199.00</span></p> <p><strong>Quantity</strong>: <span>16</span></p> </div> </a></li> <li><a class="item" href="#" id="appletv" draggable="true"> <img src="http://tutsplus.s3.amazonaws.com/tutspremium/web-development/064_drag_drop_html5/images/appletv.png" /> <div> <p><strong>AppleTV</strong></p> <p><strong>Price</strong>: <span>$299.00</span></p> <p><strong>Quantity</strong>: <span>9</span></p> </div> </a></li> <li><a class="item" href="#" id="dislpay" draggable="true"> <img src="http://tutsplus.s3.amazonaws.com/tutspremium/web-development/064_drag_drop_html5/images/display.png" /> <div> <p><strong>Cinema Display</strong></p> <p><strong>Price</strong>: <span>$899.00</span></p> <p><strong>Quantity</strong>: <span>4</span></p> </div> </a></li> <li><a class="item" href="#" id="nano" draggable="true"> <img src="http://tutsplus.s3.amazonaws.com/tutspremium/web-development/064_drag_drop_html5/images/nano.png" /> <div> <p><strong>iPod Nano</strong></p> <p><strong>Price</strong>: <span>$149.00</span></p> <p><strong>Quantity</strong>: <span>20</span></p> </div> </a></li> <li><a class="item" href="#" id="macbook" draggable="true"> <img src="http://tutsplus.s3.amazonaws.com/tutspremium/web-development/064_drag_drop_html5/images/macbook.png" /> <div> <p><strong>Macbook</strong></p> <p><strong>Price</strong>: <span>$1199.00</span></p> <p><strong>Quantity</strong>: <span>13</span></p> </div> </a></li> <li><a class="item" href="#" id="mini" draggable="true"> <img src="http://tutsplus.s3.amazonaws.com/tutspremium/web-development/064_drag_drop_html5/images/mini.png" /> <div> <p><strong>Mac Mini</strong></p> <p><strong>Price</strong>: <span>$599.00</span></p> <p><strong>Quantity</strong>: <span>18</span></p> </div> </a></li>
Вось фінальны варыянт HTML: кошык для пакупак:
<div id="cart"> <h1>Shopping Cart</h1> <ul></ul> <p id="total"><strong>Total:</strong> $<span>0.00</span></p> <hr /><h2>Drop here to add to cart</h2> </div>
І гэта наш увесь код HTML!
Поўны крэатыў
Крок 2. CSS
У ідэале, усё, што вам трэба зрабіць, каб зрабіць элемент перацягваць, усталяваць значэнне для атрыбуту draggable true; тым не менш, ёсць яшчэ сёе-тое для гэтага. Каб усё працавала правільна, вы павінны ўсталяваць некалькі рэчаў з дапамогай CSS. Па-першае, падумайце аб гэтым: што адбываецца пры націску і перацягванні "нармальнага" (неперетаскиваемого) элемента? Звычайна адбываецца вылучэнне тэксту. Таксама мы хочам пераканацца, што мы перацягваць элементы, а не толькі яго змесціва. Каб справіцца з гэтым, неабходна выкарыстоўваць наступны код CSS:
[draggable=true] { -moz-user-select:none; -webkit-user-select: none; -webkit-user-drag: element; }
Для нашага зручнасці убудаваны убудова drag-drop, які мы выкарыстоўваем, ўсталёўвае гэтыя ўласцівасці для нас, таму мы можам не мяняць яго, калі жадаем. Аднак мы зробім гэта:
[draggable=true] { cursor : move; }
Давайце пачнем працаваць над афармленнем:
html { height:100%; } body { background: #ececec; margin:0; padding:0; font: 13px/1.5 helvetica, arial, san-serif; height: 100%; } h1, h2 { text-align:center; } h2 { position:absolute; bottom: 20px; color:#fff; text-shadow:0 0 10px rgba(0, 0, 0, 0.75); display:none; } p { margin:0; }
Паколькі мы не выкарыстоўваем поўны скід стылю, вось наш псеўда-скід. Усё павінна быць зразумела. Мы ўсталёўваем вышыню на веданне 100% для элементаў html
і body
, таму што мы хочам, каб #cart
быў на ўсю вышыню экрана; для гэтага кожны бацькоўскі элемент павінен мець вышыню, роўную 100%. Таксама зьвярніце ўвагу, што мы выкарыстоўваем rgba для ўстаноўкі колеру цені; калі браўзэр не падтрымлівае гэта, для элемента h2
не будзе цені. І мы схаваем гэты h2
, усталяваўшы значэнне display: none
. Памятаеце, што h2
кажа "Кіньце сюды, каб дадаць у кошык", так што мы павінны будзем іх плаўна схаваць, калі перацягвання пачнецца і цалкам прыбраць, калі скончыцца перацягвання.
Пераходзім да нашага спісу тавараў ...
#products { float:left; list-style:none; width:65%; padding:0; } #products li { display:inline; }
Зноў, тут усё зразумела. Важным у гэтым фрагменце з'яўляецца тое, што элементы спісу будуць адлюстроўвацца ў адзін радок. Паколькі мы ўсталюем ўласцівасці display: block; float: left
для якароў, IE дадасць да элементаў спісу эфект «лесвічных прыступак»; мы можам абыйсці гэтую памылку, усталяваўшы ўласцівасць display: inline
для бацькоўскага элемента.
Гаворачы аб якарах, давайце працягнем іх афармляць далей.
.item { display:block; float:left; width:180px; height:180px; margin:10px; border:1px solid #494949; text-align:center; text-decoration:none; color: #000; overflow:hidden; } .item img { border:0; margin:10px auto; width:160px; height:160px; } .item div { background:rgb(0, 0, 0); background: rgba(0, 0, 0, 0.5); position:relative; bottom:69px; color:#f3f3f3; padding:5px 0; display:none; }
Кожны якар будзе аформлены як блок 180x180px; ён будзе запоўнены выявай прадукту. Пласт з інфармацыяй аб тавары будзе размешчаны над малюнкам у ніжняй частцы квадрата. Звярніце ўвагу, што мы павінны ўсталяваць колер фону, а затым скінуць яго для сучасных браўзэраў, таму што IE не падтрымлівае RGBa. Мы ўсталёўваем display: none
для інфармацыйнага пласта, каб мы маглі яго плаўна схаваць і паказаць, калі "пакупнік" наводзіць курсор і прыбірае яго, адпаведна.
Усё, што засталося аформіць, гэта кошык для пакупак; мы разгледзім яе тут, але, памятайце, складнікі спісаў будуць дададзеныя з дапамогай jQuery пазней, так што вы пакуль не ўбачыце, як гэта адбываецца.
#cart { float:right; background-color:#ccc; width:25%; padding:0 5%; height:100%; } #cart ul { padding:0; } #cart li { list-style:none; border-bottom:1px solid #494949; padding:5px; } #cart .quantity { font-weight:bold; padding-right:10px; margin-right:10px; border-right:1px solid #494949; display:inline-block; width:15px; text-align:right; } #cart .price { float:right; } #total { float:right; }
Элементы з класамі афармлення для quantity
і price
будуць знаходзіцца ўнутры дынамічна устаўленых элементаў спісу.
Гэта для CSS; перш чым перайсці да зоркі гэтага шоў, давайце паглядзім на праведзеную працу.

Крок 3. JavaScript
Мы дабраліся да JavaScript; згодна з HTML5 doctor:
HTML 5 DnD заснаваны на першапачатковай рэалізацыі Microsoft, якая была даступная ўжо ў Internet Explorer 5! У цяперашні час падтрымліваецца ў IE, Firefox 3.5 і Safari 4.
Вось спіс падзей, якія прапануе "Перацягні і Кінь" у HTML5:
- drag
- dragstart
- dragover
- dragenter
- dragleave
- dragend
- drop
Мы не будзем выкарыстоўваць іх усё, але паглядзім, як яны працуюць.
Спачатку, мы папрацуем з нашымі прадуктамі:
$('.item') .bind('dragstart', function (evt) { evt.dataTransfer.setData('text', this.id); $('h2').fadeIn('fast'); }) .hover( function () { $('div', this).fadeIn(); }, function () { $('div', this).fadeOut(); } );
Мы пачынаем з выбару ўсіх аб'ектаў; затым мы прывяжам функцыю да падзеі dragstart
; гэта падзея спрацоўвае, калі мы пачнем перацягваць аб'ект. Першае, што мы будзем рабіць пры перацягванні аб'екта, - гэта ўсталюем некаторыя дадзеныя; на самай справе, калі дадзеныя не ўстаноўлены, firefox не дазволіць элементу перамяшчацца. Спецыяльнае перацягвання падзей - гэта ўласцівасць аб'екта ў аб'екце падзеі, называецца dataTransfer
; мы будзем выкарыстоўваць два метаду гэтага ўласцівасці: setData
і getData
. Тут мы выкарыстоўваем метад setData
, які прымае два параметру: фармат дадзеных і дадзеныя. Мы будзем выкарыстоўваць тып дадзеных 'text'. Затым мы ўсталюем дадзеныя ідэнтыфікатара элемента, які карыстальнік цягае. Затым мы плаўна пакажам элемент h2
ў якасці падказкі для кліента.
Мы таксама выкарыстоўваем метад навядзення jQuery для паступовага з'яўлення інфармацыі аб прадукце, калі мы наводзім паказальнік мышы і знікнення, калі мы адводзім паказальнік мышы. Звярніце ўвагу, што мы перадаем вузел, які мы завісае як кантэкст, таму мы атрымліваем толькі пласт адпаведнага прадукту.
Зараз дадамо апрацоўшчыкі падзей для #cart
. Мы будзем узаемадзейнічаць з падзеямі dragover
, dragenter
і drop
:
$('#cart') .bind('dragover', function (evt) { evt.preventDefault(); }) .bind('dragenter', function (evt) { evt.preventDefault(); }) .bind('drop', function (evt) { });
Каб запусціць падзея drop, нам трэба адмяніць дзеянне па змаўчанні для падзеі dragover
; гэта падзея бесперапынна спрацоўвае пры дасягненні мэты перацягвання, калі перацягваць элементы перамяшчаецца па ёй. Толькі для IE нам трэба адмяніць дзеянне па змаўчанні на dragenter
, якое адбываецца толькі тады, калі элемент перацягвання ўваходзіць у мэтавую кропку. Прычыны адмены дзеянні па змаўчанні некалькі не канкрэтныя; калі шчыра, я іх не разумею. Вось што кажа Remy Sharp:
Тое, што паведамляе браўзэру, што гэты элемент з'яўляецца тым, які мы хочам выкарыстоўваць у падзеі перацягвання, гэта звычайнае дзеянне перацягвання. Так, адмяніўшы гэтую падзею, ён мы паведамляем браўзэру, што гэта той элемент, які павінен пачынацца перасоўванне.
Я павінен адзначыць, што jQuery крыху дапамагае нам тут; звычайна мы таксама павінны вяртаць значэнне return false
, каб ён працаваў у IE; аднак выпраўленае папярэджанне jQuery preventDefault
робіць гэта для нас.
Цяпер падзея drop
; гэта падзея таксама запускаецца для мэтавага аб'екта, якім з'яўляецца пласт div#cart
ў нашым выпадку. Перш чым мы паглядзім на функцыю, давайце пагаворым пра тое, што павінна рабіць гэтая функцыя:
- атрымаць прадукт, які мы кінулі
- калі прадукт ужо набыты, дадаць яго да колькасці набытага; у адваротным выпадку дадаць тавар у кошык
- памяншэнне колькасці прадукту
- абнавіць агульную кошт
Вось першая частка:
var id = evt.dataTransfer.getData('text'), item = $('#' + id), cartList = $("#cart ul"), total = $("#total span"), price = $('p:eq(1) span', item).text(), prevCartItem = null, notInCart = (function () { var lis = $('li', cartList), len = lis.length, i; for (i = 0; i < len; i++ ) { var temp = $(lis[i]); if (temp.data("id") === id) { prevCartItem = temp; return false; } } return true; } ()), quantLeftEl, quantBoughtEl, quantLeft;
Я ведаю; тут шмат зменных, але мы будзем выкарыстоўваць іх усё. Давайце разбярэмся; па-першае, мы атрымліваем тэкставыя дадзеныя, якія мы перадалі з падзеяй; мы перадалі id такім чынам, таму што ў аб'екце падзеі няма нічога, што паведамляе нам, які элемент быў скінуты на нашу мэта; мы атрымаем ідэнтыфікатар, а затым будзем выкарыстоўваць яго, каб знайсці элемент, які быў перанесены. Далей мы атрымліваем спіс кошыка і блок з цаной. Затым мы атрымаем цану асобнага тавару; мы ведаем, што гэта блок ў другім абзацы элемента, таму мы можам выкарыстоўваць гэты элемент у якасці параметру кантэксту. Мы ўсталюем prevCartItem
на null, але мы будзем выкарыстоўваць яго, каб даведацца, ці ёсць элемент, які мы перацягваць у кошык, у кошыку. Значэнне notInCart
- самозапускающаяся ананімная функцыя; яна будзе правярацца для кожнага элемента ў cartList (зноў жа, мы выкарыстоўваем кантэкстны параметр) і правяраем, ці з'яўляецца id
дадзеных такімі ж, як ідэнтыфікатар зменнай id
. Каб зразумець гэта, вам трэба будзе ведаць, што калі мы дадамо элементыспісу ў кошык пакупак, мы будзем выкарыстоўваць метад data
jQuery для ўстаноўкі ідэнтыфікатара прадукту для элемента. У гэтай функцыі мы правяраем элемент спісу з правільнымі дадзенымі; калі мы знойдзем адзін, і элемент ўжо знаходзіцца ў кошыку, таму мы ўсталёўваем значэнне notinCart
у значэнне false; калі ён не знаходзіцца ў кошыку, мы ўсталюем зменную ў значэнне true. Нарэшце, мы будзем выкарыстоўваць quantLeftEl
, quantBoughtEl
і quantLeft
пры абнаўленні колькасцяў.
Цяпер, аформім некаторыя дзеянні:
$("h2").fadeOut('fast'); if (notInCart) { prevCartItem = $('<li />', { text : $('p:first', item).text(), data : { id : id } }).prepend($('<span />', { 'class' : 'quantity', text : '0' })).prepend($('<span />', { 'class' : 'price', text : price })).appendTo(cartList); }
Па-першае, мы схаваем апавяшчэнне элемента h2
. Затым, калі элемент не знаходзіцца ў кошыку, мы дадамо яго ў кошык. Для гэтага мы створым элемент спісу; затым мы можам перадаць литерал аб'екта ў якасці другога параметру для задання уласцівасцяў нашага новага элемента спісу. Мы ўсталюем тэкст ў назву прадукту; які бярэм з першага абзаца прадукту. Затым мы ўсталёўваем дадзеныя, пра якія гаварылася вышэй.
Затым мы дадамо блок да гэтага элементу спісу; мы прызначым яму клас 'quantity' (не забудзьцеся паставіць клас у двукоссі, бо гэта зарэзерваваныя слова) і ўсталюйце тэкст на нуль; так, я ведаю, што лік павінна быць адзінкай, паколькі яны толькі што змясцілі тавар у кошык, але мы дадамо гэта пазней. і вы зразумееце, чаму.
Мы дадамо яшчэ адзін блок да элемента спісу, на гэты раз час цэны. Мы робім обцяканьне цэны справа, таму было б лагічна дадаць яго; але гэта выкліча памылку з плывучай кропкай у IE; блок абгарнуць тэкст справа і пад элементам спісу.
Нарэшце, мы будзем дадаваць элемент спісу ў спіс кошыка пакупак.
Апошняя частка гэтай функцыі будзе працаваць незалежна ад таго, ці знаходзіцца элемент у кошыку ці не:
quantLeftEl = $('p:last span', item); quantLeft = parseInt(quantLeftEl.text(), 10) - 1; quantLeftEl.text(quantLeft); quantBoughtEl = $('.quantity', prevCartItem); quantBoughtEl.text(parseInt(quantBoughtEl.text(), 10) + 1); if (quantLeft === 0) { item.fadeOut('fast').remove(); } total.text((parseFloat(total.text(), 10) + parseFloat(price.split('$')[1])).toFixed(2)); evt.stopPropagation(); return false;
Спачатку мы атрымаем колькасць тавару; гэта колькасць, што застаўся, пасля таго як пакупнік перацягне яго тавар у кошык; мы атрымаем колькасць, якое сапраўды засталося; але гэта радок, таму мы выкарыстоўваем натыўнымі функцыю parseInt
, каб пераўтварыць яе ў лік (выкарыстоўвайце 10 у якасці асновы для таго, каб мы атрымалі дзесятковы лік) і вычытаем адзінку з яго. Затым мы скідаем колькасць, выкарыстоўваючы метад jQuery text
.
Затым мы атрымліваем колькасць, пакупак карыстальніка; гэта элемент з класам 'quantity'; мы выкарыстоўваем prevCartItem
як кантэкст; гэта працуе, таму што калі элемент ўжо быў у кошыку, у гэтай ананімнай функцыі быў усталяваны prevCartItem
; калі яго не было ў кошыку, мы ўсталёўваем яго, калі мы ствараем кошык. Затым мы можам усталяваць тэкставае значэнне, атрымаўшы бягучае значэнне, пераўтвараючы яго ў лік і дадаўшы да яго адзінку.
Што адбываецца, калі колькасць дасягае нуля? Калі ён роўны нулю, мы схаваем элемент і выдалім яго.
Нарэшце, мы павінны абнавіць агульную цану. У нас ёсць блок з выніковай цаной, таму мы можам проста скінуць тэкст; што мы зараз робім, гэта атрымліваем цяперашні зьмест, преобразуем яго ў лік (на гэты раз мы выкарыстоўваем функцыю parseFloat
для захавання цэнтаў), падзяляем знак даляра з коштам і преобразуем яго ў лік і дадаем да двух значэнняў. Нарэшце, мы выкарыстоўваем функцыю toFixed
, каб пераканацца, што мы заўсёды паказваем правільнае значэнне ў цэнтах.
Нарэшце, мы не хочам, каб падзея drop
напластоўваюцца, таму мы спынім яго і вернем значэнне false;
Крок 4. Завершаны праект
Выдатная праца, мы скончылі; вось агляд нашай кошыка ў дзеянні:

Калі вы хочаце праверыць, што робяць іншыя падзеі перацягвання, дадайце гэта ў ваш скрыпт:
$('#cart').bind('dragleave', function (evt) { console.log('dragleave'); }); $('.item') .bind('dragend', function (evt) { console.log('dragend'); }) .bind('dragstart', function (evt) { console.log('dragstart'); }) .bind('drag', function (evt) { console.log('drag'); });
Хоць натыўны HTML5 пакуль не гатовы да прайм-тайм (Opera не падтрымлівае яго), вызначана цікава даведацца, куды ўсё рухаецца!
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post