Hide projection widget if query has no results - widget

We are building a website with the Orchard CMS where we have campaign adds.
These adds are linked to pages through tags (not the orchard tag part).
Then we built a custom filter that take these tags into consideration when fetching the campaign adds and display them in a widget.
On some pages there are tags but no campaigns that match these tags. We would like to hide the widget at this point.
One solution is to edit the widget layer every time a new campaign is added. But I would like to have a more solid solution than this.
Summary:
We would like to hide the entire projection widget when the query returns an empty result.
// Madelene

Most of the markup in the widget is rendered by the Widget.Wrapper.cshtml template. What you can do is filter what this wrapper will render based on the content of the widget itself. This way if the widget doesn't render anything, you can decide to hide the title and the other zones. Here is the code doing it:
#using Orchard.ContentManagement;
#using Orchard.Widgets.Models;
#{
var widgetPart = ((IContent)Model.ContentItem).As<WidgetPart>();
var tag = Tag(Model, "article");
var childContent = Display(Model.Child);
}
#if (!String.IsNullOrEmpty(Convert.ToString(childContent))) {
#tag.StartElement
if ((widgetPart.RenderTitle && HasText(widgetPart.Title)) || Model.Header != null) {
<header>
#if ((widgetPart.RenderTitle && HasText(widgetPart.Title))) {
<h1>#widgetPart.Title</h1>
}
#Display(Model.Header)
</header>
}
#childContent
if (Model.Footer != null) {
<footer>
#Display(Model.Footer)
</footer>
}
#tag.EndElement
}
Just create a file named Widget.Wrapper.cshtml in your theme and paste this content. You can check what was the previous content if you want to understand how it's done.

you could override the Projection widget, you can then edit the code for that widget within the cshtml file. This is by far the easiest way.
or
You could create a custom filter that did a check for the dependency and returned no items if that dependency was not met (this is a harder way of doing it)

Related

How can I use Render sub-template in a C# template in a Content module that uses lists within lists?

2SXC 10.25.2 / DNN 9.3.2
I have a 2sxc module that uses a C# template with "list" enabled. I have a content type called "pathway" and inside that I have 2 entity picker fields for "first step sessions" and then "next step sessions". These entity pickers use a "session" content type. Inside each of those "session" content types I also have an entity picker for "speaker(s)". All in all, it's a setup that I have lists within lists within lists.
When I create the loops for each of the sublists, I can easily do that within the 1 C# template but it becomes repetitive, long, and unruly because there's so much c# code where I'm looping the same session template for different entity picker sections. So, I tried using the "Render sub-template" code to simplify the template - I created new sub templates and inserted them in - it seemed to work at first, however, the template started outputting all "session" items into each item in the list.
I suspect that the subtemplate somehow loses the context of the item that it's in so it's outputting everything. Is there something special I need to know about using subtemplates with for each loops? Do I have to include params and, if so, how do I do that?
EDIT to include code sample:
Here is a small, simplified version of the code I'm working with:
#foreach(var Content in AsList(Data)) {
<h2>#Content.Title</h2>
<h3>Lead Sessions</h3>
<div class="lead-sessions text-green">
#foreach(var item in AsList(Content.LeadSessions as object)){
<h4>#item.LeadSessionTitle</h4>
<p>#item.LeadSessionText</p>
}
</div>
<h3>Next Sessions</h3>
<div class="next-sessions text-green">
#foreach(var nextitem in AsList(Content.NextSessions as object)){
<h4>#nextitem.LeadSessionTitle</h4>
<p>#nextitem.LeadSessionText</p>
}
</div>
}
I want to make a subtemplate so I don't have to repeat the same code for the sessions loop. How could I simplify this template to use a subtemplate for looping the sessions within the lead-sessions and next-sessions?
So based on the modified question, it's a bit like this
#foreach(var Content in AsList(Data)) {
<h2>#Content.Title</h2>
<h3>Lead Sessions</h3>
#RenderPage("_inner.cshtml", new { Items = Content.LeadSessions })
<h3>Next Sessions</h3>
#RenderPage("_inner.cshtml", new { Items = Content.NextSessions })
}
Second file _inner.cshtml
#{
var items = AsList(PageData["Items"]);
}
<div class="next-sessions text-green">
#foreach(var nextitem in items){
<h4>#nextitem.LeadSessionTitle</h4>
<p>#nextitem.LeadSessionText</p>
}
</div>
Yep, you can just use RenderPage without params, or pass in params like in the blog app:
#RenderPage("shared/_Category Filter.cshtml", new { MobileView = true, FilteredCategory = filteredCategory })
See https://github.com/2sic/app-blog/blob/master/_List.cshtml#L25
Then the template can retrieve the values like
#{
var filteredCategory = PageData["FilteredCategory"];
}
See https://github.com/2sic/app-blog/blob/master/shared/_Category%20Filter.cshtml#L6
You can pass around any amount of values/objects like this.
You can also create helpers - and then call those helpers. Like this
https://github.com/2sic/app-news/blob/master/shared/_Helpers.cshtml#L24-L33

Adding html elements to page with MVC Razor pages

On the html for my page I have a <script id="pagedata"></script> element which I would like to add an element to only if a certain partial is rendered. In my layout.cshtml I have the following:
#if (Brand != null)
{
#Html.Partial("_UseApp");
}
And in my _UseApp.cshtml:
#{
var iosAppUrl = // retrieve iosLink from our CRM database
var androidUrl = // retrieve android link from our CRM database
// Here I want to add the above variables to the <script id=pagedata> in the html page. Something
like this:
PageData.AddPageData("appstore", iosAppUrl);
PageData.AddPageData("playstore", androidUrl);
I cannot work out how to do this - I set breakpoints in the UseApp.cshtml file and the file is being called, but I don't know how to add these script elements. I don't want to just add them into the layout file because I want to keep the app logic separate. Can anyone help? Thanks
My approach to this would be to use jQuery, as reading HTML elements in C# is rather difficult.
In the script below, it checks if the HTML exists, and if it does, we will assign an attribute to it. The second argument in attr() will be your link, note that you can use C# to get the value from your Db, by using the model or ViewBag.
#section Scripts{
<script>
$(document).ready(function () { // on ready
if ($("#replaceWithYourId").length) { // check if ID exists
$("#pagedata").attr("data-playstore", "link") // use jQuery attr method.
}
});
</script>
}

generating page title with razor script - umbraco

So I am trying to create a script whereby depending on the document type of the page a certain pre-defined title tag format will appear, if there is nothing already written in an overwriting custom title input. I have inserted the macro within the title tag on my master template but keep on getting an Error loading Razor Script message .
Html
<title>
<umbraco:Macro Alias="NewPageTitle" runat="server"></umbraco:Macro>
</title>
Script -
#inherits umbraco.MacroEngines.DynamicNodeContext
#using umbraco.MacroEngines
#{
if(String.IsNullOrEmpty(#Model.tabName.ToString()) == false )
{
#Model.tabName
}
else if(#Model.DescendantsOrSelf("Country"))
{
<text>
Holidays in #Model.Name
</text>
}
else
{
#Model.Name;
}
}
Any help would be greatly appreciated.
Try this code out. The problem with your original code is that you were using "#Model.DescendantsOrSelf("Country")" as a boolean, and it is a list. I also removed your comparison for if(String.IsNullOrEmpty(#Model.tabName.ToString())).
Also, if you add ?umbDebugShowTrace=true to the end of your URL, you can get some valuable debugging information. There is a Chrome Extension called "Umbraco Debug" that I use to quickly access that query string and information. You may find it useful.
#inherits umbraco.MacroEngines.DynamicNodeContext
#using umbraco.MacroEngines
#{
if(String.IsNullOrEmpty(#Model.tabName.ToString()))
{
#Model.tabName
}
else if(#Model.DescendantsOrSelf("Country").Count() > 0)
{
<text>
Holidays in #Model.Name
</text>
}
else
{
#Model.Name;
}
}
its very simple just add following code into your title tag
#Umbraco.Field("pageName")
will display pageName,you may also add custom properties from document type.
e.g. you have added new property like "metaKeywords" with value "html,javascript,xml",fetch that values as following way...
#Umbraco.Field("metaKeywords")
even you don't need to add custom properties in your model

Navigate within webpage in WebView control

I'm trying to navigate within a webpage that has been loaded from a remote server in my WebView control (Cocoa application). I would like to navigate to a particular tag that i can see in the HTML code of that page. The purpose of this all is to show the part of the HTML page that is of my interest at the top of the WebView control.
I know that in HTML code you can navigate by using something like #MIDDLE, #TOP etc. However, is this possible to do from outside of the HTML code using the WebView API?
Thanks for your reply in advance!
I found the answer to my question with the help of an other question (How to scroll HTML page to given anchor using jQuery or Javascript?).
The piece of code below does the trick for me. It searches for HTML elements with attribute: class = "container" in the HTML data that is loaded in the WebView component self.webView.
-(void) scrollMyImportantHTMLPartInView
{
// Get a list of HTML elements that contain attribute class = "container" (eg. <div class "container">)
DOMNodeList *nodeList = [[[self.webView mainFrame] DOMDocument] getElementsByClassName: #"container"];
if( nodeList && nodeList.length >= 1 ) {
// get the first node (class = "container") from the list
DOMNode *domNode = [nodeList item:0];
// Make sure it's a DOM element type
if( domNode.nodeType == DOM_ELEMENT_NODE ) {
// It's now save to cast from DOMNode* to DOMElement*
DOMElement* domElement = (DOMElement*) domNode;
// Scroll begining of HTML node into view
[domElement scrollIntoView: YES];
}
}
}

tumblr custom content per tagged category

With tumblr, I need to add custom title and description meta tags on tagged category pages.
such as url.com/tagged/lifestyle needs different title/description than url.com/tagged/history
Does anyone know a block level conditional for this, or a way to make custom templates for each tagged category?
I can manipulate the title using a hack via jQuery, but this will only run on page load.
//Add an id to the title tag:
<title id="chTitle">Tumblr Blog</title>
// get the current page url
$href = document.location.href;
$primaryDir = document.location.pathname.split("/")[1];
$secondaryDir = document.location.pathname.split("/")[2];
if($secondaryDir == 'lifestyle') {
$('#chTitle').text('Lifestyle');
}else if($secondaryDir == 'history') {
$('#chTitle').text('History');
}else{
$('#chTitle').text('Title Default');
}
You could actually just take the secondary directory and pass it as a variable into the page title.
$('#chTitle').text($secondaryDir);
But you would need a default fallback for pages with no secondary dir. blog.tumblr.com/submit etc.