Drag & Drop: Interaction Groups
Using interaction groups, this example demonstrates how to tie into the Drag & Drop Utility's interesting moments to provide visual affordances for the current drag operation.
Setting up the Work Area
First we need to create the work area, players (drags) and slots (drops).
<div id="workarea"> <div class="slot" id="t1">1</div> <div class="slot bottom" id="b1">3</div> <div class="slot bottom" id="b2">4</div> <div class="slot bottom" id="b3">5</div> <div class="slot bottom" id="b4">6</div> <div class="slot" id="t2">2</div> <div class="player" id="pt1">1</div> <div class="player" id="pt2">2</div> <div class="player" id="pb1">3</div> <div class="player" id="pb2">4</div> <div class="player" id="pboth1">5</div> <div class="player" id="pboth2">6</div> </div>
<div id="workarea"> <div class="slot" id="t1">1</div> <div class="slot bottom" id="b1">3</div> <div class="slot bottom" id="b2">4</div> <div class="slot bottom" id="b3">5</div> <div class="slot bottom" id="b4">6</div> <div class="slot" id="t2">2</div> <div class="player" id="pt1">1</div> <div class="player" id="pt2">2</div> <div class="player" id="pb1">3</div> <div class="player" id="pb2">4</div> <div class="player" id="pboth1">5</div> <div class="player" id="pboth2">6</div> </div>
Now we give them some CSS to make them visible.
.slot { border: 2px solid #808080; background-color: #CDCDCD; color: #666666; text-align: center; position: relative; float: left; margin: 4px; width: 60px; height: 60px; z-index: 0; } .player { border: 2px solid #808080; color: #ffffff; text-align: center; position: relative; float: left; margin: 4px; width: 60px; height: 60px; top: 150px; z-index: 1; cursor: move; } #pt1 { clear: both; } .bottom { top: 50px; } #pt1, #pt2 { background-color: #71241A; } #pb1, #pb2 { background-color: #004C6D; } #pboth1, #pboth2 { background-color: #FFA928; } #workarea { position: relative; height: 300px; width: 500px; } #workarea .yui-dd-drop-active-valid { border: 2px solid green; } #workarea .yui-dd-drop-over { background-color: green; } #workarea .yui-dd-drop-active-invalid { border: 2px solid red; }
.slot { border: 2px solid #808080; background-color: #CDCDCD; color: #666666; text-align: center; position: relative; float: left; margin: 4px; width: 60px; height: 60px; z-index: 0; } .player { border: 2px solid #808080; color: #ffffff; text-align: center; position: relative; float: left; margin: 4px; width: 60px; height: 60px; top: 150px; z-index: 1; cursor: move; } #pt1 { clear: both; } .bottom { top: 50px; } #pt1, #pt2 { background-color: #71241A; } #pb1, #pb2 { background-color: #004C6D; } #pboth1, #pboth2 { background-color: #FFA928; } #workarea { position: relative; height: 300px; width: 500px; } #workarea .yui-dd-drop-active-valid { border: 2px solid green; } #workarea .yui-dd-drop-over { background-color: green; } #workarea .yui-dd-drop-active-invalid { border: 2px solid red; }
Setting up the YUI Instance
Now we need to create our YUI instance and tell it to load the dd-drop
, dd-proxy
and dd-constrain
modules.
YUI().use('dd-drop', 'dd-proxy', 'dd-constrain');
YUI().use('dd-drop', 'dd-proxy', 'dd-constrain');
Setting up the Drop Targets
Now that we have a YUI instance with the requested modules, we are going to create our Drop Targets.
YUI().use('dd-drop', 'dd-proxy', 'dd-constrain', function(Y) { //Get all the nodes with the class of .slot under #workarea var slots = Y.Node.get('#workarea').queryAll('.slot'); //Loop through them Y.each(slots, function(v, k) { var id = v.get('id'), groups = ['two']; //Assign them to different groups switch (id) { case 't1': case 't2': groups = ['one']; break; } //Create the Drop object var drop = new Y.DD.Drop({ node: v, //With the new groups array as a config option groups: groups }); }); });
YUI().use('dd-drop', 'dd-proxy', 'dd-constrain', function(Y) { //Get all the nodes with the class of .slot under #workarea var slots = Y.Node.get('#workarea').queryAll('.slot'); //Loop through them Y.each(slots, function(v, k) { var id = v.get('id'), groups = ['two']; //Assign them to different groups switch (id) { case 't1': case 't2': groups = ['one']; break; } //Create the Drop object var drop = new Y.DD.Drop({ node: v, //With the new groups array as a config option groups: groups }); }); });
Setting up the Drag Nodes
Now we need to create the Drag Nodes and assign them to the proper group.
YUI().use('dd-drop', 'dd-proxy', 'dd-constrain', function(Y) { //Snipped var players = Y.Node.get('#workarea').queryAll('.player'); Y.each(players, function(v, k) { var id = v.get('id'), groups = ['one', 'two']; switch (id) { case 'pt1': case 'pt2': groups = ['one']; break; case 'pb1': case 'pb2': groups = ['two']; break; } var drag = new Y.DD.Drag({ node: v, //Assign the Groups groups: groups, //Use Intersect Mode for the Target Calculations dragMode: 'intersect', }).plug(Y.Plugin.DDProxy, { //We don't want the node to move on end drag moveOnEnd: false }).plug(Y.Plugin.DDConstrained, { //Keep me inside the workarea constrain2node: '#workarea' }); });
YUI().use('dd-drop', 'dd-proxy', 'dd-constrain', function(Y) { //Snipped var players = Y.Node.get('#workarea').queryAll('.player'); Y.each(players, function(v, k) { var id = v.get('id'), groups = ['one', 'two']; switch (id) { case 'pt1': case 'pt2': groups = ['one']; break; case 'pb1': case 'pb2': groups = ['two']; break; } var drag = new Y.DD.Drag({ node: v, //Assign the Groups groups: groups, //Use Intersect Mode for the Target Calculations dragMode: 'intersect', }).plug(Y.Plugin.DDProxy, { //We don't want the node to move on end drag moveOnEnd: false }).plug(Y.Plugin.DDConstrained, { //Keep me inside the workarea constrain2node: '#workarea' }); });
Handling the Drops and Moments
Now we are going to listen for Four Drag Events: drag:start, drag:end, drag:drophit, drag:dropmiss
drag.on('drag:start', function() { //In this event we setup some styles to make the nodes look pretty var p = this.get('dragNode'), n = this.get('node'); n.setStyle('opacity', .25); if (!this._playerStart) { this._playerStart = this.nodeXY; } //Put the Drag's HTML inside the proxy p.set('innerHTML', n.get('innerHTML')); //set some styles on the proxy p.setStyles({ backgroundColor: n.getStyle('backgroundColor'), color: n.getStyle('color'), opacity: .65 }); }); drag.on('drag:end', function() { //Undo some of the styles from the start var n = this.get('node'); n.setStyle('opacity', '1'); }); drag.on('drag:drophit', function(e) { //If we drop on a target, move to its position var xy = e.drop.get('node').getXY(); this.get('node').setXY(xy); }); drag.on('drag:dropmiss', function(e) { //If we miss a target, move back to our start position if (this._playerStart) { this.get('node').setXY(this._playerStart); this._playerStart = null; } });
drag.on('drag:start', function() { //In this event we setup some styles to make the nodes look pretty var p = this.get('dragNode'), n = this.get('node'); n.setStyle('opacity', .25); if (!this._playerStart) { this._playerStart = this.nodeXY; } //Put the Drag's HTML inside the proxy p.set('innerHTML', n.get('innerHTML')); //set some styles on the proxy p.setStyles({ backgroundColor: n.getStyle('backgroundColor'), color: n.getStyle('color'), opacity: .65 }); }); drag.on('drag:end', function() { //Undo some of the styles from the start var n = this.get('node'); n.setStyle('opacity', '1'); }); drag.on('drag:drophit', function(e) { //If we drop on a target, move to its position var xy = e.drop.get('node').getXY(); this.get('node').setXY(xy); }); drag.on('drag:dropmiss', function(e) { //If we miss a target, move back to our start position if (this._playerStart) { this.get('node').setXY(this._playerStart); this._playerStart = null; } });
Full Javascript Code
YUI({base:"../../build/", timeout: 10000}).use('dd-drop', 'dd-proxy', 'dd-constrain', function(Y) { var slots = Y.Node.get('#workarea').queryAll('.slot'); Y.each(slots, function(v, k) { var id = v.get('id'), groups = ['two']; switch (id) { case 't1': case 't2': groups = ['one']; break; } var drop = new Y.DD.Drop({ node: v, groups: groups }); }); var players = Y.Node.get('#workarea').queryAll('.player'); Y.each(players, function(v, k) { var id = v.get('id'), groups = ['one', 'two']; switch (id) { case 'pt1': case 'pt2': groups = ['one']; break; case 'pb1': case 'pb2': groups = ['two']; break; } var drag = new Y.DD.Drag({ node: v, groups: groups, dragMode: 'intersect' }).plug(Y.Plugin.DDProxy, { moveOnEnd: false }).plug(Y.Plugin.DDConstrained, { constrain2node: '#workarea' }); drag.on('drag:start', function() { var p = this.get('dragNode'), n = this.get('node'); n.setStyle('opacity', .25); if (!this._playerStart) { this._playerStart = this.nodeXY; } p.set('innerHTML', n.get('innerHTML')); p.setStyles({ backgroundColor: n.getStyle('backgroundColor'), color: n.getStyle('color'), opacity: .65 }); }); drag.on('drag:end', function() { var n = this.get('node'); n.setStyle('opacity', '1'); }); drag.on('drag:drophit', function(e) { var xy = e.drop.get('node').getXY(); this.get('node').setXY(xy); }); drag.on('drag:dropmiss', function(e) { if (this._playerStart) { this.get('node').setXY(this._playerStart); this._playerStart = null; } }); }); });
YUI({base:"../../build/", timeout: 10000}).use('dd-drop', 'dd-proxy', 'dd-constrain', function(Y) { var slots = Y.Node.get('#workarea').queryAll('.slot'); Y.each(slots, function(v, k) { var id = v.get('id'), groups = ['two']; switch (id) { case 't1': case 't2': groups = ['one']; break; } var drop = new Y.DD.Drop({ node: v, groups: groups }); }); var players = Y.Node.get('#workarea').queryAll('.player'); Y.each(players, function(v, k) { var id = v.get('id'), groups = ['one', 'two']; switch (id) { case 'pt1': case 'pt2': groups = ['one']; break; case 'pb1': case 'pb2': groups = ['two']; break; } var drag = new Y.DD.Drag({ node: v, groups: groups, dragMode: 'intersect' }).plug(Y.Plugin.DDProxy, { moveOnEnd: false }).plug(Y.Plugin.DDConstrained, { constrain2node: '#workarea' }); drag.on('drag:start', function() { var p = this.get('dragNode'), n = this.get('node'); n.setStyle('opacity', .25); if (!this._playerStart) { this._playerStart = this.nodeXY; } p.set('innerHTML', n.get('innerHTML')); p.setStyles({ backgroundColor: n.getStyle('backgroundColor'), color: n.getStyle('color'), opacity: .65 }); }); drag.on('drag:end', function() { var n = this.get('node'); n.setStyle('opacity', '1'); }); drag.on('drag:drophit', function(e) { var xy = e.drop.get('node').getXY(); this.get('node').setXY(xy); }); drag.on('drag:dropmiss', function(e) { if (this._playerStart) { this.get('node').setXY(this._playerStart); this._playerStart = null; } }); }); });