Instantly share code, notes, and snippets.

Embed
What would you like to do?
Draggable elements that have been styled to indicate draggability to users
<svg viewBox="0 0 32 32">
<rect height="4" width="4" y="4" x="0">
<rect height="4" width="4" y="12" x="0">
<rect height="4" width="4" y="20" x="0">
<rect height="4" width="4" y="28" x="0">
<rect height="4" width="4" y="4" x="8">
<rect height="4" width="4" y="12" x="8">
<rect height="4" width="4" y="20" x="8">
<rect height="4" width="4" y="28" x="8">
<rect height="4" width="4" y="4" x="16">
<rect height="4" width="4" y="12" x="16">
<rect height="4" width="4" y="20" x="16">
<rect height="4" width="4" y="28" x="16">
<rect height="4" width="4" y="4" x="24">
<rect height="4" width="4" y="12" x="24">
<rect height="4" width="4" y="20" x="24">
<rect height="4" width="4" y="28" x="24">
</svg>
/**
* Styles for the main 'things' we are dragging
*
* - Give the cursor a specific state when hovering over the draggable elements
* - Give the elements a solid background
* - Create a basic rectangular shape for the draggable elements with plenty of space
* - Set the z-index to 1 as a baseline
* - Use a slight box shadow around the edges of the draggable elements
* - A solid 1px border is a good alternative if box-shadow is not your cup of tea
*/
.thing {
/**
* Setting the cursor state to 'move' or 'grab' is key to indicating draggability
* for desktop users
*/
cursor: move;
/**
* If no background is given, the draggable elements are see-through and thus will not cover
* one another when stacked, or when one is dragged over the other.
*/
background: #fcfcfc;
height: 2em;
width: 300px;
max-width: 100%;
padding: 0.5em;
margin-bottom: 0.5em;
z-index: 1;
box-shadow: rgba( 0, 0, 0, 0.3 ) 0px 0px 1px 1px;
} /* .thing */
/**
* Elements inside of each draggable .thing (such as the label) need to have the same cursor
* property as the .thing's themselves
*/
.thing * {
cursor: move;
}
/**
* Make sure that an element actively being dragged has a higher z-index than
* the others. The class 'ui-draggable-dragging' is automatically added by jQuery UI.
*/
.thing.ui-draggable-dragging {
z-index: 100;
}
/**
* The text labels for the draggable elements
*
* We're mainly styling these to make them vertically centered, so we're using absolute positioning
* combined with the `margin: auto` rule to achive this
*/
.thing label {
height: 1em;
position: absolute;
left: 1em;
top: 0;
bottom: 0;
margin: auto;
}
/**
* The group of dots which indicate draggability for each 'thing'
*
* Here, we are just declaring the dimensions and positioning. The actual dots themselves are an SVG graphic
* which is generated via JavaScript in js/draggable.js
*/
.draggable-indicator {
width: 16px;
height: 16px;
position: absolute;
right: 0.5em;
top: 0;
bottom: 0;
margin: auto;
}
/* coloring the individual dots within each group */
.draggable-indicator rect {
fill: #ccc;
}
<!-- CSS Stylesheet -->
<link rel='stylesheet' type='text/css' href='css/draggable.css' />
<!-- The things we are dragging -->
<div class='thing'><label>Thing 1</label></div>
<div class='thing'><label>Thing 2</label></div>
<div class='thing'><label>Thing 3</label></div>
<!-- jQuery and jQuery-UI -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<!-- Our own JavaScripts -->
<script type='text/javascript' src='js/draggable.js'></script>
/**
* Draggable main routine
*
* - Make our things draggable
* - Append a draggable indicator to each draggable 'thing'
*/
$('.thing').draggable();
$('.thing').append( '<div class="draggable-indicator">' + getDraggableIndicator() + '</div>' );
/**
* Subroutines
*
* - getDraggableIndicator()
*/
/**
* Return the SVG element for the draggable indicator
*
* @param object args Arguments for the svg element
*
* int sideLength The length of one side of the outer square (default: 32)
* int dotWidth The height/width of a single dot (default: 4)
* int initialX The initial x value for the first dot (default: 4)
* int initialY The initial y value for the first dot (default: 4)
* int offset The distance between dots (default: 8)
*
* @return string
*/
function getDraggableIndicator( args ) {
args = args || {};
// get the default values
var sideLength = args.sideLength || 32,
dotWidth = args.dotWidth || 4,
offset = args.offset || 8,
// zero is a legit value for the initial X and Y values, so allow for this
initialX = ( undefined === args.initialX ) ? 4 : args.initialX,
initialY = ( undefined === args.initialY ) ? 4 : args.initialY;
// build the HTML element string
var svg = '<svg viewBox="0 0 ' + sideLength + ' ' + sideLength + '">';
// do a 4x4 loop and create the <rect /> elements
for ( var i = 0; i < 4; i++ ) {
for( var j = 0; j < 4; j++ ) {
svg += '<rect x="' + ( initialX + i*offset ) + '" ' +
'y="' + ( initialY + j*offset ) + '"' +
' width="' + dotWidth + '" height="' + dotWidth + '" ' +
' />';
}
}
svg += '</svg>';
return svg;
} // end: getDraggableIndicator()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment