Customising the number of chars before the blog summary does "... more"

Topics: Administration, Customizing Orchard, Writing themes
May 23, 2011 at 4:48 PM

I like the theme that I have, but in the list of blog posts, I want more of the text of each blog post to show before it is cut off with the "... more" link that goes to the individual blog post.

How would I go about changing this?

May 23, 2011 at 5:13 PM
Edited May 23, 2011 at 5:13 PM

Basically, the easiest way to go about this is to create an alternate for the blog post body summary shape.  The Shape Tracing module makes viewing shapes/creating alternates very easy, so I would look into that. However, in this case, what you have to do is create a new file in your theme's Views folder that is named "Parts.Common.Body.Summary-BlogPost.cshtml" (I think), and put your display logic in there.  You can find the default view in Orchard.Web/Core/Common/Views/Parts.Common.Body.Summary.cshtml.  I would paste the default view content into your new view, and modify it as necessary.  For example, say you wanted it to show 300 characters instead of 200, you would have something like this:

 

@*doing excerpt generation on the way out for now so we don't stick ourselves with needing to regen excerpts for existing data
  also, doing this here, inline, until we have a pluggable processing model (both in and out)
  also, ...this is ugly *@
@{ 
    Orchard.ContentManagement.ContentItem contentItem = Model.ContentPart.ContentItem;
    string bodyHtml = Model.Html.ToString();
    var body = new HtmlString(Html.Excerpt(bodyHtml, 300).ToString().Replace(Environment.NewLine, "

 

" + Environment.NewLine + "

")); }

@body @Html.ItemDisplayLink(T("more").ToString(), contentItem)

Coordinator
May 23, 2011 at 7:44 PM
Edited May 23, 2011 at 7:46 PM

Here's the file I use in my own theme (Parts.Common.Body.Summary.cshtml):

@{ 
    Orchard.ContentManagement.ContentItem contentItem = Model.ContentPart.ContentItem;
    var bodyHtml = Model.Html.ToString();
    var more = bodyHtml.IndexOf("<!--more-->");
    if (more != -1) {
        bodyHtml = bodyHtml.Substring(0, more);
    }
    else {
        var firstP = bodyHtml.IndexOf("<p>");
        var firstSlashP = bodyHtml.IndexOf("</p>");
        if (firstP >=0 && firstSlashP > firstP) {
            bodyHtml = bodyHtml.Substring(firstP, firstSlashP + 4 - firstP);
        }
    }
    var body = new HtmlString(bodyHtml); 
}
<p>@body</p>
<p>@Html.ItemDisplayLink(T("Read more...").ToString(), contentItem)</p>

It takes the first paragraph, or if there is a <!--more--> marker it will cut there, and otherwise if it can't find a paragraph or a marker it will use the full text.

May 26, 2011 at 11:09 AM

The "<!--more-->" technique looks like a great idea, thanks.

Coordinator
May 26, 2011 at 5:48 PM

Well, can't really take credit for it. I stole the idea from WordPress.

Aug 8, 2011 at 10:15 AM
Edited Aug 8, 2011 at 10:16 AM
@{ 

Orchard.ContentManagement.ContentItem contentItem = Model.ContentPart.ContentItem;

var bodyHtml = Model.Html.ToString();
    var headerend = bodyHtml.IndexOf("<!--headerend-->");
    var start = bodyHtml.IndexOf("<!--start-->");
    var end = bodyHtml.IndexOf("<!--end-->");
    if (headerend != -1 && start != headerend-1 && end != start-1) {
    bodyHtml = new HtmlString(bodyHtml.Substring(0, headerend) + "<br/>" + bodyHtml.Substring(start, end - start));       
    }

    var body = bodyHtml;

}

@body @Html.ItemDisplayLink(T("[more...]").ToString(), contentItem)

figured i'd share my version, too. Got inspired by bertrandleroy's solution ( or wordpress's) . anyway, i used to put a headline ( i.e <h1>... ) then a picture ( which was included by <p> tags ) and then some more text passages.

so taking 300 letters for the summary usually cutted the text somewhere, and using the <p> and or <!--more--> version either threw me with only the picture, or with a picture in the summary. i didn't want either. So i altered the whole thing a little and gave it three variables that it would read out.

So now my Blogpost may look something like this

 

<h1> This is my headline </h1>

<!--headerend-->

<p> <img... some image source here> </p>

<p> First intro to this post ( rather boring ) </p>

<!--start-->

<p>Some special Text here, which hopefully lures the reader of the summary to read the whole post</p> <!--end-->

<p> Some more rather boring text, and/or at least less "luring".</p>

<p>.. repeat, till post done </p> 

 

And with the above posted method the summary renders to:

<h1> This is my headline </h1>

<p>Some special Text here, which hopefully lures the reader of the summary to read the whole post</p>

I think that's a useful solution if you want to be flexible with what is shown in the summary. Only thing you need to do is put in those 3 markers and the rest is renderd by itself, regardless of howmuch text is infront, between or after them. Ofcourse you should keep the passage between <!--start--> and <!--end--> in a reasonable size :D

 



 
Jun 26, 2012 at 11:40 PM

Thought I would tack my question on to the end of this thread. I'd like to simply add a class definition (class="button") to

@Html.ItemDisplayLink(T("[more...]").ToString(), contentItem)

Is there a simple way to do this with the existing tag or can you let me know what the format would need to change to in order to add a class? Thanks a ton!

Coordinator
Jun 27, 2012 at 1:00 AM

Yes: most Html helpers have an overload that takes a dictionary or an object, where you can specify @class.

Jun 27, 2012 at 5:52 PM

Unfortunately, that particular one doesn't already have one built in...so I guess I could build one into a helper.

Jun 27, 2012 at 10:11 PM
Edited Jun 27, 2012 at 10:12 PM

So...I decided to delve into this a bit more and see if I could just render the link myself instead of trying to extend ItemDisplayLink...since I'd like to do this from a theme and I'm not sure I want to get into extending helpers in a theme.

I found something interesting that I can't seem to understand. If I change the code

 

@Html.ItemDisplayLink(T("Read more").ToString(), contentItem)

 

to

@{
    Orchard.ContentManagement.ContentItem contentItem = Model.ContentPart.ContentItem;
    var metadata = contentItem.ContentManager.GetItemMetadata(contentItem);
}

@Html.ActionLink(T("Read more").ToString(), metadata.DisplayRouteValues["action"].ToString(), metadata.DisplayRouteValues)

it works great...I get the exact same link and things are fine. However...if I add an HTML attribute to the end of that:

@Html.ActionLink(T("Read more").ToString(), metadata.DisplayRouteValues["action"].ToString(), metadata.DisplayRouteValues, new { @class = "button" })

the link COMPLETELY changes and I get the following:

http://mysite.com/Blogs/Blog/Display?Count=4&Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object%5D&Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D

I'm not quite understanding why the addition of an HTML attribute at the end of an ActionLink helper would do that.

Coordinator
Jun 27, 2012 at 11:03 PM

I don't know, maybe you're not using the overload you think you're using. In any case, this looks like a bad idea: 

metadata.DisplayRouteValues["action"].ToString(), metadata.DisplayRouteValues
Mar 23, 2013 at 12:22 PM
Try use Url.ItemDisplayUrl...

My sample using a button as a replacement for a link:
<button onclick="location.href='@Url.ItemDisplayUrl(contentItem)'">@T("more")</button>