private void WriteTextBlockConcept(ConceptMember conceptMember, IDictionary <Member, FactModel> facts)
        {
            // To create a new table after the text block.
            var tableContext = _activeTables.Peek();

            tableContext.Table = null;

            var xConceptH2 = CreateMemberElement(conceptMember, HtmlXNames.H2);

            _xActiveNetwork.Add(xConceptH2);

            var occupiedMembers = facts.Where(item => item.Value != null).ToList();

            if (!occupiedMembers.Any())
            {
                return;
            }

            var xValueDiv = new XElement(HtmlXNames.Div);

            xValueDiv.AddClass(InlineXbrlClassNames.Fact);
            xValueDiv.AddClass(string.Format(InlineXbrlClassNames.Level, conceptMember.Depth));

            _xActiveNetwork.Add(xValueDiv);

            if (occupiedMembers.Count > 1)
            {
                xValueDiv.Add($"Found {occupiedMembers.Count} facts for this text block, but there should be at most one.");
                return;
            }

            var singleFact = occupiedMembers.First().Value;

            xValueDiv.Add(CreateFactElement(singleFact, conceptMember));
        }
        private XElement CreateHtmlTable(XmlBasedTableContext tableContext)
        {
            var xColGroup = new XElement(HtmlXNames.Colgroup);

            xColGroup.Add(new XElement(HtmlXNames.Col, new XAttribute("class", "concept")));

            var xHeaderTr = new XElement(HtmlXNames.Tr, new XElement(HtmlXNames.Th));

            foreach (var member in tableContext.LinearisedHorizontalAxis)
            {
                xColGroup.Add(new XElement(HtmlXNames.Col, new XAttribute("class", "fact")));
                var xTh = new XElement(HtmlXNames.Th, CreateMemberElement(member, HtmlXNames.Div));
                xHeaderTr.Add(xTh);
            }

            var xTable = new XElement(HtmlXNames.Table);

            xTable.AddData("horizontal-axis-role", tableContext.HorizontalAxis.Name.LocalName);
            xTable.AddClass(InlineXbrlClassNames.Table);
            xTable.Add(xColGroup);
            xTable.Add(new XElement(HtmlXNames.Thead, xHeaderTr));
            xTable.Add(new XElement(HtmlXNames.Tbody));
            _xActiveNetwork.Add(xTable);

            return(xTable);
        }
        private void CreateNonFractionFactElement(XElement element, Fact fact, ConceptMember conceptMember)
        {
            var item = conceptMember.Item;

            element.AddClass(InlineXbrlClassNames.NonFractionFact);

            // Values in iXBRL are always absolute and a sign attribute is used to express a negative fact value.
            // This is for two reasons:
            // 1. There are several ways negative amounts can be rendered, e.g. leading dash, brackets, colour-coded.
            // 2. With negated labels, the sign of the fact value is the opposite of what is displayed.
            var accountingValue = fact.GetAccountingValue(item.BalanceType);

            var scaledAbsoluteValue = Math.Abs(accountingValue) / Math.Pow(10, _settings.Scale);
            var formattedValue      = scaledAbsoluteValue.ToString("N", _settings.Culture);

            var isAccoutingValueNegative = accountingValue < 0;
            var decimals = _settings.Culture.NumberFormat.NumberDecimalDigits;

            var xNonFraction = new XElement(Namespaces.Ix + "nonFraction");

            xNonFraction.SetAttributeValue("name", item.Name.ToColonSeparated(_xHtml));
            xNonFraction.SetAttributeValue("contextRef", fact.GetContextId(_xHtml));
            xNonFraction.SetAttributeValue("unitRef", fact.Unit.Id);
            xNonFraction.SetAttributeValue("scale", _settings.Scale);
            xNonFraction.SetAttributeValue("decimals", decimals);
            xNonFraction.SetAttributeValue("format", $"ixt:{_numberFormat}");
            if (isAccoutingValueNegative)
            {
                xNonFraction.SetAttributeValue("sign", "-");
            }

            xNonFraction.Value = formattedValue;
            element.Add(xNonFraction);

            var isDisplayNegative = LabelRoles.Negatives.Contains(conceptMember.PreferredLabelRole)
                ? !isAccoutingValueNegative
                : isAccoutingValueNegative;

            element.AddClass(isDisplayNegative ? InlineXbrlClassNames.NegativeFact : InlineXbrlClassNames.PositiveFact);
            if (isDisplayNegative)
            {
                element.AddFirst("(");
                element.Add(")");
            }
        }
        private void PopulateItemMemberElement(XElement xContainer, ItemMember itemMember)
        {
            xContainer.Value = RemoveBracketedMarkers(itemMember.Label);
            xContainer.AddClass(InlineXbrlClassNames.ItemMember);

            if (itemMember.Item.IsAbstract)
            {
                xContainer.AddClass(InlineXbrlClassNames.AbstractMember);
            }

            var conceptMember = itemMember as ConceptMember;

            if (conceptMember != null && LabelRoles.Totals.Contains(conceptMember.PreferredLabelRole))
            {
                xContainer.AddClass(InlineXbrlClassNames.TotalMember);
            }

            xContainer.AddData("info", SerializeJson(CreateItemMemberInfo(itemMember)));
        }
        private XElement CreateMemberElement(Member member, XName containerName)
        {
            var xSpan = new XElement(containerName);

            xSpan.AddClass(InlineXbrlClassNames.Member);
            xSpan.AddClass(string.Format(InlineXbrlClassNames.Level, member.Depth));

            var itemMember = member as ItemMember;

            if (itemMember != null)
            {
                PopulateItemMemberElement(xSpan, itemMember);
            }
            else
            {
                xSpan.Value = member.ToString(_settings.Culture);
            }

            return(xSpan);
        }
        public override void WriteBeginPresentationNetwork(PresentationNetwork presentationNetwork)
        {
            _xActiveNetwork = new XElement(HtmlXNames.Article);
            _xActiveNetwork.AddData("role", presentationNetwork.Role.AbsoluteUri);
            _xActiveNetwork.AddClass(InlineXbrlClassNames.Network);
            _xNetworksSection.Add(_xActiveNetwork);

            var xHeader = new XElement(HtmlXNames.Header,
                                       new XElement(HtmlXNames.H1, presentationNetwork.Name));

            _xActiveNetwork.Add(xHeader);
        }
        // TODO: inline HTML inside text blocks.
        private void CreateTextualFactElement(XElement element, Fact fact, Item item)
        {
            element.AddClass(InlineXbrlClassNames.NonNumericFact);

            var xNonNumeric = new XElement(Namespaces.Ix + "nonNumeric");

            xNonNumeric.SetAttributeValue("name", item.Name.ToColonSeparated(_xHtml));
            xNonNumeric.SetAttributeValue("contextRef", fact.GetContextId(_xHtml));
            xNonNumeric.Value = fact.Value;

            element.Add(xNonNumeric);
        }
Example #8
0
        public static void ToggleClass(this XElement @this, string @class)
        {
            if (@this == null)
            {
                throw new ArgumentNullException();
            }

            if (@this.HasClass(@class))
            {
                @this.RemoveClass(@class);
            }
            else
            {
                @this.AddClass(@class);
            }
        }
        private XElement CreateFactElement(FactModel factModel, ConceptMember conceptMember)
        {
            var item = conceptMember.Item;

            var xSpan = new XElement(HtmlXNames.Span);

            xSpan.AddClass(InlineXbrlClassNames.Fact);

            if (item.DataType == DataTypeRegistry.Monetary)
            {
                CreateNonFractionFactElement(xSpan, factModel.Fact, conceptMember);
            }
            else if (DataTypeRegistry.Textual.Contains(item.DataType))
            {
                CreateTextualFactElement(xSpan, factModel.Fact, item);
            }

            return(xSpan);
        }