mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-24 01:49:12 +08:00
Updates the placement editor screen to support moving shapes into tabs (#7795)
Fixes #7791
This commit is contained in:

committed by
Sébastien Ros

parent
7373c11a1e
commit
af922a01be
@@ -28,8 +28,8 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
private readonly ShellSettings _settings;
|
||||
|
||||
public AdminController(
|
||||
IOrchardServices orchardServices,
|
||||
IContentDefinitionService contentDefinitionService,
|
||||
IOrchardServices orchardServices,
|
||||
IContentDefinitionService contentDefinitionService,
|
||||
IContentDefinitionManager contentDefinitionManager,
|
||||
IPlacementService placementService,
|
||||
Lazy<IEnumerable<IShellSettingsManagerEventHandler>> settingsManagerEventHandlers,
|
||||
@@ -101,7 +101,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
}
|
||||
|
||||
var contentTypeDefinition = _contentDefinitionService.AddType(viewModel.Name, viewModel.DisplayName);
|
||||
|
||||
|
||||
// adds CommonPart by default
|
||||
_contentDefinitionService.AddPartToType("CommonPart", viewModel.Name);
|
||||
|
||||
@@ -148,9 +148,21 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
if (contentTypeDefinition == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var grouped = _placementService.GetEditorPlacement(id)
|
||||
.OrderBy(x => x.PlacementInfo.GetPosition(), new FlatPositionComparer())
|
||||
.ThenBy(x => x.PlacementSettings.ShapeType)
|
||||
.Where(e => e.PlacementSettings.Zone == "Content")
|
||||
.GroupBy(x => x.PlacementInfo.GetTab())
|
||||
.ToDictionary(x => x.Key, y => y.ToList());
|
||||
|
||||
var content = grouped.ContainsKey("") ? grouped[""] : new List<DriverResultPlacement>();
|
||||
var listPlacements = grouped.Values.SelectMany(e => e).ToList();
|
||||
|
||||
grouped.Remove("");
|
||||
var placementModel = new EditPlacementViewModel {
|
||||
PlacementSettings = contentTypeDefinition.GetPlacement(PlacementType.Editor),
|
||||
AllPlacements = _placementService.GetEditorPlacement(id).OrderBy(x => x.PlacementSettings.Position, new FlatPositionComparer()).ThenBy(x => x.PlacementSettings.ShapeType).ToList(),
|
||||
Content = content,
|
||||
AllPlacements = listPlacements,
|
||||
Tabs = grouped,
|
||||
ContentTypeDefinition = contentTypeDefinition,
|
||||
};
|
||||
|
||||
@@ -168,20 +180,10 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
if (contentTypeDefinition == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var allPlacements = _placementService.GetEditorPlacement(id).ToList();
|
||||
var result = new List<PlacementSettings>(contentTypeDefinition.GetPlacement(PlacementType.Editor));
|
||||
|
||||
contentTypeDefinition.ResetPlacement(PlacementType.Editor);
|
||||
|
||||
foreach(var driverPlacement in viewModel.AllPlacements) {
|
||||
// if the placement has changed, persist it
|
||||
if (!allPlacements.Any(x => x.PlacementSettings.Equals(driverPlacement.PlacementSettings))) {
|
||||
result = result.Where(x => !x.IsSameAs(driverPlacement.PlacementSettings)).ToList();
|
||||
result.Add(driverPlacement.PlacementSettings);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var placementSetting in result) {
|
||||
foreach (var placement in viewModel.AllPlacements) {
|
||||
var placementSetting = placement.PlacementSettings;
|
||||
contentTypeDefinition.Placement(PlacementType.Editor,
|
||||
placementSetting.ShapeType,
|
||||
placementSetting.Differentiator,
|
||||
@@ -195,7 +197,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
|
||||
_settingsManagerEventHandlers.Value.Invoke(x => x.Saved(_settings), Logger);
|
||||
|
||||
return RedirectToAction("EditPlacement", new {id});
|
||||
return RedirectToAction("EditPlacement", new { id });
|
||||
}
|
||||
|
||||
[HttpPost, ActionName("EditPlacement")]
|
||||
@@ -234,11 +236,11 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
TryUpdateModel(edited);
|
||||
typeViewModel.DisplayName = edited.DisplayName ?? string.Empty;
|
||||
|
||||
if ( String.IsNullOrWhiteSpace(typeViewModel.DisplayName) ) {
|
||||
if (String.IsNullOrWhiteSpace(typeViewModel.DisplayName)) {
|
||||
ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString());
|
||||
}
|
||||
|
||||
if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), typeViewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase) && !String.Equals(t.Name, id)) ) {
|
||||
if (_contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), typeViewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase) && !String.Equals(t.Name, id))) {
|
||||
ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString());
|
||||
}
|
||||
|
||||
@@ -271,7 +273,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
_contentDefinitionService.RemoveType(id, true);
|
||||
|
||||
Services.Notifier.Success(T("\"{0}\" has been removed.", typeViewModel.DisplayName));
|
||||
|
||||
|
||||
return RedirectToAction("List");
|
||||
}
|
||||
|
||||
@@ -322,7 +324,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
return AddPartsTo(id);
|
||||
}
|
||||
|
||||
return RedirectToAction("Edit", new {id});
|
||||
return RedirectToAction("Edit", new { id });
|
||||
}
|
||||
|
||||
public ActionResult RemovePartFrom(string id) {
|
||||
@@ -364,7 +366,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
|
||||
Services.Notifier.Success(T("The \"{0}\" part has been removed.", viewModel.Name));
|
||||
|
||||
return RedirectToAction("Edit", new {id});
|
||||
return RedirectToAction("Edit", new { id });
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -447,8 +449,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
|
||||
[HttpPost, ActionName("EditPart")]
|
||||
[FormValueRequired("submit.Delete")]
|
||||
public ActionResult DeletePart(string id)
|
||||
{
|
||||
public ActionResult DeletePart(string id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.EditContentTypes, T("Not allowed to delete a content part.")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -497,8 +498,8 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
if (partViewModel == null) {
|
||||
// id passed in might be that of a type w/ no implicit field
|
||||
if (typeViewModel != null) {
|
||||
partViewModel = new EditPartViewModel {Name = typeViewModel.Name};
|
||||
_contentDefinitionService.AddPart(new CreatePartViewModel {Name = partViewModel.Name});
|
||||
partViewModel = new EditPartViewModel { Name = typeViewModel.Name };
|
||||
_contentDefinitionService.AddPart(new CreatePartViewModel { Name = partViewModel.Name });
|
||||
_contentDefinitionService.AddPartToType(partViewModel.Name, typeViewModel.Name);
|
||||
}
|
||||
else {
|
||||
@@ -555,7 +556,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
Services.Notifier.Success(T("The \"{0}\" field has been added.", viewModel.DisplayName));
|
||||
|
||||
if (typeViewModel != null) {
|
||||
return RedirectToAction("Edit", new {id});
|
||||
return RedirectToAction("Edit", new { id });
|
||||
}
|
||||
|
||||
return RedirectToAction("EditPart", new { id });
|
||||
@@ -573,7 +574,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
|
||||
var fieldViewModel = partViewModel.Fields.FirstOrDefault(x => x.Name == name);
|
||||
|
||||
if(fieldViewModel == null) {
|
||||
if (fieldViewModel == null) {
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
@@ -602,14 +603,14 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
|
||||
// prevent null reference exception in validation
|
||||
viewModel.DisplayName = viewModel.DisplayName ?? String.Empty;
|
||||
|
||||
|
||||
// remove extra spaces
|
||||
viewModel.DisplayName = viewModel.DisplayName.Trim();
|
||||
|
||||
if (String.IsNullOrWhiteSpace(viewModel.DisplayName)) {
|
||||
ModelState.AddModelError("DisplayName", T("The Display Name name can't be empty.").ToString());
|
||||
}
|
||||
|
||||
|
||||
if (_contentDefinitionService.GetPart(partViewModel.Name).Fields.Any(t => t.Name != viewModel.Name && String.Equals(t.DisplayName.Trim(), viewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase))) {
|
||||
ModelState.AddModelError("DisplayName", T("A field with the same Display Name already exists.").ToString());
|
||||
}
|
||||
@@ -620,7 +621,7 @@ namespace Orchard.ContentTypes.Controllers {
|
||||
|
||||
var field = _contentDefinitionManager.GetPartDefinition(id).Fields.FirstOrDefault(x => x.Name == viewModel.Name);
|
||||
|
||||
if(field == null) {
|
||||
if (field == null) {
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
|
@@ -147,6 +147,7 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Module.txt" />
|
||||
<Content Include="Scripts\admin-contenttypes.js" />
|
||||
<Content Include="Scripts\admin-placementeditor.js" />
|
||||
<Content Include="Styles\Images\menu.contenttypes.png" />
|
||||
<Content Include="Styles\Images\move.gif" />
|
||||
<Content Include="Styles\menu.contenttypes-admin.css" />
|
||||
|
@@ -4,6 +4,10 @@ namespace Orchard.ContentTypes {
|
||||
public class ResourceManifest : IResourceManifestProvider {
|
||||
public void BuildManifests(ResourceManifestBuilder builder) {
|
||||
builder.Add().DefineStyle("ContentTypesAdmin").SetUrl("orchard-contenttypes-admin.css");
|
||||
|
||||
builder.Add().DefineScript("PlacementEditor")
|
||||
.SetUrl("admin-placementeditor.js")
|
||||
.SetDependencies("jQueryUI_Sortable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,130 @@
|
||||
(function ($) {
|
||||
var assignPositions = function () {
|
||||
var position = 0;
|
||||
$('.type').each(function () {
|
||||
var input = $(this);
|
||||
var tab = input.closest(".zone-container").data("tab");
|
||||
//input = input.next();
|
||||
var postab = tab != "" ? position + "#" + tab : position + "";
|
||||
reAssignIdName(input, position); // type
|
||||
|
||||
input = input.next();
|
||||
reAssignIdName(input, position); // differentiator
|
||||
|
||||
input = input.next();
|
||||
reAssignIdName(input, position); // zone
|
||||
|
||||
input = input.next();
|
||||
reAssignIdName(input, position); // position
|
||||
|
||||
input.val(postab);
|
||||
position++;
|
||||
});
|
||||
};
|
||||
|
||||
var reAssignIdName = function (input, pos) {
|
||||
var name = input.attr('name');
|
||||
input.attr('name', name.replace(new RegExp("\\[.*\\]", 'gi'), '[' + pos + ']'));
|
||||
|
||||
var id = input.attr('id');
|
||||
input.attr('id', id.replace(new RegExp('_.*__', 'i'), '_' + pos + '__'));
|
||||
};
|
||||
|
||||
var startPos;
|
||||
|
||||
function initTab() {
|
||||
$(".tabdrag").sortable({
|
||||
placeholder: "placement-placeholder",
|
||||
connectWith: ".tabdrag",
|
||||
stop: function (event, ui) {
|
||||
assignPositions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#sortableTabs').sortable({
|
||||
placeholder: "tab-placeholder",
|
||||
start: function (event, ui) {
|
||||
var self = $(ui.item);
|
||||
startPos = self.prevAll().size();
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
assignPositions();
|
||||
$('#save-message').show();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
$("#newTab").click(function (e) {
|
||||
e.preventDefault();
|
||||
// get the new tab name, cancel if blank
|
||||
var tab = $("#tabName").val().replace(/\s/g, "");
|
||||
if (!tab.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tab.toLowerCase() === "content") {
|
||||
$("#tabName").val("");
|
||||
return;
|
||||
}
|
||||
|
||||
// in tabs already
|
||||
var tabs = getTabs(true);
|
||||
if ($.inArray(tab, tabs) >= 0) {
|
||||
$("#tabName").val("");
|
||||
return;
|
||||
}
|
||||
|
||||
$("#sortableTabs").append('<div data-tab="' + tab + '" class="zone-container tab-container"><h2><a class="delete">Delete</a>'
|
||||
+ tab + '</h2><ul class="tabdrag"></ul></div>'
|
||||
);
|
||||
// make it sortable
|
||||
initTab();
|
||||
$("#sortableTabs").sortable("refresh");
|
||||
// clear the textbox
|
||||
$("#tabName").val("");
|
||||
});
|
||||
|
||||
// remove tabs
|
||||
// append items to content, create content if not there
|
||||
$("#placement").on("click", ".delete", function (e) {
|
||||
var me = $(this);
|
||||
var parent = me.parent(".zone-container");
|
||||
var list = parent.children(".tabdrag").html();
|
||||
// get first tab
|
||||
var newList = $("#placement .tabdrag").first();
|
||||
if (newList.length) {
|
||||
parent.remove();
|
||||
newList.append(list);
|
||||
}
|
||||
|
||||
assignPositions();
|
||||
});
|
||||
|
||||
// toggle editor shapes
|
||||
$("#placement").on("click", ".toggle", function (e) {
|
||||
var $this = $(this);
|
||||
var shape = $(this).next().next();
|
||||
shape.toggle();
|
||||
if ($this.text() == 'Show Editor Shape') {
|
||||
$this.text('Hide Editor Shape');
|
||||
} else {
|
||||
$this.text('Show Editor Shape');
|
||||
}
|
||||
})
|
||||
|
||||
// returns all the tabs
|
||||
function getTabs(header) {
|
||||
var tabs = [];
|
||||
$(".zone-container").each(function (index, e) {
|
||||
tabs.push($(e).data("tab"));
|
||||
});
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
initTab();
|
||||
assignPositions();
|
||||
$('.shape-editor *').attr('disabled', 'disabled');
|
||||
$("#placement").disableSelection();
|
||||
})(jQuery);
|
@@ -18,6 +18,7 @@ using Orchard.UI.Zones;
|
||||
namespace Orchard.ContentTypes.Services {
|
||||
|
||||
public class DriverResultPlacement {
|
||||
public PlacementInfo PlacementInfo { get; set; }
|
||||
public PlacementSettings PlacementSettings { get; set; }
|
||||
public DriverResult ShapeResult { get; set; }
|
||||
public dynamic Shape { get; set; }
|
||||
@@ -201,6 +202,7 @@ namespace Orchard.ContentTypes.Services {
|
||||
|
||||
|
||||
yield return new DriverResultPlacement {
|
||||
PlacementInfo = placement,
|
||||
Shape = itemShape.Content,
|
||||
ShapeResult = contentShapeResult,
|
||||
PlacementSettings = new PlacementSettings {
|
||||
|
@@ -21,38 +21,38 @@
|
||||
|
||||
.manage-part, .manage-field {
|
||||
margin-bottom: 0;
|
||||
padding:0;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #EAEAEA;
|
||||
}
|
||||
|
||||
.manage-part h3,
|
||||
.manage-field h3 {
|
||||
display: relative;
|
||||
line-height: 1.4em;
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
.manage-part h3,
|
||||
.manage-field h3 {
|
||||
display: relative;
|
||||
line-height: 1.4em;
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.manage-part h3,
|
||||
.manage-field h3,
|
||||
.manage-part h4,
|
||||
.manage-type .manage-field .details,
|
||||
.manage-type .manage-part .manage-field,
|
||||
.manage-type .manage-part .settings {
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
.manage-part h3,
|
||||
.manage-field h3,
|
||||
.manage-part h4,
|
||||
.manage-type .manage-field .details,
|
||||
.manage-type .manage-part .manage-field,
|
||||
.manage-type .manage-part .settings {
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.manage-part h3, .manage-field h3 {
|
||||
margin: 1em 0 !important;
|
||||
padding-left: 30px;
|
||||
width: 90%;
|
||||
}
|
||||
.manage-part h3, .manage-field h3 {
|
||||
margin: 1em 0 !important;
|
||||
padding-left: 30px;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.manage-part .expando-glyph, .manage-field .expando-glyph {
|
||||
width:16px;
|
||||
height:16px;
|
||||
}
|
||||
.manage-part .expando-glyph, .manage-field .expando-glyph {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.manage-type .manage-field .settings {
|
||||
padding-bottom: 10px;
|
||||
@@ -176,38 +176,81 @@ fieldset.action {
|
||||
|
||||
|
||||
/* PLACEMENT EDITOR */
|
||||
|
||||
#placement li {
|
||||
margin-bottom: 10px;
|
||||
padding: 0px;
|
||||
border: 1px solid #eee;
|
||||
.tabdrag {
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
#placement li .shape-type {
|
||||
cursor: move;
|
||||
background-color: #eee;
|
||||
background: #EEE url(images/move.gif) no-repeat 10px 15px;
|
||||
height: 30px;
|
||||
padding: 10px 0px 0px 30px;
|
||||
.zone-container {
|
||||
border: 1px dotted #6F6F6F;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.zone-container li {
|
||||
margin-bottom: 10px;
|
||||
padding: 0px;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
#placement li .shape-editor {
|
||||
padding: 10px;
|
||||
background: white;
|
||||
}
|
||||
#placement .zone-container h2 {
|
||||
cursor: move;
|
||||
margin-top: 0px;
|
||||
padding-left: 20px;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
#placement .tab-container {
|
||||
background: white url(images/move.gif) no-repeat 10px 15px;
|
||||
}
|
||||
|
||||
.zone-container li .shape-type {
|
||||
cursor: move;
|
||||
background-color: #eee;
|
||||
background: #EEE url(images/move.gif) no-repeat 10px 10px;
|
||||
height: 30px;
|
||||
padding: 5px 0px 0px 30px;
|
||||
}
|
||||
|
||||
#placement #content-tab {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.zone-container li .toggle {
|
||||
float: right;
|
||||
padding-top: 5px;
|
||||
padding-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.zone-container li .shape-editor {
|
||||
padding: 10px;
|
||||
background: white;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#save-message {
|
||||
display: none;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#placement fieldset {
|
||||
.zone-container fieldset {
|
||||
float: inherit; /* prevent bad layout if float is defined to left in specific parts, e.g. datetimepicker */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.tab-placeholder {
|
||||
background: #FDF5BC;
|
||||
border: 1px solid #FDF5BC;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.placement-placeholder {
|
||||
background: #FDF5BC;
|
||||
border: 1px solid #FDF5BC;
|
||||
height: 100px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.zone-container .delete {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@@ -6,7 +6,8 @@ using Orchard.ContentTypes.Settings;
|
||||
namespace Orchard.ContentTypes.ViewModels {
|
||||
public class EditPlacementViewModel {
|
||||
public ContentTypeDefinition ContentTypeDefinition { get; set; }
|
||||
public PlacementSettings[] PlacementSettings { get; set; }
|
||||
public List<DriverResultPlacement> AllPlacements { get; set; }
|
||||
public Dictionary<string, List<DriverResultPlacement>> Tabs { get; set; }
|
||||
public List<DriverResultPlacement> Content { get; set; }
|
||||
}
|
||||
}
|
@@ -1,107 +1,71 @@
|
||||
@using Orchard.ContentTypes.Services
|
||||
@model Orchard.ContentTypes.ViewModels.EditPlacementViewModel
|
||||
@{
|
||||
Style.Require("ContentTypesAdmin");
|
||||
Script.Require("jQueryUI_Sortable");
|
||||
Script.Require("PlacementEditor").AtFoot();
|
||||
Layout.Title = T("Edit Placement - {0}", Model.ContentTypeDefinition.DisplayName).ToString();
|
||||
|
||||
var hiddenShapes = Model.AllPlacements.Where(x => String.IsNullOrEmpty(x.PlacementSettings.Zone) && (String.IsNullOrWhiteSpace(x.PlacementSettings.Position) || x.PlacementSettings.Position == "-"));
|
||||
int i = 0;
|
||||
}
|
||||
|
||||
@helper RenderPlacement(DriverResultPlacement p, int i) {
|
||||
var placement = p.PlacementSettings;
|
||||
<li class="place" data-shape-type="@placement.ShapeType" data-shape-differentiator="@placement.Differentiator" data-shape-zone="Content" data-shape-position="@placement.Position">
|
||||
<span class="toggle">Show Editor Shape</span>
|
||||
<div class="shape-type"><h3>@placement.ShapeType @placement.Differentiator</h3></div>
|
||||
<div class="shape-editor">
|
||||
@try {
|
||||
@Display(p.Shape)
|
||||
}
|
||||
catch {
|
||||
}
|
||||
</div>
|
||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.ShapeType, new { @class = "type" })
|
||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Differentiator, new { @class = "differentiator" })
|
||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Zone, new { @class = "zone" })
|
||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Position, new { @class = "position" })
|
||||
</li>
|
||||
}
|
||||
|
||||
<div id="save-message" class="message message-Warning">@T("You need to hit \"Save\" in order to save your changes.")</div>
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
<div id="placement">
|
||||
<div data-tab="" class="zone-container" id="content-tab">
|
||||
<h2>Content</h2>
|
||||
<ul class="tabdrag">
|
||||
@foreach (var p in Model.Content) {
|
||||
@RenderPlacement(p, i);
|
||||
i++;
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<ul id="placement">
|
||||
@for (int i = 0; i < Model.AllPlacements.Count; i++ ) {
|
||||
|
||||
var placement = Model.AllPlacements[i].PlacementSettings;
|
||||
|
||||
if(placement.Zone != "Content") {
|
||||
continue;
|
||||
<div id="sortableTabs">
|
||||
@foreach (var tab in Model.Tabs) {
|
||||
<div data-tab="@tab.Key" class="zone-container tab-container">
|
||||
<a class="delete">Delete</a>
|
||||
<h2>@tab.Key</h2>
|
||||
<ul class="tabdrag">
|
||||
@foreach (var p in tab.Value) {
|
||||
@RenderPlacement(p, i);
|
||||
i++;
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
<li data-shape-type="@placement.ShapeType" data-shape-differentiator="@placement.Differentiator" data-shape-zone="Content" data-shape-position="@placement.Position">
|
||||
<div class="shape-type"><h3>@placement.ShapeType @placement.Differentiator</h3></div>
|
||||
<div class="shape-editor">
|
||||
@try {
|
||||
@Display(Model.AllPlacements[i].Shape)
|
||||
}
|
||||
catch {
|
||||
}
|
||||
</div>
|
||||
|
||||
@* @shape.Position @(Model.PlacementSettings.Any(x => x.Equals(shape)))*@
|
||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.ShapeType, new { @class = "type" })
|
||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Differentiator, new { @class = "differentiator" })
|
||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Zone, new { @class = "zone" })
|
||||
@Html.HiddenFor(m => m.AllPlacements[i].PlacementSettings.Position, new { @class = "position" })
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input type="text" id="tabName" />
|
||||
<button class="primaryAction" id="newTab">@T("New Tab")</button>
|
||||
</div>
|
||||
|
||||
<fieldset class="action">
|
||||
<button class="primaryAction" type="submit" name="submit.Save" value="Save">@T("Save")</button>
|
||||
<button class="primaryAction" type="submit" name="submit.Restore" value="Restore" itemprop="RemoveUrl" data-message="@T("Are you sure you want to restore these placements?")">@T("Restore")</button>
|
||||
</fieldset>
|
||||
|
||||
}
|
||||
|
||||
@using (Script.Foot()) {
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
(function ($) {
|
||||
|
||||
var assignPositions = function () {
|
||||
var position = 0;
|
||||
$('.type').each(function () {
|
||||
var input = $(this);
|
||||
reAssignIdName(input, position); // type
|
||||
|
||||
input = input.next();
|
||||
reAssignIdName(input, position); // differentiator
|
||||
|
||||
input = input.next();
|
||||
reAssignIdName(input, position); // zone
|
||||
|
||||
input = input.next();
|
||||
reAssignIdName(input, position); // position
|
||||
|
||||
input.val(++position);
|
||||
});
|
||||
};
|
||||
|
||||
var reAssignIdName = function (input, pos) {
|
||||
var name = input.attr('name');
|
||||
input.attr('name', name.replace(new RegExp("\\[.*\\]", 'gi'), '[' + pos + ']'));
|
||||
|
||||
var id = input.attr('id');
|
||||
input.attr('id', id.replace(new RegExp('_.*__', 'i'), '_' + pos + '__'));
|
||||
};
|
||||
|
||||
assignPositions();
|
||||
|
||||
var startPos;
|
||||
|
||||
$('#placement').sortable({
|
||||
placeholder: "placement-placeholder",
|
||||
start: function (event, ui) {
|
||||
var self = $(ui.item);
|
||||
startPos = self.prevAll().size();
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
assignPositions();
|
||||
$('#save-message').show();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
$('.shape-editor *').attr('disabled', 'disabled');
|
||||
|
||||
$("#placement").disableSelection();
|
||||
|
||||
})(jQuery);
|
||||
//]]>
|
||||
</script>
|
||||
}
|
Reference in New Issue
Block a user