
//############### Start classes ###############

if($ != undefined)
	func = $;
else
	func = J;

function IAbstractGObject(id) {
    this.id = id;
    this.instanceOf = "IAbstractGObject";
    this.parentEnabled = true;
    this.enabled = true;
    this.visible = true;
    this.get_IsEnabled = Abstract_GetEnabled;
    this.set_IsEnabled = Abstract_SetEnabled;
    this.get_IsVisible = Abstract_GetVisible;
    this.set_IsVisible = Abstract_SetVisible;
    this.inheritFrom = ScriptGLocation;
    this.inheritFrom(id, this);
    this.inheritFrom = ScriptGSize;
    this.inheritFrom(id, this);
    this.UpdateEnabled = Abstract_UpdateEnabled;
    this.UpdateVisible = Abstract_UpdateVisible;
}

function IAbstractGObjectRotatable(id) {
    this.inheritFrom = IAbstractGObject;
    this.inheritFrom(id);
    this.instanceOf = "IAbstractGObjectRotatable";
    this.get_Angle = Rotatable_GetAngle;
    this.set_Angle = Rotatable_SetAngle;
    this.set_CenterMarker = Rotatable_SetCenterMarker;
    this.center_marker_left;
    this.center_marker_top;
}

function ITextBox(id) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "ITextBox";
    this.get_Text = ICommon_GetText;
    this.set_Text = ICommon_SetText;
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
    this.ResetPasswordBox = ITextBox_ResetPasswordBox;
    this.GetFocus = ITextBox_GetFocus;
    this.SelectAll = ITextBox_SelectAll;
    this.AssignValueToFirstTag = true;
    this.writeScriptTagExpr;
}

function IButton(id) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IButton";
    this.checked = false;
    this.get_Text = ICommon_GetText;
    this.set_Text = ICommon_SetText;
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
    this.get_IsChecked = ICommonCheck_GetIsChecked;
    this.set_IsChecked = ICommonCheck_SetIsChecked;
    this.AssignValueToFirstTag = true;
    this.writeScriptTagExpr;
}

function ILabel(id) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "ILabel";
    this.get_Text = ICommon_GetText;
    this.set_Text = ICommon_SetText;
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
    this.AssignValueToFirstTag = true;
    this.writeScriptTagExpr;
}

function ICheckBox(id, threeState) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "ICheckBox";
    this.writeCheckedTag;
    this.checked = false;
    this.status = "";
    this.threeState = threeState;
    this.get_Text = ICommon_GetText;
    this.set_Text = ICommon_SetText;
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
    this.get_IsChecked = ICommonCheck_GetIsChecked;
    this.set_IsChecked = ICommonCheck_SetIsChecked;
    this.get_IsCheckedInt = ICheckBox_GetIsCheckedInt;
    this.set_IsCheckedInt = ICheckBox_SetIsCheckedInt;
    this.AssignValueToFirstTag = true;
    this.writeScriptTagExpr;
}

function IRadioButton(id) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IRadioButton";
    this.writeCheckedTag;
    this.checked = false;
    this.get_Text = ICommon_GetText;
    this.set_Text = ICommon_SetText;
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
    this.get_IsChecked = ICommonCheck_GetIsChecked;
    this.set_IsChecked = ICommonCheck_SetIsChecked;
    this.AssignValueToFirstTag = true;
    this.writeScriptTagExpr;
}

function IGroupbox(id) {
    this.inheritFrom = IAbstractGObject;
    this.inheritFrom(id);
    this.instanceOf = "IGroupbox";
    this.get_Text = ICommon_GetText;
    this.set_Text = ICommon_SetText;
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
    this.AssignValueToFirstTag = true;
    this.writeScriptTagExpr;
}

function ILine(id, translate, rotationCenter, angle, left, top) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "ILine";
    this.translate = translate;
    this.rotationCenter = rotationCenter;
    this.angle = angle;
    this.left = left;
    this.top = top;
    this.get_X1 = ILine_GetX1;
    this.set_X1 = ILine_SetX1;
    this.get_Y1 = ILine_GetY1;
    this.set_Y1 = ILine_SetY1;
    this.get_X2 = ILine_GetX2;
    this.set_X2 = ILine_SetX2;
    this.get_Y2 = ILine_GetY2;
    this.set_Y2 = ILine_SetY2;
    this.setLeft = IGeometric_SetLeft;
    this.setTop = IGeometric_SetTop;
}

function IPolygon(id, translate, rotationCenter, angle, left, top) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IPolygon";
    this.translate = translate;
    this.rotationCenter = rotationCenter;
    this.angle = angle;
    this.left = left;
    this.top = top;
    this.get__Points = IGeometric_GetPoints;
    this.set__Points = IGeometric_GetPoints;
    this.setLeft = IGeometric_SetLeft;
    this.setTop = IGeometric_SetTop;
    this.generateDynamicFill = Generate_DynamicFill;
    this.dynamicFillColors = [];
}

function IPolyLine(id, translate, rotationCenter, angle, left, top) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IPolyLine";
    this.translate = translate;
    this.rotationCenter = rotationCenter;
    this.angle = angle;
    this.left = left;
    this.top = top;
    this.get__Points = IGeometric_GetPoints;
    this.set__Points = IGeometric_GetPoints;
    this.setLeft = IGeometric_SetLeft;
    this.setTop = IGeometric_SetTop;
}

function IRectangle(id, translate, rotationCenter, angle) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IRectangle";
    this.size = this;
    this.translate = translate;
    this.rotationCenter = rotationCenter;
    this.angle = angle;
    this.get_Width = IGeometric_GetWidth;
    this.set_Width = IGeometric_SetWidth;
    this.get_Height = IGeometric_GetHeight;
    this.set_Height = IGeometric_SetHeight;
    this.generateDynamicFill = Generate_DynamicFill;
    this.dynamicFillColors = [];
}

function IEllipse(id, translate, rotationCenter, angle, left, top) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IEllipse";
    this.size = this;
    this.translate = translate;
    this.rotationCenter = rotationCenter;
    this.angle = angle;
    this.left = left;
    this.top = top;
    this.get_Width = IGeometric_GetWidth;
    this.set_Width = IGeometric_SetWidth;
    this.get_Height = IGeometric_GetHeight;
    this.set_Height = IGeometric_SetHeight;
    this.generateDynamicFill = Generate_DynamicFill;
    this.dynamicFillColors = [];
}

function IGroupScreen(id) {
    this.inheritFrom = IAbstractGObject;
    this.inheritFrom(id);
    this.instanceOf = "IGroupScreen";
    this.get_Screen = Empty;
    this.SetScreen = IGroupScreen_SetScreen;
	this.SetScreenDic = IGroupScreen_SetScreenDic;
    this.ClearScreen = IGroupScreen_ClearScreen;
    this.selectedScreen = "";
    this.GetCurrentScreen = IGroupScreen_GetCurrentScreen;
	this.SetInitialScreen = IGroupScreen_SetInitialScreen;
    this.NeedToUpdateScroll = false;
}

function IBitmap(id, isDynamic, gifAutoPlay, gifInfiniteLoop, gifByDuration, gifCount, gifDuration) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IBitmap";
    this.isDynamicImage = isDynamic;
    this.gifAutoPlay = gifAutoPlay;
    this.gifInfiniteLoop = gifInfiniteLoop;
    this.gifByDuration = gifByDuration;
    this.gifCount = gifCount;
    this.gifDuration = gifDuration;
    this.get_Source = IBitmap_GetSource;
    this.set_Source = IBitmap_SetSource;
    this.Play = IBitmap_Play;
    this.Pause = IBitmap_Pause;
    this.Restart = IBitmap_Restart;
}

function IMenu(id) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IMenu";
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
}

function GTrend(id, duration, multipleScales, numberOfDecimals, gridPensParams) {
    this.inheritFrom = IAbstractGObject;
    this.inheritFrom(id);
    this.instanceOf = "GTrend";
    this.duration = duration;
    this.numberOfDecimals = numberOfDecimals;
    this.gridPensParams = gridPensParams;
    this.endTimeDiff = 0;
    this.isPlotPanTrend = false;
    this.subscribedPens = [];
    this.play = true;
    this.initPlotter = Trend_InitPlotter;	
    this.setDuration = setDuration;
    this.plot = Trend_Plot;	
    this.updatePlot = Trend_UpdatePlot;
    this.idPlotter = idPlotter;
    this.addPen = Trend_AddPen;
    this.removePen = Trend_RemovePen;
    this.removePen1 = Trend_RemovePen1;
    this.playPause = Trend_PlayPause;
    this.showDetails = Trend_ShowDetails;
	this.showYAxis = Trend_ShowYAxis;
	this.autoScale = Trend_AutoScale;
    this.fitToNow = Trend_FitToNow;
	this.fitScalesToView = Trend_FitScalesToView;
    this.setCursor = Trend_SetCursor;
    this.initCursor = Trend_InitCursor;
	this.initTrendTagValue = Trend_initTrendTagValueTimer;
    this.removeCursor = Trend_RemoveCursor;
    this.changeCursorColor = Trend_ChangeCursorColor;
    this.changeBackground = Trend_ChangeBackground;
    this.options = new Object();
    this.seriesoptions = [];
    this.dataPlot = [];
    this.idPlotter();
    this.setPlotData = setPlotData;
    this.setPenData = setPenData;
    this.contextmenu = Trend_ContextMenu;
    this.zoomIn = Trend_ZoomIn;
    this.zoomOut = Trend_ZoomOut;
    this.Play = Trend_Play;
    this.Pause = Trend_Pause;
    this.PlayNow = Trend_PlayNow;
    this.HidePen = Trend_HidePenScript;
    this.UpdateStartDate = Trend_UpdateStartDate;
    this.UpdateEndDate = Trend_UpdateEndDate;
    // Utilizei na API antiga para fazer o zoom por eixo X ou Y - Marcus
	// this.isOverXAxis = false;
    // this.isOverYAxis = false;
    this.startDateTag = '';
    this.endDateTag = '';
    this.isUpdatingTag = false;
    this.updateDateTag = Trend_UpdateDateTag;
    this.InitDateTag = Trend_InitDateTag;
    this.showYAxisProp = multipleScales;
	this.AddPen = Trend_UserAddPen;
	this.SetPenDescription = Trend_SetPenDescription;
	this.SetPenLineStyle = Trend_SetPenLineStyle;
	this.SetPenThickness = Trend_SetPenThickness;
	this.SetPenColor = Trend_SetPenColor;
	this.SetPenInterpolated = Trend_SetPenInterpolated;
	this.SetPenMin = Trend_SetPenMin;
	this.SetPenMax = Trend_SetPenMax;
	this.SetPenMarker = Trend_SetPenMarker;
	this.SetPenShowLegend = Trend_SetPenShowLegend;
	this.HasPenSPCMin = Trend_HasPenSPCMin;
	this.HasPenSPCMax = Trend_HasPenSPCMax;
	this.HasPenSPCAvg = Trend_HasPenSPCAvg;
	this.HasPenSPCDev = Trend_HasPenSPCDev;
	this.GetPenSPCDevSigma = Trend_GetPenSPCDevSigma;
	this.GetPenSPCMin = Trend_GetPenSPCMin;
	this.GetPenSPCMax = Trend_GetPenSPCMax;
	this.GetPenSPCAvg = Trend_GetPenSPCAvg;
	this.GetPenSPCDev = Trend_GetPenSPCDev;
	this.GetPenSPCDevPositive = Trend_GetPenSPCDevPositive;
	this.GetPenSPCDevNegative = Trend_GetPenSPCDevNegative;
	this.SetSPC = Trend_SetSPC;
	this.SetSPC = Trend_SetSPC;
	this.SetPenSPC = Trend_SetPenSPC;
	this.SetPenSPC = Trend_SetPenSPC;
	this.RemovePen = Trend_RemovePen;
    this.RemoveAllPens = Trend_RemoveAllPens;
    this.UpdateDurationEnd = Trend_UpdateDurationEnd;
    this.ShowSingleScale = Trend_SingleScales;
    this.ShowMultipleScales = Trend_MultiScales;
}

function createPen(name, isScreenTag, description, penColor, marker, lthick, interpolated, lstyle, showLegend, isSpc, spcMin, spcMax, spcAverage,
    spcStandardDeviation, spcStandardDeviationSigmaIndex) {
    var newPena = new IPena(name, isScreenTag);
    newPena.description = description;
    newPena.pencolor = penColor;
    newPena.marker = marker;
    newPena.oldMarker = marker;
    newPena.lthick = lthick;
    newPena.interpolated = interpolated;
    newPena.lstyle = lstyle;
    newPena.showLegend = showLegend;
    newPena.isSpc = isSpc;
    newPena.spcMin = spcMin;
    newPena.spcMax = spcMax;
    newPena.spcAverage = spcAverage;
    newPena.spcStandardDeviation = spcStandardDeviation;
    newPena.spcStandardDeviationSigmaIndex = spcStandardDeviationSigmaIndex;
    newPena.spcPens = [];

    if (newPena.spcMin) 
        newPena.spcPens.push(createPen(name + "_" + "Min", isScreenTag, "", penColor, '0', 1, true, 0, false, true, false, false, false, false, 1));
    if (newPena.spcMax)
        newPena.spcPens.push(createPen(name + "_" + "Max", isScreenTag, "", penColor, '0', 1, true, 0, false, true, false, false, false, false, 1));
    if (newPena.spcAverage)
        newPena.spcPens.push(createPen(name + "_" + "Average", isScreenTag, "", penColor, '0', 1, true, 0, false, true, false, false, false, false, 1));
    if (newPena.spcStandardDeviation) {
        newPena.spcPens.push(createPen(name + "_" + "StandardDeviationPositive", isScreenTag, "", penColor, '0', 1, true, 0, false, true, false, false, false, false, 1));
        newPena.spcPens.push(createPen(name + "_" + "StandardDeviationNegative", isScreenTag, "", penColor, '0', 1, true, 0, false, true, false, false, false, false, 1));
    }

    return newPena;
}

function IPena(id, isScreenTag) {
    this.instanceOf = "IPena";
    if ((id.indexOf("#") == 0) || (isScreenTag == true)) {
		var screenTag = id;
		if (id.indexOf("#") == 0)
			screenTag = id.substring(1);
			
        var mainScreenTag = "";
        var qualifier = "";
        var dotPos = screenTag.indexOf(".");
        var openArrayPos = screenTag.indexOf("[");
        var index = -1;
        if (dotPos != -1 && openArrayPos != -1)
            index = Math.Min(dotPos, openArrayPos);
        else if (dotPos == -1 && openArrayPos == -1)
            mainScreenTag = screenTag;
        else if (dotPos == -1)
            index = openArrayPos;
        else
            index = dotPos;
        if (index != -1) {
            mainScreenTag = screenTag.substring(0, index);
            qualifier = screenTag.substring(index);
        }

        this.screenTag = id;
        this.id = GetTagFromScreenTag(mainScreenTag + "#" + qualifier.toUpperCase());
    }
    else {
        this.screenTag = "";
        this.id = id;
    }

    this.set_Description = Pena_SetDescription;
    this.set_Marker = Pena_SetMarker;
    this.set_LineStyle = Pena_SetLineStyle;
    this.set_Thickness = Pena_SetThickness;
    this.get_PenColor = Pena_GetPenColor;
    this.set_PenColor = Pena_SetPenColor;
    this.set_Interpol = Pena_SetInterpol;
    this.get_ShowLegend = Pena_GetShowLegend;
    this.set_ShowLegend = Pena_SetShowLegend;
    this.get_IsSpc = Pena_GetIsSpc;
    this.hasAnySpcFunction = Pena_HasAnySpcFunction;
    this.get_SpcMin = Pena_GetSpcMin;
    this.get_SpcMax = Pena_GetSpcMax;
    this.get_SpcAverage = Pena_GetSpcAverage;
    this.get_SpcStandardDeviation = Pena_GetSpcStandardDeviation;
    this.get_spcStandardDeviationSigmaIndex = Pena_GetSpcStandardDeviationSigmaIndex;
    this.set_Spc = Pena_SetSpc;
    this.set_SpcMin = Pena_SetSpcMin;
    this.set_SpcMax = Pena_SetSpcMax;
    this.set_SpcAverage = Pena_SetSpcAverage;
    this.set_SpcStandardDeviation = Pena_SetSpcStandardDeviation;
    this.set_SpcStandardDeviationSigmaIndex = Pena_SetSpcStandardDeviationSigmaIndex;
    this.hidePen = Pena_HidePen;    
    this.isHide = false;
    this.oldColorPen;
    this.oldShowLegend = true;
	this.data = [];
}

function getParsedPenaId(penaId)
{
	while (penaId.indexOf(' ') > -1)
		penaId = penaId.replace(' ','');
		
	while (penaId.indexOf('/') > -1)
		penaId = penaId.replace('/','_');

	while (penaId.indexOf('[') > -1)
		penaId = penaId.replace('[','_');
		
	while (penaId.indexOf(']') > -1)
		penaId = penaId.replace(']','_');
		
	while (penaId.indexOf('.') > -1)
		penaId = penaId.replace('.','_');
		
	while (penaId.indexOf(',') > -1)
		penaId = penaId.replace(',','_');
		
	return penaId;
}

//CHART PARTS!!!
function IChart(id, legendWidth, legendHeight) {
    this.inheritFrom = IAbstractGObject;
    this.inheritFrom(id);
    this.instanceOf = "IChart";
    this.UpdateVisible = IChart_UpdateVisible;
    this.get_Title = Chart_GetTitle;
    this.set_Title = Chart_SetTitle;
    this.get_TitleHorizontalAlignment = Chart_GetTitleHorizontalAlignment;
    this.set_TitleHorizontalAlignment = Chart_SetTitleHorizontalAlignment;
    this.get_ShowHorizontalLines = Chart_GetShowHorizontalLines;
    this.set_ShowHorizontalLines = Chart_SetShowHorizontalLines;
    this.get_ShowVerticalLines = Chart_GetShowVerticalLines;
    this.set_ShowVerticalLines = Chart_SetShowVerticalLines;
    this.get_BackgroundColor = Chart_GetBackgroundColor;
    this.set_BackgroundColor = Chart_SetBackgroundColor;
    this.get_PlotAreaColor = Chart_GetPlotAreaColor;
    this.set_PlotAreaColor = Chart_SetPlotAreaColor;
    this.get_ShowGridBorder = Chart_GetShowGridBorder;
    this.set_ShowGridBorder = Chart_SetShowGridBorder;
    this.UpdateTitleFormat = Chart_UpdateTitleFormat;
    this.UpdateLegendFormat = Chart_UpdateLegendFormat;
    this.UpdateLegendSize = Chart_UpdateLegendSize;
    this.legendWidth = legendWidth;
    this.legendHeight = legendHeight;
    this.options = {
        title:
		{
			fontFamily: 'Arial',
			fontSize: 16,
			textColor: 'black'
		},
        legend:
        {
            textColor: 'black',
            show: true,
            placement: 'outsideGrid',
            location: 'e',
            legendWidth: legendWidth,
            legendHeight: legendHeight
        }
    }
}

function GPieGraph(id, type, legendWidth, legendHeight) {
    this.inheritFrom = IChart;
    this.inheritFrom(id, legendWidth, legendHeight);
    this.instanceOf = "GPieGraph";
    this.options.seriesDefaults = { renderer: func.jqplot.PieRenderer }
    this.chartType = "pie";
}

function GBarGraph(id, type, legendWidth, legendHeight) {
    this.inheritFrom = IChart;
    this.inheritFrom(id, legendWidth, legendHeight);
    this.instanceOf = "GBarGraph";
    this.options.axesStyles = { ticks: { textColor: 'black' }, label: { textColor: 'black'} }
    this.options.seriesDefaults = { renderer: func.jqplot.BarRenderer, pointLabels: { show: false, location: 'e', edgeTolerance: -15 } }
    this.options.shadowAngle = 135;
    if (type == 0) {
        this.options.axes = { yaxis: { renderer: func.jqplot.CategoryAxisRenderer } };
        this.options.seriesDefaults.rendererOptions = { barDirection: 'horizontal' };
    }
    else {
        this.options.axes = { xaxis: { renderer: func.jqplot.CategoryAxisRenderer } };
        this.options.seriesDefaults.rendererOptions = { barDirection: 'vertical' };
    }
    this.chartType = "bar";
}

function GScatterGraph(id, type, legendWidth, legendHeight, showMarkers) {
    this.inheritFrom = IChart;
    this.inheritFrom(id, legendWidth, legendHeight);
    this.instanceOf = "GScatterGraph";
    this.options.axesStyles = { ticks: { textColor: 'black' }, label: { textColor: 'black'} }
    this.options.seriesDefaults = { showMarker: showMarkers, fill: false, fillAndStroke: true, showLine: false, markerOptions: { style: type == 0 ? 'filledDimaond' : 'filledCircle' } }
    this.options.axesDefaults = { labelRenderer: func.jqplot.CanvasAxisLabelRenderer }
    this.options.axes = { xaxis: { renderer: func.jqplot.CategoryAxisRenderer }, yaxis: { pad: 1.05, tickOptions: { formatString: '%#.2f' } } }
    if (type != 0) {
        this.options.seriesDefaults.showLine = true;
        if (type == 2) {
            this.options.seriesDefaults.fill = true;
            this.options.seriesDefaults.fillAlpha = 0.4;
            if (showMarkers)
                this.options.seriesDefaults.shadow = false;
            else
                this.options.seriesDefaults.fillAndStroke = false;
        }
    }
    this.chartType = "line";
    this.InsertItem = GScatterGraph_InsertItem;
    this.InsertItems = GScatterGraph_InsertItems;
    this.ClearItems = GScatterGraph_ClearItems;
    this.ChangeLineType = GScatterGraph_ChangeLineType;
    this.ChangeSerieThickness = GScatterGraph_ChangeSerieThickness;
    this.ChangeSeriesThickness = GScatterGraph_ChangeSeriesThickness;
}

// END CHART PARTS

function ITab(id, tabs) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "ITab";
    this.tabs = [];
    this.disabledTabs = [];
    this.active = 0;
    var hasDisabled = false;
    for (var i = 0, l = tabs.length; i < l; i++) {
        var properties = tabs[i].split(';');
        var tabItem = new TabItem(properties[0], properties[1], properties[2]);
        this.tabs.push(tabItem);
        if (tabItem.Enabled == "false") {
            this.disabledTabs.push(i);
            hasDisabled = true;
        } else if (hasDisabled && this.active == 0)
            this.active = i;
    }
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
    this.SetVisibility = ITab_SetVisibility;
    this.SetIsEnabled = ITab_SetIsEnabled;
    this.SetVisibilityTag = ITab_SetVisibilityTag;
    this.SetIsEnabledTag = ITab_SetIsEnabledTag;
    this.ChangeSelectedIndex = ITab_ChangeSelectedIndex;
}

function IComboBox(id) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IComboBox";
    this.get_Items = IComboBox_GetItems;
    this.set_Items = IComboBox_SetItems;
    this.get_SelectedIndex = IComboBox_GetSelectedIndex;
    this.set_SelectedIndex = IComboBox_SetSelectedIndex;
    this.get_SelectedText = IComboBox_GetSelectedText;
    this.set_SelectedText = IComboBox_SetSelectedText;
    this.get_FontColor = ICommon_GetFontColor;
    this.set_FontColor = ICommon_SetFontColor;
    this.InsertItem = IComboBox_InsertItem;
    this.InsertItemAt = IComboBox_InsertItemAt;
    this.InsertItemsFromTag = IComboBox_InsertItemsFromTag;
    this.InsertItemsAtFromTag = IComboBox_InsertItemsAtFromTag;
    this.RemoveSelectedItem = IComboBox_RemoveSelectedItem;
    this.RemoveItem = IComboBox_RemoveItem;
    this.RemoveAllItems = IComboBox_RemoveAllItems;
    this.ReloadDynamic = IComboBox_ReloadDynamic;
    this.isReloading = false;
}

function IGrouping(id, children, isTemplate) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "IGrouping";
    this.children = children;
    this.get_Children = IGrouping_GetChildren;
    this.isTemplateGroup = isTemplate == undefined ? false : isTemplate;
    this.set_IsEnabled = ITemplate_SetEnabled;
}

function IMultitagViewer(id) {
	this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom('div' + id);
    this.instanceOf = "IMultitagViewer";
	this.originalName = id;
	this.contextmenu = IMultitagViewer_ContextMenu;
    this.scrollToLine = IMultiTagViewer_ScrollToLine;
	this.idMTV = idMTV;
    this.idMTV();
}

function IMultitagViewer(id, dataSource, columns, numberOfDecimals, configStartIndex, configCount, configUseCount, cellspacing) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom('div' + id);
    this.instanceOf = "IMultitagViewer";
    this.dataSource = dataSource;
    this.columnsPath = columns;
    this.originalName = id;
    this.selectedGridIndex = -1;
    this.selectedArrayIndex = -1;
    this.model = "";
    this.originalTable = "";
    this.columnsToUpdate = [];
    this.rowCount = 0;
    this.numberOfDecimals = numberOfDecimals;
    this.configStartIndex = configStartIndex;
    this.configUseCount = configUseCount;
    this.configCount = configCount;
    this.inputsToUpdate = [];
    this.keysToUpdate = [];
    this.valuesToUpdate = [];
	this.cellspacing = cellspacing;
    this.get_SelectedGridIndex = IMultitagViewer_GetSelectedGridIndex;
    this.set_SelectedGridIndex = IMultitagViewer_SetSelectedGridIndex;
    this.get_SelectedArrayIndex = IMultitagViewer_GetSelectedArrayIndex;
    this.set_SelectedArrayIndex = IMultitagViewer_SetSelectedArrayIndex;
    this.ChangeImageSource = IMultitagViewer_ChangeImageSource;
    this.ChangeBackground = IMultitagViewer_ChangeBackground;
    this.Count = IMultitagViewer_Count;
    this.Remove = IMultitagViewer_Remove;
    this.Add = IMultitagViewer_Add;
    this.Filter = IMultitagViewer_Filter;
    this.RefreshIndex = Empty;
    this.HideColumn = IMultitagViewer_HideColumn;
    this.ShowColumn = IMultitagViewer_ShowColumn;
    this.UpdateColumnValue = IMultitagViewer_UpdateColumnValue;
    this.Subscribe = IMultitagViewer_Subscribe;
    this.Reload = IMultitagViewer_Reload;
	this.tagsToSubscribe = [];
	this.propertiesToSubscribe = [];
    this.UpdateAllColumnRequest = IMultitagViewer_UpdateAllColumnRequest;
    this.UpdateAllColumnValueIndex = IMultitagViewer_UpdateAllColumnValueIndex;
    this.contextmenu = IMultitagViewer_ContextMenu;
	this.scrollToLine = IMultiTagViewer_ScrollToLine;
    this.idMTV = idMTV;
    this.idMTV();
}

function IMatrixGrid(id, columnWidth, rowHeight, tableHeight, inputEnabled, fontStyle, cellAutoSize, numberOfDecimals) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom('div' + id);
    this.instanceOf = "IMatrixGrid";
    this.dataSource = '';
	this.tagsToSubscribe = [];
	this.propertiesToSubscribe = [];
    this.ColumnIndexTag = '';
    this.RowIndexTag = '';
    this.DepthIndexTag = '';
    this.SelectedValueTag = '';
    this.originalName = id;
    this.columnsToUpdate = [];
    this.loaded = false;
    this.updateRowColOnReload = false;
    this.dsDimension = -1;
    this.dsSize1 = -1;
    this.dsSize2 = -1;
    this.dsSize3 = -1;
    this.tableHeight = tableHeight;
    this.columnWidth = columnWidth;
    this.rowHeight = rowHeight;
    this.inputEnabled = inputEnabled;
    this.numberOfDecimals = numberOfDecimals;
    this.positionX = 0;
    this.positionY = 0;
    this.positionZ = 0;
    this.fontStyle = fontStyle;
    this.cellAutoSize = cellAutoSize;
    this.get_ColumnIndex = IMatrixGrid_GetColumnIndex;
    this.set_ColumnIndex = IMatrixGrid_SetColumnIndex;
    this.get_RowIndex = IMatrixGrid_GetRowIndex;
    this.set_RowIndex = IMatrixGrid_SetRowIndex;
    this.get_DepthIndex = IMatrixGrid_GetDepthIndex;
    this.set_DepthIndex = IMatrixGrid_SetDepthIndex;
    this.set_SelectedValue = IMatrixGrid_SetSelectedValue;
    this.ChangeDataSource = IMatrixGrid_ChangeDataSource;
    this.Subscribe = IMatrixGrid_Subscribe;
    this.Reload = IMatrixGrid_Reload;
    this.ReloadDynamic = IMatrixGrid_ReloadDynamic;
    this.UpdateColumnValue = IMatrixGrid_UpdateColumnValue;
    this.EnableDisableControls = IMatrixGrid_EnableDisableControls;
    this.EnableDisableButtons = IMatrixGrid_EnableDisableButtons;
    this.ChangeDepth = IMatrixGrid_ChangeDepth;
    this.ChangeDepthButtons = IMatrixGrid_ChangeDepthButtons;
    this.ChangeSelectedLineCol = IMatrixGrid_ChangeSelectedLineCol;
    this.UpdateDivControl = IMatrixGrid_UpdateDivControl;
}


function IGAlarmViewer(id) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom('div' + id);
	this.originalId = id;
    this.instanceOf = 'IGAlarmViewer';
	this.activeAckBrush = '#008000';
	this.activeUnackBrush = '#FF0000';
	this.returnedUnackBrush = '#0000FF';
	this.eventBrush = '#000000';
	this.dateIsAbsolut = false;
	this.dateIsForward = false;
	this.dateIsBackward = false;
	this.relativeDate = "01:00:00";
	this.startDate = "Now";
	this.endDate = "08/05/2015 10:26:56";
	this.alarmTags = {};
	this.tagsAlarmTypes = new JSDictionary();
	this.selectedRow = null;
	this.isAlarmOnline = false;
    this.Ack = IGAlarmViewer_Ack;
    this.AckAll = IGAlarmViewer_AckAll;
    this.get_SelectedLine = Empty;
    this.set_SelectedLine = Empty;
    this.Filter = [];
    this.SetAbsolutStartDate = Empty;
    this.SetAbsolutEndDate = Empty;
    this.SetAbsolutStartEndDate = Empty;
    this.SetRelativeDate = Empty;
    this.SetRelativePeriod = Empty;
    this.SetRelativeDatePeriod = Empty;
	this.AddAlarmTag = IGAlarmViewer_AddAlarmTag;
	this.RemoveAlarmTag = IGAlarmViewer_RemoveAlarmTag;
	this.RemoveTagFromAlarm = IGAlarmViewer_RemoveTagFromAlarm;
    this.AddFilter = IGAlarmViewer_AddFilter;
    this.RemoveFilter = IGAlarmViewer_RemoveFilter;
    this.CleanFilter = IGAlarmViewer_CleanFilter;
    this.ListFilter = IGAlarmViewer_ListFilter;
	this.SetAlarmEvent = IGAlarmViewer_SetAlarmEvent;
	this.SetAlarm = IGAlarmViewer_SetAlarm;
	this.UpdateAlarmDates = IGAlarmViewer_UpdateAlarmDates;
	this.AddHistoryItems = IGAlarmViewer_AddHistoryItems;
	this.Subscribe = IGAlarmViewer_Subscribe;
	this.LoadAlarmHistory = IGAlarmViewer_LoadAlarmHistory;
	this.LoadEventHistory = IGAlarmViewer_LoadEventHistory;
    this.ClearEvents = IGAlarmViewer_ClearEvents;
    this.scrollToLine = IGAlarmViewer_ScrollToLine;
    this.description = '';
    this.rowAlign = 'left';
	this.screenTags = {};
}

function IAbstractAlarm(parent, tag, alarmType){
	this.parent = parent;
	this.id = parent.originalId;
    this.tag = tag;
	this.alarmType = alarmType;
	this.properties = {};
	this.isFirstAlarm = 0;
	this.lastValidValue = 0;
    this.isEnabled = false;
    this.isSubscribed = false;
	this.CreateParameters = IAbstractAlarm_CreateParameters;
	this.AlarmChanged = Empty;
	this.AlarmAckChanged = IAbstractAlarm_AlarmAckChanged;
	this.AlarmAck = IAbstractAlarm_AlarmAck;
	this.DatesChanged = IAbstractAlarm_DatesChanged;
	this.FillProperties = Empty;
	this.Subscribe = IAbstractAlarm_Subscribe;
	this.Unsubscribe = IAbstractAlarm_Unsubscribe;
    this.EnableChanged = IAbstractAlarm_EnableChanged;
	this.CheckAlarm = IAbstractAlarm_CheckAlarm;
}

function ILimitAlarm(parent, tag, alarmType){
    this.inheritFrom = IAbstractAlarm;
    this.inheritFrom(parent, tag, alarmType);
	this.AlarmChanged = ILimitAlarm_AlarmChanged;
	this.FillProperties = ILimitAlarm_FillProperties;
}

function IDeviationAlarm(parent, tag, alarmType){
    this.inheritFrom = IAbstractAlarm;
    this.inheritFrom(parent, tag, alarmType);
	this.deviationTime = new Date();
	this.intervalId = 0;
	this.AlarmChanged = IDeviationAlarm_AlarmChanged;
	this.FillProperties = IDeviationAlarm_FillProperties;
	this.CheckDeviation = IDeviationAlarm_CheckDeviation;
}

function IFreezeAlarm(parent, tag, alarmType){
    this.inheritFrom = IAbstractAlarm;
    this.inheritFrom(parent, tag, alarmType);
	this.AlarmChanged = IFreezeAlarm_AlarmChanged;
	this.FillProperties = IFreezeAlarm_FillProperties;
	this.Subscribe = IAbstractAlarm_CheckSubscribe;
	this.Unsubscribe = IAbstractAlarm_CheckUnsubscribe;
}

function IWatchDogAlarm(parent, tag, alarmType){
    this.inheritFrom = IAbstractAlarm;
    this.inheritFrom(parent, tag, alarmType);
	this.AlarmChanged = IWatchDogAlarm_AlarmChanged;
	this.FillProperties = IWatchDogAlarm_FillProperties;
	this.Subscribe = IAbstractAlarm_CheckSubscribe;
	this.Unsubscribe = IAbstractAlarm_CheckUnsubscribe;
}

function IBooleanAlarm(parent, tag, alarmType){
    this.inheritFrom = IAbstractAlarm;
    this.inheritFrom(parent, tag, alarmType);
	this.AlarmChanged = IBooleanAlarm_AlarmChanged;
	this.FillProperties = IBooleanAlarm_FillProperties;
}

function ISymbol(id) {
    this.inheritFrom = IAbstractGObjectRotatable;
    this.inheritFrom(id);
    this.instanceOf = "ISymbol";
    this.updateLayout = Symbol_UpdateLayout;
    this.setInitialColors = Symbol_setInitialColors;
    this.fillColor = "";
    this.background = "";
    this.mode = 0;
    this.flip = 0;
}

//######## NetControl

function INetControl(id, style) {
	this.inheritFrom = IAbstractGObject;
	this.inheritFrom(id);
	this.objectStyle = style;
}
	
function Controls_Slider(id, style) {
	this.inheritFrom = INetControl;
    this.inheritFrom(id, style);
    this.get_TickFrequency = Empty;
    this.set_TickFrequency = Empty;
}

function Forms_TrackBar(id, style) {
    this.inheritFrom = INetControl;
    this.inheritFrom(id, style);
    this.get_Minimum = Forms_TrackBar_GetMin;
    this.set_Minimum = Forms_TrackBar_SetMin;
    this.get_Maximum = Forms_TrackBar_GetMax;
    this.set_Maximum = Forms_TrackBar_SetMax;
    this.get_Value = Forms_TrackBar_GetValue;
    this.set_Value = Forms_TrackBar_SetValue;
    this.get_TickFrequency = Empty;
    this.set_TickFrequency = Empty;
}

//######## TrackBar
function Forms_TrackBar_GetMin() {
    return document.getElementById(this.id).min;
}

function Forms_TrackBar_SetMin(value) {
    document.getElementById(this.id).min = value;
    var val = document.getElementById(this.id).value;
    document.getElementById(this.id).value = document.getElementById(this.id).max;
    document.getElementById(this.id).value = val;
}

function Forms_TrackBar_GetMax() {
    return document.getElementById(this.id).max;
}

function Forms_TrackBar_SetMax(value) {
    document.getElementById(this.id).max = value;
    var val = document.getElementById(this.id).value;
    document.getElementById(this.id).value = document.getElementById(this.id).min;
    document.getElementById(this.id).value = val;
}

function Forms_TrackBar_GetValue() {
    return func('#' + this.id).val();
}

function Forms_TrackBar_SetValue(value) {
    return func('#' + this.id).val(value);
}

//######## ListBox

function Forms_ListBox(id, style) {
    this.inheritFrom = INetControl;
    this.inheritFrom(id, style);

    this.get_Items = Forms_ListBox_GetItems;

    this.get_SelectedIndex = Forms_ListBox_GetSelectedIndex;
    this.set_SelectedIndex = Forms_ListBox_SetSelectedIndex;

    this.get_SelectedItem = Forms_ListBox_GetSelectedItem;
    this.set_SelectedItem = Forms_ListBox_SetSelectedItem;

    this.set_SelectionMode = Forms_ListBox_SetSelectionMode;
}

function Forms_ListBox_GetItems() {
	var v_Options = document.getElementById(this.id).options;
	CreateFunctions(v_Options);
	return v_Options;
}

function Forms_ListBox_GetSelectedIndex() {
    return func('#' + this.id + ' option').index(func('#' + this.id + ' option:selected'));
}

function Forms_ListBox_SetSelectedIndex(index) {
    func('#' + this.id + ' option').eq(index).prop('selected', true); ;
}

function Forms_ListBox_GetSelectedItem() {
    return func('#' + this.id + ' option:selected').text();
}

function Forms_ListBox_SetSelectedItem(text) {
    func("select option:contains(" + text + ")").attr('selected', true);
}

function Forms_ListBox_SetSelectionMode(index) {
	this.enabled = true;
	if(isNaN(Number(index)) || isEmpty(index))
	{
		switch (index.toUpperCase())
		{
			case "ONE":
				func('#' + this.id ).removeAttr('multiple');
				break;
			case "MULTISIMPLE":
				func("select").attr("multiple", true)
				break;
			case "MULTIEXTENDED":
				func("select").attr("multiple", true)
				break;
			case "NONE":
				this.enabled = false;
				break;
			default :
				func('#' + this.id ).removeAttr('multiple');
				break;
		}
	}
	else
	{
		if(index == 0)
			this.enabled = false;
		else if(index == 1)
			 func('#' + this.id ).removeAttr('multiple');
		else
			 func("select").attr("multiple", true)
	}
	
	this.UpdateEnabled();
}

//######## ListView

function ListViewItem(sValues) {
    this.values = new Array();
	for (var valueIndex = 0; valueIndex < sValues.length; valueIndex++)
		this.values[valueIndex] = sValues[valueIndex];
}

function Forms_ListView(id, style) {
    this.inheritFrom = INetControl;
    this.inheritFrom(id, style);

	this.items = new JSList();
	this.items.ListChanged = Forms_ListView_UpdateListView;
	this.items.ListChangedTarget = this;
    this.get_Items = Forms_ListView_GetItems;

	this.columns = new JSList();
	this.columns.ListChanged = Forms_ListView_UpdateListView;
	this.columns.ListChangedTarget = this;
    this.get_Columns = Forms_ListView_GetColumns;
    
    this.fullRowSelect = false;
    this.get_FullRowSelect = Forms_ListView_GetFullRowSelect;
    this.set_FullRowSelect = Forms_ListView_SetFullRowSelect;

    this.gridLines = false;
    this.get_GridLines = Forms_ListView_GetGridLines;
    this.set_GridLines = Forms_ListView_SetGridLines;

    this.get_View = Forms_ListView_GetView;
    this.set_View = Forms_ListView_SetView;
}

function Forms_ListView_UpdateListView(){
	var listViewContent = "<table id='tbl" + this.ListChangedTarget.id + "' style='" + this.ListChangedTarget.objectStyle + "'><thead><tr>"
	for (var columnIndex = 0; columnIndex < this.ListChangedTarget.columns.get_Count(); columnIndex++)
	{
		listViewContent += "<th";
		var columnHeaderInfo = this.ListChangedTarget.columns.get_Item(columnIndex);
		var header = ""
		var width = 50;
		if (func.isArray(columnHeaderInfo))
		{
			if (columnHeaderInfo.length > 0)
				header = columnHeaderInfo[0];
		
			if (columnHeaderInfo.length > 1)
				width = columnHeaderInfo[1];
				
			listViewContent += " width='" + width + "'>" + header;
		}
		
		listViewContent += "</th>";
	}
	
	listViewContent += "</tr></thead><tbody>";
	for (var itemIndex = 0; itemIndex < this.ListChangedTarget.items.get_Count(); itemIndex++)
	{
		listViewContent += "<tr>";
		var listViewItem = this.ListChangedTarget.items.get_Item(itemIndex);
		for (var columnIndex = 0; columnIndex < listViewItem.values.length; columnIndex++)
			listViewContent += "<td>" + listViewItem.values[columnIndex] + "</td>";
		
		listViewContent += "</tr>";
	}
	
	listViewContent += "</tbody></table>";
	func("#" + this.ListChangedTarget.id).html(listViewContent);
	func('#tbl' + this.ListChangedTarget.id).flexRebuild();
}

function Forms_ListView_GetItems(){
	return this.items;
}

function Forms_ListView_GetColumns(){
	return this.columns;
}

function Forms_ListView_GetFullRowSelect(){
}

function Forms_ListView_SetFullRowSelect(bFullRowSelect){
	this.fullRowSelect = bFullRowSelect;
}

function Forms_ListView_GetGridLines(){
}

function Forms_ListView_SetGridLines(bGridLines){
    this.gridLines = bGridLines;
}

function Forms_ListView_GetView(){
}

function Forms_ListView_SetView(viewType){
}


function IGWindow() {
    this.id = "Main_Window";
    this.listObjects = [];
    this.docName = "";
    this.get_Item = IGWindow_GetItem;
    this.get_Owner = IGWindow_GetOwner;
    this.Maximize = Empty;              //
    this.Minimize = Empty;              // Não tem como fazer esses métodos
    this.Restore = Empty;               //
    this.OpenGraphic = IGWindow_OpenGraphic;
    this.Close = IGWindow_Close;
    this.get_Height = IGWindow_GetHeight;
	this.set_Height = IGWindow_SetHeight;
	this.get_Width = IGWindow_GetWidth;
	this.set_Width = IGWindow_SetWidth;
	this.get_Top = IGWindow_GetTop;
	this.set_Top = IGWindow_SetTop; 
	this.get_Left = IGWindow_GetLeft;
	this.set_Left = IGWindow_SetLeft; 
}

function ScriptGLocation(id, obj) {
    this.id = id;
    this.obj = obj;
    this.get_Top = Location_GetTop;
    this.set_Top = Location_SetTop;
    this.get_Left = Location_GetLeft;
    this.set_Left = Location_SetLeft;
}

function ScriptGSize(id, obj) {
    this.id = id;
    this.obj = obj;
    this.get_Width = Size_GetWidth;
    this.set_Width = Size_SetWidth;
    this.get_Height = Size_GetHeight;
    this.set_Height = Size_SetHeight;
    this.sizeChanged = Size_ChangedHandler;
}

function ConvertToList(array){
	var retList = new JSList();
	if(array instanceof Array){
		var retList = new JSList();
		for (var i = 0; i < ret.length; i++) {
		retList.Add(ret[i]);
		}
	}
	else if(array instanceof JSList){
		retList = array;
	}
	return retList;	
}

//######## KeyValuePair Methods

function JSKeyValuePair(key, value) {
    this.key = key;
    this.value = value;
    this.get_Key = JSKeyValuePair_GetKey;
    this.get_Value = JSKeyValuePair_GetValue;
}

function JSKeyValuePair_GetKey() {
    return this.key;
}

function JSKeyValuePair_GetValue() {
    return this.value;
}

//######## JSDictionaryEnumerator Methods

function JSDictionaryEnumerator(keys, values) {
	this.Reset = JSDictionaryEnumerator_Reset;
	this.MoveNext = JSDictionaryEnumerator_MoveNext;
	this.get_Current = JSDictionaryEnumerator_GetCurrent;
	this.count = values.length;
    this.enumeratorKeys = keys;
	this.enumeratorValues = values;
	this.enumeratorIndex = -1;
}

function JSDictionaryEnumerator_Reset() {
    this.enumeratorIndex = -1;
}

function JSDictionaryEnumerator_MoveNext() {
	if ((this.count > 0) && (this.enumeratorIndex < this.count - 1))
	{
		this.enumeratorIndex++;
		return true;
	}
	else
		return false;
}

function JSDictionaryEnumerator_GetCurrent() {
    return new JSKeyValuePair(this.enumeratorKeys[this.enumeratorIndex], this.enumeratorValues[this.enumeratorIndex]);
}

//######## JSDictionary Methods

function JSDictionary() {
    this.dicKeys = new Array();
    this.dicValues = new Array();
    this.count = 0;
    this.Add = Dictionary_Add;
    this.Remove = Dictionary_Remove;
    this.Clear = Dictionary_Clear;
    this.ContainsKey = Dictionary_ContainsKey;
    this.ContainsValue = Dictionary_ContainsValue;
    this.push = Dictionary_push;
    this.get_Count = Dictionary_GetCount;
    this.get_Item = Dictionary_GetItem;
    this.set_Item = Dictionary_SetItem;
    this.get_Keys = Dictionary_GetKeys;
    this.get_Values = Dictionary_GetValues;
    this.GetEnumerator = Dictionary_GetEnumerator;
}


function Dictionary_Add(key, value) {
    this.dicKeys[this.count] = key;
    this.dicValues[this.count] = value;
    this.count++;
}

function Dictionary_Clear(key) {
    this.dicKeys = new Array();
    this.dicValues = new Array();
    this.count = 0;
}

function Dictionary_Remove(key) {
    var indexToRemove = this.dicKeys.indexOf(key);
    this.dicKeys.splice(indexToRemove, 1);
    this.dicValues.splice(indexToRemove, 1);
    this.count--;
}


function Dictionary_push(key, value) {
    this.set_Item(key, value);
}

function Dictionary_ContainsKey(key) {
    return this.dicKeys.indexOf(key) >= 0;
}

function Dictionary_ContainsValue(value) {
    return this.dicValues.indexOf(value) >= 0;
}

function Dictionary_GetCount() {
    return this.count;
}

function Dictionary_GetItem(key) {
    var keyIndex = this.dicKeys.indexOf(key);
    return this.dicValues[keyIndex];
}

function Dictionary_SetItem(key, value) {
    var keyIndex = this.dicKeys.indexOf(key);
    this.dicValues[keyIndex] = value;
}

function Dictionary_GetKeys() {
    return this.dicKeys;
}

function Dictionary_GetValues() {
    return this.dicValues;
}

function Dictionary_GetEnumerator() {
	return new JSDictionaryEnumerator(this.dicKeys, this.dicValues);
}

//######## JSListEnumerator Methods

function JSListEnumerator(values) {
	this.Reset = JSListEnumerator_Reset;
	this.MoveNext = JSListEnumerator_MoveNext;
	this.get_Current = JSListEnumerator_GetCurrent;
	this.count = values.length;
	this.enumeratorValues = values;
	this.enumeratorIndex = -1;
}

function JSListEnumerator_Reset() {
    this.enumeratorIndex = -1;
}

function JSListEnumerator_MoveNext() {
	if ((this.count > 0) && (this.enumeratorIndex < this.count - 1))
	{
		this.enumeratorIndex++;
		return true;
	}
	else
		return false;
}

function JSListEnumerator_GetCurrent() {
    return this.enumeratorValues[this.enumeratorIndex];
}

//######## JSList Methods


function JSList() {
	this.listValues = new Array();
    this.count = 0;
    this.Add = List_Add;
	this.Insert = List_Insert;
    this.Remove = List_Remove;
	this.RemoveAt = List_RemoveAt;
	this.Clear = List_Clear;
    this.Contains = List_Contains;
    this.get_Count = List_GetCount;
    this.get_Item = List_GetItem;
    this.set_Item = List_SetItem;
	this.GetEnumerator = List_GetEnumerator;
    this.Except = List_Except;
    this.OrderBy = List_OrderBy;
    this.Distinct = List_Distinct;
	this.ListChanged;
	this.ListChangedTarget;
}

function List_Add(value) {
	if (arguments.length > 1)
	{
		this.listValues[this.count] = new Array();
		for (var argIndex = 0; argIndex < arguments.length; argIndex++)
			this.listValues[this.count][argIndex] = arguments[argIndex];
	}
	else
		this.listValues[this.count] = value;
		
	this.count++;
	if ((typeof this.ListChanged != 'undefined') && (this.ListChanged != null))
		this.ListChanged();
}

function List_Insert(index, value) {
	this.listValues.splice(index, 0, value);
	this.count++;
	if ((typeof this.ListChanged != 'undefined') && (this.ListChanged != null))
		this.ListChanged();
}

function List_Remove(value) {
    var indexToRemove = this.listValues.indexOf(value);
	if ((indexToRemove > -1) && (indexToRemove < this.count))
	{
		this.listValues.splice(indexToRemove, 1);
		this.count--;
	}
	
	if ((typeof this.ListChanged != 'undefined') && (this.ListChanged != null))
		this.ListChanged();
}

function List_RemoveAt(index) {
	if ((index > -1) && (index < this.count))
	{
		this.listValues.splice(index, 1);
		this.count--;
	}
	
	if ((typeof this.ListChanged != 'undefined') && (this.ListChanged != null))
		this.ListChanged();
}

function List_Clear() {
    this.listValues = new Array();
    this.count = 0;
	
	if ((typeof this.ListChanged != 'undefined') && (this.ListChanged != null))
		this.ListChanged();
}

function List_Contains(value) {
    return this.listValues.indexOf(value) >= 0;
}

function List_GetCount() {
    return this.count;
}

function List_GetItem(index) {
    return this.listValues[index];
}

function List_SetItem(index) {
    this.listValues[index] = value;
	if ((typeof this.ListChanged != 'undefined') && (this.ListChanged != null))
		this.ListChanged();
}

function List_GetEnumerator() {
	return new JSListEnumerator(this.listValues);
}

function List_Except(list1, caseSensitive) {
	var ret = new JSList();
	var upperThis = new JSList();
	for(var i =0; i< this.count;i++) {
		ret.Add(this.get_Item(i));
		upperThis.Add(this.get_Item(i).toUpperCase());
	}
		
	for(var j =0; j < list1.count;j++) {
		if(caseSensitive){
			if(this.Contains(list1.get_Item(j)))
				ret.Remove(list1.get_Item(j));
		}
		else {
			if(upperThis.Contains(list1.get_Item(j).toUpperCase())) {
				ret.Remove(list1.get_Item(j));
				ret.Remove(list1.get_Item(j).toUpperCase());
			}
		}
	}
	
    return ret;	
}

function List_OrderBy(){
    this.listValues.sort();
    return this;
}

function List_Distinct(){
    var ret = new JSList();
    for(var i=0; i< this.count;i++){
        if(!ret.Contains(this.get_Item(i)))
            ret.Add(this.get_Item(i));
    }

    return ret;
}

/*function List_ToArray(){
    return this.listValues;
}*/

//######## JSRandom Methods

function JSRandom(seed) {
    this.Next = Random_Next;
    this.NextDouble = Random_Next_Double;
    this.NextBytes = Random_Next_Bytes;
}

function JSRandom() {
    this.Next = Random_Next;
    this.NextDouble = Random_Next_Double;
    this.NextBytes = Random_Next_Bytes;
}

function Random_Next(min, max) {
    if (min === undefined && max === undefined)
        return Random_Next_1(0, Number.MAX_SAFE_INTEGER);
    else if (max === undefined)
        return Random_Next_1(0, min);
    else
        return Random_Next_1(min, max)
}

function Random_Next_1(min, max) {
    return Math.floor(min + Math.random() * (max + 1 - min))
}

function Random_Next_Double() {
    return Math.random();
}

function Random_Next_Bytes(buffer) {
    if (buffer !== null && buffer !== undefined) {
        for (var i = 0; i < buffer.length; i++) {
            buffer[i] = Random_Next_1(0, 255);
        }
    }
}

//############### End Classes ###############

//############### Start Methods ###############

//######## IAbstractGObject Methods
function Abstract_GetEnabled() {
    return this.enabled;
}

function Abstract_SetEnabled(enabled) {
    this.enabled = enabled;
    this.UpdateEnabled();
}

function ITemplate_SetEnabled(enabled) {
    this.enabled = enabled;
    this.UpdateEnabled();
    if (this.isTemplateGroup) {
        for (var i = 0; i < this.children.length; i++) {
            this.children[i].parentEnabled = enabled;
            this.children[i].UpdateEnabled();
        }
    }
}

function Abstract_GetVisible() {
    return this.visible;
}

function Abstract_SetVisible(visible) {
    this.visible = visible;
    this.UpdateVisible();
}

function Abstract_UpdateEnabled() {
    var clsName = this.instanceOf;
    var isInputLabelObject = clsName == "ICheckBox" || clsName == "IRadioButton";
    if (this.enabled && this.parentEnabled) {
        func('#' + this.id).css('pointer-events', 'auto');
        func('#' + this.id).css('opacity', '');
		func('#' + this.id).css('filter', '');
        func('#' + this.id).removeAttr('disabled');
        if (isInputLabelObject) {
            func("label[for='" + this.id + "']").css('pointer-events', 'auto');
            func("label[for='" + this.id + "']").removeAttr('disabled');
            func("label[for='" + this.id + "']").css('opacity', '');
            func("label[for='" + this.id + "']").css('filter', '');
        } else if (clsName === "IMatrixGrid") {
            this.EnableDisableControls();
        }
    } else {
        func('#' + this.id).css('pointer-events', 'none');
        func('#' + this.id).attr('disabled', 'disabled');
        func('#' + this.id).css('opacity', '0.5');
		func('#' + this.id).css('filter', 'alpha(opacity=50)');
        if (isInputLabelObject) {
            func("label[for='" + this.id + "']").css('pointer-events', 'none');
            func("label[for='" + this.id + "']").attr('disabled', 'disabled');
            func("label[for='" + this.id + "']").css('opacity', '0.5');
            func("label[for='" + this.id + "']").css('filter', 'alpha(opacity=50)');
        } else if (clsName === "IMatrixGrid") {
            func('#control' + this.originalName).find('button').each(function () {
                func(this).css('pointer-events', 'none');
                func(this).attr('disabled', 'disabled');
            });
            func('#control' + this.originalName).find('input').each(function () {
                func(this).css('pointer-events', 'none');
                func(this).attr('disabled', 'disabled');
            });
        }
    }
}

function Abstract_UpdateVisible() {
    var clsName = this.instanceOf;
	var func;
	if($ !=  undefined)
		func = $;
	else
		func = J;
	var isInputLabelObject = clsName == "ICheckBox" || clsName == "IRadioButton";
    if (this.visible) {
        if(clsName == "IMatrixGrid")
			func('#' + this.id).parent().show();
		else
			func('#' + this.id).show();
        if (isInputLabelObject) {
            func("label[for='" + this.id + "']").css('visibility', 'visible');
            func("label[for='" + this.id + "']").show();
        }
    } else {
        if(clsName == "IMatrixGrid")
			func('#' + this.id).parent().hide();
		else
			func('#' + this.id).hide();
        if (isInputLabelObject) {
            func("label[for='" + this.id + "']").css('visibility', 'hidden');
            func("label[for='" + this.id + "']").hide();
        }
    }
}

function Abstract_GetLocation() {
    return this.location;
}

function Abstract_GetSize() {
    return this.size;
}

//######## IAbstractGObjectRotatable Methods
function Rotatable_GetAngle() {
    var clsName = this.instanceOf;
    var isSVGObject = clsName == "ILine" || clsName == "IPolygon" || clsName == "IPolyLine" || clsName == "IRectangle" || clsName == "IEllipse" || clsName == "ILabel"|| clsName == "ICheckBox"|| clsName == "IRadioButton";;
    if (!isSVGObject) {
		var name = this.id;
		if (this.instanceOf == "ICheckBox" || this.instanceOf == "IRadioButton")
			name = 'lbl' + name;
        return parseFloat(func('#' + name).getRotateAngle());
    } else {
        return parseFloat(this.angle);
    }
}

var changingAngleByTag = false;
function Rotatable_SetAngle(angle) {
	var clsName = this.instanceOf;
	var isSVGObject = clsName == "ILine" || clsName == "IPolygon" || clsName == "IRectangle" || clsName == "IEllipse" || clsName == "IPolyLine" || clsName == "ILabel"|| clsName == "ICheckBox"|| clsName == "IRadioButton";;
	if (isSVGObject) {
	    this.angle = angle;
	}
	
	var name = this.id;
	if (this.instanceOf == "ICheckBox" || this.instanceOf == "IRadioButton")
		name = 'lbl' + name;
	if (this.center_marker_left !== undefined && this.center_marker_top !== undefined) {
	    func('#' + name).rotate({
	        center: [this.center_marker_left + "px", this.center_marker_top + "px"],
	        angle: angle
	    });
	} else {
	    func('#' + name).rotate(angle);
    }
	
	if((changingAngleByTag == undefined || changingAngleByTag == false) && this.writeScriptTagExprAngle != undefined)
        this.writeScriptTagExprAngle();
}

function Rotatable_SetCenterMarker(left, top) {
    this.center_marker_left = left;
    this.center_marker_top = top;
}

//######## ScriptGLocation Methods
function Location_GetTop() {
    var clsName = this.obj.instanceOf;
    var isSVGObject = clsName == "ILine" || clsName == "IPolygon" || clsName == "IPolyLine" || clsName == "IEllipse";
    if (isSVGObject) {
        return this.obj.top;
    } else {
        return parseFloat(func('#' + this.id).css('top'));
    }
}

function Location_SetTop(top) {
	if(top !== undefined)
	{
		top = parseFloat(top.toString());
		if(isNaN(top))
			return;
	}
    var clsName = this.obj.instanceOf;
    if (clsName == "ILine") {
        this.obj.setTop(top);
    } else if (clsName == "IEllipse") {
        func('#' + this.id).css('top', top);
        func('#' + this.id).attr('cy', top + (this.obj.get_Height() / 2));
    } else if (clsName == "ICheckBox" || clsName == "IRadioButton") {
        func('#Grp' + this.id).css('top', top);
    } else if (clsName == "ITab") {
        J('#' + this.id).css('top', top);
    } else if (clsName == "IMatrixGrid") {
        func('#' + this.id).parent().css('top', top);
    } else {
        func('#' + this.id).css('top', top);
    }
	this.obj.top = top;
	
	if(this.writeScriptTagExprSizeLocation != undefined)
        this.writeScriptTagExprSizeLocation();
}

function Location_GetLeft() {
    var clsName = this.obj.instanceOf;
    var isSVGObject = clsName == "ILine" || clsName == "IPolygon" || clsName == "IPolyLine" || clsName == "IEllipse";
    if (isSVGObject) {
        return this.obj.left;
    } else {
        return parseFloat(func('#' + this.id).css('left'));
    }
}

function Location_SetLeft(left) {
	if(left !== undefined)
	{
		left = parseFloat(left.toString());
		if(isNaN(left))
			return;
	}
    var clsName = this.obj.instanceOf;
    if (clsName == "ILine") {
        this.obj.setLeft(left);
    } else if (clsName == "IEllipse") {
        func('#' + this.id).css('left', left);
        func('#' + this.id).attr('cx', left + (this.obj.get_Width() / 2));
    } else if (clsName == "ICheckBox" || clsName == "IRadioButton") {
        func('#Grp' + this.id).css('left', left);
    } else if (clsName == "ITab") {
        J('#' + this.id).css('left', left);
    } else if (clsName == "IMatrixGrid") {
        func('#' + this.id).parent().css('left', left);
    } else {
        func('#' + this.id).css('left', left);
    }
	this.obj.left = left;
	
	if(this.writeScriptTagExprSizeLocation != undefined)
        this.writeScriptTagExprSizeLocation();
}

//######## ScriptGSize Methods
function Size_GetWidth() {
    var clsName = this.obj.instanceOf;
    if (clsName == "ICheckBox" || clsName == "IRadioButton")
        return func('#lbl' + this.id).width();
    else if (clsName == "IGroupbox")
        return roundValue(func('#' + this.id).width() + 18);
    else
        return func('#' + this.id).width();
}

function Size_SetWidth(width) {
    if (width <= 0)
        return;

    var oldWidth = this.get_Width();
    var clsName = this.obj.instanceOf;
    if (clsName == "ICheckBox" || clsName == "IRadioButton")
        func('#lbl' + this.id).width(width);
    else if (clsName == "IGroupbox")
        func('#' + this.id).width(width - 18);
    else
        func('#' + this.id).width(width);
    this.sizeChanged(oldWidth, this.get_Height());
	
	if(this.writeScriptTagExprSizeLocation != undefined)
        this.writeScriptTagExprSizeLocation();
}

function Size_GetHeight() {
    var clsName = this.obj.instanceOf;
    if (clsName == "ICheckBox" || clsName == "IRadioButton")
        return func('#lbl' + this.id).height();
    else if (clsName == "IGroupbox")
        return roundValue(func('#' + this.id).height() + 8.6);
    else
        return func('#' + this.id).height();
}

function Size_SetHeight(height) {
    if (height <= 0)
        return;

    var oldHeight = this.get_Height();
    var clsName = this.obj.instanceOf;
    if (clsName == "ICheckBox" || clsName == "IRadioButton")
        func('#lbl' + this.id).height(height);
    else if (clsName == "IGroupbox")
        func('#' + this.id).height(height - 8.6);
    else
        func('#' + this.id).height(height);
    this.sizeChanged(this.get_Width(), oldHeight);
}

function Size_ChangedHandler(oldWidth, oldHeight) {

	// Template resize children
    if (this.isTemplateGroup) {
        var widDiff = this.get_Width() / oldWidth;
        var heiDiff = this.get_Height() / oldHeight;
        for (var i = 0; i < this.children.length; i++) {
            if (this.children[i].obj.instanceOf == "ICheckBox" || this.children[i].obj.instanceOf == "IRadioButton") {
                func('#lbl' + this.children[i].id).width(this.children[i].get_Width() * widDiff);
                func('#lbl' + this.children[i].id).height(this.children[i].get_Height() * heiDiff);
            }
            else {
                func('#' + this.children[i].id).width(this.children[i].get_Width() * widDiff);
                func('#' + this.children[i].id).height(this.children[i].get_Height() * heiDiff);
            }

            if (widDiff != 1) {
                if (this.children[i].obj.instanceOf == "ILine") {
                    this.children[i].obj.setLeft(this.children[i].get_Left() * widDiff);
                } else if (this.children[i].obj.instanceOf == "IEllipse") {
                    func('#' + this.children[i].id).css('left', this.children[i].get_Left() * widDiff);
                    func('#' + this.children[i].id).attr('cx', (this.children[i].get_Left() * widDiff) + (this.children[i].obj.get_Width() / 2));
                } else if (this.children[i].obj.instanceOf == "ICheckBox" || this.children[i].obj.instanceOf == "IRadioButton") {
                    func('#' + this.children[i].id).css('left', this.children[i].get_Left() * widDiff);
                    func('#lbl' + this.children[i].id).css('left', this.children[i].get_Left() * widDiff);
                } else if (this.children[i].obj.instanceOf == "ITab") {
                    J('#' + this.children[i].id).css('left', this.children[i].get_Left() * widDiff);
                } else if (this.children[i].obj.instanceOf == "IMatrixGrid") {
                    func('#' + this.children[i].id).parent().css('left', this.children[i].get_Left() * widDiff);
                } else {
                    func('#' + this.children[i].id).css('left', this.children[i].get_Left() * widDiff);
                }
                this.children[i].obj.left = this.children[i].get_Left() * widDiff;
            }
            else if (heiDiff != 1) {
                if (this.children[i].obj.instanceOf == "ILine") {
                    this.children[i].obj.setTop(this.children[i].get_Top() * heiDiff);
                } else if (this.children[i].obj.instanceOf == "IEllipse") {
                    func('#' + this.children[i].id).css('top', this.children[i].get_Top() * heiDiff);
                    func('#' + this.children[i].id).attr('cy', (this.children[i].get_Top() * heiDiff) + (this.children[i].obj.get_Height() / 2));
                } else if (this.children[i].obj.instanceOf == "ICheckBox" || this.children[i].obj.instanceOf == "IRadioButton") {
                    func('#' + this.children[i].id).css('top', this.children[i].get_Top() * heiDiff);
                    func('#lbl' + this.children[i].id).css('top', this.children[i].get_Top() * heiDiff);
                } else if (this.children[i].obj.instanceOf == "ITab") {
                    J('#' + this.children[i].id).css('top', this.children[i].get_Top() * heiDiff);
                } else if (this.children[i].obj.instanceOf == "IMatrixGrid" || this.children[i].obj.instanceOf == "IGroupScreen") {
                    func('#' + this.children[i].id).parent().css('top', this.children[i].get_Top() * heiDiff);
                } else {
                    func('#' + this.children[i].id).css('top', this.children[i].get_Top() * heiDiff);
                }
                this.children[i].obj.top = this.children[i].get_Top() * heiDiff;
            }
        }
    }


    // Chart Replot to keep Legend and Title formats
    if (this.chartType != undefined && this.chartType != "") {
        var titleStyle = document.getElementById(this.id).getElementsByClassName('jqplot-title');
        var arrayTitleStyle = undefined;
        if (titleStyle.length > 0)
            arrayTitleStyle = [titleStyle[0].style.fontWeight, titleStyle[0].style.fontStyle, titleStyle[0].style.fontSize, titleStyle[0].style.marginTop, titleStyle[0].style.marginLeft, titleStyle[0].style.textAlign, titleStyle[0].style.color];
        var legendStyle = func('#' + this.id)[0].querySelector('table.jqplot-table-legend');
        var arrayLegendStyle = undefined;
        if (legendStyle != undefined && legendStyle != null)
            arrayLegendStyle = [legendStyle.style.fontFamily, legendStyle.style.fontSize, legendStyle.style.fontWeight, legendStyle.style.fontStyle, legendStyle.style.color];

        if (this.chartType != "pie") {
            var showHorizontalLines = this.plot.axes.yaxis.tickOptions.showGridline;
            var showVerticalLines = this.plot.axes.xaxis.tickOptions.showGridline;
            this.plot = $.jqplot(this.id, this.data, this.options);
            this.plot.axes.yaxis.tickOptions.showGridline = showHorizontalLines;
            this.plot.axes.xaxis.tickOptions.showGridline = showVerticalLines;
            this.plot.replot();
        }
        else {
            var plotAreaHei = (this.get_Height() - (Number(this.options.title.fontSize.replace("px", "")) + 8));
            var plotAreaWid = this.get_Width() - this.options.legend.legendWidth - 19;
            var diameter = (plotAreaHei < plotAreaWid ? plotAreaHei : plotAreaWid) - 40;
            this.options.seriesDefaults.rendererOptions.diameter = (diameter <= 0 ? 1 : diameter);
            this.plot = $.jqplot(this.id, [this.data], this.options);
            this.plot.replot();
        }

        var currentTitleStyle = document.getElementById(this.id).getElementsByClassName('jqplot-title');
        if (currentTitleStyle.length > 0) {
            currentTitleStyle[0].style.fontWeight = arrayTitleStyle[0];
            currentTitleStyle[0].style.fontStyle = arrayTitleStyle[1];
            currentTitleStyle[0].style.fontSize = arrayTitleStyle[2];
            currentTitleStyle[0].style.marginTop = arrayTitleStyle[3];
            currentTitleStyle[0].style.marginLeft = arrayTitleStyle[4];
            currentTitleStyle[0].style.textAlign = arrayTitleStyle[5];
            currentTitleStyle[0].style.color = arrayTitleStyle[6];
        }
        var currentLegendStyle = func('#' + this.id)[0].querySelector('table.jqplot-table-legend');
        if (currentLegendStyle !== null) {
            currentLegendStyle.style.fontFamily = arrayLegendStyle[0];
            currentLegendStyle.style.fontSize = arrayLegendStyle[1];
            currentLegendStyle.style.fontWeight = arrayLegendStyle[2];
            currentLegendStyle.style.fontStyle = arrayLegendStyle[3];
            currentLegendStyle.style.color = arrayLegendStyle[4];
        }
    }
	
	if(this.writeScriptTagExprSizeLocation != undefined)
        this.writeScriptTagExprSizeLocation();
}

//######## Common Methods
function ICommon_GetText() {
    if (this.instanceOf == "IGroupbox")
        return func('#' + this.id + ' legend').text();
    else if (this.instanceOf == "ICheckBox" || this.instanceOf == "IRadioButton")
        return func("label[for='" + this.id + "']").text();
    else if (this.instanceOf == "ILabel" || this.instanceOf == "IButton")
        return func('#' + this.id).html();
    return func('#' + this.id).val();
}

function ICommon_SetText(text) {
    if(this.AssignValueToFirstTag == false)
		    return;
    
    if ((text == "NaN") || (text == null) || (text == undefined))
		return "";

    if (this.instanceOf == "IGroupbox") {
        func('#' + this.id + ' legend').text(text.toString());
    } else if (this.instanceOf == "ICheckBox" || this.instanceOf == "IRadioButton") {
        var elem = document.getElementById("lbl" + this.id);
		elem.firstChild.textContent = text;
    } else if (this.instanceOf == "ILabel" || this.instanceOf == "IButton") {
        func('#' + this.id).html(text.toString());
    } else {
        func('#' + this.id).val(text);
    }

    if(this.writeScriptTagExpr != undefined)
        this.writeScriptTagExpr();
}

function ICommon_GetFontColor() {
	var ret = "";
    if (this.instanceOf == "IGroupbox")
        ret = func('#' + this.id + ' legend').css('color');
    else if (this.instanceOf == "IMenu")
        ret = func('#' + this.id + ' li a').css('color');
    else if (this.instanceOf == "ITab")
        ret = func('#' + this.id + ' ul li a').css('color');
    else if (this.instanceOf == "ICheckBox" || this.instanceOf == "IRadioButton")
        ret = func("label[for='" + this.id + "']").css('color');
    else
		ret = func('#' + this.id).css('color');
	
	if (ret != undefined && ret != "") {
		var hex = ret.replace("rgb(", "").replace("rgba(", "").replace(")", "").replace(" ", "");
		var rgba = hex.split(",");
		hex = rgba.length == 4 ? ("#" + parseInt(Math.round(parseFloat(rgba[3]) * 255).toString()).toString(16)) : "#";
        hex += parseInt(rgba[0]).toString(16).padStart(2, '0') + parseInt(rgba[1]).toString(16).padStart(2, '0') + parseInt(rgba[2]).toString(16).padStart(2, '0');
        return hex.toUpperCase();
	}
	return ret;
}

function ICommon_SetFontColor(color) {
    if (this.instanceOf == "IGroupbox")
        func('#' + this.id + ' legend').css('color', color);
    else if (this.instanceOf == "IMenu")
        func('#' + this.id + ' li a').css('color', color);
    else if (this.instanceOf == "ITab")
        func('#' + this.id + ' ul li a').css('color', color);
    else if (this.instanceOf == "ICheckBox" || this.instanceOf == "IRadioButton")
        func("label[for='" + this.id + "']").css('color', color);
    else {
        if(this.instanceOf == "IComboBox") {
			var length = document.getElementById(this.id).options.length;
			for(var i=0;i<length;i++)
				func('#opt' + i + this.id).css('color', color);
		}
		func('#' + this.id).css('color', color);
	}
}

//######## ITextBox Methods
function ITextBox_ResetPasswordBox() {
    func('#' + this.id).val('');
}

function ITextBox_GetFocus() {
    func('#' + this.id).focus();
}

function ITextBox_SelectAll() {
    func('#' + this.id).select();
}

//######## ICommonCheck Methods
function ICommonCheck_GetIsChecked() {
    return document.getElementById(this.id).checked;
}

function ICommonCheck_SetIsChecked(checked, suppressWrite, supressInputUpdate) {
	var originalState = checked;
    if (checked == null) {
        if (this.instanceOf == "ICheckBox" && this.threeState)
            func('#' + this.id).prop('indeterminate', true);
        checked = false;
		originalState = "indeterminate";
    } else if (this.instanceOf == "ICheckBox") {
        func('#' + this.id).prop('indeterminate', false);
    }
	
    document.getElementById(this.id).checked = checked;
	if ((supressInputUpdate != true) && (this.instanceOf == "ICheckBox" || this.instanceOf == "IRadioButton")) {
		func('#' + this.id).prop('checked', checked == null ? false : checked);
	}
    if(this.writeCheckedTag && !suppressWrite)
        this.writeCheckedTag(originalState);
}

//######## ICheckBox Methods
function ICheckBox_GetIsCheckedInt() {
	var elem = document.getElementById(this.id);
	if(this.threeState && elem.indeterminate)
		return -1;
	else
		return elem.checked ? 1 : 0;
}

function ICheckBox_SetIsCheckedInt(checked, suppressWrite, supressInputUpdate) {
    if (checked == -1) {
        this.set_IsChecked(null, suppressWrite, supressInputUpdate);
    } else if (checked == 0) {
        this.set_IsChecked(false, suppressWrite, supressInputUpdate);
    } else {
        this.set_IsChecked(true, suppressWrite, supressInputUpdate);
    }
}

//######## IRectangle/IEllipse Methods
function IGeometric_GetWidth() {
    var clsName = this.instanceOf;
    if (clsName == 'IRectangle')
        return parseFloat(func('#' + this.id).width());
	else
	{
		var rx = this.width / 2;
		var cx = rx + this.left;
		if (clsName == 'IEllipse')
            return parseFloat(func('#' + this.id).find('ellipse').attr('rx')) * 2;
		else if (clsName == 'IPolyLine')
            return parseFloat(func('#' + this.id).find('polyline').attr('rx')) * 2;
		else if (clsName == 'IPolygon')
            return parseFloat(func('#' + this.id).find('polygon').attr('rx')) * 2;
	}
}

function IGeometric_SetWidth(width) {
    var clsName = this.instanceOf;
    if (clsName == 'IRectangle')
	{
		var strokeWidth = func('#' + this.id).find('rect')[0].style.strokeWidth;
        func('#' + this.id).find('rect').attr('width', width - (strokeWidth != undefined && strokeWidth != null && strokeWidth != "" ? parseFloat(strokeWidth.toString().replace("px", "")) : 1));
		func('#' + this.id).width(width);
	}
	else
	{
		var rx = width / 2;
		var cx = rx + this.left;
		if (clsName == 'IEllipse') {
			func('#' + this.id).find('ellipse').attr('cx', cx);
			func('#' + this.id).find('ellipse').attr('rx', rx);
		}
		else if (clsName == 'IPolyLine') {
			func('#' + this.id).find('polyline').attr('cx', cx);
			func('#' + this.id).find('polyline').attr('rx', rx);
		}
		else if (clsName == 'IPolygon') {
			func('#' + this.id).find('polygon').attr('cx', cx);
			func('#' + this.id).find('polygon').attr('rx', rx);
		}
	}
}

function IGeometric_GetHeight() {
    var clsName = this.instanceOf;
    if (clsName == 'IRectangle')
        return parseFloat(func('#' + this.id).height());
	else
	{
		var ry = this.height / 2;
        var cy = ry + this.top;
		if (clsName == 'IEllipse')
            return parseFloat(func('#' + this.id).find('ellipse').attr('ry')) * 2;
		else if (clsName == 'IPolyLine')
            return parseFloat(func('#' + this.id).find('polyline').attr('ry')) * 2;
		else if (clsName == 'IPolygon') 
            return parseFloat(func('#' + this.id).find('polygon').attr('ry')) * 2;
	}
}

function IGeometric_SetHeight(height) {
    var clsName = this.instanceOf;
    if (clsName == 'IRectangle')
	{
		var strokeWidth = func('#' + this.id).find('rect')[0].style.strokeWidth;
        func('#' + this.id).find('rect').attr('height', height - (strokeWidth != undefined && strokeWidth != null && strokeWidth != "" ? parseFloat(strokeWidth.toString().replace("px", "")) : 1));
		func('#' + this.id).height(height);
	}
	else
	{
		var ry = height / 2;
        var cy = ry + this.top;
	
		if (clsName == 'IEllipse') {
			func('#' + this.id).find('ellipse').attr('cy', cy);
			func('#' + this.id).find('ellipse').attr('ry', ry);
		}
		else if (clsName == 'IPolyLine') {
			func('#' + this.id).find('polyline').attr('cy', cy);
			func('#' + this.id).find('polyline').attr('rx', ry);
		}
		else if (clsName == 'IPolygon') {
			func('#' + this.id).find('polygon').attr('cy', cy);
			func('#' + this.id).find('polygon').attr('ry', ry);
		}
	}
}

function CreateFunctions(options) {
	options.Add = function(text){
		var option = document.createElement("option");
		option.text = text;
		this.add(option);
	};
	
	options.Clear = function(){
		this.length = 0;
	};
	
	options.get_Count = function() {
		return this.length;
	};

    options.RemoveAt = function(index){
		this.remove(index);
	};

    options.get_Item = function(i){
		if ((this[i] != "null") && (this[i] != null) && (this[i] != "undefined") && (this[i] != undefined))
			return this[i].text;
		
		return this[i];
	};
	
	options.GetEnumerator = function(){
		var array = [];
		for(var i =0; i< this.length;i++)
		{
			array.push(this[i].text);
		}
		return new JSListEnumerator(array);
	};
}

//######## ILine/IPolygon/IPolyLine Methods
function ILine_GetX1() {
    return parseFloat(func('#' + this.id + '_Children').attr('x1')) + this.obj.left;
}

function ILine_SetX1(value) {
	this.obj.left = value;
	parseFloat(func('#' + this.id).css('left', value));
    return func('#' + this.id + '_Children').attr('x1', 0);
}

function ILine_GetY1() {
    return parseFloat(func('#' + this.id + '_Children').attr('y1')) + this.obj.top;
}

function ILine_SetY1(value) {
	this.obj.top = value;
	parseFloat(func('#' + this.id).css('top', value));
    return func('#' + this.id + '_Children').attr('y1', 0);
}

function ILine_GetX2() {
    return parseFloat(func('#' + this.id + '_Children').attr('x2')) + this.obj.left;
}

function ILine_SetX2(value) {
    return func('#' + this.id + '_Children').attr('x2', value - this.obj.left);
}

function ILine_GetY2() {
    return parseFloat(func('#' + this.id + '_Children').attr('y2')) + this.obj.top;
}

function ILine_SetY2(value) {
    return func('#' + this.id + '_Children').attr('y2', value - this.obj.top);
}

function IGeometric_SetLeft(left) {
    var clsName = this.instanceOf;
    if (clsName == 'ILine') {
        var X1 = this.get_X1(), X2 = this.get_X2();
        X1 = (X1 - this.left) + left;
        X2 = (X2 - this.left) + left;
        this.set_X1(X1);
        this.set_X2(X2);
    } else {
        var points = stringToPoints(func('#' + this.id + '_Children').attr('points'));
        for (var i = 0, l = points.length; i < l; i++) {
            points[i].X = (points[i].X - this.left) + left;
        }
        var stringPoints = pointsToString(points);
        func('#' + this.id + '_Children').attr('points', stringPoints);
    }
    this.left = left;
}

function IGeometric_SetTop(top) {
    var clsName = this.instanceOf;
    if (clsName == 'ILine') {
        var Y1 = this.get_Y1(), Y2 = this.get_Y2();
        Y1 = (Y1 - this.top) + top;
        Y2 = (Y2 - this.top) + top;
        this.set_Y1(Y1);
        this.set_Y2(Y2);
    } else {
        var points = stringToPoints(func('#' + this.id + '_Children').attr('points'));
        for (var i = 0, l = points.length; i < l; i++) {
            points[i].Y = (points[i].Y - this.top) + top;
        }
        var stringPoints = pointsToString(points);
        func('#' + this.id + '_Children').attr('points', stringPoints);
    }
    this.top = top;
}

function IGeometric_GetPoints() {
    return null;
}

//######## IGroupScreen Methods
function IGroupScreen_SetScreen(graphic, tag, tagVal) {
    if(graphic != ""){
		if (graphic.trim() != '') {
			graphic = graphic.replace(/\\/g, folderSeparator).replace(/\//g, folderSeparator);
			if (graphic.indexOf('.html') == -1) {
				graphic = graphic + '.html';
			}
		}
		
		var parsedScreenTags = "";
		if (tag != undefined && tag != null && tag != "" &&
			tagVal != undefined && tagVal != null && tagVal != "")
            parsedScreenTags += screenTagSeparator + tag + screenTagSeparator + tagVal;
		
		SetScreen(this.id, apiLocation + graphic, parsedScreenTags);
	}
	else{
		ClearScreen(this.id);
	}
	var screen = document.getElementById(this.id);
	if(graphic.endsWith('.html'))
		screen.selectedScreen = graphic.substr(0, graphic.length - 5);
	else
	    screen.selectedScreen = graphic;
	this.NeedToUpdateScroll = true;
}

function IGroupScreen_SetScreenDic(graphic, screenTags) {
    if (graphic != "") {
        var graphicHTMLFile = graphic;
        if (graphic.trim() != '') {
            graphic = graphic.replace(/\\/g, folderSeparator).replace(/\//g, folderSeparator);
            if (graphic.indexOf('.html') == -1) {
                graphicHTMLFile = graphic + '.html';
            }
        }

        var parsedScreenTags = "";
        var tagsFullNames = "";
        var screenTagsNames = "";
        var tagNames = screenTags.dicValues.toString().split(",");
        var screenTag = screenTags.dicKeys.toString().split(",");

        for (i = 0; i < tagNames.length; i++) {
            tagsFullNames += tagNames[i].toString() + "|"; //GetTagNames(tagNames[i].toString()) + "|";
            screenTagsNames += screenTag[i] + "|";
        }

        parsedScreenTags = graphic + screenTagSeparator + screenTagsNames + screenTagSeparator + tagsFullNames;
        SetScreen(this.id, apiLocation + graphicHTMLFile, parsedScreenTags);
    }
    else {
        ClearScreen(this.id);
    }

    var screen = document.getElementById(this.id);
    if (graphicHTMLFile.endsWith('.html'))
        screen.selectedScreen = graphicHTMLFile.substr(0, graphicHTMLFile.length - 5);
    else
        screen.selectedScreen = graphicHTMLFile;
    this.NeedToUpdateScroll = true;
}

function IGroupScreen_ClearScreen() {
    ClearScreen(this.id);
    this.NeedToUpdateScroll = true;
}

function IGroupScreen_GetCurrentScreen(){
    var screen = document.getElementById(this.id);
    return screen.selectedScreen;
}

function IGroupScreen_SetInitialScreen(screenName){
	var screen = document.getElementById(this.id);
    screen.selectedScreen = screenName;
}

//######## IBitmap Methods
function IBitmap_GetSource() {
	var bitmapSource = func('#' + this.id).attr('src');
    if ((bitmapSource != null) && (bitmapSource != undefined) && (bitmapSource != "./htmlImages/TransparentImage.png")) {
        if (bitmapSource.endsWith("_paused.png") && SVFile.FileExists(bitmapSource.toString().replace("_paused.png", ".gif")))
            return bitmapSource.toString().replace("_paused.png", ".gif").replace(/^.*[\\\/]/, '');
        return bitmapSource.toString().replace(/^.*[\\\/]/, '');
    }
	
	return "";
}

function IBitmap_SetSource(src) {
    if (!this.isDynamicImage) {
        if (src != undefined || src != null) {
            func('#' + this.id).attr('src', apiLocation + 'Images/' + src);
            if (src.toLowerCase().endsWith(".gif")) {
                if (!this.gifInfiniteLoop) {
                    var bitmapID = this.id;
                    var duration = SVFile.GetGifPlayTime(src);
                    if (this.timeout != undefined && this.timeout != null) {
                        window.clearTimeout(this.timeout);
                        this.timeout = null;
                    }
                    if (!this.gifByDuration) {
                        if (duration <= 0 || this.gifCount <= 0)
                            return;
                        this.timeout = setTimeout(function () { IBitmap_Pause(bitmapID); }, duration * this.gifCount);
                    }
                    else
                        this.timeout = setTimeout(function () { IBitmap_Pause(bitmapID); }, this.gifDuration);
                }
            }
        }
    }
}

function IBitmap_Play() {
    var scr = func('#' + this.id).attr('src');
    var source = "";
    if (scr != null && scr != undefined)
        source = scr.toString().replace(/^.*[\\\/]/, '');

    if (source != "" && source.endsWith("_paused.png")) {
        source = source.replace("_paused.png", ".gif");
        func('#' + this.id).attr('src', apiLocation + 'Images/' + source);
        if (source.toLowerCase().endsWith(".gif")) {
            if (!this.gifInfiniteLoop) {
                var bitmapID = this.id;
                var duration = SVFile.GetGifPlayTime(source);
                if (this.timeout != undefined && this.timeout != null) {
                    window.clearTimeout(this.timeout);
                    this.timeout = null;
                }
                if (!this.gifByDuration) {
                    if (duration <= 0 || this.gifCount <= 0)
                        return;
                    this.timeout = setTimeout(function () { IBitmap_Pause(bitmapID); }, duration * this.gifCount);
                }
                else
                    this.timeout = setTimeout(function () { IBitmap_Pause(bitmapID); }, this.gifDuration);
            }
        }
    }
}

function IBitmap_Pause(bitmapID) {
    if (bitmapID == undefined)
        bitmapID = this.id;

    var scr = func('#' + bitmapID).attr('src');
    var source = "";
    if (scr != null && scr != undefined)
        source = scr.toString().replace(/^.*[\\\/]/, '').replace(".gif", "_paused.png");

    if (source != "")
        func('#' + bitmapID).attr('src', apiLocation + 'Images/' + source);
}

function IBitmap_Restart() {
    var scr = func('#' + this.id).attr('src');
    var source = "";
    if (scr != null && scr != undefined)
        source = scr.toString().replace(/^.*[\\\/]/, '').replace("_paused.png", ".gif");

    if (source != "") {
        func('#' + this.id).attr('src', apiLocation + 'Images/' + source);
        if (source.toLowerCase().endsWith(".gif")) {
            if (!this.gifInfiniteLoop) {
                var bitmapID = this.id;
                var duration = SVFile.GetGifPlayTime(source);
                if (this.timeout != undefined && this.timeout != null) {
                    window.clearTimeout(this.timeout);
                    this.timeout = null;
                }
                if (!this.gifByDuration) {
                    if (duration <= 0 || this.gifCount <= 0)
                        return;
                    this.timeout = setTimeout(function () { IBitmap_Pause(bitmapID); }, duration * this.gifCount);
                }
                else
                    this.timeout = setTimeout(function () { IBitmap_Pause(bitmapID); }, this.gifDuration);
            }
        }
    }
}

//######## IChart Methods
function IChart_UpdateVisible() {
    if (this.visible) {
        func('#' + this.id).show();
        if (this.plot != null)
            Chart_Replot(this);
    }
    else
        func('#' + this.id).hide();
}

function Chart_GetTitle(){
    return func('#' + this.id)[0].querySelector(".jqplot-title").innerText;
}

function Chart_SetTitle(title) {
    func('#' + this.id)[0].querySelector(".jqplot-title").innerText = title;
    var exprName = "Expr_" + this.id + "_SetTitle";
    window[exprName](title);
}

function Chart_GetTitleHorizontalAlignment() {
    return func('#' + this.id)[0].querySelector(".jqplot-title").style.textAlign;
}

function Chart_SetTitleHorizontalAlignment(titleHorizontalAligment) {
    func('#' + this.id)[0].querySelector(".jqplot-title").style.textAlign = titleHorizontalAligment;
	func('#' + this.id)[0].querySelector(".jqplot-title").style.marginLeft = (titleHorizontalAligment.toUpperCase() == "LEFT" ? "" : "-") + "8px";
}

function Chart_GetShowHorizontalLines() {
    return this.plot.axes.yaxis.tickOptions.showGridline;
}

function Chart_SetShowHorizontalLines(showHorizontalLines) {
    this.plot.axes.yaxis.tickOptions.showGridline = showHorizontalLines;
    Chart_Replot(this);
}

function Chart_GetShowVerticalLines() {
    return this.plot.axes.xaxis.tickOptions.showGridline;
}

function Chart_SetShowVerticalLines(showVerticalLines) {
    this.plot.axes.xaxis.tickOptions.showGridline = showVerticalLines;
    Chart_Replot(this);
}

function Chart_GetBackgroundColor() {
    return func('#' + this.id)[0].style.backgroundColor;
}

function Chart_SetBackgroundColor(backgroundColor) {
    func('#' + this.id)[0].style.backgroundColor = backgroundColor;
}

function Chart_GetPlotAreaColor() {
    return this.options.grid.backgroundColor;
}

function Chart_SetPlotAreaColor(plotAreaColor) {
    this.options.grid.backgroundColor = plotAreaColor;
    Chart_Replot(this, this.options);
}

function Chart_GetShowGridBorder() {
    return func('#' + this.id)[0].style.borderWidth !== '';
}

function Chart_SetShowGridBorder(showGridBorder) {
    if (showGridBorder) {
        func('#' + this.id)[0].style.border = '2px solid';
        func('#' + this.id)[0].style.borderColor = 'black';
    }
    else {
        func('#' + this.id)[0].style.border = '';
        func('#' + this.id)[0].style.borderColor = '';
    }
}

function Chart_UpdateTitleFormat(family, size, isBold, isItalic) {
    var divTitle = func('#' + this.id)[0].querySelector(".jqplot-title");
    if (divTitle !== null) {
        divTitle.style.fontFamily = family;
        divTitle.style.fontSize = size + 'px';
        divTitle.style.fontWeight = isBold ? 'bold' : 'normal';
        divTitle.style.fontStyle = isItalic ? 'italic' : 'normal';
    }
}

function Chart_UpdateLegendFormat(family, size, isBold, isItalic) {
    var divLegend = func('#' + this.id)[0].querySelector("table.jqplot-table-legend");
    if (divLegend !== null) {
        divLegend.style.fontFamily = family;
        divLegend.style.fontSize = size + 'px';
        divLegend.style.fontWeight = isBold ? 'bold' : 'normal';
        divLegend.style.fontStyle = isItalic ? 'italic' : 'normal';
    }
}

function Chart_UpdateLegendSize(width, height) {
    var titleStyle = document.getElementById(this.id).getElementsByClassName('jqplot-title');
    var arrayTitleStyle = undefined;
    if (titleStyle.length > 0)
        arrayTitleStyle = [titleStyle[0].style.fontWeight, titleStyle[0].style.fontStyle, titleStyle[0].style.fontSize, titleStyle[0].style.marginTop, titleStyle[0].style.marginLeft, titleStyle[0].style.textAlign, titleStyle[0].style.color];
    var legendStyle = func('#' + this.id)[0].querySelector('table.jqplot-table-legend');
    var arrayLegendStyle = undefined;
    if (legendStyle != undefined && legendStyle != null)
        arrayLegendStyle = [legendStyle.style.fontFamily, legendStyle.style.fontSize, legendStyle.style.fontWeight, legendStyle.style.fontStyle, legendStyle.style.color];

    var plotAreaHei = (this.get_Height() - (Number(this.options.title.fontSize.replace("px", "")) + 8));
    if (height > plotAreaHei - 25)
        height = plotAreaHei - 25;
    if (width > this.get_Width() - (this.chartType == "line" ? 60 : 35))
        width = this.get_Width() - (this.chartType == "line" ? 60 : 35);

    if (width <= 0 || height <= 0) {
        this.options.legend = { show: false };
        if (this.chartType == "pie" && this.options.gridPadding != undefined)
            this.options.gridPadding.right = 10;
    }
    else {
        this.options.legend.show = true;
        this.options.legend.legendWidth = width;
        this.options.legend.legendHeight = height;
        if (this.chartType == "pie") {
            if (this.options.gridPadding != undefined)
                this.options.gridPadding.right = width + 19;
            var plotAreaWid = this.get_Width() - width - 19;
            var diameter = (plotAreaHei < plotAreaWid ? plotAreaHei : plotAreaWid) - 40;
            this.options.seriesDefaults.rendererOptions.diameter = (diameter <= 0 ? 1 : diameter);
        }
    }

    if (this.chartType == "pie") {
        this.plot = $.jqplot(this.id, [this.data], this.options);
        this.plot.replot();
    }
    else {
        var showHorizontalLines = this.plot.axes.yaxis.tickOptions.showGridline;
        var showVerticalLines = this.plot.axes.xaxis.tickOptions.showGridline;
        this.plot = $.jqplot(this.id, this.data, this.options);
        this.plot.axes.yaxis.tickOptions.showGridline = showHorizontalLines;
        this.plot.axes.xaxis.tickOptions.showGridline = showVerticalLines;
        this.plot.replot();
    }

    var currentTitleStyle = document.getElementById(this.id).getElementsByClassName('jqplot-title');
    if (currentTitleStyle.length > 0 && arrayTitleStyle != undefined) {
        currentTitleStyle[0].style.fontWeight = arrayTitleStyle[0];
        currentTitleStyle[0].style.fontStyle = arrayTitleStyle[1];
        currentTitleStyle[0].style.fontSize = arrayTitleStyle[2];
        currentTitleStyle[0].style.marginTop = arrayTitleStyle[3];
        currentTitleStyle[0].style.marginLeft = arrayTitleStyle[4];
        currentTitleStyle[0].style.textAlign = arrayTitleStyle[5];
        currentTitleStyle[0].style.color = arrayTitleStyle[6];
    }
    var currentLegendStyle = func('#' + this.id)[0].querySelector('table.jqplot-table-legend');
    if (currentLegendStyle !== null && arrayLegendStyle != undefined) {
        currentLegendStyle.style.fontFamily = arrayLegendStyle[0];
        currentLegendStyle.style.fontSize = arrayLegendStyle[1];
        currentLegendStyle.style.fontWeight = arrayLegendStyle[2];
        currentLegendStyle.style.fontStyle = arrayLegendStyle[3];
        currentLegendStyle.style.color = arrayLegendStyle[4];
    }
}

function Chart_Replot(chart, options) {
    var titleStyle = document.getElementById(chart.id).getElementsByClassName('jqplot-title');
    var arrayTitleStyle = undefined;
    if (titleStyle.length > 0)
        arrayTitleStyle = [titleStyle[0].style.fontWeight, titleStyle[0].style.fontStyle, titleStyle[0].style.fontSize, titleStyle[0].style.marginTop, titleStyle[0].style.marginLeft, titleStyle[0].style.textAlign, titleStyle[0].style.color];
    var legendStyle = func('#' + chart.id)[0].querySelector('table.jqplot-table-legend');
    var arrayLegendStyle = undefined;
    if (legendStyle != undefined && legendStyle != null)
        arrayLegendStyle = [legendStyle.style.fontFamily, legendStyle.style.fontSize, legendStyle.style.fontWeight, legendStyle.style.fontStyle, legendStyle.style.color];

    if (chart.chartType == "pie") {
        if (options != undefined)
            chart.plot.replot(options);
        chart.plot.replot();
    }
    else {
        var showHorizontalLines = chart.plot.axes.yaxis.tickOptions.showGridline;
        var showVerticalLines = chart.plot.axes.xaxis.tickOptions.showGridline;
        if (options != undefined) {
            chart.plot.replot(options);
            chart.plot.axes.yaxis.tickOptions.showGridline = showHorizontalLines;
            chart.plot.axes.xaxis.tickOptions.showGridline = showVerticalLines;
        }
        chart.plot.replot();
    }

    var currentTitleStyle = document.getElementById(chart.id).getElementsByClassName('jqplot-title');
    if (currentTitleStyle.length > 0 && arrayTitleStyle != undefined) {
        currentTitleStyle[0].style.fontWeight = arrayTitleStyle[0];
        currentTitleStyle[0].style.fontStyle = arrayTitleStyle[1];
        currentTitleStyle[0].style.fontSize = arrayTitleStyle[2];
        currentTitleStyle[0].style.marginTop = arrayTitleStyle[3];
        currentTitleStyle[0].style.marginLeft = arrayTitleStyle[4];
        currentTitleStyle[0].style.textAlign = arrayTitleStyle[5];
        currentTitleStyle[0].style.color = arrayTitleStyle[6];
    }
    var currentLegendStyle = func('#' + chart.id)[0].querySelector('table.jqplot-table-legend');
    if (currentLegendStyle !== null && arrayLegendStyle != undefined) {
        currentLegendStyle.style.fontFamily = arrayLegendStyle[0];
        currentLegendStyle.style.fontSize = arrayLegendStyle[1];
        currentLegendStyle.style.fontWeight = arrayLegendStyle[2];
        currentLegendStyle.style.fontStyle = arrayLegendStyle[3];
        currentLegendStyle.style.color = arrayLegendStyle[4];
    }
}

function GScatterGraph_InsertItem(serieNumber, x, y) {
    if (serieNumber == undefined || serieNumber >= this.options.series.length)
        return;

    var xIndex = -1;
    for (var i = 0; i < this.options.axes.xaxis.ticks.length; i++)
        if (this.options.axes.xaxis.ticks[i].toString() == x.toString())
            xIndex = i;

    var newData = this.data[serieNumber];
    if (xIndex < 0) {
        this.options.series.push({ label: x.toString() });
        this.options.axes.xaxis.ticks.push(x.toString());
        xIndex = this.options.series.length - 1;
    }
    while (xIndex >= newData.length)
        newData.push(0);
    newData[xIndex] = y;

    this.data[serieNumber] = newData;
    this.plot.data = this.data;
    Chart_Replot(this, this.options);
}

function GScatterGraph_InsertItems(serieNumber, listX, listY) {
    if (serieNumber == undefined || serieNumber >= this.options.series.length)
        return;

    var count = listX.length < listY.length ? listX.length : listY.length;
    for (var i = 0; i < count; i++) {
        var x = listX[i];
        var y = listY[i];

        var xIndex = -1;
        for (var z = 0; z < this.options.axes.xaxis.ticks.length; z++)
            if (this.options.axes.xaxis.ticks[z].toString() == x.toString())
                xIndex = z;

        var newData = this.data[serieNumber];
        if (xIndex < 0) {
            this.options.series.push({ label: x.toString() });
            this.options.axes.xaxis.ticks.push(x.toString());
            xIndex = this.options.series.length - 1;
        }
        while (xIndex >= newData.length)
            newData.push(0);
        newData[xIndex] = y;

        this.data[serieNumber] = newData;
        this.plot.data = this.data;
        Chart_Replot(this, this.options);
    }
}

function GScatterGraph_ClearItems(serieNumber) {
    if (serieNumber == undefined || serieNumber >= this.data.length)
        return;

    this.data[serieNumber] = [];
    this.plot.data = this.data;
    Chart_Replot(this, this.options);
}

function GScatterGraph_ChangeLineType(serieNumber, type) {
    if (serieNumber == undefined || serieNumber >= this.options.series.length)
        return;

    if (type == undefined || type == 1)
        this.options.series[serieNumber].linePattern = "dashed";
    else if (type == 2)
        this.options.series[serieNumber].linePattern = "dotted";
    else
        this.options.series[serieNumber].linePattern = "solid";
    Chart_Replot(this, this.options);
}

function GScatterGraph_ChangeSerieThickness(serieNumber, thickness) {
    if (serieNumber == undefined || thickness == undefined || serieNumber >= this.options.series.length)
        return;

    this.options.series[serieNumber].lineWidth = thickness.toString().replace(",", ".");
    Chart_Replot(this, this.options);
}

function GScatterGraph_ChangeSeriesThickness(serieNumber, thickness) {
    if (serieNumber == undefined)
        return;

    if (thickness == undefined) {
        for (var i = 0; i < this.options.series.length; i++)
            this.options.series[i].lineWidth = serieNumber.toString().replace(",", ".");
    }
    else
        this.options.series[serieNumber].lineWidth = thickness.toString().replace(",", ".");
    Chart_Replot(this, this.options);
}

//######## ITab Methods
function ITab_SetVisibility(index, visible) {
    ChangeTabVisiility(this, index, visible, false);
}

function ITab_SetIsEnabled(index, enabled) {
    ChangeTabEnable(this, index, enabled, false);
}

function ITab_SetVisibilityTag(index, visible, firstTime) {
    ChangeTabVisiility(this, index, visible, firstTime);
}

function ITab_SetIsEnabledTag(index, enabled, firstTime) {
    ChangeTabEnable(this, index, enabled, firstTime);
}

function ITab_ChangeSelectedIndex(index) {
    ChangeSelectedTab(this, index);
}

//######## IComboBox Methods
function IComboBox_GetItems() {
    var v_Options = document.getElementById(this.id).options;
	CreateFunctions(v_Options);
	return v_Options;
}

function IComboBox_SetItems(items) {
    func('#' + this.id).empty();
	if(items instanceof JSList)
	{
		for(var i =0; i < items.count; i++)
		{
			var o = new Option(items.get_Item(i), items.get_Item(i));
			func(o).html(items.get_Item(i));
			func('#' + this.id).append(o);
		}
	}
	else
	{
		for (var key in items) {
			var o = new Option(items[key], items[key]);
			func(o).html(items[key]);
			func('#' + this.id).append(o);
		}
	}
	document.getElementById(this.id).selectedIndex = -1;
}

function IComboBox_GetSelectedIndex() {
    return document.getElementById(this.id).selectedIndex;
}

function IComboBox_SetSelectedIndex(index) {
    func('#' + this.id + ' option').eq(index).prop('selected', true); ;
}

function IComboBox_GetSelectedText() {
    return func('#' + this.id + ' option:selected').text();
}

function IComboBox_SetSelectedText(text) {
    func("select option:contains(" + text + ")").attr('selected', true);
}

function IComboBox_InsertItem(item) {
    this.InsertItemAt(item, this.get_Items().length);
}

function IComboBox_InsertItemAt(item, index) {
    var cb = document.getElementById(this.id);
	var selectedIndex = cb.selectedIndex;
    var o = new Option(item, item);
    func(o).html(item);	
	cb.add(o, index);
    cb.selectedIndex = selectedIndex;
}

//prop1 = isScreenTag ou member dependendo de quem chama
function IComboBox_InsertItemsFromTag(tag, prop1, prop2) {
	this.InsertItemsAtFromTag(tag, this.get_Items().length, prop1, prop2);
}

function IComboBox_InsertItemsAtFromTag(tag, index, prop1, prop2) {
    if (tag == undefined || tag == "")
        return;

    var cb = document.getElementById(this.id);
    var prop1Bool = type(prop1) == "Boolean";
    if (prop1Bool && prop1 && prop2 == null) {
        tag = GetTagFromScreenTag(tag + '#');
        prop1 = "";
    } else if (prop2) {
        tag = GetTagFromScreenTag(tag + '#');
    }

    if (prop1 == null)
        prop1 = "";

    var tagNames = GetTagNamesFromMember(tag, prop1);
    var values = GetTagValues(tag, prop1);
    if (values != null && tagNames != "Invalid Tag") {
        var arr = values.toString().split(tagValueSeparator);
        for (var i = 0; i < arr.length; i++) {
			this.InsertItemAt(arr[i], index);
        }
    }
	
    if (tagNames != null && tagNames != "" && tagNames != "Invalid Tag") {
        var arr = tagNames.toString().split(tagValueSeparator);
        for (var i = 0; i < arr.length; i++) {
            	var expr = "Combobox_tagChanged=/=" + arr[i] + "&" + this.id + "&" + (index + i)+ "$" + arr[i]+";0";	
				AddExpressionToList(expr);
        }
	}
}

function IComboBox_ReloadDynamic(comboBoxName){
    var cb = document.getElementById(comboBoxName.toString());
	var selIndex = cb.selectedIndex;
	var dynTags = [];
	for(var i = 0; i< cb.options.length;i++)
	{
		var opt = cb.options[i];
		if(opt.style.display == "none" || opt.style.display == "inline" || opt.style.display == "block")
		{	
			var pos = i;
            var j = i - 1;
            while ((j > -1) && (cb.options[j].id == ""))
            {
                this.RemoveItem(j);
                j--;
				pos--;
            }
			
			dynTags.push(opt.label, pos);
		}
	}

	for(var i = 0; i < dynTags.length;i++)
	{
		var tagNames = GetTagNames(dynTags[i]);
		i++;
		var pos = dynTags[i];
		if (tagNames != null && tagNames != "") {		
			var arr = tagNames.toString().split(tagValueSeparator);
			for (var j = 0; j < arr.length; j++) {
				this.InsertItemsAtFromTag(arr[j], pos + j);
			}
		}
	}

	cb.selectedIndex = selIndex;
}


function Combobox_tagChanged(tag)
{
	var oTag = tag.split("&")[0];
	var combo = tag.split("&")[1];
	var index = tag.split("&")[2];
	var tagNames = GetTagNames(oTag);
	var comboObj =this.document.getElementById(combo);
	var arr = tagNames.toString().split(tagValueSeparator);
        for (var i = 0; i < arr.length; i++) {
		    comboObj.options[index].innerText = ScriptTagValues[GetKey(arr[i] +";0")].toString();
		    comboObj.options[index].tittle = arr[i];
		}
}

function IComboBox_RemoveSelectedItem() {
	var length = document.getElementById(this.id).options.length; 
	for (var i = document.getElementById(this.id).selectedIndex; i < length; i++){
		var tagRemoved = document.getElementById(this.id).options[i].tittle;
		if(tagRemoved != null && tagRemoved.toString() != "")
		{
			RemoveExpressionToList("Combobox_tagChanged=/=" + tagRemoved + "&" + this.id + "&" + i + "$" + tagRemoved+";0");
		}
	}
    func('#' + this.id + ' option:selected').remove();
	length = document.getElementById(this.id).options.length; 
	for (var i = document.getElementById(this.id).selectedIndex; i < length; i++){
		var tagRemoved = document.getElementById(this.id).options[i].tittle;
		if(tagRemoved != null && tagRemoved.toString() != "")
		{
			AddExpressionToList("Combobox_tagChanged=/=" + tagRemoved + "&" + this.id + "&" + i + "$" + tagRemoved+";0");
		}			
	}
}

function IComboBox_RemoveItem(index) {
	if(document.getElementById(this.id).options.length > index)
	{
		var length = document.getElementById(this.id).options.length; 
		for (var i = index; i < length; i++){
			var tagRemoved = document.getElementById(this.id).options[i].tittle;
			if(tagRemoved != null && tagRemoved.toString() != "")
			{
				RemoveExpressionToList("Combobox_tagChanged=/=" + tagRemoved + "&" + this.id + "&" + i + "$" + tagRemoved+";0");
			}
		}
		func('#' + this.id + ' option').eq(index).remove();
		length = document.getElementById(this.id).options.length; 
		for (var i = index; i < length; i++){
			var tagRemoved = document.getElementById(this.id).options[i].tittle;
			if(tagRemoved != null && tagRemoved.toString() != "")
			{
				AddExpressionToList("Combobox_tagChanged=/=" + tagRemoved + "&" + this.id + "&" + i + "$" + tagRemoved+";0");
			}			
		}
	}
}

function IComboBox_RemoveAllItems() {
    var length = document.getElementById(this.id).options.length; 
	for (var i = 0; i < length; i++){
		var tagRemoved = document.getElementById(this.id).options[i].tittle;
		if(tagRemoved != null && tagRemoved.toString() != "")
		{
			RemoveExpressionToList("Combobox_tagChanged=/=" + tagRemoved + "&" + this.id + "&" + i + "$" + tagRemoved+";0");
		}
	}
    func('#' + this.id).empty();
}

//######## IGrouping Methods
function IGrouping_GetChildren() {
    return this.children;
}

//######## IMultitagViewer Methods
function IMultitagViewer_GetSelectedGridIndex() {
    return this.selectedGridIndex;
}

function IMultitagViewer_SetSelectedGridIndex(index) {
    this.selectedGridIndex = index;
}

function IMultitagViewer_GetSelectedArrayIndex() {
	if(this.selectedArrayIndex < 0  || this.selectedArrayIndex > this.rowCount)
		this.selectedArrayIndex = -1;

    return this.selectedArrayIndex;
}

function IMultitagViewer_SetSelectedArrayIndex(index) {
    if(index < 0  || index >= this.rowCount)
		this.selectedArrayIndex = -1;
    else
		this.selectedArrayIndex = index;
}

function IMultitagViewer_Remove() {
    var index = this.selectedArrayIndex;
	var _dataSource = this.dataSource;
	var lineIndex = 0;
	func('#tbl' + this.originalName + ' > tbody').find('tr').each(function () {
        var line = func(this);
		if(lineIndex == index)
		{	
			line.remove();	
			PHITags.RemoveDynamicTag1(_dataSource, index);
			return false;
		}
		lineIndex++;	
    });
}

function IMultitagViewer_Add(property, value) {
    var tag = this.dataSource;
    var scrTag = GetTagFromScreenTag(tag + '#');
    if (scrTag != null && scrTag != "undefined" && scrTag != "") {
        tag = scrTag;
    }
    if (type(property) == "String") {
        PHITags.AddDynamicTag1(tag, property, value);
    } else {
        PHITags.AddDynamicTag2(tag, property, value);
    }
}

function IMultitagViewer_Count() {
    return func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').length;
}

function IMultitagViewer_Filter(property, value) {
    if (type(property) == "String") {
        func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').each(function () {
            var line = func(this);
            line.find('td[name="' + property + '"]').each(function () {
                func(this).find('input').each(function () {
                    if (this.value == value) line.show();
                    else line.hide();
                });
            });
        });
    } else {
        func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').each(function () {
            var line = func(this);
            var show = true;
            for (p in property) {
                line.find('td[name="' + property[p] + '"]').each(function () {
                    func(this).find('input').each(function () {
                        if (show && this.value == value[p]) show = true;
                        else show = false;
                    });
                });
            }
            if (show) line.show();
            else line.hide();
        });
    }
}

function IMultitagViewer_HideColumn(index, id) {
    //id será diferente de undefined apenas quando for chamado pelo método Reload.
    if(id == undefined)
		id = this.id;
		
	func('#tbl' +this.originalName).flexToggleCol(index, false);

    var lines = func('#' + id + ' table tr').each(function () {
        var line = func(this);
        var i = 0;
        line.children().each(function () {
            if (i == index)
                func(this).hide();
            i++;
        });
    });
}

function IMultitagViewer_ShowColumn(index) {
	func('#tbl' +this.originalName).flexToggleCol(index, true);
	
    var lines = func('#' + this.id + ' table tr').each(function () {
        var line = func(this);
        var i = 0;
        line.children().each(function () {
            if (i == index)
                func(this).show();
            i++;
        });
    });
}

function IMultitagViewer_ChangeBackground(index, key, color) {
    var idx = 0;
    func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').each(function () {
        var line = func(this);
        if (idx == index) {
            var changed = false;
            line.find('td[name="' + key + '"]').each(function () {
                if (!changed) func(this).css("background-color", color);
                changed = true;
            });
        }
        idx++;
    });
}

function IMultitagViewer_ChangeImageSource(index, key, image) {
    var source = apiLocation + "Images/" + image;
    var idx = 0;
    func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').each(function () {
        var line = func(this);

        if (idx == index) {
            line.find('td[name="' + key + '"]').each(function () {
                var imgObj = func(this).find("img");
                if (imgObj != null) {
                    imgObj.attr('src', source);
                }
            });
        }
        idx++;
    });
}

//0 = text, 1 = button, 2 = image, 3 = checkbox, 4 = checkbox label, 5 = selected item, 6 = selected index, 7 = dynamic color
function IMultitagViewer_UpdateColumnValue(columnIndex, lineName, inputType, keys, values) {
    var mtv = this;	
    func('#tbl' + this.originalName).find('tr[name="' + lineName + '"]').each(function () {
        var line = func(this);
        var lineIndex = lineName.replace('Line', '');
        var column = 0;
        mtv.inputsToUpdate.push(inputType);
        mtv.keysToUpdate.push(keys);
        mtv.valuesToUpdate.push(values);
        line.find('td').each(function () {
            if (column == columnIndex) {
                var col = func(this);
                col.children().each(function () {
                    var innerDiv = func(this);
                    innerDiv.children().each(function () {
                        for (var i = 0; i < mtv.inputsToUpdate.length; i++) {
                            var input = mtv.inputsToUpdate[i];
                            var key = mtv.keysToUpdate[i];
                            var value = mtv.valuesToUpdate[i];
                            switch (input) {
                                case 0:
                                    UpdateTextboxValue(func(this.parentNode), lineIndex, false, mtv.numberOfDecimals);
                                    break;
                                case 1:
                                    UpdateButtonValue(func(this.parentNode), lineIndex, false, mtv.numberOfDecimals);
                                    break;
                                case 2:
                                    UpdateImageValue(func(this.parentNode), key, value, lineIndex, false);
                                    break;
                                case 3:
                                    UpdateCheckboxValue(func(this.parentNode), lineIndex, false);
                                    break;
                                case 4:
                                    UpdateCheckboxLabel(func(this.parentNode), lineIndex, false, mtv.numberOfDecimals);
                                    break;
                                case 5:
                                    UpdateComboItem(func(this.parentNode), lineIndex, false);
                                    break;
                                case 6:
                                    UpdateComboIndex(func(this.parentNode), lineIndex, false);
                                    break;
                                case 7:
                                    UpdateColorValue(func(this.parentNode.parentNode), key, value, lineIndex, false);
                                    break;
                            }
                        }
                        mtv.inputsToUpdate = [];
                        mtv.keysToUpdate = [];
                        mtv.valuesToUpdate = [];
                    });
                });
            }
            column++;
        });
    });
}

function IMultitagViewer_UpdateAllColumnRequest(columnIndex, inputType, keys, values) {
    var column = new MTVColumnToUpdate(columnIndex, inputType, keys, values);
    this.columnsToUpdate.push(column);
}

function IMultitagViewer_UpdateAllColumnValueIndex(columnIndex, inputType, keys, values) {
    var lineIndex = 0;
    func('#tbl' + this.originalName + ' > tbody').find('tr').each(function () {
        var line = func(this);
        var column = 0;
        line.find('td').each(function () {
            if (column == columnIndex) {
                switch (inputType) {
                    case 0:
                        UpdateTextboxValue(func(this), lineIndex, true);
                        break;
                    case 1:
                        UpdateButtonValue(func(this), lineIndex, true);
                        break;
                    case 2:
                        UpdateImageValue(func(this), keys, values, lineIndex, true);
                        break;
                    case 3:
                        UpdateCheckboxValue(func(this), lineIndex, true);
                        break;
                    case 4:
                        UpdateCheckboxLabel(func(this), lineIndex, true);
                        break;
                    case 5:
                        UpdateComboItem(func(this), lineIndex, true);
                        break;
                    case 6:
                        UpdateComboIndex(func(this), lineIndex, true);
                        break;
                    case 7:
                        UpdateColorValue(func(this), keys, values, lineIndex, true);
                        break;
                }
            }
            column++;
        });
        lineIndex++;
    });
}

function IMultitagViewer_Reload(screenTagName, forceReload) {
    var MTVName = this.originalName;
    var actualCount = func('#tbl' + MTVName + ' tbody tr').length;
    if (screenTagName != null && screenTagName != 'undefined') {
        if (forceReload || this.dataSource != screenTagName.replace(/.+\//g, ''))
            this.dataSource = screenTagName.replace(/.+\//g, '');
        else
            return;
    }
	
	this.tagsToSubscribe = [];
	this.propertiesToSubscribe = [];
	
    var rowConfig = GetMTVRowConfiguration(this.dataSource, this.columnsPath, 0);
	if (rowConfig == undefined || rowConfig == null)
		return;
		
    var totalRows = rowConfig[0];
    var lastIndex = rowConfig[1];

    if(totalRows == 0){
        func('#tbl' + MTVName + ' tbody').html("");
        return;
    }

    var rows = []
    for (i = 0; i < rowConfig[2].length; i++) {
        if (i < this.configStartIndex || (i >= this.configStartIndex && (this.configUseCount && rows.length >= this.configCount)))
            continue;
        rows.push(rowConfig[2][i]);

        if (this.cellspacing != undefined && !isNaN(Number(this.cellspacing)) && Number(this.cellspacing) > 0)
			rows.push("");
	}
	
    while (totalRows > lastIndex) {
        rowConfig = GetMTVRowConfiguration(this.dataSource, this.columnsPath, lastIndex);
        for (i = 0; i < rowConfig[2].length; i++)
            rows.push(rowConfig[2][i]);
        lastIndex = rowConfig[1];
    }
	
    if (rowConfig[2] != null) {
        func('#tbl' + MTVName + ' tbody').html("");
        if (func.isArray(rowConfig[2])) {
            if (rows.length != this.rowCount)
				this.rowCount = rows.length;
				
			for (i = 0; i < rows.length; i++) {
				var htmlToInsert = this.model.replace(/{=INDEX=}/g, rows[i][0]);
                if(rows[i][1].length != undefined){
				    for (j = 0; j < rows[i][1].length; j++) {
					    var find = '{=COLUMN' + j + '=VAL=}';
					    var re = new RegExp(find, 'g');
					    htmlToInsert = htmlToInsert.replace(re, rows[i][1][j]);
						
						var parts = (rows[i][1][j]).split(";");
						this.tagsToSubscribe[this.tagsToSubscribe.length] = parts[0];
						this.propertiesToSubscribe[this.propertiesToSubscribe.length] = parseInt(parts[1]);
				    }
                }
                else {
                    //MTV com apenas uma coluna
                    //Array com apenas um objeto
					for(var key in rows[i][1]) {
						var value = rows[i][1][key];
						var find = '{=COLUMN0=VAL=}';
						var re = new RegExp(find, 'g');
						htmlToInsert = htmlToInsert.replace(re, value);
						
						var parts = value.split(";");
						this.tagsToSubscribe[this.tagsToSubscribe.length] = parts[0];
						this.propertiesToSubscribe[this.propertiesToSubscribe.length] = parseInt(parts[1]);
					}
				}
                if (this.cellspacing != undefined && !isNaN(Number(this.cellspacing)) && Number(this.cellspacing) > 0) {
                    func('#tbl' + MTVName + ' tbody').append("<tr name=\"Line" + (i + 1) + "\" style=\"height:" + this.cellspacing + "px\"></tr>");
					i++;
                }
                func('#tbl' + MTVName + ' tbody').append(htmlToInsert);
            }
        } else {
            this.rowCount = rowConfig[0];
            var htmlToInsert = this.model.replace(/{=INDEX=}/g, rowConfig[2]['a:MultiTagViewerRowConfig'][0]);
            if (rowConfig[2]['a:MultiTagViewerRowConfig'][1].length > 0) {
                for (j = 0; j < rowConfig[2]['a:MultiTagViewerRowConfig'][1].length; j++) {
                    var find = '{=COLUMN' + j + '=VAL=}';
                    var re = new RegExp(find, 'g');
                    htmlToInsert = htmlToInsert.replace(re, rowConfig[2]['a:MultiTagViewerRowConfig'][1][j]);
					
					var parts = (rowConfig[2]['a:MultiTagViewerRowConfig'][1][j]).split(";");
					this.tagsToSubscribe[this.tagsToSubscribe.length] = parts[0];
					this.propertiesToSubscribe[this.propertiesToSubscribe.length] = parseInt(parts[1]);
                }
            }
            else if (rowConfig[2]['a:MultiTagViewerRowConfig'][1].length == undefined) {
                //MTV com apenas uma coluna
                //Quando o MTV tem apenas uma coluna o 'rowConfig[2]['a:MultiTagViewerRowConfig'][1]' é um objeto string.
                //Quando tem mais de uma é um array
                var find = '{=COLUMN0=VAL=}';
                var re = new RegExp(find, 'g');
                //Conversao do objeto para string usando JSON
                //var text = JSON.stringify(rowConfig[2]['a:MultiTagViewerRowConfig'][1]);
                var tag = rowConfig[2]['a:MultiTagViewerRowConfig'][1]["b:string"];
                htmlToInsert = htmlToInsert.replace(re, tag);
				
				var parts = tag.split(";");
				this.tagsToSubscribe[this.tagsToSubscribe.length] = parts[0];
				this.propertiesToSubscribe[this.propertiesToSubscribe.length] = parseInt(parts[1]);
            }
            if (this.cellspacing != undefined && !isNaN(Number(this.cellspacing)) && Number(this.cellspacing) > 0) {
                func('#tbl' + MTVName + ' tbody').append("<tr name=\"Line" + (i + 1) + "\" style=\"height:" + this.cellspacing + "px\"></tr>");
                i++;
            }
            func('#tbl' + MTVName + ' tbody').append(htmlToInsert);
        }
		
        func('#tbl' + MTVName).flexRebuild();
        this.Subscribe();
    }
}

function IMultitagViewer_Subscribe() {
    var MTVName = this.originalName;
    var index = 0;
	
	var tagsNames = [];
	var expressionsToAdd = [];
	
	func('#tbl' + MTVName + ' tbody tr').each(function () {
        var line = func(this);
        line.find('td').each(function () {
            var column = func(this);
            if (column.attr('tag') != null && column.attr('tag') != undefined) {
                var tagName = column.attr('tag');
				while(tagName.includes("index"))
				    tagName = tagName.replace("[index]", "[" + index.toString() + "]");
                while(tagName.includes("INDEX"))
				    tagName = tagName.replace("[INDEX]", "[" + index.toString() + "]");
				
				tagsNames[tagsNames.length] =  tagName;
                expressionsToAdd[expressionsToAdd.length] = 'Expr_' + MTVName + '_' + column.attr('class') + '_' + column.attr('propName') + '=/=' + line.attr('name') + '$' + tagName;
            }
            column.children().each(function () {
                var innerDiv = func(this);
                innerDiv.children().each(function () {
                    var input = func(this);
                    var propName = input.attr('propName');
                    var tagName = input.attr('tag');					
                    if (tagName != null && tagName != undefined) {
						while(tagName.includes("index"))
							tagName = tagName.replace("[index]", "[" + index.toString() + "]");
						while(tagName.includes("INDEX"))
							tagName = tagName.replace("[INDEX]", "[" + index.toString() + "]");
                        
                        if (tagName.indexOf('-/-') != -1) {
                            var props = propName.split('-/-');
                            var tags = tagName.split('-/-');
                            for (var i = 0, l = props.length; i < l; i++) {
								tagsNames[tagsNames.length] = tags[i];
                                expressionsToAdd[expressionsToAdd.length] = 'Expr_' + MTVName + '_' + input.attr('class') + '_' + props[i] + '=/=' + line.attr('name') + '$' + tags[i];
                            }
                        } else {
							tagsNames[tagsNames.length] = tagName;
							expressionsToAdd[expressionsToAdd.length] = 'Expr_' + MTVName + '_' + input.attr('class') + '_' + propName + '=/=' + line.attr('name') + '$' + tagName;
                        }
                    }
                });
            });
        });
        index++;
    });
	
	SubscribeMany(this.tagsToSubscribe, this.propertiesToSubscribe);
	
	index = 0;
	for (index; index < tagsNames.length; index++)
		try { AddExpressionToList(expressionsToAdd[index]); } catch (e) { }
}

function IMultitagViewer_ContextMenu() {
    var menuMTV = [{
        name: 'Move Up',
        fun: function () {
            var index = 0;
            func('#tbl' + _mtv.originalName + ' tbody tr').each(function () {
                var line = func(this);
                var lineProperties = line[0];
                if (lineProperties.className.indexOf("highlight") > -1) {
                    if (index == 0)
                        func('#tbl' + _mtv.originalName + ' tbody tr').eq(index).before(line);
                    else
                        func('#tbl' + _mtv.originalName + ' tbody tr').eq(index - 1).before(line);
                    return false;
                }
                index++;
            });
        }
    }, {
        name: 'Move Down',
        fun: function () {
            var index = 0;
            func('#tbl' + _mtv.originalName + ' tbody tr').each(function () {
                var line = func(this);
                var lineProperties = line[0];
                if (lineProperties.className.indexOf("highlight") > -1) {
                    func('#tbl' + _mtv.originalName + ' tbody tr').eq(index + 1).after(line);
                    return false;
                }
                index++;
            });
        }
    }];

    return menuMTV;
}

function IMultiTagViewer_ScrollToLine(line)
{
	if (line.length) {
		var scrollDiv = func(func("#" + this.id).children()[1].children[3]);
		scrollDiv.scrollTop(scrollDiv.scrollTop() + (line.offset().top - (scrollDiv.height()/2)));
	}
}

var _mtv;
function idMTV() {
    _mtv = this;
}

//######## IAlarm Methods
function IGAlarmViewer_AddFilter(value) {
    var property = "Group";
    var valueUpper = value.toUpperCase();
    if (this.Filter.indexOf(valueUpper) == -1)
        this.Filter.push(valueUpper);

    func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').each(function () {
        var line = func(this);

        if (line.find('td[name="' + property + '"]').length > 0) {
            var group = this.getAttribute('name');
            if (group == 'not event')
                line.show();
            else {
                line.find('td[name="' + property + '"]').each(function () {
                    var text = func(this).text();
                    if (this.Filter.indexOf(text) != -1) line.show();
                    else line.hide();
                });
            }
        }
        else {
            var group = this.getAttribute('name');
            if (group == null || this.Filter.indexOf(group) != -1) line.show();
            else line.hide();
        }
    });
}

function IGAlarmViewer_RemoveFilter(value) {
    var property = "Group";
    var valueUpper = value.toUpperCase();
    var index = this.Filter.indexOf(valueUpper);
    if (index > -1)
        this.Filter.splice(index, 1);

    func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').each(function () {
        var line = func(this);

        if (line.find('td[name="' + property + '"]').length > 0) {
            var group = this.getAttribute('name');
            if (group == 'not event')
                line.show();
            else {
                line.find('td[name="' + property + '"]').each(function () {
                    var text = func(this).text();
                    if (this.Filter.length == 0) line.show();
                    else if (this.Filter.indexOf(text) != -1) line.show();
                    else line.hide();
                });
            }
        }
        else {
            var group = this.getAttribute('name');
            if (this.Filter.length == 0) line.show();
            else if (this.Filter.indexOf(group) != -1) line.show();
            else line.hide();
        }
    });
}

function IGAlarmViewer_CleanFilter() {
    this.Filter = [];

    func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').each(function () {
        var line = func(this);
        var display = func(this).css("display");
        if (display == "none") line.show();
    });
}

function IGAlarmViewer_ClearEvents() {
    func('#' + this.id.replace('div', 'tbl') + ' > tbody > tr').remove();
}

function IGAlarmViewer_ScrollToLine(line) {
    if (line.length) {
        var scrollDiv = func(func("#" + this.id).children()[1].children[3]);
        scrollDiv.scrollTop(scrollDiv.scrollTop() + (line.offset().top - (scrollDiv.height() / 2)));
    }
}

function IGAlarmViewer_ListFilter() {
    return this.Filter;
}

function IGAlarmViewer_Ack() {
	if(this.selectedRow == undefined || this.selectedRow == null) return;
	
    var tagPropertyName = this.selectedRow.attributes.tagName.value + '.' + this.selectedRow.attributes.alarmType.value;
	tagPropertyName = tagPropertyName.toUpperCase();
	this.alarmTags[tagPropertyName].AlarmAck();
}

function IGAlarmViewer_AckAll() {
    var rows = func('#tbl' + this.originalId + ' > tbody > tr');
    var alarm = this;
    rows.each(function () {
        var row = func(this)[0];
        var tagPropertyName = row.attributes.tagName.value + '.' + row.attributes.alarmType.value;
        tagPropertyName = tagPropertyName.toUpperCase();
        alarm.alarmTags[tagPropertyName].AlarmAck();
    });
}

function IGAlarmViewer_AddAlarmTag(tag, description, alarmType) {
    var name = tag.toUpperCase() + '.' + alarmType.toUpperCase();
    this.description = description;
	switch(alarmType.toUpperCase()){
		case 'LOLO':
		case 'LO':
		case 'HI':
		case 'HIHI':
            this.alarmTags[name] = new ILimitAlarm(this, tag, alarmType);
			break;
		case 'DEVIATION':
            this.alarmTags[name] = new IDeviationAlarm(this, tag, alarmType);
			break;
		case 'FREEZE':
            this.alarmTags[name] = new IFreezeAlarm(this, tag, alarmType);
			break;
		case 'WATCHDOG':
            this.alarmTags[name] = new IWatchDogAlarm(this, tag, alarmType);
			break;
		case 'ALARMTRUE':
		case 'ALARMFALSE':
            this.alarmTags[name] = new IBooleanAlarm(this, tag, alarmType);
			break;
	}
	
	if(!this.tagsAlarmTypes.ContainsKey(tag.toUpperCase())){
		var arr = [ alarmType ];
		this.tagsAlarmTypes.Add(tag.toUpperCase(), arr);
	}else{
		var arr = this.tagsAlarmTypes.get_Item(tag.toUpperCase());
		arr.push(alarmType);
		this.tagsAlarmTypes.set_Item(tag.toUpperCase(), arr);
	}
	this.alarmTags[name].FillProperties();
}

function IGAlarmViewer_RemoveAlarmTag(tag, alarmType) {
	var name = tag.toUpperCase() + '.' + alarmType.toUpperCase();
	if(this.alarmTags[name] !== undefined)
		delete this.alarmTags[name];
}

function IGAlarmViewer_RemoveTagFromAlarm(tagName){
	for(var i=this.tagsAlarmTypes.dicKeys.length-1;i>=0;i--)	
		this.tagsAlarmTypes.dicKeys.splice(i);
	var lines = func('#tbl' + this.originalId + ' tr');
	tagName = tagName.replace(".", "_").replace("[", "_").replace("]", "_");
	for(var i = lines.length-1;i >=0;i--){
		var line = lines[i];
		if(line.id.toUpperCase().startsWith("LINE" + tagName + "_"))
			line.remove();
	}
}

function IGAlarmViewer_SetAlarmEvent(arrayParameters) {
    for (var i = 0; i < arrayParameters.length; i++) {
        var parameters = arrayParameters[i];

        if (this.Filter !== undefined && this.Filter.length > 0) {
            if (parameters['Group'] == undefined || (this.Filter.indexOf(parameters['Group']) < 0 && this.Filter.indexOf(parameters['Group'].toUpperCase()) < 0))
                continue;
        }

        if (parameters['EventTime'] !== undefined && parameters['EventTime'] !== "")
            parameters['EventTime'] = ReformatDate(parameters['EventTime']);

        var rowCount = func('#tbl' + this.originalId + ' tr').length;
        var newRow = BuildAlarmRow(this, parameters['Group'], '', '', this.eventBrush, parameters);

        if (rowCount == 0 || rowCount == -1)
            func('#tbl' + this.originalId + ' > tbody:last').append(newRow);
        else
            func('#tbl' + this.originalId + ' > tbody > tr').eq(0).before(newRow);

    }
	func('#tbl'+this.originalId).flexRebuild();
}

function IGAlarmViewer_SetAlarm(alarmed, tagName, description, alarmType, parameters) {
	if(!this.isAlarmOnline)
        setAlarmHistory(this, alarmed, description, tagName, alarmType, parameters);
	else
		setAlarmOnline(this, alarmed, tagName, description, alarmType, parameters);
	func('#tbl'+this.originalId).flexRebuild();
}

function IGAlarmViewer_AddHistoryItems(arrayParameters) {
    _addHistoryItemsInBatch(arrayParameters, this);
}

function _addHistoryItemsInBatch(arrayParameters, alarm) {
    var newRow = '';
    var batch = [];
    if (alarm == undefined)
        return;
    for (var i = 100; i < arrayParameters.length; i++) {
        if (i >= arrayParameters.length)
            break;
        batch.push(arrayParameters[i]);
    }

    for (var i = 0; i < 100; i++) {
        if (i >= arrayParameters.length)
            break;
        var parameters = arrayParameters[i];
        if (alarm == undefined)
            return;

        if (alarm.Filter !== undefined && alarm.Filter.length > 0 && parameters['isEvent'] !== undefined && parameters['isEvent']) {
            if (parameters['Group'] == undefined || (alarm.Filter.indexOf(parameters['Group']) < 0 && alarm.Filter.indexOf(parameters['Group'].toUpperCase())))
                continue;
        }

        var selectedColor = '';
        if (parameters['Name'] == undefined)
            selectedColor = alarm.eventBrush;
        else
            selectedColor = GetAlarmColor(alarm, parameters['StartTime'], parameters['ReturnTime'], parameters['AckTime']);

        var name = '';
        if (parameters['Name'] != undefined)
            name = parameters['Name'];
        else
            name = parameters['Group'];
        newRow += BuildAlarmRow(alarm, name, alarm.description, '', selectedColor, parameters);
    }
    func('#div' + alarm.originalId + ' tbody').append(newRow);
    func('#tbl' + alarm.originalId).flexRebuild();
    if (batch.length > 0)
        setTimeout(_addHistoryItemsInBatch, 100, batch, alarm);
}

function IGAlarmViewer_UpdateAlarmDates(tagName, alarmType, parameters) {
    var find = '(\\[|\\]|\\.|\\,|\\ )';
    var re = new RegExp(find, 'g');
    var cleanTagName = tagName.replace(re, '_');
	var rowName = '#line' + cleanTagName + '_' + alarmType + '_' + this.originalId;
	if (func(rowName).length === 0)
		return;
	var alarmState = parameters['State'];
	var selectedRow = func(rowName);
	var selectedColor = GetAlarmColor(this, parameters['StartTime'], parameters['ReturnTime'], parameters['AckTime']);
	var returnTimeFilled = isNotEmpty(parameters['ReturnTime']);
    var ackTimeFilled = isNotEmpty(parameters['AckTime']);
    
	selectedRow.css('color', selectedColor);

    if(alarmState == enumAlarmState.ReturnedAck || (returnTimeFilled && ackTimeFilled)){
        selectedRow.remove();
        return;
    }
	for (var key in parameters)
	{
		var cell = selectedRow.find('td[name="'+key+'"]');
		var cellDiv = cell.find('div');
		if (cellDiv != undefined)
			cellDiv.html(parameters[key]);
	}
}

function IGAlarmViewer_Subscribe(active) {
	for(var key in this.alarmTags) {
		this.alarmTags[key].Subscribe(active);
	}
}

function IGAlarmViewer_LoadAlarmHistory() {
	for(var keyIndex in this.tagsAlarmTypes.dicKeys){
		getAlarmHistory(this.tagsAlarmTypes.dicKeys[keyIndex], this.tagsAlarmTypes.dicValues[keyIndex], this.startDate, this.endDate, this.dateIsAbsolut, this.dateIsForward, this.dateIsBackward, this.relativeDate, this.originalId + "_addHistoryItems");
	}
}

function IGAlarmViewer_LoadEventHistory() {
	getEventHistory(this.originalId + '_addHistoryItems');
}

//######## IAlarm Helpers
var enumAlarmState =
{
    None: 0,
    ActiveUnack: 1,
    ReturnedUnack: 2,
    ActiveAck: 3,
    ReturnedAck: 4
};

var enumAlarmTypes =
{
    Online: 0,
    History: 1,
    Event: 2,
    EventAndHistory: 3
};
var enumAlarmFields =
{
    None: 0,
    LoLo: 1,
    Lo: 2,
    Hi: 4,
    HiHi: 8,
    Deviation: 16,
    Freeze: 32,
    WatchDog: 64,
    True: 128,
    False: 256
};

//######## IGWindow Methods
function IGWindow_GetOwner() {
    CreateWindowFunctions();
    return parent.window.Window;
}

function IGWindow_GetItem(name) {
    return GetTagFromScreenTag(name + '#');
}

function IGWindow_Close() {
    var canClose = canCloseGraphic(window.docName);
    if (canClose) {
        window.close();
        for (var index = windowOpened.length; index--;) {
            if (windowOpened[index].location.pathname == window.location.pathname)
                windowOpened.splice(index, 1);
        }
    }
}

function IGWindow_OpenGraphic(graphic, prop1, prop2) {
    var canOpen = canOpenGraphic(graphic);
    if (canOpen) {
        graphic = graphic.replace(/\\/g, folderSeparator).replace(/\//g, folderSeparator);
        var myURL = window.location.href;
        var myDir = myURL.substring(0, myURL.lastIndexOf(folderSeparator) + 1) + apiLocation;
        var wi;
        var parameters = GetGraphicInfoParameters(screen);
        wi = window.open('about:blank', '_blank', parameters);
        if (prop1 != undefined && prop2 != undefined) {
            var tagsFullNames = "";
            var screenTagsNames = "";
            var tagNames = prop2.toString().split(",");
            var screenTag = prop1.toString().split(",");
            for (i = 0; i < tagNames.length; i++) {
                tagsFullNames += GetTagFullName(tagNames[i].toString()) + "|";
                screenTagsNames += screenTag[i] + "|";
            }

            wi.document.cookie = graphic + tagValueSeparator + screenTagsNames + tagValueSeparator + tagsFullNames;
        }
        else if (prop1 != undefined && prop2 == undefined) {
            var tagFullName = GetTagNames(prop1.toString());
            var tagName = prop1.toString();
            wi.document.cookie = graphic + tagValueSeparator + tagName + tagValueSeparator + tagFullName;
        }

        wi.location.href = myDir + graphic + ".html";
        wi.focus();

        if ((graphicInfo != undefined) && (graphicInfo.length == 6) && (graphicInfo[0].toString().toUpperCase() == 'TRUE')) {
            popUpObj = wi;
            LoadModalDiv();
        }
    }
}

var popUpObj = null;
function LoadModalDiv() {
	var parentWindow = window;
	while ((parentWindow.parent != undefined) && (parentWindow != parentWindow.parent))
		parentWindow = parentWindow.parent;
		
	var bcgDiv = parentWindow.document.getElementById("divBackgroundPopupOpened");
	bcgDiv.style.display = "block";
}

function HideModalDiv() {
	var parentWindow = window;
	while ((parentWindow.parent != undefined) && (parentWindow != parentWindow.parent))
		parentWindow = parentWindow.parent;

	var bcgDiv = parentWindow.document.getElementById("divBackgroundPopupOpened");
	bcgDiv.style.display = "none";
	popUpObj = null;
}
function OnCloseChildDialog() {
	if ((popUpObj != undefined) && (popUpObj.closed == false))
	{
		popUpObj.close();
		popUpObj = null;
	}
}

function OnDialogClose() {
	var parentWindow = window.opener;
	while ((parentWindow != undefined) && (parentWindow.parent != undefined) && (parentWindow != parentWindow.parent))
		parentWindow = parentWindow.parent;

	if (window.opener != null && !window.opener.closed)
		parentWindow.HideModalDiv();
}

function IGWindow_GetHeight() {
	return func('#' + this.id).innerHeight();
}

function IGWindow_SetHeight(height) {
	var offsetHeight = window.outerHeight - window.innerHeight;
	var offsetWidth = window.outerWidth - window.innerWidth;
	func('#' + this.id).innerHeight(height);
	window.resizeTo(func('#' + this.id).innerWidth() + offsetWidth, func('#' + this.id).innerHeight() + offsetHeight);
}

function IGWindow_GetWidth() {
	return func('#' + this.id).innerWidth();
}

function IGWindow_SetWidth(width) {
	var offsetHeight = window.outerHeight - window.innerHeight;
	var offsetWidth = window.outerWidth - window.innerWidth;
	func('#' + this.id).innerWidth(width);
	window.resizeTo(func('#' + this.id).innerWidth() + offsetWidth, func('#' + this.id).innerHeight() + offsetHeight);
}

function IGWindow_GetTop() {
	if ((navigator.userAgent.indexOf("Trident") > 0 || navigator.userAgent.indexOf("MSIE") > 0))
		return window.screenTop;
	else
		return window.screenY;
}

function IGWindow_SetTop(top) {
	if ((navigator.userAgent.indexOf("Trident") > 0 || navigator.userAgent.indexOf("MSIE") > 0))
		window.screenTop = top;
	else
		window.screenY = top;
} 

function IGWindow_GetLeft() {
	if ((navigator.userAgent.indexOf("Trident") > 0 || navigator.userAgent.indexOf("MSIE") > 0))
		return window.screenLeft;
	else
		return window.screenX;
}

function IGWindow_SetLeft(left) {
    if ((navigator.userAgent.indexOf("Trident") > 0 || navigator.userAgent.indexOf("MSIE") > 0))
		window.screenLeft = top;
	else
		window.screenX = top;
} 

function CreateWindowFunctions() {
	//Criado esta função caso o usuário use a função GetItem seguida da GetOwner. Ex.: Window.get_Owner().get_Item("var")
	window.Window.get_Item = function(name){
		return GetTagFromScreenTag(name + '#');
	};

	//As funções abaixo foram criadas caso o usuário instancia o GetOwner.
	window.Window.get_Owner = function() {
		if (parent.window.opener == null)
			return null;
			
		return parent.window.opener.Window;
	}
	
	window.Window.get_Height = function() {
		return this.innerHeight;
	}
	
	window.Window.get_Top = function() {
		var doc = document.documentElement;
		return (this.pageYOffset || doc.scrollTop)  - (doc.clientTop || 0);
	}
}

//######## IMatrixGrid Methods
function IMatrixGrid_ChangeDataSource(tagName) {
    var matrixGrid = this;
    if (matrixGrid.dataSource != tagName) {
        this.loaded = true;
        if (!this.updateRowColOnReload) {
            matrixGrid.positionX = 0;
            matrixGrid.positionY = 0;
            matrixGrid.positionZ = 0;
        }
        matrixGrid.dataSource = tagName;
        var rowConfig = GetMatrixGridConfiguration(matrixGrid.dataSource);
        matrixGrid.dsDimension = rowConfig[0];
        matrixGrid.dsSize1 = rowConfig[1];
        matrixGrid.dsSize2 = rowConfig[2];
        matrixGrid.dsSize3 = rowConfig[3];
        matrixGrid.EnableDisableControls();
        matrixGrid.Reload();
        func('#control' + matrixGrid.originalName).find('input').each(function () {
            func(this).val(matrixGrid.positionZ);
        });
        if (this.updateRowColOnReload) {
            this.ChangeSelectedLineCol(true);
            this.updateRowColOnReload = false;
        }
    }
}

function IMatrixGrid_ReloadDynamic() {
    var matrixGrid = this;
    var rowConfig = GetMatrixGridConfiguration(matrixGrid.dataSource);
    matrixGrid.dsDimension = rowConfig[0];
    matrixGrid.dsSize1 = rowConfig[1];
    matrixGrid.dsSize2 = rowConfig[2];
    matrixGrid.dsSize3 = rowConfig[3];
    matrixGrid.Reload();
}

function IMatrixGrid_GetColumnIndex() {
    return this.positionX;
}

function IMatrixGrid_SetColumnIndex(index, updateSelValue) {
    if (index >= 0 && index < this.dsSize1 && parseInt(this.positionX) != parseInt(index)) {
        if (updateSelValue != false) updateSelValue = true;
        this.positionX = parseInt(index);
        if (this.ColumnIndexTag != "" && parseInt(ScriptTagValues[GetKey(this.ColumnIndexTag)]) != parseInt(index)) {
            var tagAttr = this.ColumnIndexTag.split(';');
            DirectWriteTag(tagAttr[0], tagAttr[1], index);
        }
        var matrixGrid = this;
        setTimeout(function () {
            matrixGrid.ChangeSelectedLineCol(updateSelValue);
        }, 150);
    }
    else if (!this.loaded) {
        this.positionX = parseInt(index);
        this.updateRowColOnReload = true;
    }
}

function IMatrixGrid_GetRowIndex() {
    return this.positionY;
}

function IMatrixGrid_SetRowIndex(index, updateSelValue) {
    if (index >= 0 && index < this.dsSize2 && parseInt(this.positionY) != parseInt(index)) {
        if (updateSelValue != false) updateSelValue = true;
        this.positionY = parseInt(index);
        if (this.RowIndexTag != "" && parseInt(ScriptTagValues[GetKey(this.RowIndexTag)]) != parseInt(index)) {
            var tagAttr = this.RowIndexTag.split(';');
            DirectWriteTag(tagAttr[0], tagAttr[1], index);
        }
        var matrixGrid = this;
        setTimeout(function () {
            matrixGrid.ChangeSelectedLineCol(updateSelValue);
        }, 150)
    }
    else if (!this.loaded) {
        this.positionY = parseInt(index);
        this.updateRowColOnReload = true;
    }
}

function IMatrixGrid_GetDepthIndex() {
    return this.positionZ;
}

function IMatrixGrid_SetDepthIndex(index, updateSelValue) {
    if (parseInt(this.positionZ) != parseInt(index)) {
        this.ChangeDepth(index);
    }
}

function IMatrixGrid_SetSelectedValue(newValue) {
    var matrixGrid = this;
    func('#div' + this.originalName).find('tr[name="Line' + matrixGrid.positionY + '"]').each(function () {
        var line = func(this);
        line.find('td[name="Col' + matrixGrid.positionX + '"]').each(function () {
            var col = func(this);
            if (ScriptTagValues[GetKey(col.attr('tag'))] != newValue) {
                var tagAttr = col.attr('tag').split(';');
                DirectWriteTag(tagAttr[0], tagAttr[1], newValue);
            }
        });
    });
}

function IMatrixGrid_Reload() {
    var MatrixName = this.originalName;
    func('#div' + MatrixName).html("");
    var table = document.createElement("table");
    table.id = 'tbl' + MatrixName;
    table.appendChild(createMatrixGridHeader(this.dsSize1, this.columnWidth, this.fontStyle));
    table.appendChild(createMatrixGridLines(this.dsDimension, this.dsSize1, this.dsSize2, this.positionZ, this.dataSource, this.rowHeight, this.columnWidth, this.inputEnabled, this.fontStyle));
    func('#div' + MatrixName).append(table);
    func('#tbl' + MatrixName).flexigrid({ minHeight: this.tableHeight, minwidth: this.columnWidth, singleSelect: true, resizable: false, showToggleBtn: false, colMove: false, addColumnHeader: true });
	
	this.tagsToSubscribe = [];
	this.propertiesToSubscribe = [];

	var tagNames = GetTagNames(this.dataSource);
	if (tagNames != null && tagNames != "") {		
		var arr = tagNames.toString().toUpperCase().split(tagValueSeparator);
		for (var i = 0; i < arr.length; i++) {
			this.tagsToSubscribe[i] = arr[i];
			this.propertiesToSubscribe[i] = 0;
		}
	}
	
	SubscribeMany(this.tagsToSubscribe, this.propertiesToSubscribe);
    this.Subscribe();
}

function IMatrixGrid_Subscribe() {
    var MatrixName = this.originalName;
    var lineIndex = 0;
    func('#tbl' + MatrixName + ' tbody tr').each(function () {
        var line = func(this);
        var columnIndex = 0;
        line.find('td').each(function () {
            var column = func(this);
            if (column.attr('tag') != null && column.attr('tag') != undefined && column.attr('tag') != '')
                AddExpressionToList('Expr_' + MatrixName + '_Text=/=Line' + lineIndex + '/' + columnIndex + '$' + column.attr('tag')); ;
            columnIndex++
        });
        lineIndex++;
    });
}

function IMatrixGrid_UpdateColumnValue(columnIndex, lineName) {
    var matrixGrid = this;
    var colWidth = 0;
    var a = func('#div' + this.originalName);
    func('#div' + this.originalName).find('tr[name="' + lineName + '"]').each(function () {
        var line = func(this);
        var lineIndex = lineName.replace('Line', '');
        var column = 0;
        line.find('td').each(function () {
            if (column == columnIndex) {
                var col = func(this);
                col.children().each(function () {
                    var innerDivWidth = 0;
                    var innerDiv = func(this);
                    innerDiv.children().each(function () {
                        var input = func(this);
                        if (input != null) {
                            var tag = col.attr('tag');
                            var tagValue = ScriptTagValues[GetKey(tag)];
                            if (matrixGrid.numberOfDecimals >= 0)
                                tagValue = ParseTagFloat(tagValue, matrixGrid.numberOfDecimals);
                            input.val(tagValue);
                            var inputWidth = tagValue.toString().width(matrixGrid.font + "px arial");
                            if (inputWidth > innerDivWidth)
                                innerDivWidth = inputWidth;
                            if (matrixGrid.cellAutoSize)
                                input.css('width', innerDivWidth + 5);
                            var inputVal = this.value;
                            var columnIdx = col.attr('name').replace('Col', '');
                            setTimeout(function () {
                                var positionX = matrixGrid.positionX;
                                var positionY = matrixGrid.positionY;
                                if (matrixGrid.ColumnIndexTag != "" && parseInt(ScriptTagValues[GetKey(matrixGrid.ColumnIndexTag)]) != parseInt(positionX))
                                    positionX = parseInt(ScriptTagValues[GetKey(matrixGrid.ColumnIndexTag)]);
                                if (matrixGrid.RowIndexTag != "" && parseInt(ScriptTagValues[GetKey(matrixGrid.RowIndexTag)]) != parseInt(positionY))
                                    positionY = parseInt(ScriptTagValues[GetKey(matrixGrid.RowIndexTag)]);
                                if (positionX.toString() == columnIdx && positionY.toString() == lineIndex && matrixGrid.SelectedValueTag != "" &&
									ScriptTagValues[GetKey(matrixGrid.SelectedValueTag)] != this.value) {
                                    var tagAttr = matrixGrid.SelectedValueTag.split(';');
                                    DirectWriteTag(tagAttr[0], tagAttr[1], inputVal);
                                }
                            }, 250);
                        }
                        if (matrixGrid.cellAutoSize)
                            innerDiv.css('width', innerDivWidth + 5);
                    });
                    colWidth = col[0].clientWidth;
                });
            }
            column++;
        });
    });

    if (matrixGrid.cellAutoSize && colWidth > 0) {
        var header = func('#div' + this.originalName).find('tr[name="header"]');
        if (header != undefined) {
            var column = header.find('th[axis="col' + columnIndex + '"]');
            if (column != undefined) {
                var content = column.find('div');
                if (content != undefined)
                    content.css('width', colWidth);
            }
        }
    }
}

function IMatrixGrid_EnableDisableControls() {
    var matrixGrid = this;
    func('#control' + this.originalName).find('button').each(function () {
        if (matrixGrid.enabled && matrixGrid.dsDimension == 3) {
            matrixGrid.EnableDisableButtons(func(this));
        } else {
            func(this).css('pointer-events', 'none');
            func(this).attr('disabled', 'disabled');
        }
    });
    func('#control' + this.originalName).find('input').each(function () {
        if (matrixGrid.enabled && matrixGrid.dsDimension == 3) {
            func(this).css('pointer-events', 'auto');
            func(this).removeAttr('disabled');
        } else {
            func(this).css('pointer-events', 'none');
            func(this).attr('disabled', 'disabled');
        }
    });
}

function IMatrixGrid_EnableDisableButtons($btn) {
    if ($btn.attr('name') == 'begin' || $btn.attr('name') == 'back') {
        if (this.positionZ == 0) {
            $btn.css('pointer-events', 'none');
            $btn.attr('disabled', 'disabled');
        } else {
            $btn.css('pointer-events', 'auto');
            $btn.removeAttr('disabled');
        }
    } else {
        if (this.positionZ == this.dsSize3 - 1) {
            $btn.css('pointer-events', 'none');
            $btn.attr('disabled', 'disabled');
        } else {
            $btn.css('pointer-events', 'auto');
            $btn.removeAttr('disabled');
        }
    }
}

function IMatrixGrid_ChangeDepth(newValue, updateSelValue) {
    var matrixGrid = this;
    if (updateSelValue != false) updateSelValue = true;
    if (newValue >= 0 && newValue < this.dsSize3) {
        matrixGrid.positionZ = parseInt(newValue);
        matrixGrid.Reload();
        if (this.DepthIndexTag != "" && parseInt(ScriptTagValues[GetKey(this.DepthIndexTag)]) != parseInt(newValue)) {
            var tagAttr = this.DepthIndexTag.split(';');
            DirectWriteTag(tagAttr[0], tagAttr[1], newValue);
        }
        matrixGrid.ChangeSelectedLineCol(updateSelValue);
    }
    if (matrixGrid.dsDimension == 3) {
        func('#control' + this.originalName).find('input').each(function () {
            func(this).val(matrixGrid.positionZ);
        });
        func('#control' + this.originalName).find('button').each(function () {
            matrixGrid.EnableDisableButtons(func(this));
        });
    }
}

function IMatrixGrid_ChangeDepthButtons(direction) {
    var newValue = -1;
    if (direction == 'begin')
        newValue = 0;
    else if (direction == 'back')
        newValue = parseInt(this.positionZ) - 1;
    else if (direction == 'foward')
        newValue = parseInt(this.positionZ) + 1;
    else if (direction == 'end')
        newValue = parseInt(this.dsSize3) - 1;
    this.ChangeDepth(newValue);
}

function IMatrixGrid_ChangeSelectedLineCol(updateSelValue) {
    var matrixGrid = this;
    func("#tbl" + this.originalName + " .highlight").removeClass("highlight");
    func('#div' + this.originalName).find('tr[name="Line' + matrixGrid.positionY + '"]').each(function () {
        var line = func(this);
        line.find('td[name="Col' + matrixGrid.positionX + '"]').each(function () {
            var col = func(this);
            col.addClass("highlight");
            if (updateSelValue) {
                col.find('input').each(function () {
                    var $input = func(this);
                    if (matrixGrid.SelectedValueTag != "" && ScriptTagValues[GetKey(matrixGrid.SelectedValueTag)] != this.value) {
                        var tagAttr = matrixGrid.SelectedValueTag.split(';');
                        DirectWriteTag(tagAttr[0], tagAttr[1], this.value);
                    }
                });
            }
        });
    });
}

function IMatrixGrid_UpdateDivControl() {
    if (this.dsDimension !== 3) {
        document.getElementById('control' + this.originalName).style.display = 'none';
        func('#' + this.id).height(func('#' + this.id).height() + func('#control' + this.originalName).height());
        var divs = document.getElementById(this.id).getElementsByClassName('bDiv');
        for (var i = 0; i < divs.length; i++)
            divs[i].style.height = func('#' + this.id).height() + "px";
    } else {
        document.getElementById('control' + this.originalName).style.display = '';
    }
}

//######## IAbstractAlarm Methods

function IAbstractAlarm_CreateParameters() {
	var parameters = new Array();
	parameters['Priority'] = ScriptTagValues[GetKey(this.properties['Priority'])];
	parameters['Message'] = ScriptTagValues[GetKey(this.properties['Message'])];
	parameters['Group'] = ScriptTagValues[GetKey(this.properties['Group'])];
	parameters['TagName'] = ScriptTagValues[GetKey(this.properties['Name'])];
	parameters['StartTime'] = ScriptTagValues[GetKey(this.properties['StartTime'])];
	parameters['ReturnTime'] = ScriptTagValues[GetKey(this.properties['ReturnTime'])];
	parameters['AckTime'] = ScriptTagValues[GetKey(this.properties['AckTime'])];
	parameters['Type'] = this.alarmType;
	parameters['State'] = ScriptTagValues[GetKey(this.properties['State'])];
	parameters['LastState'] = ScriptTagValues[GetKey(this.properties['LastState'])];
	return parameters;
}

function IAbstractAlarm_AlarmAckChanged() {
	if(!this.parent.isAlarmOnline && this.isFirstAlarm < 1)
		return;
	
	var parameters = this.CreateParameters();
    if (isNotEmpty(parameters['StartTime']))
        this.parent.SetAlarm(false, this.tag, this.parent.description, this.alarmType, parameters);
}

function IAbstractAlarm_AlarmAck() {
	var tagProperty = this.properties['Ack'].split(';');
	DirectWriteTag(tagProperty[0], tagProperty[1], !ScriptTagValues[GetKey(this.properties['Ack'])]);
}

function IAbstractAlarm_DatesChanged() {	
	var parameters = {};
	parameters['State'] = ScriptTagValues[GetKey(this.properties['State'])];
	parameters['StartTime'] = ScriptTagValues[GetKey(this.properties['StartTime'])];
	parameters['ReturnTime'] = ScriptTagValues[GetKey(this.properties['ReturnTime'])];
	parameters['AckTime'] = ScriptTagValues[GetKey(this.properties['AckTime'])];
	this.parent.UpdateAlarmDates(this.tag, this.alarmType, parameters);
}

function IAbstractAlarm_Subscribe(subscribeEnable) {
	this.isEnabled = ScriptTagValues[GetKey(this.properties['IsEnabled'])];
	if(subscribeEnable) 
        AddExpressionToList(this.parent.originalId + '_EnableChanged' + tagValueSeparator + this.tag + '.' + this.alarmType + '$'+this.properties['IsEnabled']);
	else
		RemoveExpressionToList(this.parent.originalId + '_EnableChanged' + tagValueSeparator + this.tag + '.' + this.alarmType + '$'+this.properties['IsEnabled']);
	if (this.isEnabled == true && !this.isSubscribed)
    {
		DefaultSubscribe(this, true);
        this.isSubscribed = true;
    }
}

function IAbstractAlarm_Unsubscribe(unsubscribeEnable) {
	if(unsubscribeEnable) 
        AddExpressionToList(this.parent.originalId + '_EnableChanged' + tagValueSeparator + this.tag + '.' + this.alarmType + '$'+this.properties['IsEnabled']);
    if(this.isSubscribed)
    {
	    DefaultSubscribe(this, false);
        this.isSubscribed = false;
    }
}

function IAbstractAlarm_EnableChanged() {
	this.isEnabled = ScriptTagValues[GetKey(this.properties['IsEnabled'])];
    if(this.isEnabled)
	    this.Subscribe(false);
    else
        this.Unsubscribe(false);
}

function IAbstractAlarm_CheckSubscribe(subscribeEnable) {
	this.isEnabled = ScriptTagValues[GetKey(this.properties['IsEnabled'])];
    if(subscribeEnable)
        AddExpressionToList(this.parent.originalId + '_EnableChanged' + tagValueSeparator + this.tag + '.' + this.alarmType + '$'+this.properties['IsEnabled']);
	if (this.isEnabled == true && !this.isSubscribed)
	{
		DefaultSubscribe(this, true);
		if(this.parent.isAlarmOnline)
			AddExpressionToList(this.parent.originalId + '_CheckAlarm' + tagValueSeparator + this.tag + '.' + this.alarmType + '$'+this.properties['State']);
        this.isSubscribed = true;
	}
}

function IAbstractAlarm_CheckUnsubscribe(unsubscribeEnable) {
	if(unsubscribeEnable) 
        AddExpressionToList(this.parent.originalId + '_EnableChanged' + tagValueSeparator + this.tag + '.' + this.alarmType + '$'+this.properties['IsEnabled']);
    if(this.isSubscribed)
    {
	    DefaultSubscribe(this, false);
	    if(this.parent.isAlarmOnline)
		    RemoveExpressionToList(this.parent.originalId + '_CheckAlarm' + tagValueSeparator + this.tag + '.' + this.alarmType + '$'+this.properties['State']);
        this.isSubscribed = false;
    }
}

function IAbstractAlarm_CheckAlarm() {
	var alarmState = ScriptTagValues[GetKey(this.properties['State'])];
	if(alarmState == enumAlarmState.ActiveUnack) {
		var parameters = this.CreateParameters();
        this.parent.SetAlarm(true, this.tag, this.parent.description, this.alarmType, parameters);
	}
}

function ILimitAlarm_AlarmChanged() {
	if(!this.parent.isAlarmOnline && this.isFirstAlarm < 1) {
		this.isFirstAlarm++;
		return;
	}
	
	if (this.isEnabled == true)
	{
		var limit = ScriptTagValues[GetKey(this.properties['Limit'])];
		var parameters = this.CreateParameters();
		var tagValue = ScriptTagValues[GetKey(this.properties['Value'])];
		if(this.alarmType == 'Lo' || this.alarmType == 'LoLo') {
			if (tagValue < limit)
                this.parent.SetAlarm(true, this.tag, this.parent.description, this.alarmType, parameters);
			else
                this.parent.SetAlarm(false, this.tag, this.parent.description, this.alarmType, parameters);
		} else {
			if (tagValue > limit)
                this.parent.SetAlarm(true, this.tag, this.parent.description, this.alarmType, parameters);
			else
                this.parent.SetAlarm(false, this.tag, this.parent.description, this.alarmType, parameters);
		}
	}
}

function ILimitAlarm_FillProperties() {
	var requestedProperties = GetDefaultAlarmProperties(this.alarmType);
	requestedProperties.Add('Limit', this.alarmType.toUpperCase()+'.LIMIT');
	this.properties = BuildAlarmProperties(this.tag, requestedProperties);
}

function IDeviationAlarm_AlarmChanged(){
	if(!this.parent.isAlarmOnline && this.isFirstAlarm < 1) {
		this.isFirstAlarm++;
		this.deviationTime = null;
		return;
	}
	
	if (this.isEnabled == true)
	{
		var variance = ScriptTagValues[GetKey(this.properties['Variance'])];
		var alarmState = ScriptTagValues[GetKey(this.properties['State'])];
		var parameters = this.CreateParameters();
		var tagValue = ScriptTagValues[GetKey(this.properties['Value'])];
		if ((Math.abs(tagValue - this.lastValidValue) > variance) || (alarmState == enumAlarmState.ActiveUnack))
		{
            this.parent.SetAlarm(true, this.tag, this.parent.description, this.alarmType, parameters);
			this.deviationTime = new Date();
		}
		this.lastValidValue = tagValue;
	}
}

function IDeviationAlarm_CheckDeviation(){
	if (this.isEnabled == true)
	{
		var now = new Date();
		var timeToLevelUp = ScriptTagValues[GetKey(this.properties['TimeToLevelUp'])];
		if ((this.deviationTime != null) && (now.getTime() - this.deviationTime.getTime()) > timeToLevelUp * 1000)
		{
			var parameters = this.CreateParameters();
			if(parameters['StartTime'] != undefined && parameters['StartTime'] != null && parameters['StartTime'] != "")
                this.parent.SetAlarm(false, this.tag, this.parent.description, this.alarmType, parameters);
			this.deviationTime = null;
		}
	}
}

function IDeviationAlarm_FillProperties() {
	var requestedProperties = GetDefaultAlarmProperties(this.alarmType);
	requestedProperties.Add('Variance', this.alarmType.toUpperCase()+'.VARIANCE');
	requestedProperties.Add('TimeToLevelUp', this.alarmType.toUpperCase()+'.TIMETOLEVELUP');
	requestedProperties.Add('LastValidValue', this.alarmType.toUpperCase()+'.LASTVALIDVALUE');
	this.properties = BuildAlarmProperties(this.tag, requestedProperties);
	var caller = this;
	this.intervalId = setInterval(function(){ caller.CheckDeviation(); }, 1000);
}

function IFreezeAlarm_AlarmChanged(){
	if(!this.parent.isAlarmOnline && this.isFirstAlarm < 1) {
		this.isFirstAlarm++;
		return;
	}
	
	if (this.isEnabled == true)
	{
		var deadBandFreeze = ScriptTagValues[this.properties['DeadBand']];
		var parameters = this.CreateParameters();
		var tagValue = ScriptTagValues[GetKey(this.properties['Value'])];
		if (Math.abs(tagValue - this.lastValidValue) > deadBandFreeze)
            this.parent.SetAlarm(false, this.tag, this.parent.description, this.alarmType, parameters);
		this.lastValidValue = tagValue;
	}
}

function IFreezeAlarm_FillProperties() {
	var requestedProperties = GetDefaultAlarmProperties(this.alarmType);
	requestedProperties.Add('DeadBand', this.alarmType.toUpperCase()+'.DEADBAND');
	requestedProperties.Add('Time', this.alarmType.toUpperCase()+'.TIME');
	requestedProperties.Add('LastValidValue', this.alarmType.toUpperCase()+'.LASTVALIDVALUE');
	this.properties = BuildAlarmProperties(this.tag, requestedProperties);
}

function IWatchDogAlarm_AlarmChanged(){
	if(!this.parent.isAlarmOnline && this.isFirstAlarm < 1) {
		this.isFirstAlarm++;
		return;
	}
	
	if (this.isEnabled == true)
	{
		var parameters = this.CreateParameters();
		var tagValue = ScriptTagValues[GetKey(this.properties['Value'])];
		
		if (tagValue != this.lastValidValue)
            this.parent.SetAlarm(false, this.tag, this.parent.description, this.alarmType, parameters);
		this.lastValidValue = tagValue;
	}
}

function IWatchDogAlarm_FillProperties() {
	var requestedProperties = GetDefaultAlarmProperties(this.alarmType);
	requestedProperties.Add('Time', this.alarmType.toUpperCase()+'.TIME');
	requestedProperties.Add('LastValidValue', this.alarmType.toUpperCase()+'.LASTVALIDVALUE');
	this.properties = BuildAlarmProperties(this.tag, requestedProperties);
}

function IBooleanAlarm_AlarmChanged() {
	if(!this.parent.isAlarmOnline && this.isFirstAlarm < 1) {
		this.isFirstAlarm++;
		return;
	}
	
	if (this.isEnabled == true)
	{
		var parameters = this.CreateParameters();
		var tagValue = ScriptTagValues[GetKey(this.properties['Value'])];
		if(this.alarmType == 'AlarmTrue') {
			if (tagValue)
                this.parent.SetAlarm(true, this.tag, this.parent.description,  this.alarmType, parameters);
			else
                this.parent.SetAlarm(false, this.tag, this.parent.description, this.alarmType, parameters);
		} else {
			if (!tagValue)
                this.parent.SetAlarm(true, this.tag, this.parent.description, this.alarmType, parameters);
			else
                this.parent.SetAlarm(false, this.tag, this.parent.description, this.alarmType, parameters);
		}
	}
}

function IBooleanAlarm_FillProperties() {
	var requestedProperties = GetDefaultAlarmProperties(this.alarmType);
	this.properties = BuildAlarmProperties(this.tag, requestedProperties);
}

function Symbol_UpdateLayout(symbolName, fillcolor, background, mode, flip) {
    if (fillcolor === undefined || fillcolor === '')
        fillcolor = this.fillcolor;
    else
        this.fillColor = fillcolor;
    if (background === undefined || background === '')
        background = this.background;
    else
        this.background = background;

    this.mode = mode;
    this.flip = flip;

    var path = apiLocation + 'SymbolLibrary/PNG/' + symbolName;
    if (fillcolor.startsWith("#"))
        fillcolor = fillcolor.substr(1);
    if (background.startsWith("#"))
        background = background.substr(1);
    path += "_" + fillcolor + "_" + background + "_" + mode + "_" + flip + ".png";

    func('#' + this.id).attr('src', path);
}

function Symbol_setInitialColors(fillcolor, background) {
    this.fillcolor = fillcolor;
    this.background = background;

}
//############### End Methods ###############

//############### Start Helpers ###############

//######## MTV Helpers
function MTVColumnToUpdate(columnIndex, inputType, keys, values) {
    this.index = columnIndex;
    this.type = inputType;
    this.keys = keys;
    this.values = values;
}

function UpdateTextboxValue(column, line, isIndex, numberOfDecimals) {
    var input = column.find("input"); 
    if (input != null) {
        if (!isIndex) {
            var tag = input.attr('tag') !== undefined ? input.attr('tag') : undefined;
            if (tag == undefined && column.context.innerHTML != undefined && column.context.innerHTML.indexOf(" tag=\"") != -1) {
                var startIndex = column.context.innerHTML.indexOf(" tag=\"");
                tag = column.context.innerHTML.substring(startIndex + 6, column.context.innerHTML.indexOf("\"", startIndex + 6));
            }
            tag = tag.replace('(=INDEX=)', line);
            while (tag.includes("[index]"))
                tag = tag.replace("[index]", "[" + line.toString() + "]");
            while (tag.includes("[INDEX]"))
                tag = tag.replace("[INDEX]", "[" + line.toString() + "]");

            var expr = input.attr('expr') != undefined ? input.attr('expr').replace('(=INDEX=)', line) : '';
			var newValue = ScriptTagValues[GetKey(tag)];
            if (newValue == undefined) {
                try {
                    newValue = eval(tag)
                }
                catch (e) {
                }
            }
            if (numberOfDecimals >= 0)  {  
				var columnType = input.attr('tagType');
				if(columnType == undefined){
					columnType = GetTagType(tag);
					input.attr('tagType', columnType);
				}
				if(columnType == 'Float')
					newValue = ParseTagFloat(newValue, numberOfDecimals);
            }
			
            if (expr !== '')
                newValue = expr.replace("{<=val=>}", newValue);
            
            input.val(newValue);
        } else {
            input.val(line);
        }
    }
}

function UpdateButtonValue(column, line, isIndex, numberOfDecimals) {
    var input = column.find("button");
    if (input != null) {
        if (!isIndex) {
            var tag = input.attr('tag') !== undefined ? input.attr('tag') : undefined;
			if (tag == undefined && column.context.innerHTML != undefined && column.context.innerHTML.indexOf(" tag=\"") != -1) {
				var startIndex = column.context.innerHTML.indexOf(" tag=\"");
				tag = column.context.innerHTML.substring(startIndex + 6, column.context.innerHTML.indexOf("\"", startIndex + 6));
			}
			if (tag != undefined) {
				tag = tag.replace('(=INDEX=)', line);
				while(tag.includes("[index]"))
					tag = tag.replace("[index]", "[" + line.toString() + "]");
				while(tag.includes("[INDEX]"))
					tag = tag.replace("[INDEX]", "[" + line.toString() + "]");
				
				var newValue = ScriptTagValues[GetKey(tag)];
				if (newValue == undefined)
					newValue = eval(tag);
				
				if (numberOfDecimals >= 0)  {  
					var columnType = input.attr('tagType');
					if(columnType == undefined){
						columnType = GetTagType(tag);
						input.attr('tagType', columnType);
					}
					if(columnType == 'Float')
						newValue = ParseTagFloat(newValue, numberOfDecimals);
				}
				input.html(newValue);
			}
        } else {
            input.html(line);
        }
    }
}

function UpdateImageValue(column, keys, images, line, isIndex) {
    var isDefault = true;
    var input = column.find("img");
    if (input != null) {
        if (!isIndex) {
            var tag = column.attr('tag');
			if (tag == undefined && column.context.innerHTML != undefined && column.context.innerHTML.indexOf(" tag=\"") != -1) {
				var startIndex = column.context.innerHTML.indexOf(" tag=\"");
				tag = column.context.innerHTML.substring(startIndex + 6, column.context.innerHTML.indexOf("\"", startIndex + 6));
			}
			if(tag != undefined)
			{
				while(tag.includes("[index]"))
					tag = tag.replace("[index]", "[" + line.toString() + "]");
				while(tag.includes("[INDEX]"))
					tag = tag.replace("[INDEX]", "[" + line.toString() + "]");
					
				var tagValue = ScriptTagValues[GetKey(tag)].toString();	
				if (tagValue == undefined)
					tagValue = eval(tag);
				
				UpdateInputImage(input, keys, images, tagValue, isDefault);
			}
        } else {
            UpdateInputImage(input, keys, images, line.toString(), isDefault);
        }
    }
}

function UpdateInputImage(input, keys, images, value, isDefault) {
    var _isDefault = isDefault;
    for (i = 1; i < keys.length; i++) {
        if (checkBooleanEquals(value, keys[i])) {
            input.attr("src", images[i]);
            _isDefault = false;
            break;
        }
    }
    if (_isDefault)
        input.attr("src", images[0]);
}

function UpdateColorValue(column, keys, colors, line, isIndex) {
    var isDefault = true;
    if (column != null) {
        if (!isIndex) {
            var tag = column.attr('tag');
			if (tag == undefined && column.context.innerHTML != undefined && column.context.innerHTML.indexOf(" tag=\"") != -1) {
				var startIndex = column.context.innerHTML.indexOf(" tag=\"");
				tag = column.context.innerHTML.substring(startIndex + 6, column.context.innerHTML.indexOf("\"", startIndex + 6));
            }

            var expr = column.attr('expr') != undefined ? column.attr('expr').replace('(=INDEX=)', line) : '';
            var tagValue = undefined;
            var tagExpr = expr !== '' ? expr : tag;

            if (tagExpr != undefined) {
                while (tagExpr.includes("[index]"))
                    tagExpr = tagExpr.replace("[index]", "[" + line.toString() + "]");
                while (tagExpr.includes("[INDEX]"))
                    tagExpr = tagExpr.replace("[INDEX]", "[" + line.toString() + "]");
					
                var tagValue = ScriptTagValues[GetKey(tagExpr)];
                if (tagValue == undefined) {
                    try {
                        tagValue = eval(tagExpr);
                    } catch (e){
                        tagValue = undefined;
                    }
                }
                else
                    tagValue = tagValue.toString();
				UpdateColumnColor(column, keys, colors, tagValue, isDefault);
			}
        } else {
            UpdateColumnColor(column, keys, colors, line.toString(), isDefault);
        }
    }
}

function UpdateColumnColor(column, keys, colors, value, isDefault) {
    var _isDefault = isDefault;
    for (i = 1; i < keys.length; i++) {
        if (checkBooleanEquals(value, keys[i])) {
            ColumnChangeColor(column, colors[i]);
            _isDefault = false;
            break;
        }
    }
    if (_isDefault) {
        ColumnChangeColor(column, colors[0]);
    }
}

function checkBooleanEquals(value1, value2) {
    var sValue1 = value1.toString();
    var sValue2 = value2.toString();
    if (sValue1.toLowerCase() == "true" || sValue1.toLowerCase() == "false") {
        if (sValue1.toLowerCase() == "true") {
            return sValue2.toLowerCase == "true" || sValue2 == "1";
        } else {
            return sValue2.toLowerCase == "false" || sValue2 == "0";
        }
    }
    else
        return value1 == value2;
}

function ColumnChangeColor(column, color) {
    column.css("background", color);
    column.css("background-size", "100% 100%");
    var input = column.find("input");
    if (input != null) {
        input.css("background", color);
        input.css("background-size", "100% 100%");
    }
}

function UpdateCheckboxValue(column, line, isIndex) {
    var input = column.find("input");
    if (input != null) {
        if (!isIndex) {
            var tag = input.attr('tag') !== undefined ? input.attr('tag') : undefined;
			if (tag == undefined && column.context.innerHTML != undefined && column.context.innerHTML.indexOf(" tag=\"") != -1) {
				var startIndex = column.context.innerHTML.indexOf(" tag=\"");
				tag = column.context.innerHTML.substring(startIndex + 6, column.context.innerHTML.indexOf("\"", startIndex + 6));
			}
			if (tag != undefined) {
				tag = tag.replace('(=INDEX=)', line);
				while(tag.includes("[index]"))
					tag = tag.replace("[index]", "[" + line.toString() + "]");
				while(tag.includes("[INDEX]"))
					tag = tag.replace("[INDEX]", "[" + line.toString() + "]");
				
				var newValue = ScriptTagValues[GetKey(tag)];
				if (newValue == undefined)
					newValue = eval(tag);
				
				input.prop('checked', newValue);
			}
        } else {
            input.prop('checked', line);
        }
    }
}

function UpdateCheckboxLabel(column, line, isIndex, numberOfDecimals) {
    var input = column.find("label");
    if (input != null) {
        if (!isIndex) {
            var tag = input.attr('tag') !== undefined ? input.attr('tag') : undefined;
			if (tag == undefined && column.context.innerHTML != undefined && column.context.innerHTML.indexOf(" tag=\"") != -1) {
				var startIndex = column.context.innerHTML.indexOf(" tag=\"");
				tag = column.context.innerHTML.substring(startIndex + 6, column.context.innerHTML.indexOf("\"", startIndex + 6));
			}
			if (tag != undefined) {
				tag = tag.replace('(=INDEX=)', line);
				while(tag.includes("[index]"))
					tag = tag.replace("[index]", "[" + line.toString() + "]");
				while(tag.includes("[INDEX]"))
					tag = tag.replace("[INDEX]", "[" + line.toString() + "]");
				
				var newValue = ScriptTagValues[GetKey(tag)];
				if (newValue == undefined)
					newValue = eval(tag);
				if (numberOfDecimals >= 0)  {  
					var columnType = input.attr('tagType');
					if(columnType == undefined){
						columnType = GetTagType(tag);
						input.attr('tagType', columnType);
					}
					if(columnType == 'Float')
						newValue = ParseTagFloat(newValue, numberOfDecimals);
				}

				input.text(newValue);
				input.val(newValue);
			}
        } else {
            input.text(line);
            input.val(line);
        }
    }
}

function UpdateComboItem(column, line, isIndex) {
    var input = column.find("select");
    if (input != null) {
        if (!isIndex) {
            var tag = '';
            if (input.attr('tag').indexOf('-/-') != -1)
                tag = input.attr('tag').split('-/-')[0];
            else
                tag = input.attr('tag');
				
            tag = tag.replace('(=INDEX=)', line);
            var newValue = ScriptTagValues[GetKey(tag)];
			if (newValue == undefined)
				newValue = eval(tag);
			
            input.val(newValue);
        } else {
            input.val(line);
        }
    }
}

function UpdateComboIndex(column, line, isIndex) {
    var input = column.find("select");
    if (input != null) {
        if (!isIndex) {
            var tag = '';
            if (input.attr('tag').indexOf('-/-') != -1)
                tag = input.attr('tag').split('-/-')[1];
            else
                tag = input.attr('tag');
				
            tag = tag.replace('(=INDEX=)', line);
			if (newValue == undefined)
				newValue = eval(tag);
			
            input.find('option').eq(newValue).prop('selected', true);
        } else {
            input.find('option').eq(line).prop('selected', true);
        }
    }
}

//######## IGAlarmViewer Helpers
function getUniqueCode(strValue){
    var hash = 0;
    if (strValue.length == 0) return hash;
    for (var i = 0; i < strValue.length; i++) {
        var cCode = strValue.charCodeAt(i);
        hash = ((hash<<5)-hash)+cCode;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
}

function BuildJSONFromParameters(parameters){
	return {"Name":parameters['Name'],"Type":parameters['Type'],"Priority":parameters['Priority'],"Message":parameters['Message'],"Group":parameters['Group'],"StartTime":parameters['StartTime'],"ReturnTime":parameters['ReturnTime'],"AckTime":parameters['AckTime']};
}

function setAlarmHistory(caller, alarmed, description, tagName, alarmType, parameters) {
	var rowCount = func('#tbl'+caller.originalId+' tbody tr').length;
	var alarmState = parameters['State'];
	var lastAlarmState = parameters['LastState'];
	var selectedColor = GetAlarmColor(caller, parameters['StartTime'], parameters['ReturnTime'], parameters['AckTime']);
	if(isEmpty(parameters['Name'])) parameters['Name'] = tagName;
	var rowHash = getUniqueCode(JSON.stringify(BuildJSONFromParameters(parameters)));
	//check if there is already a row with the configured parameters
	if(func('#tbl'+caller.originalId+' tbody').find('tr[hashcode="'+rowHash+'"]').length == 0){
        var newRow = BuildAlarmRow(caller, tagName, description, alarmType, selectedColor, parameters);
		if(rowCount == 0)
			func('#tbl'+caller.originalId+' tbody').append(newRow);
		else
			func('#tbl'+caller.originalId+' tbody tr').eq(0).before(newRow);
	}
}

function setAlarmOnline(caller, alarmed, tagName, description, alarmType, parameters) {
	var rowCount = func('#tbl'+caller.originalId+' tbody tr').length;
	var alarmState = parameters['State'];
	var lastAlarmState = parameters['LastState'];
    var find = '(\\[|\\]|\\.|\\,|\\ )';
    var re = new RegExp(find, 'g');
    var cleanTagName = tagName.replace(re, '_');
	var rowId = '#line' + cleanTagName + '_' + alarmType + '_' + caller.originalId;
	var selectedColor = GetAlarmColor(caller, parameters['StartTime'], parameters['ReturnTime'], parameters['AckTime']);
	
	if (alarmed == true)
	{
		if(alarmState == enumAlarmState.None) return;
				
		if (func(rowId).length !== 0)
		{
			if (selectedColor != caller.activeAckBrush)
				func(rowId).css('color', selectedColor);

			return;
		}

        var newRow = BuildAlarmRow(caller, tagName, description, alarmType, selectedColor, parameters);
		if(rowCount == 0)
			func('#tbl'+caller.originalId+' tbody').append(newRow);
		else
			func('#tbl'+caller.originalId+' tbody tr').eq(0).before(newRow);
	}
	else
	{
		if (func(rowId).length === 0)
			return;

		if ((alarmState == enumAlarmState.ReturnedAck) || ((alarmState == enumAlarmState.ActiveAck) && (lastAlarmState == enumAlarmState.ReturnedUnack)))
        {
			func(rowId).remove();
            return;
        }
		if (selectedColor != caller.activeAckBrush)
			func(rowId).css('color', selectedColor);
		return;
	}
}

function GetAlarmColor(caller, startTime, returnTime, ackTime){
    var selectedColor = caller.activeUnackBrush;
    var format = projectDateTimeFormat.replace('tt','a');
    var isActiveAck = (isNotEmpty(startTime) && isEmpty(returnTime) && isNotEmpty(ackTime));
    var isReturnedUnack = (isNotEmpty(startTime) && isNotEmpty(returnTime) && isEmpty(ackTime));
    if(isEmpty(returnTime) || isEmpty(ackTime)){
        if(isActiveAck)
            selectedColor = caller.activeAckBrush;
        else if(isReturnedUnack)
            selectedColor = caller.returnedUnackBrush;
    }else{
		var returnDate = Date.parseString(returnTime, format);
		var ackDate = Date.parseString(ackTime, format);
        if(returnDate > ackDate)
            selectedColor = caller.returnedUnackBrush;
        else
            selectedColor = caller.activeAckBrush;
    }
	return selectedColor;
}

function isNotEmpty(obj){
    return !isEmpty(obj);
}

function isEmpty(obj){
    return obj == undefined || obj == null || obj.toString() == "";
}

function BuildAlarmRow(caller, name, description, alarmType, selectedColor, parameters) {
    var list = caller.ListFilter();
    if (parameters['Group'] != undefined && list.length >= 1 && name == parameters['Group'] && list.indexOf(parameters['Group']) == -1 && list.indexOf(parameters['Group'].toUpperCase()) == -1) {
        name = parameters['Group'];
        selectedColor = '#000';
    } else {
        if (name === undefined || name === null) {
            name = '';
        }
    }
    var find = '(\\[|\\]|\\.|\\,|\\ )';
    var re = new RegExp(find, 'g');
    var cleanTagName = name.toString().replace(re, '_');
	var rowHash = getUniqueCode(JSON.stringify(BuildJSONFromParameters(parameters))); //build an unique hashcode to indentify this row when necessary
	var rowId = 'line' + cleanTagName + '_' + alarmType + '_' + caller.originalId;
	var newRow = '<tr id="' + rowId + '" name="' + name + '" hashcode="'+rowHash+'" tagName="' + name + '" alarmType="' + alarmType + '" style="height: 26px; color: ' + selectedColor + ';">';
	func('#div'+caller.originalId+' th').each(function(index) 
	{
        var header = this.id;
        var textAlign = document.getElementById(header).style.textAlign;
		if (header == "Tag Name") {
			newRow += '<td name="Tag Name" style="text-align: ' + textAlign + ';">';
			if(name != parameters['Group'])
				newRow += name;
			else
				newRow += '&nbsp;';
			newRow += '</td>';
        }
        else if (header == "Tag Description")
            newRow += '<td name="Tag Name" style="text-align: ' + textAlign + ';">' + description + '</td>';
        else if (header == "Type")
            newRow += BuildAlarmColumn('Type', parameters['Type'], textAlign);
		else if (header == "Priority")
            newRow += BuildAlarmColumn('Priority', parameters['Priority'], textAlign);
		else if (header == "Message")
            newRow += BuildAlarmColumn('Message', parameters['Message'], textAlign);
		else if (header == "Group")
            newRow += BuildAlarmColumn('Group', parameters['Group'], textAlign);
		else if (header == "Start Time") 
            newRow += BuildAlarmColumn('StartTime', parameters['StartTime'], textAlign);
		else if (header == "Ack Time")
            newRow += BuildAlarmColumn('AckTime', parameters['AckTime'], textAlign);
		else if (header == "Return Time") 
            newRow += BuildAlarmColumn('ReturnTime', parameters['ReturnTime'], textAlign);
		else if (header == "Event Time") 
            newRow += BuildAlarmColumn('EventTime', parameters['EventTime'], textAlign);
	});

	newRow = newRow + '</tr>';
	return newRow;
}

function BuildAlarmColumn(name, value, textAlign){
    var newColumn = '<td name="' + name + '" style="text-align: ' + textAlign + ';">';
	if(isNotEmpty(value))
		newColumn += value;
	else
		newColumn += '&nbsp;';
	newColumn += '</td>';
	return newColumn;
}

//######## IAstractAlarm Helpers
function GetDefaultAlarmProperties(alarmType) {
	var requestedProperties = new JSDictionary();
	requestedProperties.Add('Name', 'NAME');
	requestedProperties.Add('Value', 'VALUE');
	requestedProperties.Add('IsEnabled', alarmType.toUpperCase()+'.ISENABLED');
	requestedProperties.Add('Priority', alarmType.toUpperCase()+'.PRIORITY');
	requestedProperties.Add('Message', alarmType.toUpperCase()+'.MESSAGE');
	requestedProperties.Add('Group', alarmType.toUpperCase()+'.GROUP');
	requestedProperties.Add('StartTime', alarmType.toUpperCase()+'.STARTTIME');
	requestedProperties.Add('ReturnTime', alarmType.toUpperCase()+'.RETURNTIME');
	requestedProperties.Add('AckTime', alarmType.toUpperCase()+'.ACKTIME');
	requestedProperties.Add('State', alarmType.toUpperCase()+'.STATE');
	requestedProperties.Add('LastState', alarmType.toUpperCase()+'.LASTSTATE');
	requestedProperties.Add('Ack', alarmType.toUpperCase()+'.ACK');
	return requestedProperties;
}

function BuildAlarmProperties(tag, requestedProperties) {
	var properties = {};
	var returnedProperties = GetTagPropertiesIndexes(tag, requestedProperties.dicValues);
	for(var i = 0; i < requestedProperties.count; i++){
		properties[requestedProperties.dicKeys[i]] = returnedProperties[i];
	}
	return properties;
}

function DefaultSubscribe(caller, subscribe) {
    if(subscribe) {
	    AddExpressionToList(caller.parent.originalId + '_AlarmChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['State']);
	    AddExpressionToList(caller.parent.originalId + '_AlarmAckChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['Ack']);
	    if(caller.parent.isAlarmOnline) {
		    AddExpressionToList(caller.parent.originalId + '_DateChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['StartTime']);
		    AddExpressionToList(caller.parent.originalId + '_DateChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['ReturnTime']);
		    AddExpressionToList(caller.parent.originalId + '_DateChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['AckTime']);
	    }
    } else {
	    RemoveExpressionToList(caller.parent.originalId + '_AlarmChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['State']);
	    RemoveExpressionToList(caller.parent.originalId + '_AlarmAckChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['Ack']);
	    if(caller.parent.isAlarmOnline) {
		    RemoveExpressionToList(caller.parent.originalId + '_DateChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['StartTime']);
		    RemoveExpressionToList(caller.parent.originalId + '_DateChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['ReturnTime']);
		    RemoveExpressionToList(caller.parent.originalId + '_DateChanged' + tagValueSeparator + caller.tag + '.' + caller.alarmType + '$'+caller.properties['AckTime']);
	    }
    }
}

//######## Tab Helpers
function TabItem(name, enabled, visible) {
    this.Name = name;
    this.Enabled = enabled;
    this.Visible = visible;
}

function ChangeTabVisiility(tab, index, visible, firstTime) {
    if (index < tab.tabs.length) {
        var name = tab.id + tab.tabs[index].Name;
        tab.tabs[index].Visible = visible;
        if (visible) {
            J('#link' + name).show();
            J('#' + name).show();
        } else {
            J('#link' + name).hide();
            J('#' + name).hide();
        }
        if (!firstTime) ChangeSelectedTab(tab, index);
    }
}

function ChangeTabEnable(tab, index, enabled, firstTime) {
    if (index < tab.tabs.length) {
        tab.tabs[index].Enabled = enabled;
        if (enabled) {
            J('#' + tab.id).tabs('enable', index);
        } else {
            J('#' + tab.id).tabs('disable', index);
        }
        if (!firstTime) ChangeSelectedTab(tab, index);
    }
}

function ChangeSelectedTab(itab, index) {
    if (index < itab.tabs.length) {
        var found = false;
        for (var i = index, l = itab.tabs.length; i < l; i++) {
            found = IsTrue(itab.tabs[i].Enabled) && IsTrue(itab.tabs[i].Visible);
            if (found) {
                J('#' + itab.id).tabs('option', 'active', i);
                break;
            }
        }
        if (!found) {
            for (var i = 0, l = itab.tabs.length; i < l; i++) {
                found = itab.tabs[i].Enabled && itab.tabs[i].Visible;
                if (found) {
                    J('#' + itab.id).tabs('option', 'active', i);
                    break;
                }
            }
        }
    }
}

//######## Matrix Grid Helpers
function createTR(id, rowHeight, fontStyle) {
    var tr = document.createElement('tr');
    var $tr = func(tr);
	tr.id = id;
    $tr.attr('name', id);
    $tr.css("font-size", fontStyle[0]);
    $tr.css('font-family', fontStyle[1]);
    $tr.css('font-weight', fontStyle[2]);
    $tr.css('font-style', fontStyle[3]);
    if (rowHeight != undefined) {
        $tr.attr('height', rowHeight);
    }
    return tr;
};

function createTH(html, columnWidth, fontStyle) {
    var th = document.createElement('th');
    th.innerHTML = html;
    if (columnWidth != undefined) {
        var $th = func(th);
        $th.attr('width', columnWidth);
        $th.css("font-size", fontStyle[0]);
        $th.css('font-family', fontStyle[1]);
        $th.css('font-weight', fontStyle[2]);
        $th.css('font-style', fontStyle[3]);
    }
    return th;
};

function createTD(html, tag, name, width, enabled, fontStyle) {
    var td = document.createElement('td');
    var $td = func(td);
    if (html !== '') {
        td.innerHTML = html;
    } else {
        $td.attr('tag', tag);
        $td.attr('name', name);
        var input = document.createElement('input');
        func(input).css('width', width);
        func(input).css('font-size', fontStyle[0]);
        func(input).css('font-family', fontStyle[1]);
        func(input).css('font-weight', fontStyle[2]);
        func(input).css('font-style', fontStyle[3]);
        if (!enabled)
            func(input).attr('disabled', 'disabled');
        input.type = 'text';
        input.val = tag;
        td.appendChild(input);
    }
    return td;
};

function createMatrixGridHeader(size, columnWidth, fontStyle) {
    var header = document.createElement('thead');
    var headerLine = createTR('header', undefined, fontStyle);
    headerLine.appendChild(createTH('&nbsp;', 25, fontStyle));
    for (var i = 0; i < size; i++) {
        headerLine.appendChild(createTH(i, columnWidth, fontStyle));
    }
    header.appendChild(headerLine);
    return header;
}

function createMatrixGridLines(dimension, size1, size2, pos3, dataSource, rowHeight, columnWidth, enabled, fontStyle) {
    var body = document.createElement('tbody');
    for (var i = 0; i < size2; i++) {
        var valueLine = createTR('Line' + i, rowHeight, fontStyle);
        valueLine.appendChild(createTD(i, ''));
        for (var j = 0; j < size1; j++) {
            valueLine.appendChild(createTD('', matrixGridGetTag(dimension, dataSource, j, i, pos3), 'Col' + j, columnWidth, enabled, fontStyle));
        }
        body.appendChild(valueLine);
    }
    return body;
}

function matrixGridGetTag(dimension, dataSource, index1, index2, index3) {
    var tag = dataSource;
    if (dimension == 1)
        tag += '[' + index1 + ']';
    else if (dimension == 2)
        tag += '[' + index1 + ',' + index2 + ']';
    else if (dimension == 3)
        tag += '[' + index1 + ',' + index2 + ',' + index3 + ']';
    return tag + ';0';
}

//######## Point Objects Helpers
function Empty() {
}

function IsTrue(value) {
    return String(value).toLowerCase() == "true";
}

function Point(x, y) {
    this.X = parseFloat(x);
    this.Y = parseFloat(y);
}

function stringToPoints(arg) {
    var points = []
    var res = arg.split(" ");
    for (var i = 0, l = res.length; i < l; i++) {
        if (res[i].indexOf(',') > -1) {
            var p = res[i].split(',');
            points.push(new Point(p[0], p[1]));
        }
    }
    return points;
}

function pointsToString(arg) {
    var res = [];
    for (var i = 0, l = arg.length; i < l; i++) {
        res.push(arg[i].X + "," + arg[i].Y);
    }
    return res.join(' ');
}

function type(obj) {
    return Object.prototype.toString.call(obj).slice(8, -1);
}

//######## GTrend Objects Helpers
var _trend;
function idPlotter() {
    _trend = this;
}

function Trend_InitPlotter() {
	var trend = this;
	
	this.options = {
		series: {
			shadowSize: 0,	// Drawing is faster without shadows
			lines: {
				show: true,
				step: false
			},
			dashes: {
			  show: true
			},
		},
		yaxis: {
		    zoomRange: false
		},
		yaxes: [],
		xaxis: {
			show: true,					
			mode: "time",					
			min: new Date().getTime() - this.duration, 
			max: new Date().getTime(),
			timezone: "browser"
		},
		//grid: {
		//	backgroundColor: "#" + func("#" + this.id + "_BackgroundColor").val()					
		//},
		legend: { 
			labelFormatter: function(label, series) {
				// series is the series object for the label
				// label is the original label
				if(trend.subscribedPens[label] == undefined)
				{
					for (i = 0; i < trend.subscribedPens.length; i++) {
						if(trend.subscribedPens[trend.subscribedPens[i]].screenTag == label){
							if (trend.subscribedPens[trend.subscribedPens[i]].showLabel){
							    if (trend.showYAxisProp) {
							        if (!trend.subscribedPens[trend.subscribedPens[i]].isHide)
							            series.yaxis.options.axisLabel = label;
							    }
							    else
							        series.yaxis.options.axisLabel = "";
								return "<font color=\"black\">" + label + "</font>";
							}
							else
								break;	
						}
					}
				}
				else
				{
					if (trend.subscribedPens[label].showLabel) {
						if(trend.subscribedPens[label].description != "")
						{
						    if (trend.showYAxisProp) {
						        if (!trend.subscribedPens[label].isHide)
						            series.yaxis.options.axisLabel = trend.subscribedPens[label].description;
						    }
						    else
						        series.yaxis.options.axisLabel = "";
							return "<font color=\"black\">" + trend.subscribedPens[label].description + "</font>";
						}
						else
						{
						    if (trend.showYAxisProp) {
						        if (!trend.subscribedPens[label].isHide)
						            series.yaxis.options.axisLabel = label;
						    }
						    else
						        series.yaxis.options.axisLabel = "";
							return "<font color=\"black\">" + label + "</font>";
						}
					}
					else {
					    if (trend.subscribedPens[label].isHide && series.yaxis.options.axisLabel === trend.subscribedPens[label].description)
					        series.yaxis.options.axisLabel = "";
						return null;
					}
				}
			},				
			labelBoxBorderColor: "white",
			backgroundColor: "white",
		},
		zoom: {
			interactive: true
		},
		pan: {				
			interactive: true
		}
	};

	var placeholder = func("#" + this.id + '_Chart');
	
	placeholder.bind("mouseup", function (event, plot, item) {
	    if (this.isPlotPanTrend) {
	        getHistoryItems();
	        this.isPlotPanTrend = false;
	    } 
	});
	// show pan/zoom messages to illustrate events 
	// atualizar o min e max dos eixos
	placeholder.bind("plotpan", function (event, plot) {
	    UpdateMinMaxAxis(event, plot, false);
	    this.isPlotPanTrend = true;
	});

	placeholder.bind("plotzoom", function (event, plot) {
		UpdateMinMaxAxis(event, plot, true);
	});

    placeholder.bind("plothover",  function (event, pos, item) {
		_hoverPlotPosition = pos;
    });

    func("#" + this.id + "_StartDate").datetimepicker({ format: 'dd/MM/yyyy hh:mm:ss', language: 'pt-BR' }).on('changeDate', function (e) { _trend.updatePlot(true); });
    func("#" + this.id + "_StartDateDuration").on('change', function (e) { _trend.updatePlot(null); });
    func("#" + this.id + "_EndDate").datetimepicker({ format: 'dd/MM/yyyy hh:mm:ss', language: 'pt-BR' }).on('changeDate', function (e) { _trend.updatePlot(false); });
    if(document.getElementById(this.id + "_CursorColor").style.visibility != "hidden")
        func("#" + this.id + "_CursorColor").pickAColor();
    //if(document.getElementById(this.id + "_BackgroundColor").style.visibility != "hidden")
    //    func("#" + this.id + "_BackgroundColor").pickAColor({ showHexInput: true });
    func("#pencolor").pickAColor();
    func("#" + this.id + "_StartDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
    func("#" + this.id + "_StartDate").data('datetimepicker').setLocalDate(new Date(new Date().getTime() - this.duration));
    func("#" + this.id + "_EndDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
    func("#" + this.id + "_EndDate").data('datetimepicker').setLocalDate(new Date());
    this.setDuration(this.duration);
    this.setPlotData();    
    _trend.plot();

    setInterval(function (trend) { trend.plot(); }, 500, this);
    getHistoryItems();
	this.initTrendTagValue();
}

function GetProjectDateTimeFormatWithPMAM() {
    var ret = projectDateTimeFormat.replace("tt", "").trim();
    if (!ret.includes("yyyy"))
        ret = ret.replace("yy", "yyyy");
    if (new Date().getHours() > 11)
        ret = ret + " PM";
    else
        ret = ret + " AM";
    return ret;
}

function UpdateMinMaxAxis(event, plot, zoom) {
	var axes = plot.getAxes();		
	var plotAxes = _trend.plotter.getAxes();		
	plotAxes.yaxis.min = axes.yaxis.min;
	plotAxes.yaxis.max = axes.yaxis.max;
	_trend.options.xaxis.min = axes.xaxis.min;
	_trend.options.xaxis.max = axes.xaxis.max;		
	_trend.endTimeDiff = axes.xaxis.max - new Date().getTime();
	if (zoom)
	    _trend.setDuration(axes.xaxis.max - axes.xaxis.min);
}

function Trend_AddPen(Pena) {
	var pen = new IPena(Pena.id);
    var pen_name = getParsedPenaId(Pena.id);
    var tName = this.id + pen_name;
    pen.tName = tName;
    if (!Pena.isSpc) {
        var tdTagStyle = this.gridPensParams.showTag ? "" : "style=display:none;";
        var tdDescriptionStyle = this.gridPensParams.showDescription ? "" : "style=display:none;";
        var tdSampleStyle = this.gridPensParams.showSample ? "" : "style=display:none;";
        var tdLineStyleStyle = this.gridPensParams.showLineStyle ? "" : "style=display:none;";
        var tdThicknessStyle = this.gridPensParams.showThickness ? "" : "style=display:none;";
        var tdPenColorStyle = this.gridPensParams.showPenColor ? "" : "style=display:none;";
        var tdInterpolatedStyle = this.gridPensParams.showInterpolated ? "" : "style=display:none;";
        var tdMinStyle = this.gridPensParams.showMin ? "" : "style=display:none;";
        var tdCursorValueStyle = this.gridPensParams.showCursorValue ? "" : "style=display:none;";
        var tdTagValueStyle = this.gridPensParams.showTagValue ? "" : "style=display:none;";
        var tdMaxStyle = this.gridPensParams.showMax ? "" : "style=display:none;";
        var tdResetStyle = this.gridPensParams.showReset ? "" : "style=display:none;";
        var tdMarkerStyle = this.gridPensParams.showMarker ? "" : "style=display:none;";
        var tdShowLegendStyle = this.gridPensParams.showShowLegend ? "" : "style=display:none;";
        var tdHideStyle = this.gridPensParams.showHide ? "" : "style=display:none;";
        var tdSPCStyle = this.gridPensParams.showSPC ? "" : "style=display:none;";
        var tdRemoveStyle = this.gridPensParams.showRemove ? "" : "style=display:none;";
        var row = "<tr id='line_" + tName + "'><td id=lTag_" + tName + " " + tdTagStyle + ">";
        if (Pena.id.search('/') > -1 || Pena.screenTag.search('/') > -1)
            row += Pena.screenTag === "" ? Pena.id.substring(Pena.id.lastIndexOf("/") + 1) : Pena.screenTag.substring(Pena.screenTag.lastIndexOf("/") + 1);
        else
            row += Pena.screenTag === "" ? Pena.id : Pena.screenTag;
        row += "</td><td " + tdDescriptionStyle + "><input id='desc_" + tName + "' type='text' value='" + Pena.description + "' style='max-width:90px;'></td><td " + tdSampleStyle + " > ";
        row += Pena.interpolated ?
            "<svg style='position:relative;width:70px; height:15px;'>" +
            "<g><polyline id='penSample_" + tName + "' points='0,15 5,5 10,10 15,0' style='stroke:" + Pena.pencolor + ";stroke-width:" +
            Pena.lthick + "px;fill-opacity:0;'  transform='translate(0,0) rotate(0 106.5,162.5)' ></g>" + "</svg>"
            :
            "<svg style='position:relative;width:70px; height:15px;'>" +
            "<g><polyline id='penSample_" + tName + "' points='0,15 5,15 5,5 15,5 15,15 20,15' style='stroke:" + Pena.pencolor + ";stroke-width:" + Pena.lthick +
            "px;fill-opacity:0;' transform='translate(0,0) rotate(0 106.5,162.5)' ></g>" + "</svg>";
        row += "</td>" +
            "<td " + tdLineStyleStyle + "> <select id='lstyle_" + tName + "' selectedIndex='" + Pena.lstyle + "'>" +
            "<option value='[]' " + isSelectedOption(Pena.lstyle, 0) + ">___</option>" +
            "<option value='[4, 2]' " + isSelectedOption(Pena.lstyle, 1) + ">- -</option>" +
            "<option value='[2, 3]' " + isSelectedOption(Pena.lstyle, 2) + ">_.</option>" +
            "<option value='[3, 4]' " + isSelectedOption(Pena.lstyle, 3) + ">_..</option>" +
            "<option value='[1, 1]' " + isSelectedOption(Pena.lstyle, 4) + ">...</option>" +
            "</select></td>" +
            "<td " + tdThicknessStyle + "> <input id='lthick_" + tName + "' type='text' value='" + Pena.lthick + "'></td>" +
            "<td " + tdPenColorStyle + "> <input id='penColor_" + tName + "' type='text' value='" + Pena.pencolor + "' class='pick-a-color' style='width:50px;'></td>" +
            "<td " + tdInterpolatedStyle + "> <input id='interpol_" + tName + "' type='checkbox' " + (Pena.interpolated ? "checked" : "") + " ></td > " +
            "<td " + tdMinStyle + "> <input id='lMin_" + tName + "' type='text'></input></td > " +
            "<td " + tdCursorValueStyle + "> <label id='lCursor_" + tName + "'></label></td > " +
            "<td " + tdTagValueStyle + "> <label id='lTagValue_" + tName + "'></label></td > " +
            "<td " + tdMaxStyle + "> <input id='lMax_" + tName + "' type='text'></input></td > " +
            "<td " + tdResetStyle + "> <button id='bReset_" + tName + "' type=\"button\">Reset Scales</button></td>" +
            "<td " + tdMarkerStyle + "> <select id='penMarker_" + tName + "' selectedIndex=" + Pena.marker + "><option " + isSelectedOption(Pena.marker, 0) + ">None</option> <option " +
            isSelectedOption(Pena.marker, 1) + ">Circle</option><option " + isSelectedOption(Pena.marker, 2) + ">Triangle</option></select></td>" +
            "<td " + tdShowLegendStyle + "><input id='legend_" + tName +
            "' type='checkbox' " + (Pena.showLegend ? "checked" : "") + " style='width:100px'></td><td " + tdHideStyle + "> <input id='hide_" + tName + "' type='checkbox' " + "style = 'width:100px' ></td > " +
            "<td " + tdSPCStyle + "> <input id='spcMin_" + tName + "' type='checkbox' " + (Pena.spcMin ? "checked" : "") +
            " style='display: inline-block;vertical-align: top;margin-top: 6px;'><label style='display: inline-block;margin-right:2px;margin-top: 3px;'>Min</label>" +
            "<label style='display: inline-block;vertical-align: top;margin-left:margin-right:2px;2px;margin-top: 3px;' id='lbSpclMin_" + tName + "_Min'></label>" +
            "<input id='spcMax_" + tName + "' type='checkbox' " + (Pena.spcMax ? "checked" : "") +
            " style='display: inline-block;vertical-align: top;margin-top: 6px;'><label style='display: inline-block;margin-right:2px;margin-top: 3px;'>Max</label>" +
            "<label style='display: inline-block;vertical-align: top;margin-left:2px;margin-right:2px;margin-top: 3px;' id='lbSpclMax_" + tName + "_Max'></label>" +
            "<input id='spcAverage_" + tName + "' type='checkbox' " + (Pena.spcAverage ? "checked" : "") +
            " style='display: inline-block;vertical-align: top;margin-top: 6px;'><label style='display: inline-block;margin-right:2px;margin-top: 3px;'>Avg</label>" +
            "<label style='display: inline-block;vertical-align: top;margin-left:2px;margin-right:2px;margin-top: 3px;' id='lbSpclAverage_" + tName + "_Average'></label>" +
            "<input id='spcStandardDeviation_" + tName + "' type='checkbox' " + (Pena.spcStandardDeviation ? "checked" : "") +
            " style='display: inline-block;vertical-align: top;margin-left:2px;margin-top: 6px;'><label style='display: inline-block;margin-top: 3px;'>Dev</label>" +
            "<label style='display: inline-block;vertical-align: top;margin-left:2px;margin-right:2px;margin-top: 3px;' id='lbSpclStandardDeviation_" + tName + "_StandardDeviation'></label>" +
            "<select id='spcStandardDeviationSigma_" + tName + "' style='width:50px;height:25px;vertical-align: top;margin-left:2px'><option value='1' " +
            isSelectedOption(Pena.spcStandardDeviationSigmaIndex, 1) + ">1s</option>" + "<option value='2' " + isSelectedOption(Pena.spcStandardDeviationSigmaIndex, 2) +
            ">2s</option><option value='3' " + isSelectedOption(Pena.spcStandardDeviationSigmaIndex, 3) + ">3s</option></select></td><td " + tdRemoveStyle + "><input id='remove_" + Pena.id
            + "' onclick='" + this.id + ".removePen(\"" + Pena.id + "\",\"" + tName + "\")' type='button' value='X'></td></tr>";
    }
    if (Pena.lstyle == 0)
	{
		pen.linePattern = [];
		pen.linePattern.show = false;
	}
	else
	{
		if (Pena.lstyle == 1)
			pen.linePattern = [4, 2];
		else if (Pena.lstyle == 2)
			pen.linePattern = [2, 3];
		else if (Pena.lstyle == 3)
			pen.linePattern = [3, 4];
		else if (Pena.lstyle == 4)
			pen.linePattern = [1, 1];
		pen.linePattern.show = true;
	}

    pen.lineWidth = Pena.lthick;
    var markerOpt = new Object();

    if (Pena.marker == 0)
        markerOpt.show = false;
    else {
        markerOpt.show = true;
		if (Pena.marker == 2)
            markerOpt.style = "triangle";
        markerOpt.size = pen.lineWidth;
    }
    pen.interpolated = Pena.interpolated;
	pen.oldMarker = Pena.oldMarker;
    pen.markerOptions = markerOpt;
    pen.color = Pena.pencolor;
    pen.label = Pena.description != "" ? Pena.description : Pena.id;
    pen.set_Description(pen.label);
    pen.screenTag = Pena.screenTag;
    pen.showLabel = Pena.showLegend;
    pen.oldShowLegend = !pen.showLabel;
    pen.isSpc = Pena.isSpc;
    pen.spcMin = Pena.spcMin;
    pen.spcMax = Pena.spcMax;
    pen.spcAverage = Pena.spcAverage;
    pen.spcStandardDeviation = Pena.spcStandardDeviation;
    pen.spcStandardDeviationSigmaIndex = Pena.spcStandardDeviationSigmaIndex;

    this.seriesoptions.push(pen);
    if (this.options != null) {
        this.options.series = this.seriesoptions;
    }
    pen.serieIndex = this.subscribedPens.length;
    this.subscribedPens.push(pen.id);
    this.subscribedPens[pen.id] = pen;
    if (!Pena.isSpc) {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.text = "function PenasCallBack_" + tName + "() { " + this.id + ".setPenData('" + pen.id + "'); }";

        document.body.appendChild(script);
        AddExpressionToList('PenasCallBack_' + tName + '$' + Pena.id + ';0');
    }
    func("#" + this.id + "_Grid").append(row);
    func("#" + this.id + "_Grid").ready(new function () {
        func('#penColor_' + tName).pickAColor();
        func("#penColor_" + tName).on("change", function () {
            var color = func("#penColor_" + tName).val();
            pen.set_PenColor(color);
        });
        func("#penMarker_" + tName).on("change", function () {
            if (!pen.isHide)
                pen.set_Marker(func("#penMarker_" + tName)[0].selectedIndex);
            pen.oldMarker = func("#penMarker_" + tName)[0].selectedIndex;
        });
        func("#desc_" + tName).change(function (e) {
            pen.set_Description(func("#desc_" + tName).val());
        });
        func("#desc_" + tName).keypress(function (e) {
            if (e.keyCode == 13) {
                pen.set_Description(func("#desc_" + tName).val());
                return false;
            }
        });
        func("#lstyle_" + tName).on("change", function () {
            pen.set_LineStyle(func("#lstyle_" + tName).val());
        });
        func("#lthick_" + tName).change(function (e) {
            pen.set_Thickness(func("#lthick_" + tName).val());
        });
        func("#lthick_" + tName).keypress(function (e) {
            if (e.keyCode == 13) {
                pen.set_Thickness(func("#lthick_" + tName).val());
                return false;
            }
        });
        func("#interpol_" + tName).change(function (e) {
            pen.set_Interpol(this.checked);
        });
        func("#lMin_" + tName).keypress(function (e) {
            if (e.keyCode == 13) {
				var newValue = func("#lMin_" + tName).val();
				newValue = parseInt(newValue);
				var axis = _trend.plotter.getYAxes();
				var penName = func("#desc_" + tName).val();
				if(penName == "")
					penName = func("#lTag_" + tName)[0].innerText;
				if(!isNaN(newValue))
				{
					for(var i = 0;i < axis.length;i++)
					{
						if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
                        {
                            if(newValue < axis[i].max)
							    axis[i].options.min = newValue;					
                            else
                                axis[i].options.min = axis[i].max - 1;
                        }
					}
				}
				else
				{
					for(var i = 0;i < axis.length;i++)
					{
						if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
						{
							 document.getElementById("lMin_" + tName).value = axis[i].max;					
							 break;
						}
					}
				}
                return false;
            }
        });
        func("#lMin_" + tName).keypress(function (e) {
            if (e.keyCode == 13) {
				var newValue = func("#lMin_" + tName).val();
				newValue = parseInt(newValue);
				var axis = _trend.plotter.getYAxes();
				var penName = func("#desc_" + tName).val();
				if(penName == "")
					penName = func("#lTag_" + tName)[0].innerText;
				if(!isNaN(newValue))
				{
					for(var i = 0;i < axis.length;i++)
					{
						if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
                        {
                            if(newValue < axis[i].max)
							    axis[i].options.min = newValue;					
                            else
								this.value = axis[i].min;	
                        }
					}
				}
				else
				{
					for(var i = 0;i < axis.length;i++)
					{
						if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
						{
							 this.value = axis[i].min;					
							 break;
						}
					}
				}
                return false;
            }
        });
		func("#lMax_" + tName).keypress(function (e) {
            if (e.keyCode == 13) {
				var newValue = func("#lMax_" + tName).val();
				newValue = parseInt(newValue);
				var axis = _trend.plotter.getYAxes();			
				var penName = func("#desc_" + tName).val();
				if(penName == "")
					penName = func("#lTag_" + tName)[0].innerText;
				if(!isNaN(newValue))
				{
					for(var i = 0;i < axis.length;i++)
					{
						if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
                        {
                            if(newValue > axis[i].min)
							    axis[i].options.max = newValue;					
                            else
								this.value = axis[i].max;	
                        }
					}
				}
				else
				{
					for(var i = 0;i < axis.length;i++)
					{
						if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
						{
							 this.value = axis[i].max;					
							 break;
						}
					}
				}
                return false;
            }
        });
        func("#bReset_" + tName).click(function(e){
				var axis = _trend.plotter.getYAxes();			
				var penName = func("#desc_" + tName).val();
				if(penName == "")
					penName = func("#lTag_" + tName)[0].innerText;
				for(var i = 0;i < axis.length;i++)
				{
				    if (_trend.showYAxisProp) {
				        if (axis[i].options.axisLabel === penName) {
				            axis[i].options.max = undefined;
				            axis[i].options.min = undefined;
				        }
				    } else {
				        axis[i].options.max = undefined;
				        axis[i].options.min = undefined;
				    }
				}
			return false;
		});
        func("#legend_" + tName).change(function (e) {
            pen.oldShowLegend = !this.checked;
            if (!pen.isHide)
                pen.set_ShowLegend(this.checked);
        });
        func("#hide_" + tName).change(function (e) {
            pen.hidePen(this.checked);
            if (!this.checked) {
				pen.set_Marker(pen.oldMarker);
                pen.set_ShowLegend(!pen.oldShowLegend);
                pen.set_Spc(pen.spcMin, pen.id + "_Min");
                pen.set_Spc(pen.spcMax, pen.id + "_Max");
                pen.set_Spc(pen.spcAverage, pen.id + "_Average");
                pen.set_Spc(pen.spcStandardDeviation, pen.id + "_StandardDeviationPositive");
                pen.set_Spc(pen.spcStandardDeviation, pen.id + "_StandardDeviationNegative");
            }
            else {
				pen.set_Marker(0);
                pen.set_ShowLegend(false);
                pen.set_Spc(false, pen.id + "_Min");
                pen.set_Spc(false, pen.id + "_Max");
                pen.set_Spc(false, pen.id + "_Average");
                pen.set_Spc(false, pen.id + "_StandardDeviationPositive");
                pen.set_Spc(false, pen.id + "_StandardDeviationNegative");
            }
        });
        func("#spcMin_" + tName).change(function (e) {
            pen.set_SpcMin(this.checked);
        });
        func("#spcMax_" + tName).change(function (e) {
            pen.set_SpcMax(this.checked);
        });
        func("#spcAverage_" + tName).change(function (e) {
            pen.set_SpcAverage(this.checked);
        });
        func("#spcStandardDeviation_" + tName).change(function (e) {
            pen.set_SpcStandardDeviation(this.checked);
        });
        func("#spcStandardDeviationSigma_" + tName).on("change", function () {
            pen.set_SpcStandardDeviationSigmaIndex(func("#spcStandardDeviationSigma_" + tName)[0].value);
        });
    });
}

function isSelectedOption(selected, actual) {
    if (selected == actual)
        return "selected";
    else
        return "";
}

function Trend_HidePenScript(tagName, hide) {
    func.each(_trend.subscribedPens, function (index, value) {
        if (tagName.toUpperCase() === value.toUpperCase()) {
            _trend.subscribedPens[value].hidePen(hide);
        }
    });
}

function Pena_HidePen(hide) {
    _trend.subscribedPens[this.id].isHide = hide;
    this.isHide = hide;
    var color = '00000000';
    if (hide) {
        this.oldColorPen = this.get_PenColor();
        var index = _trend.subscribedPens.indexOf(this.id);
        if (index >= 0)
            _trend.plotter.getData()[index].yaxis = undefined;
    }
    else
        color = this.oldColorPen;
    this.set_PenColor(color);
}

function Trend_UpdateStartDate(date) {
    func("#" + this.id + "_StartDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
    func("#" + this.id + "_StartDate").data('datetimepicker').setLocalDate(date);
    Trend_UpdatePlot(true);
}

function Trend_UpdateEndDate(date) {
    func("#" + this.id + "_EndDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
    func("#" + this.id + "_EndDate").data('datetimepicker').setLocalDate(date);
    Trend_UpdatePlot(false);
}

function Trend_RemovePen(tag, tName) {
    func("#line_" + tName).remove();
    for (var i = this.subscribedPens.length - 1; i >= 0; i--) {
        if (this.subscribedPens[i] == tag) {
            this.removePen1(this.subscribedPens[i]);
        }
        else if (getParsedPenaId(this.subscribedPens[i]) == tag) {
            this.removePen1(getParsedPenaId(this.subscribedPens[i]));
        }
    }
}

function Trend_RemoveAllPens() {
    for (var i = this.subscribedPens.length - 1; i >= 0; i--) {
        this.removePen1(this.subscribedPens[i]);
    }
}

function Trend_RemovePen1(penName) {
    var index = this.subscribedPens.indexOf(penName);
    if (index >= 0) {
        var pen = this.subscribedPens[penName];
        if (pen.hasAnySpcFunction()) {
            if (pen.spcMin) {
                var spcMinName = penName + "_Min";
                this.removePen1(spcMinName);
            }
            if (pen.spcMax) {
                var spcMaxName = penName + "_Max";
                this.removePen1(spcMaxName);
            }
            if (pen.spcMin) {
                var spcAverageName = penName + "_Average";
                this.removePen1(spcAverageName);
            }
            if (pen.spcStandardDeviation) {
                var spcStandardDeviationPositveName = penName + "_StandardDeviationPositive";
                this.removePen1(spcStandardDeviationPositveName);

                var spcStandardDeviationNegativeName = penName + "_StandardDeviationNegative";
                this.removePen1(spcStandardDeviationNegativeName);
            }
            index = this.subscribedPens.indexOf(penName);
        }
        this.subscribedPens[penName] = "";
        this.subscribedPens.splice(index, 1);
        this.dataPlot.splice(index, 1);
        this.seriesoptions.splice(index, 1);
    }

    var row = document.getElementById("line_" + this.id + penName);
    if (row != undefined)
        row.remove();

    var tagsGrid = document.getElementById(this.id + "_Grid");
    if (tagsGrid != undefined) {
        var gridPenName = "line_" + this.id + penName.replace("[", "_").replace("]", "_")
        if (tagsGrid.rows[gridPenName] != undefined) {
            tagsGrid.rows[gridPenName] = "";
            tagsGrid.rows[gridPenName].remove();
        }
    }
}

function Pena_SetDescription(value) {
    this.description = value;
}

function Pena_SetMarker(value) {
    this.marker = value;
    if (this.marker == 0) {
        this.markerOptions.show = false;
    }
    else {		
        this.markerOptions = new Object();
		this.markerOptions.show = true;
        if (this.marker == 2)
            this.markerOptions.style = "triangle";
        else
            this.markerOptions.style = "circle";
        this.markerOptions.size = parseInt(this.lineWidth);
    }
}

function Pena_SetThickness(value) {	
	if (value > 0 && value <= 10) {
		func("#lthick_" + this.tName).removeClass("ui-state-error");	
		this.lineWidth = value;
		if (this.marker != 0)
			this.markerOptions.size = parseInt(value);
	}
	else 
		func("#lthick_" + this.tName).addClass("ui-state-error");	
}

function Pena_GetPenColor() {
    var color = this.color;
    if (color.startsWith('#'))
        color = color.substring(1);
    return color;
}

function Pena_SetPenColor(value) {
    this.color = "#" + value;
    func("#penSample_" + this.tName).css("stroke", this.color);
}

function Pena_SetInterpol(value) {
    this.interpolated = value;
}

function Pena_SetLineStyle(value) {	
	this.linePattern = eval(value);
	if ((this.linePattern != []) && (this.linePattern.length > 0))
		this.linePattern.show = true;
	else
		this.linePattern.show = false;
}

function Pena_GetShowLegend() {
    return this.showLabel;
}

function Pena_SetShowLegend(value) {
    this.showLabel = value;
}

function Pena_GetIsSpc() {
    return this.isSpc;
}

function Pena_HasAnySpcFunction() {
    return this.spcMin || this.spcMax || this.spcAverage || this.spcStandardDeviation;
}

function Pena_GetSpcMin() {
    return this.spcMin;
}

function Pena_GetSpcMax() {
    return this.spcMax;
}

function Pena_GetSpcAverage() {
    return this.spcAverage;
}

function Pena_GetSpcStandardDeviation() {
    return this.spcStandardDeviation;
}

function Pena_GetSpcStandardDeviationSigmaIndex() {
    return this.spcStandardDeviationSigmaIndex;
}

function Pena_SetSpc(value, penName) {
    if (value) {
        var pen = createPen(penName, false, '', '#' + this.get_PenColor(), '0', 1, true, 0, false, true, false, false, false, false, 1);
        _trend.addPen(pen);
    }
    else
        _trend.removePen1(penName);
}

function Pena_SetSpcMin(value) {
    this.spcMin = value;
    this.set_Spc(value, this.id + "_Min");
}

function Pena_SetSpcMax(value) {
    this.spcMax = value;
    this.set_Spc(value, this.id + "_Max");
}

function Pena_SetSpcAverage(value) {
    this.spcAverage = value;
    this.set_Spc(value, this.id + "_Average");
}

function Pena_SetSpcStandardDeviation(value) {
    this.spcStandardDeviation = value;
    this.set_Spc(value, this.id + "_StandardDeviationPositive");
    this.set_Spc(value, this.id + "_StandardDeviationNegative");
}

function Pena_SetSpcStandardDeviationSigmaIndex(value) {
    this.spcStandardDeviationSigmaIndex = value;
}

function Trend_ShowDetails() {
	var cursorPos = _trend.plotter.getCrosshairPosition();
	if (cursorPos !== undefined)
		_cursorPosition = cursorPos.x;
    func("#" + this.id + "_Details").toggle();
    if (func("#" + this.id + "_Details").is(":visible"))
    {
		func("#" + this.id + "_Chart").height(this.ChartHeight); 
	}
    else
    {
		this.ChartHeight = func("#" + this.id + "_Chart").height();
		var trendHeight = func("#" + this.id).height();
		var toolBarHeight = func("#" + this.id + "_ToolBar").height(); 
		func("#" + this.id + "_Chart").height(trendHeight - toolBarHeight); 
	}		
	this.redraw = true;
}

function Trend_ZoomIn() {
    this.plotter.zoom();
}

function Trend_ZoomOut() {
    this.plotter.zoomOut();
}

var _isCursorDisable = true;
var _cursorTimer;
var _trendTagValueTimer;
var _hoverPlotPosition;
function Trend_SetCursor(posX)
{
    document.getElementById(this.id + "_LabelCursorTimestamp").style.display = "inline-block";
    document.getElementById(this.id + "_CursorTimestamp").style.display = "inline-block";
    var pos = { x: posX, y: 0 };
    _cursorPosition = posX;
	this.plotter.lockCrosshair(pos);
	if(_cursorTimer != undefined)
	{
		clearInterval(_cursorTimer);
		_cursorTimer = undefined;
	}
    _cursorTimer = setInterval(function () {CursorTimer();}, 1000);
	_isCursorDisable = false;
    var crosshair = this.plotter.getOptions().crosshair;
	if(crosshair != undefined)
		crosshair.color = _actualCursorColor;
}

function Trend_InitCursor() {
    var posX = this.plotter.width() > 50 ? this.plotter.width() - 50 : 1;
    this.setCursor(posX);
}

function Trend_initTrendTagValueTimer() {
	if(_trendTagValueTimer != undefined)
	{
		clearInterval(_trendTagValueTimer);
		_trendTagValueTimer = undefined;
	}
    _trendTagValueTimer = setInterval(function () {TrendTagValueTimer();}, 1000);
}

function Trend_RemoveCursor(posX) {
    document.getElementById(this.id + "_LabelCursorTimestamp").style.display = "none";
    document.getElementById(this.id + "_CursorTimestamp").style.display = "none";
	var crosshair = _trend.plotter.getOptions().crosshair;
	if(crosshair != undefined)	
		crosshair.color = "transparent";
	clearInterval(_cursorTimer);
    var data = _trend.plotter.getData();
	for(var i =0; i <data.length;i++)	{
		var labelName = "lCursor_" + _trend.id + data[i].label;
		labelName = labelName.replace("[", "_").replace("]", "_").replace(".", "_");
		var cursorValue = document.getElementById(labelName);
		if(cursorValue != undefined)
			cursorValue.innerText = "";
	}
	_isCursorDisable = true;
}

function CursorTimer() {
    var cursorPos = _trend.plotter.getCrosshairPosition();
    var canvasX = cursorPos !== undefined ? cursorPos.x : (_trend.plotter.width() > 50 ? _trend.plotter.width() - 50 : 1);
    var data = _trend.plotter.getData();
    for (var i = 0; i < data.length; i++) {
        var item = findNearbyItem(canvasX, 0, data[i]);
        var lCursorName = "lCursor_" + _trend.id + getParsedPenaId(data[i].label);
        if (item == undefined) {
            if (document.getElementById(lCursorName) != undefined)
                document.getElementById(lCursorName).innerText = "";
            else {
                var tagName = getParsedPenaId(GetTagFromScreenTag(data[i].label + '#'))
                if (document.getElementById("lCursor_" + _trend.id + tagName) != undefined)
                    document.getElementById("lCursor_" + _trend.id + tagName).innerText = "";
            }
        }
        else if (document.getElementById(lCursorName) != undefined) {
            if (isFloat(item.datapoint[1])) 
                document.getElementById(lCursorName).innerText = item.datapoint[1].toFixed(_trend.numberOfDecimals);            
            else
                document.getElementById(lCursorName).innerText = item.datapoint[1];
        }
        else {
            var tagName = getParsedPenaId(GetTagFromScreenTag(data[i].label + '#'));
            if (document.getElementById("lCursor_" + _trend.id + tagName) != undefined) {
                if (isFloat(item.datapoint[1]))
                    document.getElementById("lCursor_" + _trend.id + tagName).innerText = item.datapoint[1].toFixed(_trend.numberOfDecimals);
                else
                    document.getElementById("lCursor_" + _trend.id + tagName).innerText = item.datapoint[1];
            }
        }
    }

    //updating Cursor (Timestamp)
    var xax = _trend.options.xaxis;
    if (xax !== undefined && cursorPos !== undefined) {
        var cent = 1 - (cursorPos.x / _trend.plotter.width());
        var equivalent = Math.round(cent * (xax.max - xax.min));
        var date = new Date(xax.max - equivalent);
        if (date != undefined) {
            var formatedDate = date.getDate().toString().padStart(2, '0') + "/" + (date.getMonth() + 1).toString().padStart(2, '0') + "/" + date.getFullYear() + " ";
            formatedDate += date.getHours().toString().padStart(2, '0') + ":" + date.getMinutes().toString().padStart(2, '0') + ":" + date.getSeconds().toString().padStart(2, '0');
            document.getElementById(_trend.id + "_DateCursorTimestamp").value = ReformatDate(date, projectDateTimeFormat);
        }
    }
}

function TrendTagValueTimer(){
	var data = _trend.plotter.getData();
	for (var i = 0; i < data.length; i++) {
		var labelName = "lTagValue_" + _trend.id + data[i].label;
		labelName = labelName.replace("[", "_").replace("]", "_").replace(".", "_");
		var elTagValue = document.getElementById(labelName);
		if (data[i].label != undefined && data[i].label != null && data[i].label != "" && elTagValue != undefined){
			var _tagValue = ScriptTagValues[GetKey(String(data[i].label).toUpperCase() + ";0")];
			if (isFloat(_tagValue))
				elTagValue.innerText = _tagValue.toFixed(_trend.numberOfDecimals);
			else
				elTagValue.innerText = _tagValue;
		}
	}
}

function findNearbyItem(mouseX, mouseY, series) 
{
    var options = _trend.plotter.getOptions();
    var maxDistance = options.grid.mouseActiveRadius,
	    smallestDistance = maxDistance + 1,
        item = null, foundPoint = false, i, j, ps;

    var s = series,
    axisx = s.xaxis,
    axisy = s.yaxis,
    points = s.datapoints.points,
    mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
    maxx = maxDistance / axisx.scale,

    ps = s.datapoints.pointsize;
    // with inverse transforms, we can't use the maxx
    // optimization, sadly
    if (axisx.options.inverseTransform)
        maxx = Number.MAX_VALUE;

    if (s.lines.show || s.dashes.show || s.points.show) {
        for (j = 0; j < points.length; j += ps) {
            var x = points[j], y = points[j + 1];
            if (x == null)
                continue;

            // For points and lines, the cursor must be within a
            // certain distance to the data point
            if (x - mx > maxx || x - mx < -maxx)
                continue;

            // We have to calculate distances in pixels, not in
            // data units, because the scales of the axes may be different
            var dx = Math.abs(axisx.p2c(x) - mouseX),
                dist = dx;

            // use <= to ensure last point takes precedence
            // (last generally means on top of)
            if (dist < smallestDistance) {
                smallestDistance = dist;
                item = [i, j / ps];
            }
        }
    }

    if (s.bars.show && !item) { // no other point can be nearby
        var barLeft, barRight;
        switch (s.bars.align) {
            case "left":
                barLeft = 0;
                break;
            case "right":
                barLeft = -s.bars.barWidth;
                break;
            default:
                barLeft = -s.bars.barWidth / 2;
        }

        barRight = barLeft + s.bars.barWidth;
        for (j = 0; j < points.length; j += ps) {
            var x = points[j], b = points[j + 2];
            if (x == null)
                continue;

            // for a bar graph, the cursor must be inside the bar
			if (series.bars.horizontal ?
                (mx <= Math.max(b, x) && mx >= Math.min(b, x)) :
                (mx >= x + barLeft && mx <= x + barRight)){
                    item = [i, j / ps];
					break;
            }
        }
    }

    if (item) {
        i = item[0];
        j = item[1];
		ps = series.datapoints.pointsize;

		return { datapoint: series.datapoints.points.slice(j * ps, (j + 1) * ps),
                dataIndex: j,
			    series: series};
    }

    return null;
}

function Trend_AutoScale() {
	this.fitToNow();
	this.fitScalesToView();
}

function Trend_FitToNow()
{
	this.endTimeDiff = 0;
	this.updatePlot(null);   
}

function Trend_FitScalesToView()
{
	var trend = this;
	var placeholder = func("#" + this.id + '_Chart');
	var data = [];
	
	func.each(this.seriesoptions, function (index, value) {
		var label;
		if (value.screenTag === "")
			label = value.id;
		else
			label = value.screenTag;
		data.push({
			points: {show: value.markerOptions.show, radius: value.markerOptions.size, symbol: value.markerOptions.style},
			data: trend.dataPlot[index], 			
			label: label, 
			color: value.color, 
			lines: {show: !value.linePattern.show, steps: !value.interpolated, lineWidth: value.lineWidth},
			dashes: {show: value.linePattern.show, dashLength: value.linePattern},
		});
	});
	this.plotter = func.plot(placeholder, data, this.options);
}

function Trend_ShowYAxis() {
    this.showYAxisProp = !this.showYAxisProp;
}

function Trend_SingleScales() {
    if (this.showYAxisProp == true) {
        this.showYAxisProp = false;
        var button = document.getElementById(this.id + "_showYAxis");
        if (button != undefined) {
            button.style.backgroundImage = "url(./htmlImages/MultiScales.png)";
            button.title = "Show multiple verticals scales";
        }
    }
}

function Trend_MultiScales() {
    if (this.showYAxisProp == false) {
        this.showYAxisProp = true;
        var button = document.getElementById(this.id + "_showYAxis");
        if (button != undefined) {
            button.style.backgroundImage = "url(./htmlImages/SingleScale.png)";
            button.title = "Show single vertical scale";
        }
    }
}

var _actualCursorColor = "#000000";
function Trend_ChangeCursorColor() {
	var hexValue = func("#" + this.id + "_CursorColor").val();
	_actualCursorColor = "#" + hexValue;
	var crosshair = _trend.plotter.getOptions().crosshair;
	if(crosshair != undefined && !_isCursorDisable)
		crosshair.color = _actualCursorColor;
}

function Trend_ChangeBackground() {
    var hexValue = func("#" + this.id + "_BackgroundColor").val();
    //this.options.grid.backgroundColor = "#" + hexValue;
    var _opt = this.plotter.getOptions();
    if(_opt != undefined && _opt.grid != undefined)
    {
    //    _opt.grid.backgroundColor = this.options.grid.backgroundColor;
    }
}

function Trend_Plot() {
    this.idPlotter();
	this.setPlotData();        
	var trend = this;
	var placeholder = func("#" + this.id + '_Chart');
	var data = [];
	
	func.each(this.seriesoptions, function (index, value) {
		var label;
		if (value.screenTag === "")
			label = value.id;
		else
			label = value.screenTag;
		data.push({
			points: {show: value.markerOptions.show, radius: value.markerOptions.size, symbol: value.markerOptions.style},
			data: trend.dataPlot[index], 			
			label: label, 
			color: value.color, 
			lines: {show: !value.linePattern.show, steps: !value.interpolated, lineWidth: value.lineWidth},
			dashes: {show: value.linePattern.show, dashLength: value.linePattern},
		});
	});
	
	if (trend.showYAxisProp) {
	    func.each(data, function (index, value) {
            if (!_trend.subscribedPens[_trend.subscribedPens[index]].isHide && !trend.subscribedPens[_trend.subscribedPens[index]].isSpc)
			    value.yaxis = index + 1;
		});
	}
	
	if (this.play) {
		this.options.xaxis.max = new Date().getTime() + this.endTimeDiff;
		this.options.xaxis.min = this.options.xaxis.max - this.duration;
		
		if (this.plotter == undefined || this.redraw) {
			var yAxis, yMin, yMax;
			if (this.redraw) {
				yAxis = this.plotter.getAxes().yaxis;
				yMin = yAxis.min;
				yMax = yAxis.max;
			}
			this.plotter = func.plot(placeholder, data, this.options);
			if (this.redraw) {
				yAxis = this.plotter.getAxes().yaxis;
				yAxis.options.min = yMin;
				yAxis.options.max = yMax;
				this.plotter.setupGrid();
				this.plotter.draw();
			}
			if (!_isCursorDisable) {
				var pos = { x: (_cursorPosition == undefined ? (_trend.plotter.width() > 50 ? _trend.plotter.width() - 50 : 1) : _cursorPosition), y: 0 };
				_cursorPosition = pos.x;
				this.plotter.lockCrosshair(pos);
				if(_trend.plotter.getOptions().crosshair != undefined)
					_trend.plotter.getOptions().crosshair.color = _actualCursorColor;
			}
			this.redraw = false;
		}
		else {
			this.plotter.setData(data);
			var axes = this.plotter.getAxes();
			axes.xaxis.options.min = this.options.xaxis.min;
			axes.xaxis.options.max = this.options.xaxis.max;
			this.plotter.setupGrid();
			this.plotter.draw();
            for(var i=0; i< _trend.seriesoptions.length;i++)
			{	
				if(_trend.showYAxisProp)
				{
					var opt = _trend.seriesoptions;
					var yAxis = _trend.plotter.getYAxes();
					for(var i =0; i < opt.length;i++)
					{
					    var tName = _trend.id + _trend.seriesoptions[i].id;
					    tName = getParsedPenaId(tName);
					    if(document.getElementById("lMax_" + tName) != null && document.activeElement != document.getElementById("lMax_" + tName) && document.getElementById("lMax_" + tName).value != yAxis[i].max.toFixed(0))
							document.getElementById("lMax_" + tName).value = yAxis[i].max.toFixed(0);
					    if(document.getElementById("lMin_" + tName) != null && document.activeElement != document.getElementById("lMin_" + tName) && document.getElementById("lMin_" + tName).value != yAxis[i].min.toFixed(0))
							document.getElementById("lMin_" + tName).value = yAxis[i].min.toFixed(0);
					}
				}
				else
				{
				    var tName = _trend.id + _trend.seriesoptions[i].id;
				    tName = getParsedPenaId(tName);
					if(document.getElementById("lMax_" + tName) != null && document.activeElement != document.getElementById("lMax_" + tName) && document.getElementById("lMax_" + tName).value != axes.yaxis.max.toFixed(0))
						document.getElementById("lMax_" + tName).value = axes.yaxis.max.toFixed(0);
					if(document.getElementById("lMin_" + tName) != null && document.activeElement != document.getElementById("lMin_" + tName) && document.getElementById("lMin_" + tName).value != axes.yaxis.min.toFixed(0))
						document.getElementById("lMin_" + tName).value = axes.yaxis.min.toFixed(0);
				}
			}
		}
			
        //atualizando o Start e o End Date
		if (this.options != null) {
            if (document.activeElement.id !== this.id + '_StartDateText') {
                var date = new Date(this.options.xaxis.min);
                func("#" + this.id + "_StartDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
                func('#' + this.id + '_StartDate').data('datetimepicker').setLocalDate(date);
                this.updateDateTag(date, true);
            }
            if (document.activeElement.id !== this.id + '_EndDateText') {
                var date = new Date(this.options.xaxis.max);
                func("#" + this.id + "_EndDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
                func('#' + this.id + '_EndDate').data('datetimepicker').setLocalDate(date);
                this.updateDateTag(date, false);
            }
		}
    }
}

function Trend_UpdateDateTag(date, isStartDate) {
    if (isStartDate) {
        if (this.startDateTag !== '')
            DirectWriteTag(this.startDateTag, "0", date);
    }
    else {
        if (this.endDateTag !== '')
            DirectWriteTag(this.endDateTag, "0", date);
    }
}

function Trend_InitDateTag(startDateTag, endDateTag) {
    this.startDateTag = startDateTag;
    this.endDateTag = endDateTag;

    if (this.startDateTag !== '' && !this.isUpdatingTag) {
        var startDate = ScriptTagValues[GetKey(this.startDateTag + ";0")];
        this.UpdateStartDate(startDate);
    }
    if (this.endDateTag !== '' && !this.isUpdatingTag) {
        var endDate = ScriptTagValues[GetKey(this.endDateTag + ";0")];
        this.UpdateEndDate(endDate);
    }
}

function Trend_UpdatePlot(isStartDate) {
    if (isStartDate == null) {
        _trend.duration = moment.duration(document.getElementById('' + _trend.id + '_StartDateDuration').value);
        _trend.options.xaxis.min = _trend.options.xaxis.max - _trend.duration;
    }
    else {
        //fazer o Start e o End Date serem reajustados apos um dos dois serem alterados
        if (!isStartDate) {
            _trend.options.xaxis.max = func('#' + _trend.id + '_EndDate').data('datetimepicker').getLocalDate().getTime();
            _trend.options.xaxis.min = _trend.options.xaxis.max - _trend.duration;
        }
        else {
            _trend.options.xaxis.min = func('#' + _trend.id + '_StartDate').data('datetimepicker').getLocalDate().getTime();
            _trend.options.xaxis.max = _trend.options.xaxis.min + _trend.duration;
        }
        _trend.endTimeDiff = _trend.options.xaxis.max - new Date().getTime();
    }
    getHistoryItems();
	resizeInputTrend();
}

function Trend_UserAddPen(tagName, description, lineStyle = 0, thickness = 1, penColor = "#000000", interpol = true, marker = 0, showLegend = true, showSpcMin = false, showSpcMax = false, showSpcAvg = false, showSpcDev = false, spcDevSigma = 1) {
	//var bValid = true;
	//bValid = bValid && checkLength(tagname, "tagname", 3, 4096);
	//bValid = bValid && checkTag(tagname);
	//if (bValid) {
		Pena = createPen(tagName, false, description, penColor, marker, thickness, interpol, lineStyle, showLegend, false, showSpcMin, showSpcMax, showSpcAvg, showSpcDev, spcDevSigma);
		_trend.addPen(Pena);
		for (var i = 0; i < Pena.spcPens.length; i++)
			_trend.addPen(Pena.spcPens[i]);
	//}
}

function Trend_SetPenDescription(tagName, description) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_Description(description);
		document.getElementById("desc_" + _trend.id + tagName).value = description;
	}
}

function Trend_SetPenLineStyle(tagName, lineStyle) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_LineStyle(lineStyle);
		document.getElementById("lstyle_" + _trend.id + tagName).selectedIndex = lineStyle;
	}
}

function Trend_SetPenThickness(tagName, thickness) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_Thickness(thickness);
		document.getElementById("lthick_" + _trend.id + tagName).value = thickness;
	}
}

function Trend_SetPenColor(tagName, penColor) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_PenColor(penColor);
		document.getElementById("penColor_" + _trend.id + tagName).value = penColor;
	}
}

function Trend_SetPenInterpolated(tagName, interpol) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_Interpol(interpol);
		document.getElementById("interpol_" + _trend.id + tagName).checked = interpol;
	}
}

function Trend_SetPenMin(tagName, min) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		var newValue = parseInt(min);
		var axis = _trend.plotter.getYAxes();			
		var penName = pen.description;
		if(penName == "")
			penName = pen.id;
		if(!isNaN(newValue))
		{
			for(var i = 0;i < axis.length;i++)
			{
				if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
				{
					if(newValue > axis[i].min)
						axis[i].options.min = newValue;					
					else
						this.value = axis[i].min;	
					
					document.getElementById("lMin_" + _trend.id + tagName).value = min;
				}
			}
		}
		else
		{
			for(var i = 0;i < axis.length;i++)
			{
				if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
				{
					this.value = axis[i].min;
					document.getElementById("lMin_" + _trend.id + tagName).value = min;					 
					break;
				}
			}
		}
	}
}

function Trend_SetPenMax(tagName, max) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		var newValue = parseInt(max);
		var axis = _trend.plotter.getYAxes();			
		var penName = pen.description;
		if(penName == "")
			penName = pen.id;
		if(!isNaN(newValue))
		{
			for(var i = 0;i < axis.length;i++)
			{
				if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
				{
					if(newValue > axis[i].min)
						axis[i].options.max = newValue;					
					else
						this.value = axis[i].max;
					document.getElementById("lMax_" + _trend.id + tagName).value = max;
				}
			}
		}
		else
		{
			for(var i = 0;i < axis.length;i++)
			{
				if(!_trend.showYAxisProp || penName == axis[i].options.axisLabel)
				{
					this.value = axis[i].max;
					document.getElementById("lMax_" + _trend.id + tagName).value = max;
					break;
				}
			}
		}
	}
}

function Trend_SetPenMarker(tagName, marker) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_Marker(marker);
		document.getElementById("penMarker_" + _trend.id + tagName).selectedIndex = marker;
	}
}

function Trend_SetPenShowLegend(tagName, showLegend) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_ShowLegend(showLegend);
		document.getElementById("legend_" + _trend.id + tagName).checked = showLegend;
	}
}

function Trend_HasPenSPCMin(tagName) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
		return pen.get_SpcMin();
}

function Trend_HasPenSPCMax(tagName) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
		return pen.get_SpcMax();
}

function Trend_HasPenSPCAvg(tagName) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
		return pen.get_SpcAverage();
}

function Trend_HasPenSPCDev(tagName) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
		return pen.get_SpcStandardDeviation();
}

function Trend_GetPenSPCDevSigma(tagName) {
	var originalData = subscribedPens[tagName];
    if (originalData !== undefined) {
        var average = null;
        var sum = 0, count = 0, sumOfDerivation = 0;
        for (var i = 0; i < originalData.data.length; i++) {
            var dataValue = originalData.data[i][1];

            sumOfDerivation += dataValue * dataValue;
            sum += dataValue;
            count += 1;
        }

		var sumOfDerivationAverage = null, standardDeviation = null, sigma = null;
        if (count > 0) {
            average = sum / count;
            sumOfDerivationAverage = sumOfDerivation / count;
            standardDeviation = Math.sqrt(sumOfDerivationAverage - (average * average));
            sigma = originalData.get_spcStandardDeviationSigmaIndex();
        }
		return sigma;
	}
}

function Trend_GetPenSPCMin(tagName) {
	var startDate = func('#' + _trend.id + '_StartDate').data('datetimepicker').getLocalDate().getTime();
    var endDate = func('#' + _trend.id + '_EndDate').data('datetimepicker').getLocalDate().getTime();
    var spcValues = getSpcValues(this.subscribedPens, tagName, startDate, endDate);
	return spcValues[0];
}

function Trend_GetPenSPCMax(tagName) {
	var startDate = func('#' + _trend.id + '_StartDate').data('datetimepicker').getLocalDate().getTime();
    var endDate = func('#' + _trend.id + '_EndDate').data('datetimepicker').getLocalDate().getTime();
    var spcValues = getSpcValues(this.subscribedPens, tagName, startDate, endDate);
	return spcValues[1];
}

function Trend_GetPenSPCAvg(tagName) {
	var startDate = func('#' + _trend.id + '_StartDate').data('datetimepicker').getLocalDate().getTime();
    var endDate = func('#' + _trend.id + '_EndDate').data('datetimepicker').getLocalDate().getTime();
    var spcValues = getSpcValues(this.subscribedPens, tagName, startDate, endDate);
	return spcValues[2];
}

function Trend_GetPenSPCDev(tagName) {
	var originalData = subscribedPens[tagName];
    if (originalData !== undefined) {
        var average = null;
        var sum = 0, count = 0, sumOfDerivation = 0;
        for (var i = 0; i < originalData.data.length; i++) {
            var dataValue = originalData.data[i][1];

            sumOfDerivation += dataValue * dataValue;
            sum += dataValue;
            count += 1;
        }

		var sumOfDerivationAverage = null, standardDeviation = null, sigma = null;
        if (count > 0) {
            average = sum / count;
            sumOfDerivationAverage = sumOfDerivation / count;
            standardDeviation = Math.sqrt(sumOfDerivationAverage - (average * average));
            sigma = originalData.get_spcStandardDeviationSigmaIndex();
        }
		return standardDeviation;
	}
}

function Trend_GetPenSPCDevPositive(tagName) {
	var startDate = func('#' + _trend.id + '_StartDate').data('datetimepicker').getLocalDate().getTime();
    var endDate = func('#' + _trend.id + '_EndDate').data('datetimepicker').getLocalDate().getTime();
    var spcValues = getSpcValues(this.subscribedPens, tagName, startDate, endDate);
	return spcValues[3];
}

function Trend_GetPenSPCDevNegative(tagName) {
	var startDate = func('#' + _trend.id + '_StartDate').data('datetimepicker').getLocalDate().getTime();
    var endDate = func('#' + _trend.id + '_EndDate').data('datetimepicker').getLocalDate().getTime();
    var spcValues = getSpcValues(this.subscribedPens, tagName, startDate, endDate);
	return spcValues[4];
}

function Trend_SetSPC(showSPC) {
	var i = 0;
	while (i < _trend.seriesoptions.length)
	{
		this.seriesoptions[i].set_SpcMin(showLegend);
		this.seriesoptions[i].set_SpcMax(showLegend);
		this.seriesoptions[i].set_SpcAverage(showLegend);
		this.seriesoptions[i].set_SpcStandardDeviation(showLegend);
		
		document.getElementById("spcMin_" + _trend.id + this.seriesoptions[i].id).checked = showSPC;
		document.getElementById("spcMax_" + _trend.id + this.seriesoptions[i].id).checked = showSPC;
		document.getElementById("spcAverage_" + _trend.id + this.seriesoptions[i].id).checked = showSPC;
		document.getElementById("spcStandardDeviation_" + _trend.id + this.seriesoptions[i].id).checked = showSPC;
		
		i++;
	}
}

function Trend_SetSPC(showSpcMin, showSpcMax, showSpcAvg, showSpcDev, spcDevSigma) {
	var i = 0;
	while (i < _trend.seriesoptions.length)
	{
		this.seriesoptions[i].set_SpcMin(showSpcMin);
		this.seriesoptions[i].set_SpcMax(showSpcMax);
		this.seriesoptions[i].set_SpcAverage(showSpcAvg);
		this.seriesoptions[i].set_SpcStandardDeviation(showSpcDev);
		this.seriesoptions[i].set_SpcStandardDeviationSigmaIndex(spcDevSigma);
		
		document.getElementById("spcMin_" + _trend.id + this.seriesoptions[i].id).checked = showSpcMin;
		document.getElementById("spcMax_" + _trend.id + this.seriesoptions[i].id).checked = showSpcMax;
		document.getElementById("spcAverage_" + _trend.id + this.seriesoptions[i].id).checked = showSpcAvg;
		document.getElementById("spcStandardDeviation_" + _trend.id + this.seriesoptions[i].id).checked = showSpcDev;
		document.getElementById("spcStandardDeviationSigma_" + _trend.id + this.seriesoptions[i].id).selectedIndex = spcDevSigma;
		
		i++;
	}
}

function Trend_SetPenSPC(tagName, showSPC) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_SpcMin(showLegend);
		pen.set_SpcMax(showLegend);
		pen.set_SpcAverage(showLegend);
		pen.set_SpcStandardDeviation(showLegend);
		
		document.getElementById("spcMin_" + _trend.id + tagName).checked = showSPC;
		document.getElementById("spcMax_" + _trend.id + tagName).checked = showSPC;
		document.getElementById("spcAverage_" + _trend.id + tagName).checked = showSPC;
		document.getElementById("spcStandardDeviation_" + _trend.id + tagName).checked = showSPC;
	}
}

function Trend_SetPenSPC(tagName, showSpcMin, showSpcMax, showSpcAvg, showSpcDev, spcDevSigma) {
	var pen = this.subscribedPens[tagName];
	if (pen != undefined && pen != null)
	{
		pen.set_SpcMin(showSpcMin);
		pen.set_SpcMax(showSpcMax);
		pen.set_SpcAverage(showSpcAvg);
		pen.set_SpcStandardDeviation(showSpcDev);
		pen.set_SpcStandardDeviationSigmaIndex(spcDevSigma);
		
		document.getElementById("spcMin_" + _trend.id + tagName).checked = showSpcMin;
		document.getElementById("spcMax_" + _trend.id + tagName).checked = showSpcMax;
		document.getElementById("spcAverage_" + _trend.id + tagName).checked = showSpcAvg;
		document.getElementById("spcStandardDeviation_" + _trend.id + tagName).checked = showSpcDev;
		document.getElementById("spcStandardDeviationSigma_" + _trend.id + tagName).selectedIndex = spcDevSigma;
	}
}

function Trend_RemovePen(tagName) {
    this.removePen1(tagName);
    if (!this.play) {
        this.Play();
        this.plot();
        this.Pause();
    }
}

function Trend_UpdateDurationEnd(duration, date) {
	setDuration(duration);
	Trend_UpdateEndDate(date);
}

function _getMultiplierDouble(trendPointsMultipliers) {
    if (trendPointsMultipliers !== null && trendPointsMultipliers !== undefined) {
        switch (trendPointsMultipliers.toString()) {
            case "0,1":
            case "0.1":
                return 0.1;
            case "0,25":
            case "0.25":
                return 0.25;
            case "0,5":
            case "0.5":
                return 0.5;
            case "0,7":
            case "0.7":
                return 0.7;
            default:
            case "1":
                return 1;
            case "2":
                return 2;
            case "3":
                return 3;
            case "5":
                return 5;
            case "10":
                return 10;
        }
    }

    return 1;
}

function getHistoryItems() {
    func.each(_trend.subscribedPens, function (index, value) {
        var sizeIntervalFactor = _trend.get_Width() / 1000;
        var multiplier = _getMultiplierDouble(trendPointsMultipliers);
        var interval = ((_trend.duration._milliseconds !== undefined ? _trend.duration._milliseconds : _trend.duration) / 240 * sizeIntervalFactor) / (5 * multiplier);
        interval = Number.parseInt(interval);
        var items = GetTagHistory(value, _trend.options.xaxis.min, _trend.options.xaxis.max, interval);
        if (items != null) {
            var listOfValues = _trend.dataPlot[index];
            for (var i = 0; i < items.length; i++) {
                var item = JSON.parse(items[i]);
                item[0] = new Date(item[0] + new Date().getTimezoneOffset() * 60000).getTime();
                _trend.dataPlot[index].push(item);
                listOfValues.push(item);                
            }

            var newListOfValues = _trend.dataPlot[index].slice();
           
            for (var i = 0; i < listOfValues.length; i++) {
                var canAdd = true;
                for (var j = 0; j < _trend.dataPlot[index].length; j++) {
                    if (_trend.dataPlot[index][j][0] === listOfValues[i][0]) {
                        canAdd = false;
                        break;                        
                    }
                }
                if (canAdd) 
                    newListOfValues.push(listOfValues[i]);
            }
            var orderedList = newListOfValues.sort(_comparatorTrendValues);
            _trend.subscribedPens[value].data = orderedList;
            _trend.dataPlot[index] = orderedList;

        }
    });
}

function _comparatorTrendValues(a, b) {
    if (a[0] < b[0]) return -1;
    if (a[0] > b[0]) return 1;
    return 0;
}

function setPenData(id) {
    if (this.subscribedPens[id] != null && this.subscribedPens[id] != "") {
        var index = this.subscribedPens.indexOf(this.subscribedPens[id].id);
        var tagValue = ScriptTagValues[GetKey(this.subscribedPens[id].id + ";0")];
        var date = new Date().getTime();
        var array = [date, tagValue];		
        this.subscribedPens[id].data.push(array);
    }
}

function getSpcValues(subscribedPens, id, startDate, endDate) {
    var originalData = subscribedPens[id];
    if (originalData !== undefined) {
        var min = null, max = null, average = null, standardDev = null, standardPositive = null, standardNegative = null;
        var sum = 0, count = 0, sumOfDerivation = 0;
        for (var i = 0; i < originalData.data.length; i++) {
            var ts = originalData.data[i][0];
            if (ts < startDate || ts > endDate)
                continue;
            var dataValue = originalData.data[i][1];
            if (min == null || dataValue < min)
                min = dataValue
            if (max == null || dataValue > max)
                max = dataValue

            sumOfDerivation += dataValue * dataValue;
            sum += dataValue;
            count += 1;
        }

        if (count > 0) {
            average = sum / count;
            var sumOfDerivationAverage = sumOfDerivation / count;
            var standardDeviation = Math.sqrt(sumOfDerivationAverage - (average * average));
            var sigma = originalData.get_spcStandardDeviationSigmaIndex();
            standardDev = standardDeviation;
            standardPositive = average + (sigma * standardDeviation);
            standardNegative = average - (sigma * standardDeviation);
        }
        else {
            min = null;
            max = null;
        }

        var ret = [];
        ret.push(min);
        ret.push(max);
        ret.push(average);
        ret.push(standardDev);
        ret.push(standardPositive);
        ret.push(standardNegative);
        return ret;
    }
}

function convertSpcValueInData(value, startDate, endDate) {
    var data = [];

    var data1 = [];
    data1.push(startDate);
    data1.push(value);

    var data2 = [];
    data2.push(endDate);
    data2.push(value);

    data.push(data1);
    data.push(data2);
    return data;
}

function setPlotData() {
    var actualTime = new Date().getTime();
    var dataPlot = this.dataPlot;
    var subscribedPens = this.subscribedPens;

    var startDate = func('#' + _trend.id + '_StartDate').data('datetimepicker').getLocalDate().getTime();
    var endDate = func('#' + _trend.id + '_EndDate').data('datetimepicker').getLocalDate().getTime();
    var dicSpcValues = {};
    for (var i = 0; i < this.subscribedPens.length; i++) {
        var pena = subscribedPens[subscribedPens[i]];
        if (pena.hasAnySpcFunction()) {
            if (!(pena.id in dicSpcValues)) {
                var spcValues = getSpcValues(subscribedPens, pena.id, startDate, endDate);
                dicSpcValues[pena.id] = spcValues;
            }
        }
    }

    func.each(this.subscribedPens, function (index, value) {
        if (value != null) {
            //se a série não existir, insere			
            if (dataPlot.length == index) {
                var tagValue = ScriptTagValues[GetKey(value + ";0")];
                var array = [actualTime, tagValue];
                v = [];
                v.push(array);
                dataPlot.push(v);
            }
            //se existir incrementa
            else {
                var pena = subscribedPens[value];
                if (pena.get_IsSpc()) {
                    data = [];
                    var indexType = value.lastIndexOf("_");
                    if (indexType >= 0) {
                        var originalPenName = value.substr(0, indexType)
                        var type = value.substr(indexType + 1);
                        if (originalPenName in dicSpcValues) {
                            var spcValues = dicSpcValues[originalPenName];
                            var data = null;
                            switch (type) {
                                case "Min":
                                    var penId = 'lbSpclMin_' + pena.tName;
                                    var spcValue = '-';
                                    if (spcValues.length > 0) {
                                        var min = spcValues[0];                                        
                                        if (min != null) {
                                            spcValue = min.toFixed(2);
                                            data = convertSpcValueInData(min, startDate, endDate);
                                        }
                                    }
                                    document.getElementById(penId).innerHTML = spcValue;
                                    break;
                                case "Max":
                                    var penId = 'lbSpclMax_' + pena.tName;
                                    var spcValue = '-';
                                    if (spcValues.length > 1) {
                                        var max = spcValues[1];
                                        if (max != null) {
                                            spcValue = max.toFixed(2);
                                            data = convertSpcValueInData(max, startDate, endDate);
                                        }
                                    }
                                    document.getElementById(penId).innerHTML = spcValue;
                                    break;
                                case "Average":
                                    var penId = 'lbSpclAverage_' + pena.tName;
                                    var spcValue = '-';
                                    if (spcValues.length > 2) {
                                        var average = spcValues[2];
                                        if (average != null) {
                                            spcValue = average.toFixed(2);
                                            data = convertSpcValueInData(average, startDate, endDate);
                                        }
                                    }
                                    document.getElementById(penId).innerHTML = spcValue;
                                    break;
                                case "StandardDeviationPositive":
                                    var penId = 'lbSpclStandardDeviation_' + pena.tName.substr(0, pena.tName.lastIndexOf("Positive"));
                                    var spcValue = '-';
                                    if (spcValues.length > 4) {
                                        var standardDeviation = spcValues[3];
                                        var standardDeviationPositive = spcValues[4];
                                        if (standardDeviation != null)
                                            spcValue = standardDeviation.toFixed(2);
                                        if (standardDeviationPositive != null)                                             
                                            data = convertSpcValueInData(standardDeviationPositive, startDate, endDate);                                        
                                    }
                                    document.getElementById(penId).innerHTML = spcValue;
                                    break;
                                case "StandardDeviationNegative":
                                    var penId = 'lbSpclStandardDeviation_' + pena.tName.substr(0, pena.tName.lastIndexOf("Negative"));
                                    var spcValue = '-';
                                    if (spcValues.length > 5) {
                                        var standardDeviation = spcValues[3];
                                        var standardDeviationNegative = spcValues[5];
                                        if (standardDeviation != null)
                                            spcValue = standardDeviation.toFixed(2);
                                        if (standardDeviationNegative != null) 
                                            data = convertSpcValueInData(standardDeviationNegative, startDate, endDate);
                                    }
                                    document.getElementById(penId).innerHTML = spcValue;
                                    break;
                            }
                        }
                        if (data != null) {
                            dataPlot[index] = [];
                            dataPlot[index].push(data[0]);
                            dataPlot[index].currentPoint = data[1];
                            dataPlot[index].push(data[1]);
                        }
                    }
                }
                else {
                    var data = pena.data;
                    if (data != null) {
                        var currentPoint = [actualTime, func(data).get(-1)[1]];
                        var tagValue = currentPoint[1];
                        if (dataPlot[index].currentPoint != currentPoint) {
                            // if (dataPlot[index].currentPoint != undefined && !subscribedPens[value].interpolated) {
                            // var vPoint = [currentPoint[0] - 1, dataPlot[index].currentPoint[1]];
                            //dataPlot[index].push(vPoint);
                            // }
                            // último valor verdadeiro inserido
                            dataPlot[index].currentPoint = currentPoint;
                            dataPlot[index].push(currentPoint);
                            // } else if (!subscribedPens[value].interpolated) {
                            // var vPoint = [actualTime, tagValue];
                            //dataPlot[index].push(vPoint);
                        }
                    }
                }
            }
        }
    });
    this.dataPlot = dataPlot;
}

function Trend_PlayPause(isPlaying) {
    if (isPlaying) {
        this.Pause();
    } else {
        this.Play();
    }
}

function Trend_Play() {
    if (!this.play) {
        this.play = true;
        func("#" + this.id + "_Pause").removeAttr("disabled");
        func("#" + this.id + "_Play").attr("disabled", "disabled");
        func("#" + this.id + "_StartDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
        if (this.options.axes == undefined)
            func("#" + this.id + "_StartDate").data('datetimepicker').setLocalDate(new Date(this.options.xaxis.min));
        else
            func("#" + this.id + "_StartDate").data('datetimepicker').setLocalDate(new Date(this.options.axes.xaxis.min));
        func("#" + this.id + "_EndDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
        if (this.options.axes == undefined)
            func("#" + this.id + "_EndDate").data('datetimepicker').setLocalDate(new Date(this.options.xaxis.max));
        else
            func("#" + this.id + "_EndDate").data('datetimepicker').setLocalDate(new Date(this.options.axes.xaxis.max));
    }
}

function Trend_Pause() {
    if (this.play) {
        this.play = false;
        func("#" + this.id + "_Pause").attr("disabled", "disabled");
        func("#" + this.id + "_Play").removeAttr("disabled");
    }
}

function Trend_PlayNow() {
    if (!this.play) {
        this.play = true;
        func("#" + this.id + "_Pause").removeAttr("disabled");
        func("#" + this.id + "_Play").attr("disabled", "disabled");
    }
    func("#" + this.id + "_StartDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
    func("#" + this.id + "_StartDate").data('datetimepicker').setLocalDate(new Date(new Date().getTime() - this.duration));
    func("#" + this.id + "_EndDate").data('datetimepicker').format = GetProjectDateTimeFormatWithPMAM();
    func("#" + this.id + "_EndDate").data('datetimepicker').setLocalDate(new Date());
    Trend_UpdatePlot(false);
}

function setDuration(ticks) {
    this.duration = ticks;
    var t = new TimeSpan(ticks);
    var days = t.days().toString();
    var hours = t.hours().toString();
    var min = t.minutes().toString();
    var sec = t.seconds().toString();

    if (days.length == 1)
        days = "0" + days;
    if (hours.length == 1)
        hours = "0" + hours;
    if (min.length == 1)
        min = "0" + min;
    if (sec.length == 1)
        sec = "0" + sec;

    if (t.days() > 0)
        document.getElementById('' + this.id + '_StartDateDuration').value = days + "." + hours + ":" + min + ":" + sec;
    else
        document.getElementById('' + this.id + '_StartDateDuration').value = hours + ":" + min + ":" + sec;
}

function resizeInputTrend() {
    if (func("#" + _trend.id + "_StartDateDuration").val().length < 1)
        func("#" + _trend.id + "_StartDateDuration").attr('size', 1);
    else if (func("#" + _trend.id + "_StartDateDuration").attr("mw") > 0) {
        var max_width = func("#" + _trend.id + "_StartDateDuration").attr("mw");
        if (func("#" + _trend.id + "_StartDateDuration").val().length < max_width) {
            func("#" + _trend.id + "_StartDateDuration").attr('size', func("#" + _trend.id + "_StartDateDuration").val().length);
        }
        else {
            func("#" + _trend.id + "_StartDateDuration").attr('size', max_width);
        }
    }
    else
        func("#" + _trend.id + "_StartDateDuration").attr('size', func("#" + _trend.id + "_StartDateDuration").val().length);
}

function Trend_ContextMenu() {
    var menuTrend = [{
        name: 'Fit to now',
        img: apiLocation + 'htmlImages/FitTimeToView.png',
        title: 'Make visible area fit time to display entire contents',
        fun: function () {
            _trend.fitToNow();          
        }
    }, {
        name: 'Fit Scale to view',
        img: apiLocation + 'htmlImages/FitScaleToView.png',
        title: 'Make visible area fit scale to disply entire contents',
        fun: function () {
            _trend.fitScalesToView();
        }
    }, {
        name: 'Save screenshot',
        img: apiLocation + 'htmlImages/SaveIcon.png',
        title: 'Specify name of image file to save screenshot to',
        fun: function () {
            html2canvas(func("#" + _trend.id + "_Chart"), {
                onrendered: function (canvas) {
                    var imgString = canvas.toDataURL("image/png");
                    var a = document.createElement('a');
                    a.download = _trend.id + '.png';
                    a.href = imgString;
                    a.click();
                }
            });
        }
    }, {
        name: 'Copy screenshot',
        img: apiLocation + 'htmlImages/CopyScreenshotIcon.png',
        title: 'Copy screenshot of charts to clipboard',
        fun: function () {

        }
    }, {
        name: 'Report feedback',
        img: apiLocation + 'htmlImages/ReportFeedbackIcon.png',
        title: 'Create an e-mail message to report feedback or submit a bug',
        fun: function () {
            window.location.href ='mailto:suporte@phisystems.com.br';
        }
    }, {
        name: 'Set cursor here',
        img: apiLocation + 'htmlImages/SetCursorIcon.png',
        title: 'Sets the cursor into position',
        fun: function () {
        	var posX = this.parentElement.offsetLeft - _trend.plotter.offset().left;
			_trend.setCursor(posX);
        }
    }, {
        name: 'Remove cursor',
        img: apiLocation + 'htmlImages/ResetCursorIcon.png',
        title: 'Removes the cursor',
        fun: function () {
            _trend.removeCursor();
        }
    }];

    return menuTrend;
}

function Generate_DynamicFill(tagName, elementName, orientation, flip) {
    var dynamicFillValues = GetDynamicFillGradient(tagName, orientation, flip);
    var grad = document.getElementById('fillGrad_' + elementName);
    if (grad !== null) {
        while (grad.firstChild) {
            grad.removeChild(grad.firstChild);
        }
        var isVertical = orientation == 0;
        for (var i = 0; i < dynamicFillValues.length; i++) {            
            var stop = document.createElementNS("http://www.w3.org/2000/svg", "stop");
            var offset = dynamicFillValues[i];
            if (offset === "max" || offset === "min")
                continue;
            var newStyle = "";
            var minOrMax = dynamicFillValues[2];
            var index = 0;
            if (minOrMax == "min") {
                index = 0;
            } else if (minOrMax == "max") {
                index = 1;
            } else {
                if (i < 2) {
                    if (isVertical && !flip || !isVertical && flip)
                        index = 0;
                    else
                        index = 1;
                }
                else {
                    if (isVertical && !flip || !isVertical && flip)
                        index = 1;
                    else
                        index = 0;
                }
            }
            newStyle = "stop-color:" + this.dynamicFillColors[index] + ";";
            //if (dynamicFillValues.length == oldStyles.length || dynamicFillValues.length > oldStyles.length) {
                
            //} else {
            //    var minOrMax = dynamicFillValues[2];
            //    if (minOrMax == "min")
            //        newStyle = "stop-color:" + this.dynamicFillColors[0] + ";";
            //    else 
            //        newStyle = "stop-color:" + this.dynamicFillColors[0] + ";";
            //}
            if (offset.Contains(","))
                offset = offset.replace(",", ".");
            newStyle += "stop-opacity: 1;"
            offset = offset.substr(0, offset.length - 1);
            stop.setAttribute("offset", offset);
            stop.setAttribute("style", newStyle);            
            grad.appendChild(stop); 
        }
    }
}


//Validação e Funções do Dialog
$(function () {	
	var func;
	if($ != undefined)
		func = $;
	else
		func = J;
	
    var tagname = func("#tagname"),
		description = func("#description"),
		pencolor = func("#pencolor"),
		marker = func("#marker"),
		lthick = func("#lthick"),
		interpolated = func("#interpolated"),
        lstyle = func("#lstyle"),
        legend = func("#legend"),
        allFields = func([]).add(tagname).add(description).add(pencolor).add(marker).add(lthick).add(interpolated).add(lstyle).add(legend),
		tips = func(".validateTips");

    function updateTips(t) {
        tips
				.text(t)
				.addClass("ui-state-highlight");
        setTimeout(function () {
            tips.removeClass("ui-state-highlight", 1500);
        }, 500);
    }

    function checkLength(o, n, min, max) {
        if (o.val().length > max || o.val().length < min) {
            o.addClass("ui-state-error");
            updateTips("Length of " + n + " must be between " +
				  min + " and " + max + ".");
            return false;
        } else {
            return true;
        }
    }

    function checkTag(tag) {
        var oTag = tag.val();
		if(oTag.search("@") == 0) {
			oTag = oTag.substring(1);
			tag.val(oTag);
		}
        //checando se a tag é válida
        if (ScriptTagValues[GetKey(tag.val() + ";0")] == "?????") {
            tag.addClass("ui-state-error");
            updateTips("Tag " + tag.val() + " invalida");
        }
        else
            return true;
    }

    function checkRegexp(o, regexp, n) {
        if (!(regexp.test(o.val()))) {
            o.addClass("ui-state-error");
            updateTips(n);
            return false;
        } else {
            return true;
        }
    }

    func("#dialog-form").dialog({
        autoOpen: false,
        modal: true,
        buttons: {
            "Add Pen": function () {
                var bValid = true;
                allFields.removeClass("ui-state-error");
                bValid = bValid && checkLength(tagname, "tagname", 3, 4096);
                bValid = bValid && checkTag(tagname);
                /*bValid = bValid && checkLength( email, "email", 6, 80 );
                bValid = bValid && checkLength( password, "password", 5, 16 );		 
                bValid = bValid && checkRegexp( name, /^[a-z]([0-9a-z_])+$/i, "Username may consist of a-z, 0-9, underscores, begin with a letter." );
                // From jquery.validate.js (by joern), contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
                bValid = bValid && checkRegexp( email, /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, "eg. ui@jquery.com" );
                bValid = bValid && checkRegexp( password, /^([0-9a-zA-Z])+$/, "Password field only allow : a-z 0-9" );
                */
                if (bValid) {
                    Pena = createPen(tagname.val(), false, description.val(), '#' + pencolor.val(), marker.val(), lthick.val(), interpolated[0].checked, lstyle.val(), legend[0].checked,
                        false, spcMin.checked, spcMax.checked, spcAverage.checked, spcStandardDeviation.checked, spcStandardDeviationSigmaIndex.value);
                    _trend.addPen(Pena);
                    for (var i = 0; i < Pena.spcPens.length; i++)
                        _trend.addPen(Pena.spcPens[i]);
                    func(this).dialog("close");
                }
            },
            Cancel: function () {
                func(this).dialog("close");
            }
        },
        close: function () {
            allFields.val("").removeClass("ui-state-error");
            pencolor.val("000000");
            marker.val(0);
            interpolated.removeAttr('checked');
            lstyle.val(0);
            lthick.val("1");
            legend.removeAttr('checked');
        }
    });
});

function OPCDaBrowser_Create() {
    var row = "<div id='OPCDABrowserDialog' title='OPC DA Item Browser' style='display:none;Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI'; text-align:Left;  '>";
    row += "<div id='OPCDABrowserLabel1' style='position: absolute; left: 26px; top: 28px; width: 64px; height: 18px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI'; text-align:Left; ' >OPC Server:</div>";
    row += "<select name ='OPCDABrowserServerComboBox' id ='OPCDABrowserServerComboBox'  style='position:absolute; top:21px; left:95px; width:144px; height:22px; '></select>";
    row += "<div id='OPCDABrowserLabel2' style='position: absolute; left: 256px; top: 61px; width: 34px; height: 14px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI'; text-align:Left;' >Filter:</div>";
    row += "<input id='OPCDABrowserFilterTextBox' type='text' style='position: absolute; left: 293px; top: 54px; width: 92px; height: 17px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI';' value=''>";
    row += "<button id='OPCDABrowserOKButton' type='button' value='OK' style='position: absolute; left: 394px; top: 14px; width: 60px; height: 30px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI';'>OK</button>";
    row += "<button id='OPCDABrowserCancelButton' type='button' value='Cancel' style='position: absolute; left: 394px; top: 48px; width: 60px; height: 30px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI';'>Cancel</button>";
    row += "<div id='OPCDABrowserTreeView1' style='position: absolute; left: 28px; top: 59px; width: 211px; height: 230px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI'; text-align:Left;' ></div>";
    row += "<div id='OPCDABrowserLabel3' style='position: absolute; left: 257px; top: 99px; width: 34px; height: 15px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI'; text-align:Left;' >Items:</div>";
    row += "<ul id='OPCDABrowserLeavesList' style='list-style-type:none; border-style:ridge; overflow-y:scroll; position: absolute; left: 252px; top: 105px; width: 154px; height: 176px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI'; text-align:Left;' ></ul>";
    row += "<div id='OPCDABrowserLabel4' style='position: absolute; left: 33px; top: 329px; width: 92px; height: 18px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI'; text-align:Left;' >Selected Item ID:</div>";
    row += "<input id='OPCDABrowserSelectedTextBox' type='text' style='position: absolute; left: 140px; top: 320px; width: 311px; height: 18px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI';' value=''>";
    row += "<div id='OPCDABrowserLabel5' style='position: absolute; left: 85px; top: 362px; width: 89px; height: 14px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI'; text-align:Left;' >Status:</div>";
    row += "<input id='OPCDABrowserStatusTextBox' type='text' style='position: absolute; left: 140px; top: 353px; width: 311px; height: 18px; Color: #000000; background: #FFFFFF; font-size: 12px; font-family: 'Segoe UI';' value=''>";
    row += "</div>";
    row += "<div id='itemBrowserLabel' style='display:none;' ></div>";
    var func;
	if($ !=  undefined)
		func = $("body")
	else
		func = J("body")
	func.append(row);
}

function rgb2hex(rgb) {
    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    return "#" + ("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[3], 10).toString(16)).slice(-2);
}
//############### End Helpers ###############

//############### Begin EventsFallThrough ###############
function ExecuteEventsFallThrough(event)
{
    if ((!executeEventsFallThroughObjects) || ((event.pageX == -1) && (event.pageY == -1)))
        return;

	var elements = GetAllElementsAt(event.pageX, event.pageY);
	if ((elements != undefined) && (elements != null))
	{
		elements.each(function() {
			var targetId = event.target.id;
			if (event.target.className.toString().toUpperCase().Contains("SVG"))
			{
				var oParent = event.target.parentNode;
				targetId = oParent.id;
				while ((targetId == "") && (oParent.parentNode != undefined))
				{
					oParent = oParent.parentNode;
					targetId = oParent.id;
				}
			}
            else if(event.target.nodeName != undefined && event.target.nodeName.toUpperCase() == "IMG" && 
                        event.target.parentNode != undefined && event.target.parentNode.nodeName != undefined &&
                        event.target.parentNode.nodeName.toUpperCase() == "BUTTON")
			{
				targetId = event.target.parentNode.id;
			}
			
            if (targetId !== '' && (window[func(this)[0].id] != undefined) && (func(this)[0].id != targetId) && (window[func(this)[0].id].tagName == undefined) && event.target.accessKey != "innerChild")
			{
				var e = $.Event( event.type, { pageX: -1, pageY: -1, which: event.which, target: event.target } );
				$('#' + func(this)[0].id.toString()).trigger( e );
			}
		});
	}
}

function CanExecuteLogic(oObject, event)
{
	var elements = GetAllElementsAt(event.pageX, event.pageY);
	var canExecuteLogic = true;
	if ((elements != undefined) && (elements != null))
	{
		elements.each(function() {
			var targetId = oObject.id;
			if (event.target.className.toString().toUpperCase().Contains("SVG"))
			{
				var oParent = event.target.parentNode;
				targetId = oParent.id;
				while ((targetId == "") && (oParent.parentNode != undefined))
				{
					oParent = oParent.parentNode;
					targetId = oParent.id;
				}
			}
		
			if ((window[func(this)[0].id] != undefined) && (func(this)[0].id != targetId) && (window[func(this)[0].id].tagName == undefined))
			{
				if (($('#' + oObject.id.toString()).css('z-index') < $('#' + func(this)[0].id.toString()).css('z-index')) &&
					($.isFunction(window[func(this)[0].id.toString()].get_IsEnabled)) && (!window[func(this)[0].id.toString()].get_IsEnabled()))
				{
					canExecuteLogic = false;
					return;
				}
			}
		});
	}
	
	return canExecuteLogic;
}
			
function GetAllElementsAt(x, y) {
    if ((x == -1) && (y == -1))
        return null;

	var $elements = func("body *").map(function() {
		var $this = func(this);
		var offset = $this.offset();
		var left = offset.left;
		var top = offset.top;
		var height = $this.innerHeight();
		var width = $this.innerWidth();

		var right = left + width;
		var bottom = top + height;

		return (x <= right && x >= left) && (y <= bottom && y >= top) ? $this : null;
	});

	return $elements;
}

function isValidUrl(url) {
    try { url = new URL(url); }
    catch (ex) { return false; }
    return url.protocol === "http:" || url.protocol === "https:";
}

String.prototype.width = function (font) {
    var f = font || '12px arial';
    var o = $('<div></div>').text(this).css({ 'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f }).appendTo($('body'));
    var w = o.width();
    o.remove();
    return w;
}
//############### End EventsFallThrough ###############