Created
August 13, 2015 02:06
-
-
Save MerrittMelker/667676e02cb257da3e88 to your computer and use it in GitHub Desktop.
Example of Sitefinity Feather Navigation Custom widget
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model Ks.Sf.Web.Model.OpaHeaderController.OpaHeaderView | |
@using Telerik.Sitefinity.Services; | |
@using Telerik.Sitefinity.Modules.Pages; | |
@using Telerik.Sitefinity.Frontend.Mvc.Helpers; | |
@using Ks.Sf.Web.Mvc.Controllers; | |
@using ServiceStack | |
@using Telerik.Sitefinity.Frontend.Navigation.Mvc.Models | |
@{ | |
var searchTextBoxId = Guid.NewGuid(); | |
var searchButtonId = Guid.NewGuid(); | |
var currentTopLevelNodeUrl = string.Empty; | |
} | |
@Html.Script(ScriptRef.JQuery, "top", false) | |
@Html.Script(Url.WidgetContent("Mvc/Scripts/Angular/angular.min.js"), "top") | |
<div ng-app="opaHeaderApp"> | |
<div ng-controller="opaHeaderCtrl"> | |
<nav class="navbar navbar-default"> | |
<div class=" container"> | |
<div class="navbar-header"> | |
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> | |
<span class="sr-only">Toggle navigation</span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
</button> | |
<a href="@Model.RootNodeUrl" class="navbar-brand"><img src="@Model.ImageUrl" class="img-responsive" /></a> | |
</div> | |
<div id="navbar" class="navbar-collapse collapse"> | |
<div class="navbar-form navbar-right"> | |
<form> | |
<div class="inner-addon left-addon search-container"> | |
<span class="glyphicon glyphicon-search"></span> | |
<input type="text" title="@Html.Resource("SearchInput")" class="form-control" placeholder="Search" value="@Html.Raw(ViewBag.SearchQuery)" id="@Html.Raw(searchTextBoxId)"> | |
<button style="display: none;" id="@Html.Raw(searchButtonId)"></button> | |
<input type="hidden" data-sf-role="resultsUrl" value="@Model.SearchResultsUrl" /> | |
<input type="hidden" data-sf-role="indexCatalogue" value="@Model.SearchIndex" /> | |
<input type="hidden" data-sf-role="wordsMode" value="AllWords" /> | |
<input type="hidden" data-sf-role="disableSuggestions" value='false' /> | |
<input type="hidden" data-sf-role="minSuggestionLength" value="3" /> | |
<input type="hidden" data-sf-role="suggestionFields" value="Title,Content" /> | |
<input type="hidden" data-sf-role="language" value="" /> | |
<input type="hidden" data-sf-role="suggestionsRoute" value="/restapi/search/suggestions" /> | |
<input type="hidden" data-sf-role="searchTextBoxId" value='@("#" + searchTextBoxId.ToString())' /> | |
<input type="hidden" data-sf-role="searchButtonId" value='@("#" + searchButtonId.ToString())' /> | |
</div> | |
</form> | |
</div> | |
<ul class="nav navbar-nav navbar-right tk-proxima-nova"> | |
@foreach (var node in Model.Nodes) | |
{ | |
if (node.IsCurrentlyOpened || node.HasChildOpen) { currentTopLevelNodeUrl = node.Url; } | |
<li> | |
<div> | |
@if (node.ChildNodes.Count > 0) | |
{ | |
<a href="@node.Url" class="@if(node.IsCurrentlyOpened || node.HasChildOpen) {<text>active</text>}"> | |
@node.Title | |
</a> | |
<span data-toggle="dropdown" class="glyphicon stage-arrow dropdown-toggle" ng-class="'@node.Url' === currentNodeUrl && subMenuExpanded ? 'glyphicon-menu-up' : 'glyphicon-menu-down'" ng-click="toggle('@node.Url')"></span> | |
} | |
else | |
{ | |
<a class="@if(node.IsCurrentlyOpened || node.HasChildOpen) {<text>active</text>}" href="@node.Url">@node.Title</a> | |
} | |
@if (node.ChildNodes.Count > 0) | |
{ | |
<ul class="dropdown-menu"> | |
@foreach (var childNode in node.ChildNodes) | |
{ | |
<li><a href="@childNode.Url" target="_self">@childNode.Title</a></li> | |
} | |
</ul> | |
} | |
</div> | |
</li> | |
} | |
</ul> | |
</div> | |
</div> | |
</nav> | |
@foreach (var node in Model.Nodes) | |
{ | |
if (node.ChildNodes.Count > 0) | |
{ | |
<div class="subNav tk-proxima-nova hidden-md hidden-sm hidden-xs" style="width: 100%;" ng-show="'@node.Url' === currentNodeUrl && subMenuExpanded"> | |
<div class="container"> | |
<ul> | |
@foreach (var childNode in node.ChildNodes) | |
{ | |
<li><a class="@if (childNode.IsCurrentlyOpened || childNode.HasChildOpen) {<text>active</text>}" href="@childNode.Url">@childNode.Title</a></li> | |
} | |
</ul> | |
</div> | |
</div> | |
} | |
} | |
</div> | |
</div> | |
<script> | |
var myApp = angular.module('opaHeaderApp', []); | |
myApp.controller('opaHeaderCtrl', ['$scope', function ($scope) { | |
$scope.subMenuExpanded = true; | |
$scope.nodes = []; | |
$scope.currentNodeUrl = '@currentTopLevelNodeUrl'; | |
$scope.toggle = function (nodeUrl) { | |
if (nodeUrl === $scope.currentNodeUrl) { | |
$scope.subMenuExpanded = !$scope.subMenuExpanded; | |
} else { | |
$scope.subMenuExpanded = true; | |
} | |
$scope.currentNodeUrl = nodeUrl; | |
} | |
}]); | |
</script> | |
@Html.Script(Url.WidgetContent("Mvc/Scripts/SearchBox/Search-box.js"), "bottom", false) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Web; | |
using System.Web.Mvc; | |
using Ks.Sf.Web.Model.OpaHeaderController; | |
using ServiceStack.Text; | |
using Telerik.Sitefinity.Frontend.Mvc.Infrastructure.Controllers.Attributes; | |
using Telerik.Sitefinity.Frontend.Navigation.Mvc.Models; | |
using Telerik.Sitefinity.Frontend.Navigation.Mvc.StringResources; | |
using Telerik.Sitefinity.Modules.Libraries; | |
using Telerik.Sitefinity.Modules.Pages.Configuration; | |
using Telerik.Sitefinity.Mvc; | |
using Telerik.Sitefinity.Web; | |
namespace Ks.Sf.Web.Mvc.Controllers | |
{ | |
[ControllerToolboxItem(Name = "OpaNavigation_MVC", Title = "OPA Header", | |
SectionName = ToolboxesConfig.NavigationControlsSectionName, CssClass = WidgetIconCssClass)] | |
[Localization(typeof (NavigationResources))] | |
public class OpaHeaderController : Controller | |
{ | |
internal const string WidgetIconCssClass = "sfNavigationIcn sfMvcIcn"; | |
private int? _levelsToInclude = 2; | |
private OpaHeaderView _model; | |
public string SelectedImage { get; set; } | |
public string SearchIndex { get; set; } | |
public string SearchResultsPageId { get; set; } | |
protected INavigationModel Model | |
{ | |
get { return _model ?? (_model = InitializeModel()); } | |
} | |
public virtual int? LevelsToInclude | |
{ | |
get { return _levelsToInclude; } | |
set { _levelsToInclude = value; } | |
} | |
public PageSelectionMode SelectionMode { get; set; } | |
public bool ShowParentPage { get; set; } | |
public string CssClass { get; set; } | |
public Guid SelectedPageId { get; set; } | |
public string SerializedSelectedPages { get; set; } | |
public string SerializedExternalPages { get; set; } | |
public bool OpenExternalPageInNewTab { get; set; } | |
protected override void HandleUnknownAction(string actionName) | |
{ | |
Index().ExecuteResult(ControllerContext); | |
} | |
private OpaHeaderView InitializeModel() | |
{ | |
var smp = SiteMapBase.GetSiteMapProvider(SiteMapBase.DefaultSiteMapProviderName); | |
var selectedPages = JsonSerializer.DeserializeFromString<SelectedPageModel[]>(SerializedSelectedPages); | |
var imageUrl = GetImageUrl(); | |
var searchResultsPageId = GetSearchResultsUrl(smp); | |
var rootNodeUrl = GetRootNodeUrl(smp); | |
return new OpaHeaderView(SelectionMode, SelectedPageId, selectedPages, LevelsToInclude, ShowParentPage, | |
CssClass, OpenExternalPageInNewTab, imageUrl, SearchIndex, searchResultsPageId, rootNodeUrl); | |
} | |
private static string GetRootNodeUrl(SiteMapProvider siteMapProvider) | |
{ | |
return siteMapProvider.RootNode == null | |
? null | |
: RouteHelper.ResolveUrl(siteMapProvider.RootNode.Url, UrlResolveOptions.Rooted); | |
} | |
private string GetSearchResultsUrl(SiteMapProvider siteMapProvider) | |
{ | |
Guid guid; | |
if (!Guid.TryParse(SearchResultsPageId, out guid)) return null; | |
var node = siteMapProvider.FindSiteMapNodeFromKey(guid.ToString("D")); | |
return node == null ? null : RouteHelper.ResolveUrl(node.Url, UrlResolveOptions.Rooted); | |
} | |
private string GetImageUrl() | |
{ | |
Guid imageGuid; | |
if (!Guid.TryParse(SelectedImage, out imageGuid)) return null; | |
var imageItem = LibrariesManager.GetManager().GetImage(imageGuid); | |
return imageItem == null ? null : imageItem.ResolveMediaUrl(); | |
} | |
public ActionResult Index() | |
{ | |
return View("Default", Model); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment