Visualization - Number - Number

From Q
Jump to navigation Jump to search
VizIcon Number.svg

The Number Options in Displayr allow you to visually represent a single number as an HTML widget. The Number visualization simply represents a number in text form.

Example

The following visualization is based on the number in a combo box. The visualization will automatically update when the value in the combo box is altered.

Create a number visualization in Displayr

1. Go to Insert > Visualization > Number > Number
2. Under Inputs > DATA SOURCE > Data Source, select the type of your data source
3. Under Inputs > DATA SOURCE > Input data, type in your number or specify the location of the number.

Object Inspector Options

For more details, see Visualization - Number Options

Code

// VERSION 2.4.0
var displayr = Q.isOnTheWeb();
function isEmpty(x) { return (x == undefined || x.getValue() == null && (x.getValues() == null || x.getValues().length == 0)) }
function isEmptyString(x) { return (x == undefined || x == null || x == "") }
var allow_control_groups = Q.fileFormatVersion() > 10.9;
var font_list = !!Q.GetAvailableFontNames ? Q.GetAvailableFontNames() : ["Arial", "Arial Black", "Century Gothic", "Comic Sans MS", "Courier New", "Georgia", "Impact", "Open Sans", "Tahoma", "Times New Roman", "Trebuchet MS", "Verdana"];
var default_font_color = "#2C2C2C";

var controls = [];
if (allow_control_groups);
    form.group("OUTPUT");
var template_prompt = "Create a template to control settings for all visualizations in the document by inserting 'Visualization > Template'";
var qDisplayOpt = form.comboBox({name: "formDisplay", label: "Display", visible: displayr ? false : true, alternatives: ["Number", "Number in an oval", "Number in a rectangle", "Number in a donut", "Number on a gauge", "Number on a bar", "Number on an icon", "Pictograph (single icon)", "Pictograph (repeated icons)"], default_value: "Number"});
controls.push(qDisplayOpt);
var displayOpt = qDisplayOpt.getValue();
var show_icons = ["Number on an icon", "Pictograph (single icon)", "Pictograph (repeated icons)"].indexOf(displayOpt) != -1;
var show_shapes = !show_icons && displayOpt != "Number";
var min_vpad = show_icons ? 0 : -1000;

var inputpromptextra = "";
if (displayOpt == "Pictograph (single icon)" || displayOpt == "Number in a donut" || displayOpt == "Number on a bar")
{
    controls.push(form.textBox({name: "formDenominator", label: "Maximum value", required: true, default_value: "100", prompt: "Denominator which the input value will be shown as a proportion of"}));
    inputpromptextra = " Increase maximum value for values greater than 100%.";
}
if (["Number on a gauge", "Number on a bar", "Pictograph (single icon)"].indexOf(displayOpt) != -1)
{
    controls.push(form.textBox({name: "formMinimumValue", label: "Minimum value", required: true, default_value: 0, prompt: "Lower bound of the gauge"}));
}
if (displayOpt == "Number on a gauge")
{
    controls.push(form.textBox({name: "formDenominator", label: "Maximum value", required: true, default_value: "100%", prompt: "Upper bound of the gauge"}));
    inputpromptextra = " Increase maximum value for values greater than 100%.";
}

if (displayOpt == "Pictograph (repeated icons)")
{
    controls.push(form.textBox({label: "Total icons", name:"formTotalIcons", type:"number", required:false, prompt:"Leave blank to determine from Input data"}));
    controls.push(form.textBox({label: "Scale", name:"formScale", default_value: "1", prompt: "The value that one icon represents"}));
}
form.setHeading("Visualization - " + displayOpt);


if (allow_control_groups);
    form.group("DATA SOURCE");
var qDatOpt = form.comboBox({name: "formDataSource", label: "Data source", alternatives: ["Type or paste value", "Use an existing R output", "Table", "Variable - Average", "Variable - Sum", "Variable - Percentage"], default_value: "Table"});
controls.push(qDatOpt);
var datOpt = qDatOpt.getValue();

var showPercent = false;
if (datOpt == "Type or paste value")
{ 
     controls.push(form.textBox({name: "formInputText", label: "Input data", prompt: "Enter a numeric value, e.g. 45% or 0.45." + inputpromptextra, required: true})) // for shapes, this can be text
} else if (datOpt == "Use an existing R output" || datOpt == "Table")
{
    if (datOpt == "Use an existing R output")
    {
        var inputR = form.dropBox({name: "formInputR", label: "Input data", types: ["RItem:integer,numeric,character"], required: true});
        controls.push(inputR);
    }
    else
    {
        var inputTable = form.dropBox({name: "formInputTable", label: "Input data", types: ["Table", "RItem:matrix,array,data.frame,table,integer,numeric,character"]});
        controls.push(inputTable);
    }

    if ((datOpt == "Use an existing R output" && inputR.getValue() != null) ||
        (datOpt == "Table" && inputTable.getValue() != null))
    {
        var rowOpts = ["Typing row names or indices", "Choosing from Combo Box or List Box control"]
        var columnOpts = ["Typing column names or indices", "Choosing from Combo Box or List Box control"]
        
        var qSelectRowsOpt;
        if (displayr)
        {
            qSelectRowsOpt = form.comboBox({label: "Select rows to show by", name: "formSelectRowsOpt", alternatives: rowOpts, default_value: rowOpts[0]});
            controls.push(qSelectRowsOpt);
        }

        var qSelectRowsCtrl = form.dropBox({label: "Row", name: "formTableRowCtrl", types: ["Control: listbox,combobox"], required: datOpt == "Table"});
        var qSelectRowsText = form.textBox({name: "formTableRow", label: "Row", prompt: "Enter name or index of row of the entry you want to display", required: datOpt == "Table", default_value: 1});


        if (!!qSelectRowsOpt && qSelectRowsOpt.getValue() != rowOpts[0])
            controls.push(qSelectRowsCtrl);
        else
            controls.push(qSelectRowsText);

        var qSelectColumnsOpt;
        if (displayr)
        {
            qSelectColumnsOpt = form.comboBox({label: "Select columns to show by", name: "formSelectColumnsOpt", alternatives: columnOpts, default_value: columnOpts[0]});
            controls.push(qSelectColumnsOpt);
        }

        var qSelectColumnsCtrl = form.dropBox({label: "Column", name: "formTableColumnCtrl", types: ["Control: listbox,combobox"], required: false});
        var qSelectColumnsText = form.textBox({name: "formTableColumn", label: "Column", prompt: "Enter name or index of column of the entry you want to display.", required: false, default_value: 1});

        if (!!qSelectColumnsOpt && qSelectColumnsOpt.getValue() != columnOpts[0])
           controls.push(qSelectColumnsCtrl); 
        else
            controls.push(qSelectColumnsText);
    }

} else if (datOpt == "Variable - Percentage")
{
	showPercent = true;
    var percentVar = form.dropBox({name: "formInputVariable", label: "Input data", types: ["Variable: Numeric, Date/Time, Money, Text, Categorical, OrderedCategorical"]});
    controls.push(percentVar);
    if (percentVar.getValue() != null)
        controls.push(form.textBox({name: "formCategory", label: "Category", required: false, prompt: "Enter name of category you want to display. For categorical variables, names can be separated by commas to show the total percentage; for numeric variables, use a dash to specify a range."}));

} else
    controls.push(form.dropBox({name: "formInputVariable", label: "Input data", types: ["Variable: Numeric, Date/Time, Money, Text, Categorical, OrderedCategorical"]}));


if (allow_control_groups)
    form.page("Format")
var qTemplate = form.dropBox({name: "formTemplate", label: "Use template", types: ["RItem:AppearanceTemplate"], required: false, prompt: template_prompt});
controls.push(qTemplate);
var use_default_fonts = !isEmpty(qTemplate); 

if (show_shapes)
{
    if (allow_control_groups)
        form.group("Shape");
    controls.push(form.numericUpDown({name: "formFillOpacity", label: "Fill opacity", minimum: 0.0, maximum: 1.0, increment: 0.1, default_value: 1.0}));

    if (displayOpt != "Number in a donut" && displayOpt != "Number on a bar")
    {
        var qBorderWd = form.numericUpDown({name: "formBorderWidth", label: "Border width", default_value: 0.0, minimum: 0.0, maximum: 0.5, increment: 0.005, prompt: "Width of border as a proportion of the graphic width"});
        controls.push(qBorderWd);
        var borderWd = qBorderWd.getValue();
        if (borderWd > 0.0)
        {
            controls.push(form.colorPicker({name: "formBorderColor", label: "Border color", default_value: "#FFFFFF"}));
            controls.push(form.numericUpDown({name: "formBorderOpacity", label: "Border opacity", minimum: 0.0, maximum: 1.0, increment: 0.1, default_value: 0.5}));
        }
    }
}
if (displayOpt == "Number in a donut" || displayOpt == "Number on a gauge")
{
    controls.push(form.colorPicker({name: "formBaseColor", label: "Base color", default_value: "#E5E8EE"}));
    controls.push(form.numericUpDown({name: "formHoleSize", label: "Hole radius %", default_value: 0.65, minimum: 0.0, maximum: 1.0, increment: 0.05}));
}

var is_custom_icon = false;
if (show_icons)
{
    if (allow_control_groups)
        form.group("ICONS");
    var custom_label = "(Custom icon)";
    var icon = form.comboBox({name: "formIcon", label: "Icon", alternatives: [
        custom_label, "Apple","Baby", "Beer", "Bread","Cake", "Car", "Chicken", "Circle", "Cross", "Elephant", "Face - Happy", "Face - Neutral", "Face - Sad", "Globe", "Gun", "Heart", "House", "Money", "Soldier", "Square", "Star", "Sick person", "Stick man", "Stick woman", "Thumbs up", "Thumbs down", "Tick", "Trolley", "Truck",  "User", "Water drop", "Weight", "Wine"], default_value: "Stick man"});
    controls.push(icon);
    is_custom_icon = icon.getValue() == custom_label;

    if (is_custom_icon)
    {
        controls.push(form.textBox({name: "formCustomUrl", label: "Icon URL", type: "text", required: true}));
        controls.push(form.textBox({name: "formCustomBaseUrl", label: "Base icon URL", type: "text", required: false, prompt: "Leave blank to hide unfilled icons"}));
    }
    if (displayOpt == "Pictograph (repeated icons)")
    {
        var layoutOpt = form.comboBox({label: "Layout constrained by", name: "formLayout", alternatives: ["Number of rows", "Number of columns", "Width-to-height ratio"], default_value: "Width-to-height ratio"});
        controls.push(layoutOpt);
        if (layoutOpt.getValue() == "Number of rows")
            controls.push(form.numericUpDown({label: "Number of rows", name:"formIconRows", minimum: 1, default_value: 1}));
        if (layoutOpt.getValue() == "Number of columns")
            controls.push(form.numericUpDown({label: "Number of columns", name:"formIconCols", minimum: 1, default_value: 1}));
        if (layoutOpt.getValue() == "Width-to-height ratio")
            controls.push(form.textBox({label: "Width-to-height ratio", name:"formWHRatio", type:"number", required:false, prompt:"Leave blank to use RObject dimensions"}));
        controls.push(form.numericUpDown({label: "Row padding", name:"formPadRow", minimum: 0, maximum: 0.99, default_value: 0, increment:0.01, prompt: "Specify padding between rows as a proportion (0 to 0.99) of the total height"}));
        controls.push(form.numericUpDown({label: "Column padding", name:"formPadCol", minimum: 0, maximum: 0.99, default_value: 0, increment:0.01, prompt: "Specify padding between columns as a proportion (0 to 0.99) of the total width"}));
    }
    controls.push(form.comboBox({label: "Direction of fill", name: "formFillDirection", alternatives: ["From left", "From right", "From bottom", "From top", "Radial"], default_value: "From left"}));
    var sizeOpt = form.checkBox({label: "Autosize", name: "formAutosize", default_value:1});
    controls.push(sizeOpt);
    if (!sizeOpt.getValue())
        controls.push(form.numericUpDown({label: "Icon width", name:"formIconWidth", minimum: 1, default_value: 50, increment:10, maximum:10000}));
    if (!is_custom_icon)
    {
        var baseOpt = form.checkBox({label: "Hide base image", name:"formHideBase", default_value: displayOpt == "Pictograph (repeated icons)"});
        controls.push(baseOpt);
        if (!baseOpt.getValue())
            controls.push(form.colorPicker({label: "Icon base color", name: "formBaseColor", default_value:"#E5E8EE"}));
    }
}

if (!is_custom_icon)
{
    if (allow_control_groups)
    {
        if (displayOpt == "Number")
            form.group({label:"NUMBER FILL COLOR", expanded:true});
        else
            form.group("FILL COLOR");
    }

    controls.push(form.colorPicker({name: "formColor0", label: "Default fill color", default_value: "#3E7DCC", prompt: "Color used if input value is smaller than any of the thresholds below"})); 
    var ci = 1;
    var thres = "";
    while (ci == 1 || thres != "")
    {
        var qThres = form.textBox({name: "formThres" + ci, label: "Threshold " + ci, required: false, prompt: "Value" + (thres == "" ? "" : " (greater than or equal to " + thres + ")") + " above which fill color " + ci + " is used."});
        controls.push(qThres);
        var thres = qThres.getValue();
        if (thres != "")
            controls.push(form.colorPicker({name: "formColor" + ci, label: "Fill color " + ci, default_value: "#3E7DCC", prompt: "Color used if input value is greater than or equal to " + thres}));
        ci = ci + 1;
    }
}

var qGlobalFontFamily = "Arial";
var qGlobalFontColor = "#808080";
var qGlobalFontUnits = "pt";
if (allow_control_groups)
    form.group("FONT");
var qUseDefaultFonts = form.checkBox({name: "formGlobalFontDefault", label: "Use default or template font settings", default_value: use_default_fonts, prompt: template_prompt});
controls.push(qUseDefaultFonts);
var use_default_fonts = qUseDefaultFonts.getValue();

if (!use_default_fonts)
{
    var globalFontFamily = form.comboBox({name: "formGlobalFontFamily", label: "Global font family", alternatives: font_list, default_value: "Arial", editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."});
    controls.push(globalFontFamily);
    var qGlobalFontFamily = globalFontFamily.getValue();
    var globalFontColor = form.colorPicker({name: "formGlobalFontColor", label: "Global font color", default_value: "#808080"});
    controls.push(globalFontColor);
    var qGlobalFontColor = globalFontColor.getValue();
    controls.push(form.comboBox({name: "formFontUnits", label: "Font units", alternatives: ["pt", "px"], default_value: "pt", prompt: "Are font sizes specified in terms of points or pixels?"}));
}

if (allow_control_groups)
    form.group("DATA LABEL");
var datalabOpt = "Overlayed on icon";
var dataVAlign = "Middle";
if (show_icons)
{
    var qDatalabOpt = form.comboBox({name:"dLabPos", label: "Show data label", alternatives: ["None", "Overlayed on icon", "Above icons", "Below icons"], default_value: "Below icons"});
    controls.push(qDatalabOpt);
    datalabOpt = qDatalabOpt.getValue();
}
if (datalabOpt != "None")
{
    controls.push(form.textBox({name:"dLabPrefix", label:"Prefix", type:"text", required:false}));
    controls.push(form.textBox({name:"dLabSuffix", label:" Suffix", type:"text", required:false}));
    controls.push(form.checkBox({name: "dPercentSuffix", label: "Automatically append % sign to percentages", default_value: true, prompt: "A percentage sign is automatically appended if the input data appears to be a percentage. If the value does not contain data indicating its number type, then manully enter a % sign in the suffix textbox above."}));
    controls.push(form.numericUpDown({name:"dLabDigits", label: "Decimals shown", minimum: 0, maximum: 6}));
    controls.push(form.comboBox({name:"dLabHAlign", label:"Horizontal alignment", alternatives: ["Left", "Center", "Right"], default_value: displayOpt == "Number on a bar" ? "Left" : "Center"}));
    if (datalabOpt == "Overlayed on icon" && !show_icons)
    {
        var qDataVAlign = form.comboBox({name:"dLabVAlign", label:"Vertical alignment", alternatives: ["Top", "Middle", "Bottom"], default_value: displayOpt == "Number on a gauge" ? "Bottom" : "Middle"});
        controls.push(qDataVAlign);
        var dataVAlign = qDataVAlign.getValue();
    }
    if (!(show_icons && datalabOpt == "Overlayed on icon"))
    {
        controls.push(form.numericUpDown({name:"dLabPad", label: "Vertical padding", maximum: 1000, minimum: min_vpad, default_value: 0.0, prompt: "Increase to move data label away from center"}));
        controls.push(form.numericUpDown({name:"dLabXPad", label: "Horizontal padding", maximum: 1000, minimum: -1000, default_value: 0.0, prompt: "Move data labels left (negative) or right (positive)"}));
    }
    var labFontDefault = form.checkBox({name: "dLabFontDefault", label: "Use default or template font settings", default_value: use_default_fonts, prompt: template_prompt});
    controls.push(labFontDefault);
    var dLabFontDefault = labFontDefault.getValue();
    if (!dLabFontDefault)
    {
        controls.push(form.comboBox({name: "dLabFont", label: "Font family", alternatives: font_list, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."}));
        if (displayOpt != "Number")
            controls.push(form.colorPicker({name: "dLabColor", label: "Color", default_value: qGlobalFontColor}));
        controls.push(form.numericUpDown({name:"dLabSize", label: "Font size", minimum: 5, maximum: 100, default_value: 24}));
        controls.push(form.comboBox({name: "dLabWeight", label: "Font weight", alternatives: ["Normal", "Bold"], default_value: "Normal"}));
    }

}

if (displayOpt == "Number on a gauge")
{
    if (allow_control_groups)
        form.group("GAUGE LABELS")
    var qTickOpt = form.checkBox({name: "formTickShow", label: "Show minimum and maximum values", default_value: true, prompt: "Show minimum and maximum values on the gauge"});
    controls.push(qTickOpt);
    var tickOpt = qTickOpt.getValue();
    if (tickOpt)
    {
        controls.push(form.checkBox({name: "formTickInside", label: "Labels inside gauge", default_value: false}));
        controls.push(form.textBox({name:"formTickPrefix", label:"Prefix", type:"text", required:false}));
        controls.push(form.textBox({name:"formTickSuffix", label:" Suffix", type:"text", required:false}));
        //controls.push(form.comboBox({name:"formTickNumType", label:" Number type", alternatives: ["Automatic", "Number", "Percentage", "Percentage (no sign)", "Scientific"], default_value: numTypeOpt}));
        controls.push(form.numericUpDown({name:"formTickDigits", label: "Decimals shown", minimum: 0, maximum: 6, default_value: 0}));
        var qTickFontDefault = form.checkBox({name: "formTickFontDefault", label: "Use default or template font settings", default_value: use_default_fonts, prompt: template_prompt});
        controls.push(qTickFontDefault);
        var tickFontDefault = qTickFontDefault.getValue();
        if (!tickFontDefault)
        {
            controls.push(form.numericUpDown({name:"formTickFontSize", label: "Font size", minimum: 5, maximum: 100, default_value: 9}));
            controls.push(form.comboBox({name: "formTickFontFamily", label: "Font family", alternatives: font_list, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."}));
            controls.push(form.colorPicker({name: "formTickFontColor", label: "Color", default_value: "#B3B3B3"}));
        }
    }
}

if (allow_control_groups)
    form.group("TEXT ABOVE")
if (datalabOpt != "Above icons")
{
    var qTextAbove = form.textBox({name:"formTextAbove", label: "Text above", required: false});
    controls.push(qTextAbove);
    var textAbove = qTextAbove.getValue();
    if (!isEmptyString(textAbove))
    {
        if (show_shapes && dataVAlign != "Top")
            controls.push(form.checkBox({name: "formTextAboveInside", label: "Text inside shape", default_value: false}));
        controls.push(form.comboBox({name:"formTextAboveHAlign", label:"Horizontal alignment", alternatives: ["Left", "Center", "Right"], default_value: "Center"}));
        controls.push(form.numericUpDown({name:"formTextAbovePad", label: "Vertical padding", maximum: 1000, minimum: min_vpad, default_value: 0.0, prompt: "Increase to move text away from center"}));
        controls.push(form.numericUpDown({name:"formTextAboveXPad", label: "Horizontal padding", maximum: 1000, minimum: -1000, default_value: 0.0, prompt: "Move text left (negative) or right (positive)"}));

        var qTextAboveFontDefault = form.checkBox({name: "formTextAboveFontDefault", label: "Use default or template font settings", default_value: use_default_fonts, prompt: template_prompt});
        controls.push(qTextAboveFontDefault);
        var textAboveFontDefault = qTextAboveFontDefault.getValue();
        if (!textAboveFontDefault)
        {
            controls.push(form.numericUpDown({name:"formTextAboveSize", label: "Font size", minimum: 5, maximum: 100, default_value: 10}));
            controls.push(form.comboBox({name: "formTextAboveWeight", label: "Font weight", alternatives: ["Normal", "Bold"], default_value: "Normal"}));
           controls.push(form.comboBox({name: "formTextAboveFont", label: "Font family", alternatives: font_list, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."}));
            controls.push(form.colorPicker({name: "formTextAboveColor", label: "Color", default_value: qGlobalFontColor}));
        }
    }
}
if (allow_control_groups)
    form.group("TEXT BELOW")
if (datalabOpt != "Below icons")
{
    var qTextBelow = form.textBox({name:"formTextBelow", label: "Text below", required: false});
    controls.push(qTextBelow);
    var textBelow = qTextBelow.getValue();
    if (!isEmptyString(textBelow))
    {
        if (show_shapes && dataVAlign != "Bottom")
            controls.push(form.checkBox({name: "formTextBelowInside", label: "Text inside shape", default_value: false}));
        controls.push(form.comboBox({name:"formTextBelowHAlign", label:"Horizontal alignment", alternatives: ["Left", "Center", "Right"], default_value: "Center"}));
        controls.push(form.numericUpDown({name:"formTextBelowPad", label: "Vertical padding", maximum: 1000, minimum: min_vpad, default_value: 0.0, prompt: "Increase to move text away from center"}));
        controls.push(form.numericUpDown({name:"formTextBelowXPad", label: "Horizontal padding", maximum: 1000, minimum: -1000, default_value: 0.0, prompt: "Move text left (negative) or right (positive)"}));
        
        var qTextBelowFontDefault = form.checkBox({name: "formTextBelowFontDefault", label: "Use default or template font settings", default_value: use_default_fonts, prompt: template_prompt});
        controls.push(qTextBelowFontDefault);
        var textBelowFontDefault = qTextBelowFontDefault.getValue();
        if (!textBelowFontDefault)
        {
            controls.push(form.numericUpDown({name:"formTextBelowSize", label: "Font size", minimum: 5, maximum: 100, default_value: 10}));
            controls.push(form.comboBox({name: "formTextBelowWeight", label: "Font weight", alternatives: ["Normal", "Bold"], default_value: "Normal"}));
            controls.push(form.comboBox({name: "formTextBelowFont", label: "Font family", alternatives: font_list, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."}));
            controls.push(form.colorPicker({name: "formTextBelowColor", label: "Color", default_value: qGlobalFontColor}));
        }
    }
}

if (!show_icons)
{
    if (allow_control_groups)
        form.group("HOVERTEXT")
    var qHoverText = form.textBox({name: "formHoverText", label: "Hover text", required: false, prompt: "Optional text to show on hover"});
    controls.push(qHoverText);
    var hoverText = qHoverText.getValue();
    if (!isEmptyString(hoverText))
    {
        var qHoverFontDefault = form.checkBox({name: "formHoverFontDefault", label: "Use default or template font settings", default_value: use_default_fonts, prompt: template_prompt});
        controls.push(qHoverFontDefault);
        var hoverFontDefault = qHoverFontDefault.getValue();
        if (!hoverFontDefault)
        {
            controls.push(form.colorPicker({name: "formHoverBgColor", label: "Hover background color", default_value: "#808080"}));
            controls.push(form.numericUpDown({name:"formHoverFontSize", label: "Font size", minimum: 5, maximum: 100, default_value: 11}));
            controls.push(form.comboBox({name: "formHoverFontFamily", label: "Font family", alternatives: font_list, default_value: qGlobalFontFamily, editable: true, prompt: "Select the font to use. You can also type the name of a font directly (including custom fonts)."}));
            controls.push(form.colorPicker({name: "formHoverFontColor", label: "Color", default_value: "#FFFFFF"}));
        }
    }
}

if (allow_control_groups)
    form.group("BACKGROUND")
var qBgOpt = form.checkBox({name: "formTransparent", label: "Transparent background", default_value: true});
controls.push(qBgOpt);
var bgOpt = qBgOpt.getValue();
if (!bgOpt)
{
    controls.push(form.colorPicker({name: "formBgColor", label: "Background color", default_value: "#FFFFFF"}));
    if (!show_icons)
        controls.push(form.numericUpDown({name: "formBgOpacity", label: "Background opacity", minimum: 0.0, maximum: 1.0, increment: 0.1, default_value: 1.0}));
}
controls.push(form.numericUpDown({name: "formMarginRight", label: "Right margin", maximum: 1000, default_value: 0}));
controls.push(form.numericUpDown({name: "formMarginLeft", label: "Left margin", maximum: 1000, default_value: 0}));
controls.push(form.numericUpDown({name: "formMarginTop", label: "Top margin", maximum: 1000, default_value: 0}));
controls.push(form.numericUpDown({name: "formMarginBottom", label: "Bottom margin", maximum: 1000, default_value: 0}));

form.setInputControls(controls);
# VERSION 2.4.0
library(flipTransformations)
library(flipTables)
library(flipPictographs)
        
value <- NULL
warnFilterOrWeight <- TRUE
getIndex <- function(index)
{
    if (nchar(index) > 0)
        return(index)
    else
        return(1)
}

select.row <- if (exists("formTableRowCtrl")) formTableRowCtrl else get0("formTableRow")
select.column <- if (exists("formTableColumnCtrl")) formTableColumnCtrl else get0("formTableColumn")

number.type <- "None"    
if (formDataSource == "Type or paste value") {
   value <- ParseText(formInputText)
   if (isTRUE(grepl("%", attr(value, "statistic"))))
    number.type <- "Percent"
} else if (formDataSource == "Use an existing R output") {
   value <- SelectEntry(formInputR, getIndex(select.row), getIndex(select.column), return.single.value = TRUE)
   if (isTRUE(grepl("%", attr(value, "format"))))
      number.type <- "Percent"
   else if (isTRUE(grepl("%", attr(value, "statistic"))))
      number.type <- "Percent"
} else if (formDataSource == "Table") {
    value <- SelectEntry(formInputTable, select.row, select.column, return.single.value = TRUE)
   if (isTRUE(grepl("%", attr(value, "format"))))
      number.type <- "Percent"
   else if (isTRUE(grepl("%", attr(value, "statistic"))))
      number.type <- "Percent"
} else {
    warnFilterOrWeight <- FALSE
    value <- SummarizeVariable(formInputVariable, type = formDataSource, category = get0("formCategory"),
                weights = QPopulationWeight, subset = QFilter)
    if (formDataSource == "Variable - Average")
        number.type <- "Average"
    else if (formDataSource == "Variable - Sum")
        number.type <- "Sum"
    else if (formDataSource == "Variable - Percentage")
        number.type <- "Percent"
}
default.digits <- QAppearance$Number$DecimalPlaces[[number.type]]
if (is.null(default.digits))
    default.digits <- QAppearance$Number$DecimalPlaces[["None"]]

if (warnFilterOrWeight && length(QFilter) > 1)
    warning("Filters have not been used. They can only be applied to variables.")
if (warnFilterOrWeight && length(QPopulationWeight) > 1)
    warning("Weights have not been used. They can only be applied to variables.")
       
ci <- 1
fill.color <- NA
while (is.na(fill.color))
{
    thres.str <- get0(paste0("formThres", ci), ifnotfound = "")
    thres.val <- ParseText(thres.str, same.as = value)

    if (thres.str  == "" && ci == 1)
        fill.color <- get0("formColor0", ifnotfound = "transparent")
    else if (thres.str == "")
        fill.color <- get0(paste0("formColor", ci - 1))
    else if (is.na(thres.val))
    {
        warning("Threshold ", ci, " is not numeric. Using default fill color.")
        fill.color <- formColor0
    }
    else if (value < thres.val)
        fill.color <- get0(paste0("formColor", ci - 1))
    else
        ci <- ci + 1
}

# As of version 2.4.0, we treat percentages as basically a suffix to a number
# That is we do not multiply by 100
percent.suffix <- isTRUE(get0("dPercentSuffix")) && number.type == "Percent"
rmPctAttr <- function(x)
{
    if (isTRUE(grepl("%", attr(x, "statistic", exact = TRUE))))
        attr(x, "statistic") <- NULL
    if (isTRUE(grepl("%", attr(x, "format", exact = TRUE)))) {
        x <- x * 100
        attr(x, "format") <- NULL
    }
    return(x)
}


font.family = "Arial"
font.color = "#808080"
template <- get0("formTemplate")
if (is.null(template))
    template <- list(global.number.font = list(units = "pt"), number.fonts = list(
        `Data label` = list(family = font.family, color = font.color, size = 24, weight = "Normal"),
        `Gauge labels` = list(family = font.family, color = "#B3B3B3", size = 9), 
        `Text above` = list(family = font.family, color = font.color, size = 10, weight = "Normal"),
        `Text below` = list(family = font.family, color = font.color, size = 10, weight = "Normal"),
        `Hover text` = list(family = font.family, color = "#FFFFFF", font.size = 11, bg.color = "#808080")))


viz <- VisualizeNumber(rmPctAttr(value),
    display = formDisplay,
    total.icons = if (exists("formTotalIcons")) as.numeric(formTotalIcons) else NA, 
    maximum.value = if (exists("formDenominator")) rmPctAttr(ParseText(formDenominator)) else NA, 
    minimum.value = if (exists("formMinimumValue")) rmPctAttr(ParseText(formMinimumValue)) else 0.0, 
    scale = if (exists("formScale")) rmPctAttr(ParseText(formScale)) else 1, 
    layout = get0("formLayout", ifnotfound = NA), 
    number.rows = get0("formIconRows", ifnotfound = NA),
    number.cols = get0("formIconCols", ifnotfound = NA), 
    width.height.ratio = if (exists("formWHRatio") && !is.na(as.numeric(formWHRatio))) as.numeric(formWHRatio) else QOutputSizeWidth/QOutputSizeHeight, 
    image = if (isTRUE(get0("formIcon") == "(Custom icon)")) formCustomUrl else formIcon,
    base.image = get0("formCustomBaseUrl", ifnotfound = ""),
    is.custom.url = isTRUE(get0("formIcon") == "(Custom icon)"),
    hide.base.image = get0("formHideBase", ifnotfound = FALSE),
    auto.size = formAutosize,
    icon.width = formIconWidth,
    base.color = get0("formBaseColor", ifnotfound = "#000000"),
    hole.size = get0("formHoleSize"),
    tick.show = get0("formTickShow", ifnotfound = FALSE),
    tick.outside = !isTRUE(get0("formTickInside")),
    tick.number.type = "Number",
    tick.decimals = get0("formTickDigits"),
    tick.prefix = get0("formTickPrefix"),
    tick.suffix = paste0(if (percent.suffix) "%" else "", get0("formTickSuffix")),
    tick.font.size = get0("formTickFontSize", ifnotfound = template$number.fonts$`Gauge labels`$size),
    tick.font.family = get0("formTickFontFamily", ifnotfound = template$number.fonts$`Gauge labels`$family),
    tick.font.color = get0("formTickFontColor", ifnotfound = template$number.fonts$`Gauge labels`$color),
    pad.row = get0("formPadRow", ifnotfound = 0.0),
    pad.col = get0("formPadCol", ifnotfound = 0.0), 
    fill.direction = get0("formFillDirection"),
    fill.color = if (formDisplay == "Number") "transparent" else fill.color,
    fill.opacity = get0("formFillOpacity", ifnotfound = 1.0),
    label.data.number.type = "Number",
    label.data.decimals = if (!is.null(get0("dLabDigits"))) dLabDigits else default.digits,
    label.data.position = get0("dLabPos"),
    label.data.prefix = get0("dLabPrefix"),
    label.data.suffix = paste0(if (percent.suffix) "%" else "", get0("dLabSuffix")),
    label.data.valign = get0("dLabVAlign", ifnotfound = "Middle"),
    label.data.halign = get0("dLabHAlign"),
    label.data.pad = get0("dLabPad", ifnotfound = 0.0),
    label.data.xpad  = get0("dLabXPad", ifnotfound = 0.0), 
    label.data.font.family = get0("dLabFont", ifnotfound = template$number.fonts$`Data label`$family),
    label.data.font.color = if (formDisplay == "Number") fill.color else get0("dLabColor", ifnotfound = template$number.fonts$`Data label`$color),
    label.data.font.size = get0("dLabSize", ifnotfound = template$number.fonts$`Data label`$size),
    label.data.font.weight = get0("dLabWeight", ifnotfound = template$number.fonts$`Data label`$weight),
    text.above = get0("formTextAbove"),
    text.above.outside = !isTRUE(get0("formTextAboveInside")),
    text.above.halign = get0("formTextAboveHAlign"),
    text.above.pad = get0("formTextAbovePad", ifnotfound = 0.0),
    text.above.xpad = get0("formTextAboveXPad", ifnotfound = 0.0),
    text.above.font.family = get0("formTextAboveFont", ifnotfound = template$number.fonts$`Text above`$family),
    text.above.font.color = get0("formTextAboveColor", ifnotfound = template$number.fonts$`Text above`$color),
    text.above.font.size = get0("formTextAboveSize", ifnotfound = template$number.fonts$`Text above`$size),
    text.above.font.weight = get0("formTextAboveWeight", ifnotfound = template$number.fonts$`Text above`$weight),
    text.below = get0("formTextBelow"),
    text.below.outside = !isTRUE(get0("formTextBelowInside")),
    text.below.halign = get0("formTextBelowHAlign"),
    text.below.pad = get0("formTextBelowPad", ifnotfound = 0.0),
    text.below.xpad = get0("formTextBelowXPad", ifnotfound = 0.0), 
    text.below.font.family = get0("formTextBelowFont", ifnotfound = template$number.fonts$`Text below`$family),
    text.below.font.color = get0("formTextBelowColor", ifnotfound = template$number.fonts$`Text below`$color),
    text.below.font.size = get0("formTextBelowSize", ifnotfound = template$number.fonts$`Text below`$size),
    text.below.font.weight = get0("formTextBelowWeight", ifnotfound = template$number.fonts$`Text below`$weight),
    border.color = get0("formBorderColor"),
    border.opacity = get0("formBorderOpacity", ifnotfound = 1.0),
    border.width = get0("formBorderWidth", ifnotfound = 0.0),
    background.color = get0("formBgColor", ifnotfound = "white"),
    background.opacity = if (formTransparent) 0.0 else get0("formBgOpacity", ifnotfound = 1.0),
    hover.text = get0("formHoverText"),
    hover.bg.color = get0("formHoverBgColor", ifnotfound = template$number.fonts$`Hover text`$bg.color),
    hover.font.family = get0("formHoverFontFamily", ifnotfound = template$number.fonts$`Hover text`$family),
    hover.font.size = get0("formHoverFontSize", ifnotfound = template$number.fonts$`Hover text`$size),
    hover.font.color = get0("formHoverFontColor", ifnotfound = template$number.fonts$`Hover text`$color),
    font.unit = get0("formFontUnits", ifnotfound = template$global.number.font$units),
    margin.left = formMarginLeft,
    margin.right = formMarginRight,
    margin.top = formMarginTop,
    margin.bottom = formMarginBottom)
{
    "shape": "None"
}