Skip to content

Instantly share code, notes, and snippets.

@mhull mhull/Draggable.html
Last active Oct 13, 2017

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
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.