Skip to content

Instantly share code, notes, and snippets.

@jeremy-farrance
Last active February 20, 2021 17:36
Show Gist options
  • Save jeremy-farrance/7c70505a2f991801ace3ab83a39323c4 to your computer and use it in GitHub Desktop.
Save jeremy-farrance/7c70505a2f991801ace3ab83a39323c4 to your computer and use it in GitHub Desktop.
Dnn/2sxc Content-App - Heading Component? for @renderpage
@*
>>> this is an early, incomplete version with lots of debugging and unfinished thinking 20210219 JRF
- this version is appx from CUA MAIL 2021 on Dnn 9.07.x with 2sxc 11.11.04
>>> Dependencies
- 2sxc 11+ + RazorBlade 3+
- AccuKit; only for debugging using sbe()
*@
@inherits ToSic.Sxc.Dnn.RazorComponent
@using ToSic.Razor.Blade;
@*
Example of calling from another page, each/all args optional
@RenderPage("_Shared--Heading.cshtml")
or you can include (override) any or all of these values
@RenderPage("_Shared--Heading.cshtml",
new {
title = "Passed in Title",
tag = "h4",
align = "center",
class = "my-3"
}
)
WHAT THIS SHARED CODE DOES
Make a module heading (title) handling all possible View setup cases,
just add (example below) and the heading will get displayed as expected
regardless of what is set (or not) in the View, falling back through
any other available options gracefully.
FUTURE IDEAS
- Put the debug output in a Bootstrap collapsible (Accordion?)
- handle emitting a default (synthetic) or settings for an #Anchor
- the above should have a built in way for a content editor to a) see it and b) copy it
- handle adding custom class and custom style?
IMPORTANT - Intended order of precedence:
1. passed in values (title, tag, etc) << though this is NOT the usual or intended usage
2. Header.Presentation << best for List Views
3. Header
4. Content.Presentation << best for single item Views
5. Content (not sure this makes any sense, use case?)
6. default/fallback settings in this script (for when all-else-fails)
H1 SPECIAL HANDLING
Since "good SEO" usually encourages only one H1 tag per page, by default
we do a DIV tag instead with class="h1". Thanks to Bootstrap, this looks
visually identical to the viewer. But there are cases where you need to
specify a real H1, so we do this by having the HeaderItem.Type dropdown
set the default H1 to a value of "~h1" (kinda like specifying a
synthetic h1). Code below detects the tilde which triggers the switch.
HEADING TYPE - its important to know what the dropdown values are:
Heading 1:~h1
Heading 2:h2
Heading 3 (default):h3
Heading 4:h4
Heading 5:h5
Heading 6:h6
Hide:hide
Display 1:display-1
Display 2:display-2
Display 3:display-3
Display 4:display-4
Normal (p):p
Bold (p+bold):pbold
Small (p+small):psmall
Heading 1 (using a real H1 tag):h1
NOTE: a fringe-case and oddity; we do not handle the case where
- the user is public, not-logged-in
- View's Content-Type IsDemoItem
- and not IsPublished >>> this combo makes Content == null
*@
@{
// 0 is the tag, 1 is the class, 2 is the sxc Toolbar, and 3 is the Title
const string tagTemplateHx = "<{0} class=\"{1}\" {2}>{3}</{0}>";
const string tagTemplateH1 = "<div class=\"{0} {1}\" {2}>{3}</div>";
// not using this yet, future
// var intro = PageData["intro"] ?? null; // or "" ?
const string defaultTitle = "Default Heading";
const string defaultTag = "h3";
const string defaultAlign = "";
const string defaultClass = "";
string title = string.Empty;
string tag = string.Empty;
string align = string.Empty;
string attrClass = string.Empty;
@* undocumented feature? *@
bool showToolbar = PageData["toolbar"] ?? true;
HtmlString editToolbar = Edit.TagToolbar(Content, settings: new { hover = "left", classes = "mt-n4" });
@*
We work through the order of precedence (above) and
fall thru as soon as one of them is valid.
1.
2. if we have a Content..Presentation and its !IsDemoItem...
*@
if (Content != null && Content.Presentation != null) // && !Content.Presentation.IsDemoItem
{
title = Text.First(Content.Presentation.Heading, title);
tag = Text.First(Content.Presentation.Type, tag);
align = Text.First(Content.Presentation.Align, align);
editToolbar = Edit.TagToolbar(Content.Presentation, settings: new { hover = "left", classes = "mt-n4" });
} // end .Presentation not null
@* if we have a .Header and its !IsDemoItem... *@
if (Header != null) // && !Header.IsDemoItem
// hey, technically speaking the .IsDemoItem is the default?? Lightbulb?
{
title = Text.First(Header.Heading, title);
tag = Text.First(Header.Type, tag);
align = Text.First(Header.Align, align);
editToolbar = Edit.TagToolbar(Header, settings: new { hover = "left", classes = "mt-n4" });
@* should this be in play?
if (Header.Presentation != null)
{
if (Header.Presentation.Type != null)
{
tag = Header.Presentation.Type;
}
}
*@
} // end .Header not null
@* Heading, title *@
// our final fallback is to display the Module Title
title = Text.First(PageData["title"], title, Dnn.Module.ModuleTitle, defaultTitle);
@* Heading Type, tag (HTML, etc) *@
tag = Text.First(PageData["tag"], tag, defaultTag);
@* Heading Align, using Bootstrap *@
align = Text.First(PageData["align"], align, defaultAlign);
@* Build the Class(es) *@
attrClass = Text.Has(align) ? "text-" + align.Trim() : "";
attrClass = Text.First(PageData["class"], attrClass, defaultAlign);
@* handle special cases *@
if (tag.StartsWith("display")) // Bootstrap classes "display-1" etc.
{
attrClass = tag + " " + attrClass;
tag = "div";
}
if (tag == "pbold") // <p><strong>
{
title = Tag.Strong(title).ToString();
tag = "p";
}
if (tag == "psmall") // <p><small>
{
title = Tag.Small(title).ToString();
tag = "p";
}
@* start of extensive DEBUGGING output, just remove "false &&" here: *@
if(false && AccuKit.sbe() == "dev")
{
<h5>Debug output from _shared--Heading.cshtml</h5>
if(Content == null)
{
<h6>Content is null</h6>
}
else
{
<pre>
Content.IsDemoItem : @Content.IsDemoItem
Content.IsPublished : @Content.IsPublished
.EntityId and Title : @Content.EntityId, @Content.EntityTitle
isDemoInTitle() : @isDemoInTitle(Content.EntityTitle)
</pre>
}
@*
Content.Presentation == null : @(Content.Presentation == null)
Content.Presentation.IsDemoItem : @(Content.Presentation != null && Content.Presentation.IsDemoItem)
Content.Presentation.IsPublished : @(Content.Presentation != null && Content.Presentation.IsPublished)
.EntityId and Title : @Content.Presentation.EntityId, @Content.Presentation.EntityTitle)
Header == null : @(Header == null)
&& Header.IsDemoItem : @(Header != null && Header.IsDemoItem)
*@
<pre>
<strong>Our variables so far...</strong>
title = @title
tag = @tag
align = @align
isDemoInTitle(title) = @isDemoInTitle(title)
editToolbar = @Html.Raw(editToolbar)
</pre>
if(Content.Presentation == null)
{
<h6>View's Content.Presentation is null</h6>
}
else
{
<h4 @Edit.TagToolbar(Content.Presentation, settings: new { hover = "left", classes = "mt-n3" });>
View's Content.Presentation
</h4>
<pre>
- GetType(): @Content.Presentation.GetType()
- EntityTitle: @Content.Presentation.EntityTitle
- IsDemoItem: @Content.Presentation.IsDemoItem
- Heading: @Content.Presentation.Heading
- Heading Type: @Content.Presentation.Type
- Heading Align: @Content.Presentation.Align
</pre>
} @* end of Content.Presentation is/not null *@
if(Header == null)
{
<h6>Header is null</h6>
}
else
{
<h4 @Edit.TagToolbar(Header, settings: new { hover = "left", classes = "mt-n3" });>
View's Header
</h4>
<pre>
- GetType(): @Header.GetType()
- EntityTitle: @Header.EntityTitle
- IsDemoItem: @Header.IsDemoItem
- Heading: @Header.Heading
- Heading Type: @Header.Type
- Heading Align: @Header.Align
</pre>
if(Header.Presentation == null)
{
<h6>View's Header.Presentation is null</h6>
}
else
{
<h4 @Edit.TagToolbar(Header.Presentation, settings: new { hover = "left", classes = "mt-n3" });>
Header.Presentation
</h4>
<pre>
- GetType(): @Header.Presentation.GetType()
- EntityTitle: @Header.Presentation.EntityTitle
- IsDemoItem: @Header.Presentation.IsDemoItem
- Heading: @Header.Presentation.Heading
- Heading Type: @Header.Presentation.Type
- Heading Align: @Header.Presentation.Align
</pre>
} // end of Header.Presentation == null
} // end of Header != null
<hr>
<pre>
Heading
- PageData["title"]: @PageData["title"]
- Dnn.Module.ModuleTitle: @Dnn.Module.ModuleTitle
- defaultTitle: @defaultTitle
Heading Type
- PageData["tag"]: @PageData["tag"]
- defaultTag: @defaultTag
Heading Align
- PageData[""]: @PageData["align"]
- defaultAlign: @defaultAlign
And the finals are
title = @title
tag = @tag
align = @align
toolbar = <pre>@editToolbar</pre>
</pre>
}
@* end of extensive DEBUGGING output *@
}
@* start of HEADING OUTPUT *@
@if (tag != "hide")
{
string tagTemplate = tagTemplateHx;
if(tag[0] == '~') // same as .StartsWith()
{
tag = tag.Substring(1);
tagTemplate = tagTemplateH1;
}
@Html.Raw(string.Format(tagTemplate,
tag,
attrClass,
doTb(showToolbar, editToolbar),
title)
)
}
else
{
if (Edit.Enabled)
{
@Html.Raw(string.Format(tagTemplateHx,
"h3",
attrClass,
doTb(showToolbar, editToolbar),
"[ title is hidden ]"))
}
}
@* end of HEADING OUTPUT *@
@functions {
public HtmlString doTb(bool show, HtmlString tb)
{
if(show)
{
return tb;
}
else
{
return new HtmlString(string.Empty);
}
}
public bool isDemoInTitle(string title)
{
if (title.ToLower().Contains("demo"))
{
return true;
}
if (title.ToLower().Contains("placeholder"))
{
return true;
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment