Fixing and improving Pager and List theming

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2013-02-08 12:36:58 -08:00
parent 006bef1de8
commit d50b0f8eee
2 changed files with 115 additions and 44 deletions

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
@@ -28,20 +27,24 @@ namespace Orchard.Core.Shapes {
private readonly Work<WorkContext> _workContext;
private readonly Work<IResourceManager> _resourceManager;
private readonly Work<IHttpContextAccessor> _httpContextAccessor;
private readonly Work<IShapeFactory> _shapeFactory;
public CoreShapes(
Work<WorkContext> workContext,
Work<IResourceManager> resourceManager,
Work<IHttpContextAccessor> httpContextAccessor
Work<IHttpContextAccessor> httpContextAccessor,
Work<IShapeFactory> shapeFactory
) {
_workContext = workContext;
_resourceManager = resourceManager;
_httpContextAccessor = httpContextAccessor;
_shapeFactory = shapeFactory;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public dynamic New { get { return _shapeFactory.Value; } }
public void Discover(ShapeTableBuilder builder) {
// the root page shape named 'Layout' is wrapped with 'Document'
@@ -490,49 +493,49 @@ namespace Orchard.Core.Shapes {
routeData.Remove(pageKey); // to keep from having "page=1" in the query string
}
// first
Shape.Add(Display.Pager_First(Value: firstText, RouteValues: routeData, Pager: Shape));
Shape.Add(New.Pager_First(Value: firstText, RouteValues: new RouteValueDictionary(routeData), Pager: Shape));
// previous
if (currentPage > 2) { // also to keep from having "page=1" in the query string
routeData[pageKey] = currentPage - 1;
}
Shape.Add(Display.Pager_Previous(Value: previousText, RouteValues: routeData, Pager: Shape));
Shape.Add(New.Pager_Previous(Value: previousText, RouteValues: new RouteValueDictionary(routeData), Pager: Shape));
}
// gap at the beginning of the pager
if (firstPage > 1 && numberOfPagesToShow > 0) {
Shape.Add(Display.Pager_Gap(Value: gapText, Pager: Shape));
Shape.Add(New.Pager_Gap(Value: gapText, Pager: Shape));
}
// page numbers
if (numberOfPagesToShow > 0 && firstPage != lastPage) {
if (numberOfPagesToShow > 0) {
for (var p = firstPage; p <= lastPage; p++) {
if (p == currentPage) {
Shape.Add(Display.Pager_CurrentPage(Value: p, RouteValues: routeData, Pager: Shape));
Shape.Add(New.Pager_CurrentPage(Value: p, RouteValues: new RouteValueDictionary(routeData), Pager: Shape));
}
else {
if (p == 1)
routeData.Remove(pageKey);
else
routeData[pageKey] = p;
Shape.Add(Display.Pager_Link(Value: p, RouteValues: routeData, Pager: Shape));
Shape.Add(New.Pager_Link(Value: p, RouteValues: new RouteValueDictionary(routeData), Pager: Shape));
}
}
}
// gap at the end of the pager
if (lastPage < totalPageCount && numberOfPagesToShow > 0) {
Shape.Add(Display.Pager_Gap(Value: gapText, Pager: Shape));
Shape.Add(New.Pager_Gap(Value: gapText, Pager: Shape));
}
// next and last pages
if (Page < totalPageCount) {
// next
routeData[pageKey] = Page + 1;
Shape.Add(Display.Pager_Next(Value: nextText, RouteValues: routeData, Pager: Shape));
Shape.Add(New.Pager_Next(Value: nextText, RouteValues: new RouteValueDictionary(routeData), Pager: Shape));
// last
routeData[pageKey] = totalPageCount;
Shape.Add(Display.Pager_Last(Value: lastText, RouteValues: routeData, Pager: Shape));
Shape.Add(New.Pager_Last(Value: lastText, RouteValues: new RouteValueDictionary(routeData), Pager: Shape));
}
return Display(Shape);
@@ -562,7 +565,7 @@ namespace Orchard.Core.Shapes {
[Shape]
public IHtmlString Pager_CurrentPage(HtmlHelper Html, dynamic Display, object Value) {
var tagBuilder = new TagBuilder("span");
tagBuilder.InnerHtml = Html.Encode(Value is string ? (string)Value : Display(Value));
tagBuilder.InnerHtml = EncodeOrDisplay(Value, Display, Html).ToString();
return MvcHtmlString.Create(tagBuilder.ToString());
}
@@ -583,21 +586,13 @@ namespace Orchard.Core.Shapes {
[Shape]
public IHtmlString Pager_Link(HtmlHelper Html, dynamic Shape, dynamic Display, object Value) {
var RouteValues = (object)Shape.RouteValues;
RouteValueDictionary rvd;
if (RouteValues == null) {
rvd = new RouteValueDictionary();
}
else {
rvd = RouteValues is RouteValueDictionary ? (RouteValueDictionary)RouteValues : new RouteValueDictionary(RouteValues);
}
string value = Html.Encode(Value is string ? (string)Value : Display(Value));
return @Html.ActionLink(value, (string)rvd["action"], (string)rvd["controller"], rvd, null);
Shape.Metadata.Alternates.Clear();
Shape.Metadata.Type = "ActionLink";
return Display(Shape);
}
[Shape]
public IHtmlString ActionLink(HtmlHelper Html, dynamic Shape, dynamic Display, object Value) {
public IHtmlString ActionLink(HtmlHelper Html, UrlHelper Url, dynamic Shape, dynamic Display, object Value) {
var RouteValues = (object)Shape.RouteValues;
RouteValueDictionary rvd;
if (RouteValues == null) {
@@ -606,15 +601,23 @@ namespace Orchard.Core.Shapes {
else {
rvd = RouteValues is RouteValueDictionary ? (RouteValueDictionary)RouteValues : new RouteValueDictionary(RouteValues);
}
string value = Html.Encode(Value is string ? (string)Value : Display(Value));
return @Html.ActionLink(value, (string)rvd["action"], (string)rvd["controller"], rvd, null);
var action = Url.Action((string)rvd["action"], (string)rvd["controller"], rvd);
IEnumerable<string> classes = Shape.Classes;
IDictionary<string, string> attributes = Shape.Attributes;
attributes.Add("href", action);
string id = Shape.Id;
var tag = GetTagBuilder("a", id, classes, attributes);
tag.InnerHtml = EncodeOrDisplay(Value, Display, Html).ToString();
return Html.Raw(tag.ToString());
}
[Shape]
public IHtmlString Pager_Gap(HtmlHelper Html, dynamic Display, object Value) {
var tagBuilder = new TagBuilder("span");
tagBuilder.InnerHtml = Html.Encode(Value is string ? (string)Value : Display(Value));
tagBuilder.InnerHtml = EncodeOrDisplay(Value, Display, Html).ToString();
return MvcHtmlString.Create(tagBuilder.ToString());
}
@@ -628,37 +631,88 @@ namespace Orchard.Core.Shapes {
string Id,
IEnumerable<string> Classes,
IDictionary<string, string> Attributes,
string ItemTag,
IEnumerable<string> ItemClasses,
IDictionary<string, string> ItemAttributes) {
if (Items == null)
return;
// prevent multiple enumerations
var items = Items.ToList();
var itemDisplayOutputs = Items.Select(item => Display(item)).Where(output => !string.IsNullOrWhiteSpace(output.ToHtmlString())).ToList();
var count = itemDisplayOutputs.Count();
// var itemDisplayOutputs = Items.Select(item => Display(item)).Where(output => !string.IsNullOrWhiteSpace(output.ToHtmlString())).ToList();
var count = items.Count();
if (count < 1)
return;
var listTagName = string.IsNullOrEmpty(Tag) ? "ul" : Tag;
const string itemTagName = "li";
string listTagName = null;
if (Tag != "-") {
listTagName = string.IsNullOrEmpty(Tag) ? "ul" : Tag;
}
var listTag = GetTagBuilder(listTagName, Id, Classes, Attributes);
Output.Write(listTag.ToString(TagRenderMode.StartTag));
var listTag = String.IsNullOrEmpty(listTagName) ? null : GetTagBuilder(listTagName, Id, Classes, Attributes);
string itemTagName = null;
if (ItemTag != "-") {
itemTagName = string.IsNullOrEmpty(ItemTag) ? "li" : ItemTag;
}
if (listTag != null) {
Output.Write(listTag.ToString(TagRenderMode.StartTag));
}
var itemTags = new List<TagBuilder>();
var itemOutputs = new List<string>();
// give the item shape the possibility to alter its container tag
var index = 0;
foreach (var itemDisplayOutput in itemDisplayOutputs) {
var itemTag = GetTagBuilder(itemTagName, null, ItemClasses, ItemAttributes);
if (index == 0)
itemTag.AddCssClass("first");
if (index == count - 1)
itemTag.AddCssClass("last");
Output.Write(itemTag.ToString(TagRenderMode.StartTag));
Output.Write(itemDisplayOutput);
Output.Write(itemTag.ToString(TagRenderMode.EndTag));
foreach (var item in items) {
var itemTag = String.IsNullOrEmpty(itemTagName) ? null : GetTagBuilder(itemTagName, null, ItemClasses, ItemAttributes);
if (item is IShape) {
item.Tag = itemTag;
}
var itemOutput = Display(item).ToHtmlString();
if (!String.IsNullOrWhiteSpace(itemOutput)) {
itemTags.Add(itemTag);
itemOutputs.Add(itemOutput);
}
else {
count--;
}
++index;
}
Output.Write(listTag.ToString(TagRenderMode.EndTag));
index = 0;
foreach(var itemOutput in itemOutputs) {
var itemTag = itemTags[index];
if (itemTag != null) {
if (index == 0)
itemTag.AddCssClass("first");
if (index == count - 1)
itemTag.AddCssClass("last");
Output.Write(itemTag.ToString(TagRenderMode.StartTag));
}
Output.Write(itemOutput);
if (itemTag != null) {
Output.Write(itemTag.ToString(TagRenderMode.EndTag));
}
++index;
}
if (listTag != null) {
Output.Write(listTag.ToString(TagRenderMode.EndTag));
}
}
[Shape]
@@ -718,5 +772,20 @@ namespace Orchard.Core.Shapes {
private string EncodeAlternateElement(string alternateElement) {
return alternateElement.Replace("-", "__").Replace(".", "_");
}
/// <summary>
/// Encode a value if it's a string, or render it if it's a Shape
/// </summary>
private IHtmlString EncodeOrDisplay(dynamic Value, dynamic Display, HtmlHelper Html) {
if (Value is IHtmlString) {
return Value;
}
if (Value is IShape) {
return Display(Value).ToString();
}
return Html.Raw(Html.Encode(Value.ToString()));
}
}
}

View File

@@ -1,5 +1,7 @@
@{
// number of page number links to show, 0 means no link, 1 means only the current page, or more accepted.
Model.Quantity = 0;
Model.PreviousText = T("Newer");
Model.NextText = T("Older");
Model.Classes.Add("group");