block by harrystevens 8dc0b9b1676f8bf69399da9a497b94e4

Sort HTML Elements by Hue

Full Screen

This project sorts HTML elements (divs) by their hue.

Libraries used: d3.js, underscore.js, and jQuery

Based on this Stack Overflow discussion.

index.html

<html>
	<head>
		<link rel="stylesheet" href="styles.css" />
	</head>
	<body>

		How big do you want your grid?

		<span class="grid-size-option link" data-grid-size="3">3x3</span>
		<span class="grid-size-option link" data-grid-size="4">4x4</span>
		<span class="grid-size-option link" data-grid-size="5">5x5</span>
		<span class="grid-size-option link" data-grid-size="6">6x6</span>
		<span class="grid-size-option link" data-grid-size="7">7x7</span>
		<span class="grid-size-option link" data-grid-size="8">8x8</span>
		<span class="grid-size-option link" data-grid-size="9">9x9</span>
		<span class="grid-size-option link" data-grid-size="10">10x10</span>
		<span class="link sort">SORT!</span>

		<div class="grid"></div>

		<!-- js -->
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
		<script src="https://d3js.org/d3.v4.min.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
		<script src="scripts.js"></script>

	</body>
</html>

scripts.js

// Function draws a grid.
// x is the cell dimensions
function drawGrid(x) {

	// Empty the grid so we don't append to previously created elements
	$('.grid').empty();

	// Create the number of rows necessary
	for (var i = 0; i < x; i++) {
		$('.grid').append('<div class="grid-row">');
	}

	// Add the appropriate amount of cell wrappers to each row
	$('.grid-row').each(function() {
		$('.grid-row').append('<div class="grid-cell-wrapper">');
	});

	function resize(width) {
		// Set the sizes of the cell wrapper and the cell inside of it
		$('.grid-cell-wrapper').css('width', width);
		$('.grid-cell-wrapper').css('height', $('.grid-cell-wrapper').width());
		$('.grid-row').css('height', $('.grid-cell-wrapper').width());
		$('.grid-cell-wrapper').append('<div class="grid-cell">');
		$('.grid-cell').css('width', $('.grid-cell-wrapper').width() * .98);
		$('.grid-cell').css('height', $('.grid-cell-wrapper').width() * .98);
	}

	// responsive!
	resize($('.grid-row').width() / x);
	$(window).resize(function() {
		resize($('.grid-row').width() / x);
	});

	// Randomly assign colors to the background
	d3.selectAll('.grid-cell').style('background', function() {
		return 'hsl(' + Math.random() * 360 + ',100%,50%)';
	});

}

// Function to convert RGB colors to HSL, which can then be sorted by hue. See: https://stackoverflow.com/questions/11923659/javascript-sort-rgb-values
function rgbToHsl(c) {
	var r = c[0] / 255, g = c[1] / 255, b = c[2] / 255;
	var max = Math.max(r, g, b), min = Math.min(r, g, b);
	var h, s, l = (max + min) / 2;

	if (max == min) {
		h = s = 0;
		// achromatic
	} else {
		var d = max - min;
		s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
		switch(max) {
			case r:
				h = (g - b) / d + (g < b ? 6 : 0);
				break;
			case g:
				h = (b - r) / d + 2;
				break;
			case b:
				h = (r - g) / d + 4;
				break;
		}
		h /= 6;
	}
	return new Array(h * 360, s * 100, l * 100);
}

// This turns your color string from the RGB background-color value of the cells into an array of numbers,
// which can then be converted into HSL
function colorStringToNumbers(array) {
	var numberArray = [];

	for (var i = 0; i < array.length; i++) {
		numberArray.push(Number(array[i].trim()));
	}
	return numberArray;
}

// Create the object from the squares that lets us sort them
function createColorJSON(array) {
	var json = [];

	for (var i = 0; i < array.length; i++) {
		var obj = {};

		// The key value pairs are the index, the div selector, the div rgb color, the convert hsl color's hue
		obj.index = i;
		obj.selector = array[i];
		obj.color = $(obj.selector).find('.grid-cell').css('background-color');
		obj.hue = rgbToHsl(colorStringToNumbers(((obj.color.split('(')[1]).split(')')[0]).split(',')))[0];

		json.push(obj);
	}

	return json;

}

function sortSquares(json) {

	var sorted = _.sortBy(json,'hue');

	$('.grid-cell').each(function(i){
		$(this).css('background-color',sorted[i].color);
	});

}

$(document).ready(function() {

	// Start by drawing a grid of 5x5 dimensions
	drawGrid(3);

	// Then allow the user to select the size of the grid
	$('.grid-size-option').click(function() {
		var size = $(this).attr('data-grid-size');
		drawGrid(size);
	});

	// Let the user sort the squares
	$('.sort').click(function(){
		sortSquares(createColorJSON($('.grid-cell-wrapper')));
	});

});

styles.css

body {
	margin: 0 auto;
	display: table;
	font-family: "Helvetica Neue", sans-serif;
}

.link {
	color: #1a8cff;
	cursor: pointer;
	-webkit-user-select: none; /* Chrome all / Safari all */
	-moz-user-select: none; /* Firefox all */
	-ms-user-select: none; /* IE 10+ */
}
.link:hover {
	color: #0066cc;
	text-decoration: underline;
}

.grid {
	margin-top: 5px;
}
.grid-size-option {
	margin-right: 17px;
}
.grid-cell-wrapper {
	float: left;
}