This example builds on the Column Sort example. It makes use of the Y.Color module. It also shows how to filter the Model List of the DataTable to get a subset of the data.
Click on the column headers to sort the color swatches in different ways. Filter the data with the radio buttons on the right.
Note: be sure to add the yui3-skin-sam
classname to the
page's <body>
element or to a parent element of the widget in order to apply
the default CSS skin. See Understanding Skinning.
<body class="yui3-skin-sam"> <!-- You need this skin class -->
To add column sorting functionality to any DataTable, simply include the datatable-sort
module in your use()
line and add the sortable: true
configuration to the configuration objects of the columns you want to be sortable, as shown in the Column Sorting example.
Note, if you want all columns to be sortable, simply set sortable: true
on the DataTable instance.
YUI().use("datatable-sort", function(Y) { // code goes here });
This example also uses the color-harmony
module
YUI().use("datatable-sort", 'color-harmony', function(Y) { // code goes here });
Color Data
The color data for this example comes from http://www.w3.org/TR/css3-color/#svg-color. The data contains only the name of the color and its hex value.var myData = [ {name: 'antiquewhite', hex: 'faebd7'}, {name: 'aqua', hex: '00ffff'}, {name: 'aquamarine', hex: '7fffd4'}, // ... a lot more colors {name: 'whitesmoke', hex: 'f5f5f5'}, {name: 'yellow', hex: 'ffff00'}, {name: 'yellowgreen', hex: '9acd32'} ];
Generating a Color Number
Sorting and filtering can help users find the right color. Hex values don't help much in sorting the colors in a visually logical way. Later in the code, the following function will use the Y.Color module to generate a special color number for each hex value. This color number will be more useful in sorting and filtering.
/* This takes a hex value and generates a numeric string * in the format "01.23.45" * Each pair of digits represents the Hue, Saturation, or Brightness * of the color in a range of 00 to 99 (always 2 digits). * These strings sort in a more visually logical way for colors. * The sequence of digits can be changed to sort in different ways. * such as hh.ss.bb for sorting first by hue, then saturation, * or bb.hh.ss for sorting first by brightness, then hue, then saturation. * The dots are only for human readability */ function getColorNum(hex, sortType) { // An array of color property values // [hue, saturation, lightness] var HSL = Y.Color.toArray(Y.Color.toHSL(hex)), hNum, // hue sNum, // saturation // get the computed brightness from the hex value bNum = Y.Color.getBrightness(hex).toString(); // isolate hue part from HSL. converted to 2 digits hNum = Math.floor((HSL[0] * 10) / 36.01).toString(); hNum = (hNum.length < 2) ? ('0' + hNum) : hNum; // isolate sat part from HSL. converted to 2 digits sNum = Math.floor((HSL[1] * 10) / 10.01).toString(); sNum = (sNum.length < 2) ? ('0' + sNum) : sNum; // assure brightness is 2 digits bNum = (bNum.length < 2) ? ('0' + bNum) : bNum; bNum = (bNum === "100") ? "99" : bNum; if (sortType === "hbs") { return hNum + '.' + bNum + '.' + sNum; // hue.bright.sat } else if (sortType === "bhs") { return bNum + '.' + hNum + '.' + sNum; // bright.hue.sat } }
The DataTable Instance
The DataTable instance will include:- Column configs that add new columns
- A recordType that will populate the DataTable's ModelList so that some of the additional columns can be sortable
- Data
- An initial sorting config
myTable = new Y.DataTable({ columns: [ // code goes here ], recordType: { // code goes here }, data: myData, sortBy: { hbs: 'desc' } }).render("#cTable");
We'll now add the details to the DataTable instance.
Formatter - Adding Columns
The provided data from var = myData
only has two properties per row to use as columns, but we are adding more columns in the columns
config. A Swatch column allows users to see the colors. We used a formatter to set the content to be a <div>
with the background color accessed from the hex value of each row. Since there's no swatch property in myData
, this column cannot be made sortable.
We're also adding 2 columns that will allow sorting by Hue and Brightness priorities respectively. The DataTables ModelList (where myData is stored) doesn't contain any data for these columns yet. That will be added by the recordType
. See next snippet.
myTable = new Y.DataTable({ columns: [ { key: "swatch", label: 'Swatch', // Use formatter to add a div swatch in each cell // Color the background-color from hex value in each row formatter: function(o) { return '<div class="swatch" style="' + 'background-color: #' + o.data.hex + ';' + '"></div>'; }, sortable: false, allowHTML: true }, { key: "name", label: 'Color Name', sortable: true }, { key: "hex", label: 'Hex', sortable: true }, { key: "hbs", label: 'Hue', // hue.bright.sat sortable: true }, { key: "bhs", label: 'Bright', // bright.hue.sat sortable: true } ], recordType: { // see the next code snippet below }, data: myData, sortBy: { hbs: 'desc' } }).render("#cTable");
RecordType - Sortable Generated Columns
As described in the Sortable Generated Columns example, we're using a getter
to return a color number string from the getColorNum
function shown above. This puts these values in the DataTable's ModelList so they'll be filterable and the columns can be sortable.
myTable = new Y.DataTable({ columns: [ // see the previous code snippet above ], recordType: { swatch: {}, name: {}, hex: {}, hbs: { getter: function() { // create a new attribute in the model // and generate a sortable color number // from the hex value for each Model return getColorNum(this.get('hex'), 'hbs'); } }, bhs: { getter: function() { // do the same for bright.hue.sat return getColorNum(this.get('hex'), 'bhs'); } } }, data: myData, sortBy: { hbs: 'desc' } // initial sorting }).render("#cTable");
Filtering
The filterModel
function filters the original data of the DataTable to get a subset. See the example Filtering the Model List for a simpler example of filtering.
// This filters the DataModel to have a subset of it's original // data function filterModel(filterType) { // reset model list to include all colors to prepare for filter myTable.set('data', myData); var list = myTable.data, filteredData = list.filter({asList: true}, function (list) { var hbsStr = list.get('hbs'), // get the hue emphasized color number bright = hbsStr.substring(3, 5), // only the 2 brightness digits sat = hbsStr.substring(6, 8), // only the 2 saturation digits type; // clicked filter type // Depending on which filter radio was clicked, // filter the DataTable's modelList to include a // subset of models/rows/colors if (filterType === 'filter-all') { // Don't show black, white, or grays type = sat >= 1; } else if (filterType === 'filter-tint') { // Bright colors that are not gray or white type = (bright >= 75) && (sat >= 1); } else if (filterType === 'filter-shade') { // Darker colors that are not grayish type = (bright <= 50) && (sat >= 20); } else if (filterType === 'filter-midtone') { // Middle brightness colors that are not grayish type = (bright >= 50) && (bright <= 75) && (sat >= 20); } else if (filterType === 'filter-mute') { // Low saturation (grayish) but not pure grays type = (sat <= 55) && (sat >= 1); } else if (filterType === 'filter-gray') { // Only colors that are completely gray type = sat === '00'; } return type; }); myTable.set('data', filteredData); }
The filterModel
function is used in these ways.
// initial filtering of the dataTable's modelList to muted colors filterModel('filter-mute'); // listen for filter change Y.all('.filters').on('click', function(e) { filterModel(e.target.get('id')); });
Full Code Listing
The CSS
.example { zoom: 1; } .example:after { content: ""; display: block; clear: both; } .left-column { overflow: hidden; float: left; } .right-column { margin-left: 390px; } /* Swatch styling */ .yui3-skin-sam td.yui3-datatable-cell { /* override vertical cell padding so swatches fill cells */ padding: 0 0.5em; } .yui3-skin-sam td.yui3-datatable-col-swatch { padding: 0; } .swatch { height: 1.4em; } #cTable .yui3-datatable-cell { font-size: 70%; } #cTable .view-small .yui3-datatable-cell { font-size: 25%; } /* layout styles */ #small-swatch-checkbox { margin-top: 4em; } .filter-radios label { display: block; } .example .content { padding: 0 5px; } /* Styles for UI sample swatches in filtering radios */ .filter-radios label span { background: url(../assets/datatable/img/swatch_colors.png) no-repeat; display: inline-block; vertical-align: middle; height: 30px; width: 80px; margin: 0.3em; } .filter-radios .examples-all { background-position: 0px 0px; } .filter-radios .examples-tint { background-position: 0px -30px; } .filter-radios .examples-midtone { background-position: 0px -60px; } .filter-radios .examples-shade { background-position: 0px -90px; } .filter-radios .examples-mute { background-position: 0px -120px; } .filter-radios .examples-gray { background-position: 0px -150px; }
The HTML
<div class="left-column"> <div id="cTable"></div> </div> <div class="right-column"> <div class="filter-radios"> <!-- Radios for filtering colors --> <label for="filter-all"> <input id="filter-all" class="filters" type="radio" name="filters"/> <span class="examples-all"></span>All Colors </label> <label for="filter-tint"> <input id="filter-tint" class="filters" type="radio" name="filters"/> <span class="examples-tint"></span>Tints </label> <label for="filter-midtone"> <input id="filter-midtone" class="filters" type="radio" name="filters"/> <span class="examples-midtone"></span>Mid-tones </label> <label for="filter-shade"> <input id="filter-shade" class="filters" type="radio" name="filters"/> <span class="examples-shade"></span>Shades </label> <label for="filter-mute"> <input id="filter-mute" class="filters" type="radio" checked name="filters"/> <span class="examples-mute"></span>Muted </label> <label for="filter-gray"> <input id="filter-gray" class="filters" type="radio" name="filters"/> <span class="examples-gray"></span>Black, white, and grays </label> </div> <!-- Small swatches checkbox --> <label for="small-swatch-checkbox"> <input id="small-swatch-checkbox" type="checkbox"/> Small swatches (fit more on the page) </label> </div>
The JavaScript
YUI().use('datatable-sort', 'color-harmony', function (Y) { // The source of this data is http://www.w3.org/TR/css3-color/ var filterBy, myData = [ {name: 'antiquewhite', hex: 'faebd7'}, {name: 'aqua', hex: '00ffff'}, {name: 'aquamarine', hex: '7fffd4'}, {name: 'beige', hex: 'f5f5dc'}, {name: 'bisque', hex: 'ffe4c4'}, {name: 'black', hex: '000000'}, {name: 'blanchedalmond', hex: 'ffebcd'}, {name: 'blue', hex: '0000ff'}, {name: 'blueviolet', hex: '8a2be2'}, {name: 'brown', hex: 'a52a2a'}, {name: 'burlywood', hex: 'deb887'}, {name: 'cadetblue', hex: '5f9ea0'}, {name: 'chartreuse', hex: '7fff00'}, {name: 'chocolate', hex: 'd2691e'}, {name: 'coral', hex: 'ff7f50'}, {name: 'cornflowerblue', hex: '6495ed'}, {name: 'cornsilk', hex: 'fff8dc'}, {name: 'crimson', hex: 'dc143c'}, {name: 'cyan', hex: '00ffff'}, {name: 'darkblue', hex: '00008b'}, {name: 'darkcyan', hex: '008b8b'}, {name: 'darkgoldenrod', hex: 'b8860b'}, {name: 'darkgray', hex: 'a9a9a9'}, {name: 'darkgreen', hex: '006400'}, {name: 'darkkhaki', hex: 'bdb76b'}, {name: 'darkmagenta', hex: '8b008b'}, {name: 'darkolivegreen', hex: '556b2f'}, {name: 'darkorange', hex: 'ff8c00'}, {name: 'darkorchid', hex: '9932cc'}, {name: 'darkred', hex: '8b0000'}, {name: 'darksalmon', hex: 'e9967a'}, {name: 'darkseagreen', hex: '8fbc8f'}, {name: 'darkslateblue', hex: '483d8b'}, {name: 'darkslategray', hex: '2f4f4f'}, {name: 'darkturquoise', hex: '00ced1'}, {name: 'darkviolet', hex: '9400d3'}, {name: 'deeppink', hex: 'ff1493'}, {name: 'deepskyblue', hex: '00bfff'}, {name: 'dimgray', hex: '696969'}, {name: 'dodgerblue', hex: '1e90ff'}, {name: 'firebrick', hex: 'b22222'}, {name: 'forestgreen', hex: '228b22'}, {name: 'fuchsia', hex: 'ff00ff'}, {name: 'gainsboro', hex: 'dcdcdc'}, {name: 'gold', hex: 'ffd700'}, {name: 'goldenrod', hex: 'daa520'}, {name: 'gray', hex: '808080'}, {name: 'green', hex: '008000'}, {name: 'greenyellow', hex: 'adff2f'}, {name: 'hotpink', hex: 'ff69b4'}, {name: 'indianred', hex: 'cd5c5c'}, {name: 'indigo', hex: '4b0082'}, {name: 'khaki', hex: 'f0e68c'}, {name: 'lawngreen', hex: '7cfc00'}, {name: 'lemonchiffon', hex: 'fffacd'}, {name: 'lightblue', hex: 'add8e6'}, {name: 'lightcoral', hex: 'f08080'}, {name: 'lightgoldenrodyellow', hex: 'fafad2'}, {name: 'lightgray', hex: 'd3d3d3'}, {name: 'lightgreen', hex: '90ee90'}, {name: 'lightpink', hex: 'ffb6c1'}, {name: 'lightsalmon', hex: 'ffa07a'}, {name: 'lightseagreen', hex: '20b2aa'}, {name: 'lightskyblue', hex: '87cefa'}, {name: 'lightslategray', hex: '778899'}, {name: 'lightsteelblue', hex: 'b0c4de'}, {name: 'lime', hex: '00ff00'}, {name: 'limegreen', hex: '32cd32'}, {name: 'maroon', hex: '800000'}, {name: 'mediumaquamarine', hex: '66cdaa'}, {name: 'mediumblue', hex: '0000cd'}, {name: 'mediumorchid', hex: 'ba55d3'}, {name: 'mediumpurple', hex: '9370db'}, {name: 'mediumseagreen', hex: '3cb371'}, {name: 'mediumslateblue', hex: '7b68ee'}, {name: 'mediumspringgreen', hex: '00fa9a'}, {name: 'mediumturquoise', hex: '48d1cc'}, {name: 'mediumvioletred', hex: 'c71585'}, {name: 'midnightblue', hex: '191970'}, {name: 'moccasin', hex: 'ffe4b5'}, {name: 'navajowhite', hex: 'ffdead'}, {name: 'navy', hex: '000080'}, {name: 'oldlace', hex: 'fdf5e6'}, {name: 'olive', hex: '808000'}, {name: 'olivedrab', hex: '6b8e23'}, {name: 'orange', hex: 'ffa500'}, {name: 'orangered', hex: 'ff4500'}, {name: 'orchid', hex: 'da70d6'}, {name: 'palegoldenrod', hex: 'eee8aa'}, {name: 'palegreen', hex: '98fb98'}, {name: 'paleturquoise', hex: 'afeeee'}, {name: 'palevioletred', hex: 'db7093'}, {name: 'papayawhip', hex: 'ffefd5'}, {name: 'peachpuff', hex: 'ffdab9'}, {name: 'peru', hex: 'cd853f'}, {name: 'pink', hex: 'ffc0cb'}, {name: 'plum', hex: 'dda0dd'}, {name: 'powderblue', hex: 'b0e0e6'}, {name: 'purple', hex: '800080'}, {name: 'red', hex: 'ff0000'}, {name: 'rosybrown', hex: 'bc8f8f'}, {name: 'royalblue', hex: '4169e1'}, {name: 'saddlebrown', hex: '8b4513'}, {name: 'salmon', hex: 'fa8072'}, {name: 'sandybrown', hex: 'f4a460'}, {name: 'seagreen', hex: '2e8b57'}, {name: 'sienna', hex: 'a0522d'}, {name: 'silver', hex: 'c0c0c0'}, {name: 'skyblue', hex: '87ceeb'}, {name: 'slateblue', hex: '6a5acd'}, {name: 'slategray', hex: '708090'}, {name: 'springgreen', hex: '00ff7f'}, {name: 'steelblue', hex: '4682b4'}, {name: 'tan', hex: 'd2b48c'}, {name: 'teal', hex: '008080'}, {name: 'thistle', hex: 'd8bfd8'}, {name: 'tomato', hex: 'ff6347'}, {name: 'turquoise', hex: '40e0d0'}, {name: 'violet', hex: 'ee82ee'}, {name: 'wheat', hex: 'f5deb3'}, {name: 'white', hex: 'ffffff'}, {name: 'whitesmoke', hex: 'f5f5f5'}, {name: 'yellow', hex: 'ffff00'}, {name: 'yellowgreen', hex: '9acd32'} ]; /* This takes a hex value and generates a numeric string * in the format "01.23.45" * Each pair of digits represents the Hue, Saturation, or Brightness * of the color in a range of 00 to 99 (always 2 digits). * These strings sort in a more visually logical way for colors. * The sequence of digits can be changed to sort in different ways. * such as hh.ss.bb for sorting first by hue, then saturation, * or bb.hh.ss for sorting first by brightness, then hue, then saturation. * The dots are only for human readability */ function getColorNum(hex, sortType) { // An array of color property values // [hue, saturation, lightness] var HSL = Y.Color.toArray(Y.Color.toHSL(hex)), hNum, // hue sNum, // saturation // get the computed brightness from the hex value bNum = Y.Color.getBrightness(hex).toString(); // isolate hue part from HSL. converted to 2 digits hNum = Math.floor((HSL[0] * 10) / 36.01).toString(); hNum = (hNum.length < 2) ? ('0' + hNum) : hNum; // isolate sat part from HSL. converted to 2 digits sNum = Math.floor((HSL[1] * 10) / 10.01).toString(); sNum = (sNum.length < 2) ? ('0' + sNum) : sNum; // assure brightness is 2 digits bNum = (bNum.length < 2) ? ('0' + bNum) : bNum; bNum = (bNum === "100") ? "99" : bNum; if (sortType === "hbs") { return hNum + '.' + bNum + '.' + sNum; // hue.bright.sat } else if (sortType === "bhs") { return bNum + '.' + hNum + '.' + sNum; // bright.hue.sat } } myTable = new Y.DataTable({ columns: [ { key: "swatch", label: 'Swatch', // Use formatter to add a div swatch in each cell // Color the background-color from hex value in each row formatter: function(o) { return '<div class="swatch" style="' + 'background-color: #' + Y.Escape.html(o.data.hex) + ';' + '"></div>'; }, sortable: false, allowHTML: true }, { key: "name", label: 'Color Name', sortable: true }, { key: "hex", label: 'Hex', sortable: true }, { key: "hbs", label: 'Hue', // hue.bright.sat sortable: true }, { key: "bhs", label: 'Bright', // bright.hue.sat sortable: true } ], recordType: { swatch: {}, name: {}, hex: {}, hbs: { getter: function() { // create a new attribute in the model // and generate a sortable color number // from the hex value for // hue.bright.sat return getColorNum(this.get('hex'), 'hbs'); } }, bhs: { getter: function() { // do the same for bright.hue.sat return getColorNum(this.get('hex'), 'bhs'); } } }, data: myData, sortBy: { hbs: 'desc' } // initial sorting }).render("#cTable"); // listener for swatch size Y.one('#small-swatch-checkbox').on('click', function(e) { var datatable = Y.one('#cTable .yui3-datatable'); if (e.target.get('checked')) { datatable.addClass('view-small'); } else { datatable.removeClass('view-small'); } }); // This filters the DataModel to have a subset of it's original // data function filterModel(filterType) { // reset model list to include all colors to prepare for filter myTable.set('data', myData); var list = myTable.data, filteredData = list.filter({asList: true}, function (list) { var hbsStr = list.get('hbs'), // get the hue emphasized color number bright = hbsStr.substring(3, 5), // only the 2 brightness digits sat = hbsStr.substring(6, 8), // only the 2 saturation digits type; // clicked filter type // Depending on which filter radio was clicked, // filter the DataTable's modelList to include a // subset of models/rows/colors if (filterType === 'filter-all') { // Don't show black, white, or grays type = sat >= 1; } else if (filterType === 'filter-tint') { // Bright colors that are not gray or white type = (bright >= 75) && (sat >= 1); } else if (filterType === 'filter-shade') { // Darker colors that are not grayish type = (bright <= 50) && (sat >= 20); } else if (filterType === 'filter-midtone') { // Middle brightness colors that are not grayish type = (bright >= 50) && (bright <= 75) && (sat >= 20); } else if (filterType === 'filter-mute') { // Low saturation (grayish) but not pure grays type = (sat <= 55) && (sat >= 1); } else if (filterType === 'filter-gray') { // Only colors that are completely gray type = sat === '00'; } return type; }); myTable.set('data', filteredData); } // initial filtering of the dataTable's modelList to muted colors filterModel('filter-mute'); // listen for filter change Y.all('.filters').on('click', function(e) { filterModel(e.target.get('id')); }); });