blob: 8899116fbe4d896c7683e698b1772a0b43d443de [file] [log] [blame]
/**
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
*/
/**
* Class: mxStylesheetCodec
*
* Codec for <mxStylesheet>s. This class is created and registered
* dynamically at load time and used implicitely via <mxCodec>
* and the <mxCodecRegistry>.
*/
var mxStylesheetCodec = mxCodecRegistry.register(function()
{
var codec = new mxObjectCodec(new mxStylesheet());
/**
* Function: encode
*
* Encodes a stylesheet. See <decode> for a description of the
* format.
*/
codec.encode = function(enc, obj)
{
var node = enc.document.createElement(this.getName());
for (var i in obj.styles)
{
var style = obj.styles[i];
var styleNode = enc.document.createElement('add');
if (i != null)
{
styleNode.setAttribute('as', i);
for (var j in style)
{
var value = this.getStringValue(j, style[j]);
if (value != null)
{
var entry = enc.document.createElement('add');
entry.setAttribute('value', value);
entry.setAttribute('as', j);
styleNode.appendChild(entry);
}
}
if (styleNode.childNodes.length > 0)
{
node.appendChild(styleNode);
}
}
}
return node;
};
/**
* Function: getStringValue
*
* Returns the string for encoding the given value.
*/
codec.getStringValue = function(key, value)
{
var type = typeof(value);
if (type == 'function')
{
value = mxStyleRegistry.getName(style[j]);
}
else if (type == 'object')
{
value = null;
}
return value;
};
/**
* Function: decode
*
* Reads a sequence of the following child nodes
* and attributes:
*
* Child Nodes:
*
* add - Adds a new style.
*
* Attributes:
*
* as - Name of the style.
* extend - Name of the style to inherit from.
*
* Each node contains another sequence of add and remove nodes with the following
* attributes:
*
* as - Name of the style (see <mxConstants>).
* value - Value for the style.
*
* Instead of the value-attribute, one can put Javascript expressions into
* the node as follows if <mxStylesheetCodec.allowEval> is true:
* <add as="perimeter">mxPerimeter.RectanglePerimeter</add>
*
* A remove node will remove the entry with the name given in the as-attribute
* from the style.
*
* Example:
*
* (code)
* <mxStylesheet as="stylesheet">
* <add as="text">
* <add as="fontSize" value="12"/>
* </add>
* <add as="defaultVertex" extend="text">
* <add as="shape" value="rectangle"/>
* </add>
* </mxStylesheet>
* (end)
*/
codec.decode = function(dec, node, into)
{
var obj = into || new this.template.constructor();
var id = node.getAttribute('id');
if (id != null)
{
dec.objects[id] = obj;
}
node = node.firstChild;
while (node != null)
{
if (!this.processInclude(dec, node, obj) && node.nodeName == 'add')
{
var as = node.getAttribute('as');
if (as != null)
{
var extend = node.getAttribute('extend');
var style = (extend != null) ? mxUtils.clone(obj.styles[extend]) : null;
if (style == null)
{
if (extend != null)
{
mxLog.warn('mxStylesheetCodec.decode: stylesheet ' +
extend + ' not found to extend');
}
style = new Object();
}
var entry = node.firstChild;
while (entry != null)
{
if (entry.nodeType == mxConstants.NODETYPE_ELEMENT)
{
var key = entry.getAttribute('as');
if (entry.nodeName == 'add')
{
var text = mxUtils.getTextContent(entry);
var value = null;
if (text != null && text.length > 0 && mxStylesheetCodec.allowEval)
{
value = mxUtils.eval(text);
}
else
{
value = entry.getAttribute('value');
if (mxUtils.isNumeric(value))
{
value = parseFloat(value);
}
}
if (value != null)
{
style[key] = value;
}
}
else if (entry.nodeName == 'remove')
{
delete style[key];
}
}
entry = entry.nextSibling;
}
obj.putCellStyle(as, style);
}
}
node = node.nextSibling;
}
return obj;
};
// Returns the codec into the registry
return codec;
}());
/**
* Variable: allowEval
*
* Static global switch that specifies if the use of eval is allowed for
* evaluating text content. Default is true. Set this to false if stylesheets
* may contain user input.
*/
mxStylesheetCodec.allowEval = true;