Skip to content

Instantly share code, notes, and snippets.

@ValYouW
Created September 28, 2014 22:07
Show Gist options
  • Save ValYouW/911d50324585876fafbd to your computer and use it in GitHub Desktop.
Save ValYouW/911d50324585876fafbd to your computer and use it in GitHub Desktop.
A Pen by ValYouW.
<div id="pgWrapper">
<table id="pgTable" class="pgTable" cellspacing="0" cellpadding="5">
<tr class="pgGroupRow">
<td colspan="2">Group 1</td>
</tr>
<tr class="pgRow">
<td class="pgCell">Filter</td><td class="pgCell">On</td>
</tr>
<tr class="pgRow">
<td class="pgCell">Filter Size</td><td class="pgCell">200</td>
</tr>
</table>
<div>

Javascript Property Grid

Create a simple property grid to display and edit an object properties. Currently supports text/number/color/checkbox

A Pen by ValYouW on CodePen.

License.

var OTHER_GROUP_NAME = 'Other';
// This is our settings object
var setObj = {
accumulateTicks: true,
filter: false,
filterSize: 200,
buyColor: '#00ff00',
sellColor: '#ff0000',
noGroup: 'I have no group'
};
// This is our settings object metadata
var metaObj = {
filter: {group: 'Behavior', name: 'Filter', type: 'boolean'},
filterSize: {group: 'Behavior', name: 'Filter size', type: 'number', min: 0, max: 500, step: 10},
accumulateTicks: {group: 'Behavior', name: 'Accumulate ticks', type: 'boolean'},
buyColor: {group: 'Appearance', name: 'Buy color', type: 'color'},
sellColor: {group: 'Appearance', name: 'Sell color', type: 'color'}
};
/**
* Generates the property grid
* @param {object} obj - The object whose properties we want to display
* @param {object} meta - A metadata object describing the obj properties
*/
function generatePropertyGrid(obj, meta) {
meta = meta && typeof meta === 'object' ? meta : {};
var groupsCellsHTML = { Other: '' };
var groupsRowHTML = { };
var theTable = $('#pgTable');
var postInitFuncs = [];
var currGroup;
for (var prop in obj) {
// Check what is the group of the current property or use the default 'Other' group
currGroup = (meta[prop] && meta[prop].group) || OTHER_GROUP_NAME;
// If this is the first time we run into this group create the group row
if (currGroup !== OTHER_GROUP_NAME && !groupsRowHTML[currGroup]) {
groupsRowHTML[currGroup] = getGroupRowHtml(currGroup);
}
// Initialize the group cells html
groupsCellsHTML[currGroup] = groupsCellsHTML[currGroup] || '';
// Append the current cell html into the group html
groupsCellsHTML[currGroup] += getPropertyRowHtml(prop, obj[prop], meta[prop], postInitFuncs);
}
// Now we have all the html we need, just assemble it
var innerHTML = '';
for (var group in groupsRowHTML) {
// Add the group row
innerHTML += groupsRowHTML[group];
// Add the group cells
innerHTML += groupsCellsHTML[group];
}
// Finally we add the 'Other' group
innerHTML += getGroupRowHtml(OTHER_GROUP_NAME);
innerHTML += groupsCellsHTML[OTHER_GROUP_NAME];
// Set the innerHTML to the table
theTable.html(innerHTML);
// Call the post init functions
for (var i = 0; i < postInitFuncs.length; ++i) {
if (typeof postInitFuncs[i] === 'function') {
postInitFuncs[i]();
}
}
// just in case make sure we are not holding any reference to the functions
postInitFuncs = null;
}
/**
* Gets the html of a group header row
* @param {string} displayName - The group display name
*/
function getGroupRowHtml(displayName) {
return '<tr class="pgGroupRow"><td colspan="2">' + displayName + '</td></tr>';
}
/**
* Gets the html of a specific property row
* @param {string} name - The property name
* @param {*} value - The current property value
* @param {object} meta - A metadata object describing this property
* @param {function[]} [postCreateInitFuncs] - An array to fill with functions to run after the grid was created
*/
function getPropertyRowHtml(name, value, meta, postCreateInitFuncs) {
meta = meta || {};
// We use the name in the meta if available
var displayName = meta.name || name;
var type = meta.type || '';
var valueHTML;
switch(type) {
case 'number':
valueHTML = '<input type="text" id="' + name + '" value="' + value + '" style="width:50px" />';
postCreateInitFuncs && postCreateInitFuncs.push(initSpinner(name, meta.min, meta.max, meta.step));
break;
case 'boolean':
valueHTML = '<input type="checkbox" id="' + name + '" value="' + name + '" ' + (value ? 'checked' : '') + ' />';
break;
case 'color':
valueHTML = '<input type="text" id="' + name + '" />';
postCreateInitFuncs && postCreateInitFuncs.push(initColorPicker(name, value));
break;
default:
valueHTML = '<input type="text" id="' + name + '" value="' + value + '"</input>';
}
return '<tr class="pgRow"><td class="pgCell">' + displayName + '</td><td class="pgCell">' + valueHTML + '</td></tr>';
}
/**
* Gets an init function to a number textbox
* @param {string} id - The number textbox id
* @param {number} [min] - The min number allowed
* @param {number} [max] - The max number allowed
* @param {number} [step] - The increment step
* @returns {function}
*/
function initSpinner(id, min, max, step) {
if (!id) {return null;}
var options = {};
if (typeof min === 'number') {options.min = min;}
if (typeof max === 'number') {options.max = max;}
if (typeof step === 'number') {options.step = step;}
return function() {
$('#' + id).spinner(options);
};
}
/**
* Gets an init function to a color textbox
* @param {string} id - The color textbox id
* @param {string} color - The current selected color (e.g #000000)
* @returns {function}
*/
function initColorPicker(id, color) {
if (!id) {return null;}
var options = { preferredFormat: "hex", showInput: true, showInitial: true };
if (typeof color === 'string') {options.color = color;}
return function() {
$('#' + id).spectrum(options);
};
}
// Lets create the grid
generatePropertyGrid(setObj, metaObj);
body {
font-family: 'verdana';
font-size: 12px;
}
.pgTable {
border: solid 1px #95B8E7;
}
.pgGroupRow {
background-color: #E0ECFF;
font-weight: bold;
}
.pgRow{}
.pgCell {
border: dotted 1px #ccc
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment