This is a javascript function giving a new way to customize a javascript widget by using CSS class. Web editor and widget developper take advantage, because it is easy to use for the web editor and it is easy to cast the option/parameter for the widget developper.
The front end (web editor)
This give to a web editor with a basic knowledge of HTML and CSS the ability to customize a widget quickly. How to use the “class” attribute are the specific knowledge required for the web editor. In the HTML5 specification (3.2.3.9 Embedding[…]) include a way to for doing the same thing.
To use it, check what is the default namespace required by the widget and read the parameter specification of the widget for more detail about the options can be set. Any undesired options for a widget will be discarded, it the same if the type are not good, eg. The widget want a integer and a string are provided, this option wont be use by the widget (fall back to the default).
CSS Option Class vs HTML5 data-* attribute
Not done yet, but that will implemented and the HTML5 data will overwrite any CSS Option Class. It’s possible after this will be done, this project get a new name.
Javascript web developper
This make an awsome tool only because that give a safe way to control the input from the user and prevet any undesired error and simplify the data casting. Imagine, you define an Json option structure for a given element and after a simple call you get the all the desired option customized by the web editor.
Witch option have priority ?
- Default options set inside the widgets
- Overwritten options (in javascript) when the widget is called
- Overwritten options with CSS,
- Overwritten option on HTML5 data attribute set [Not developped available yet]
How to use it ?
- Build you Json configuration object as usual with an addition of specific instruction
- Call the read of custom configuration for your element and specify with Json configuration object to use.
- Get return a new Json object with the customization
For an example, we want to let the user to set a width for a widget x.
As traditional we have the following Json configuration object
var o = {
width: 100
}
Now we need to define a namespace for the Json configuration object. That will force the web editor to prefix all option by the specified namespace with a dash between the namespace and the option. The beginning of the CSS option will be “widget-x-width”. That will give us the following
var o = {
'default-namespace': 'widget-x',
width: 100
}
Now let set the casting. In our case that will be “number”. FYI, serveral type of casting is available documented bellow.
var o = {
'default-namespace': 'widget-x',
'width-typeof': 'number',
width: 100
}
Horay ! now the web editor all be able to set the width value at 150 with the following css “widget-x-width-150” but if he try anything else like “widget-x-width-abc” that will be discarded/ignored.
Now we will let the web editor to autocreate the property as he need.
var o = {
'default-namespace': 'widget-x',
'width-typeof': 'number',
'width-autocreate': true
}
Currently the behaviour is if the web editor set “widget-x-width-150 widget-x-width-200” only the last value will be good (200). Now we will allow the web editor to set an array of casted value. This can be useful in some case.
var o = {
'default-namespace': 'widget-x',
'width-typeof': 'number',
'width-autocreate': true,
'width-overwrite-array-mode": true
}
That will result for the same input “widget-x-width-150 widget-x-width-200” to an array [150, 200]. If you already set a default value, that wont be overwritted, the new value will be added to the array.
What’s about for sub object ? That is supported. take as in input parameter the following “widget-x-ele1-width-150” and the following Json configuration object
var o = {
'default-namespace': 'widget-x',
'ele1-typeof': 'string',
'ele1-autocreate': true
}
That will return the following new configuration
var o = {
'default-namespace': 'widget-x',
'ele1-typeof': 'string',
'ele1-autocreate': true,
ele1: width-150
}
With the following Json configuration object
var o = {
'default-namespace': 'widget-x',
'ele1': {
'width-autocreate': true,
'width-typeof': 'number'
}
}
will give
var o = {
'default-namespace': 'widget-x',
'ele1': {
'width-autocreate': true,
'width-typeof': 'number',
'width': 150
}
}
Available typeof
- string (default)
- boolean (‘0’ <=> false AND ‘1’ <=> true)
- number
- locked (this said that property can not be changed)
Namespace separator
Ah yeah, I foget to say you can customize the namespace separator. That separator is between the namespace and the property. At the same level of your namespace declaration you need to add a parameter “default-namespace-separator” with a string value representing the separator. The default are the dash “-“.
Options separator
Also you can customize the separator between each parameter. At the same level of your namespace declaration, add a parameter “default-separator” with a string value. The default are the space ” “.
Auto creation
It possible to set auto creation for all parameter. By default this feature are turned off for security reason but you can that on by adding a parameter “default-autocreate” at the same level of your namespace declaration with any [type of] value
Here the source code of that famous function. Please note this is an extract from the open source project Chart and Graph plugin. 😉
/**
* Function to get CSS Option Class
*
* @param:sourceOption // Required: your Json configuration object
* @param: strClass // Required: This is a string, normally representing an extract of the class attribute for a given element
* @param: namespace // Optional: Just another way to specify the namespace to use
**/
function setClassOptions(sourceOptions, strClass, namespace){
// Test: optSource
if(typeof(sourceOptions) != "object"){
console.log("Empty source");
return {};
}
// Get a working copy for the sourceOptions
sourceOptions = jQuery.extend(true, {}, sourceOptions);
/*
// Check if some option need to be removed
function unsetOption(opt, currLevel, maxLevel){
if(currLevel > maxLevel || !$.isArray(opt)){
return;
}
var arrToRemove = [];
for(key in opt){
// if the key are ending "-remove", get the key to remove
if(key.lenght > 7 && key.substr(key.lenght - 7) == "-remove"){
arrToRemove.push(key.substr(0, key.lenght - 7));
} else {
// get it deeper if applicable
if(typeof(opt[key])) == "object"){
currLevel ++;
if(currLevel < maxLevel){
unsetOption(opt[key], currLevel, maxLevel);
}
}
}
}
for(i=0;i
// This is a valid parameter, start the convertion to a JSON object
// Get all defined parameter
var arrParameter = this.split(separatorNS).slice(arrNamespace.length);
// That variable is use for synchronization
var currObj = sourceOptions;
// Set the default property name (this can be overwrited later)
var propName = arrNamespace[arrNamespace.length - 1];
for(i=0; i