#21304: Fixed Text Element HTML filter issues.

- Implemented HTML filters for Html, Text and Paragraph elements
- Tokens are only processed on the front-end, not in the editor page itself. This also prevents an exception when the {Shape.Execute} token is used with a theme specific shape.

Work Item: 21304
This commit is contained in:
Sipke Schoorstra
2015-04-03 01:46:57 +02:00
parent af110a8399
commit eb61269d85
36 changed files with 365 additions and 143 deletions

View File

@@ -1,9 +1,17 @@
using Orchard.Layouts.Elements;
using System.Collections.Generic;
using System.Linq;
using Orchard.Layouts.Elements;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.ViewModels;
using Orchard.Services;
namespace Orchard.Layouts.Drivers {
public class HtmlElementDriver : ElementDriver<Html> {
private readonly IEnumerable<IHtmlFilter> _htmlFilters;
public HtmlElementDriver(IEnumerable<IHtmlFilter> htmlFilters) {
_htmlFilters = htmlFilters;
}
protected override EditorResult OnBuildEditor(Html element, ElementEditorContext context) {
var viewModel = new HtmlEditorViewModel {
@@ -18,5 +26,17 @@ namespace Orchard.Layouts.Drivers {
return Editor(context, editor);
}
protected override void OnDisplaying(Html element, ElementDisplayContext context) {
var text = element.Content;
var flavor = "html";
var processedText = ApplyHtmlFilters(text, flavor);
context.ElementShape.ProcessedText = processedText;
}
private string ApplyHtmlFilters(string content, string flavor) {
return _htmlFilters.Aggregate(content, (t, filter) => filter.ProcessContent(t, flavor));
}
}
}

View File

@@ -1,9 +1,17 @@
using Orchard.Layouts.Elements;
using System.Collections.Generic;
using System.Linq;
using Orchard.Layouts.Elements;
using Orchard.Layouts.Framework.Display;
using Orchard.Layouts.Framework.Drivers;
using Orchard.Layouts.ViewModels;
using Orchard.Services;
namespace Orchard.Layouts.Drivers {
public class ParagraphElementDriver : ElementDriver<Paragraph> {
private readonly IEnumerable<IHtmlFilter> _htmlFilters;
public ParagraphElementDriver(IEnumerable<IHtmlFilter> htmlFilters) {
_htmlFilters = htmlFilters;
}
protected override EditorResult OnBuildEditor(Paragraph element, ElementEditorContext context) {
var viewModel = new ParagraphEditorViewModel {
@@ -18,5 +26,17 @@ namespace Orchard.Layouts.Drivers {
return Editor(context, editor);
}
protected override void OnDisplaying(Paragraph element, ElementDisplayContext context) {
var text = element.Content;
var flavor = "html";
var processedText = ApplyHtmlFilters(text, flavor);
context.ElementShape.ProcessedText = processedText;
}
private string ApplyHtmlFilters(string content, string flavor) {
return _htmlFilters.Aggregate(content, (t, filter) => filter.ProcessContent(t, flavor));
}
}
}

View File

@@ -14,17 +14,14 @@ namespace Orchard.Layouts.Drivers {
}
protected override EditorResult OnBuildEditor(Text element, ElementEditorContext context) {
var flavor = GetFlavor();
var viewModel = new TextEditorViewModel {
Flavor = flavor,
Text = element.Content
Content = element.Content
};
var editor = context.ShapeFactory.EditorTemplate(TemplateName: "Elements.Text", Model: viewModel);
if (context.Updater != null) {
context.Updater.TryUpdateModel(viewModel, context.Prefix, null, null);
element.Content = viewModel.Text;
element.Content = viewModel.Content;
}
return Editor(context, editor);
@@ -32,18 +29,14 @@ namespace Orchard.Layouts.Drivers {
protected override void OnDisplaying(Text element, ElementDisplayContext context) {
var text = element.Content;
var flavor = GetFlavor();
var processedText = ToHtml(text, flavor);
var flavor = "textarea";
var processedText = ApplyHtmlFilters(text, flavor);
context.ElementShape.ProcessedText = processedText;
}
private string ToHtml(string content, string flavor) {
private string ApplyHtmlFilters(string content, string flavor) {
return _htmlFilters.Aggregate(content, (t, filter) => filter.ProcessContent(t, flavor));
}
private static string GetFlavor() {
return "textarea";
}
}
}

View File

@@ -1,7 +1,8 @@
using Orchard.Layouts.Helpers;
using Orchard.Layouts.Framework.Elements;
using Orchard.Layouts.Helpers;
namespace Orchard.Layouts.Framework.Elements {
public abstract class ContentElement : Element, IContentElement {
namespace Orchard.Layouts.Elements {
public abstract class ContentElement : Element {
public override string Category {
get { return "Content"; }
}

View File

@@ -1,4 +1,3 @@
using Orchard.Layouts.Framework.Elements;
using Orchard.Localization;
namespace Orchard.Layouts.Elements {

View File

@@ -1,5 +1,3 @@
using Orchard.Layouts.Framework.Elements;
namespace Orchard.Layouts.Elements {
public class Paragraph : ContentElement {
public override string ToolboxIcon {

View File

@@ -1,5 +1,3 @@
using Orchard.Layouts.Framework.Elements;
namespace Orchard.Layouts.Elements {
public class Text : ContentElement {
public override string ToolboxIcon {

View File

@@ -1,5 +0,0 @@
namespace Orchard.Layouts.Framework.Elements {
public interface IContentElement {
string Content { get; set; }
}
}

View File

@@ -29,6 +29,6 @@ Features:
Dependencies: Orchard.Layouts, Orchard.Projections
Orchard.Layouts.Tokens:
Name: Element Tokens
Description: Provides an element token provider, enabling elements to be rendered using a token.
Description: Provides an element token provider that enables elements to be rendered using a token and enables tokens to be used inside of various elements such as Html, Text and Paragraph.
Category: Layout
Dependencies: Orchard.Layouts, Orchard.Tokens

View File

@@ -99,6 +99,7 @@
<Content Include="Scripts\LayoutEditor.min.js">
<DependentUpon>LayoutEditor.js</DependentUpon>
</Content>
<Content Include="Scripts\LayoutEditor\Directives\Html.js" />
<Content Include="Scripts\LayoutEditor\Directives\Editor.js" />
<Content Include="Scripts\LayoutEditor\Directives\Canvas.js" />
<Content Include="Scripts\LayoutEditor\Directives\Child.js" />
@@ -130,6 +131,7 @@
<Content Include="Scripts\Models\Container.js" />
<Content Include="Scripts\Models\Content.js" />
<Content Include="Scripts\Models\Element.js" />
<Content Include="Scripts\Models\Html.js" />
<Content Include="Scripts\Models\Grid.js" />
<Content Include="Scripts\Models\Helpers.js" />
<Content Include="Scripts\Models\Row.js" />
@@ -419,6 +421,7 @@
<Compile Include="Drivers\CanvasElementDriver.cs" />
<Compile Include="Drivers\ShapeElementDriver.cs" />
<Compile Include="Elements\Canvas.cs" />
<Compile Include="Elements\ContentElement.cs" />
<Compile Include="Elements\Shape.cs" />
<Compile Include="Filters\TokensFilter.cs" />
<Compile Include="Framework\Drivers\ImportContentContextWrapper.cs" />
@@ -437,8 +440,6 @@
<Compile Include="Framework\Display\ElementCreatingDisplayShapeContext.cs" />
<Compile Include="Framework\Drivers\ImportElementContext.cs" />
<Compile Include="Framework\Drivers\ImportLayoutContext.cs" />
<Compile Include="Framework\Elements\ContentElement.cs" />
<Compile Include="Framework\Elements\IContentElement.cs" />
<Compile Include="Handlers\ElementDriversCoordinator.cs" />
<Compile Include="Helpers\DictionaryExtensions.cs" />
<Compile Include="Helpers\EditorResultExtensions.cs" />
@@ -612,6 +613,9 @@
<Content Include="Scripts\LayoutEditor.js.bundle" />
<Content Include="Scripts\Models.js.bundle" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\LayoutEditor.Template.Html.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -63,42 +63,6 @@
return deferred.promise();
};
//this.addElement = function (contentType) {
// var elementType = contentType.id;
// var deferred = new $.Deferred();
// var dialog = new window.Orchard.Layouts.Dialog(".dialog-template." + self.settings.editorDialogName);
// if (contentType.hasEditor) {
// var url = self.settings.endpoints.add + "&typeName=" + elementType;
// dialog.show();
// dialog.load(url);
// dialog.element.on("command", function(e, args) {
// if (args.command == "add" || args.command == "save") {
// deferred.resolve(args);
// dialog.close();
// }
// });
// } else {
// var url = self.settings.endpoints.addDirect;
// $.ajax(url, {
// data: {
// typeName: elementType,
// __RequestVerificationToken: self.settings.antiForgeryToken
// },
// type: "POST"
// }).then(function(response) {
// deferred.resolve({
// element: response
// });
// });
// }
// return deferred.promise();
//};
var serializeCanvas = function () {
var layoutData = self.editor.canvas.toObject();
return JSON.stringify(layoutData, null, "\t");

View File

@@ -430,7 +430,7 @@ angular
if (!$scope.element.inlineEditingIsActive) {
$scope.element.inlineEditingIsActive = true;
$element.find(".layout-toolbar-container").show();
var selector = "#layout-editor-" + $scope.$id + " .layout-content-h-t-m-l .layout-content-markup[data-templated=false]";
var selector = "#layout-editor-" + $scope.$id + " .layout-html .layout-content-markup[data-templated=false]";
var firstContentEditorId = $(selector).first().attr("id");
tinymce.init({
selector: selector,
@@ -631,6 +631,42 @@ angular
angular
.module("LayoutEditor")
.directive("orcLayoutContent", ["$sce", "scopeConfigurator", "environment",
function ($sce, scopeConfigurator, environment) {
return {
restrict: "E",
scope: { element: "=" },
controller: ["$scope", "$element",
function ($scope, $element) {
scopeConfigurator.configureForElement($scope, $element);
$scope.edit = function () {
$scope.$root.editElement($scope.element).then(function (args) {
$scope.$apply(function () {
if (args.cancel)
return;
$scope.element.data = args.element.data;
$scope.element.setHtml(args.element.html);
});
});
};
// Overwrite the setHtml function so that we can use the $sce service to trust the html (and not have the html binding strip certain tags).
$scope.element.setHtml = function (html) {
$scope.element.html = html;
$scope.element.htmlUnsafe = $sce.trustAsHtml(html);
};
$scope.element.setHtml($scope.element.html);
}
],
templateUrl: environment.templateUrl("Content"),
replace: true
};
}
]);
angular
.module("LayoutEditor")
.directive("orcLayoutHtml", ["$sce", "scopeConfigurator", "environment",
function ($sce, scopeConfigurator, environment) {
return {
restrict: "E",
@@ -662,7 +698,7 @@ angular
$scope.element.setHtml($scope.element.html);
}
],
templateUrl: environment.templateUrl("Content"),
templateUrl: environment.templateUrl("Html"),
replace: true,
link: function (scope, element) {
// Mouse down events must not be intercepted by drag and drop while inline editing is active,

View File

@@ -18,6 +18,7 @@
<file>LayoutEditor/Directives/Child.js</file>
<file>LayoutEditor/Directives/Column.js</file>
<file>LayoutEditor/Directives/Content.js</file>
<file>LayoutEditor/Directives/Html.js</file>
<file>LayoutEditor/Directives/Grid.js</file>
<file>LayoutEditor/Directives/Row.js</file>
<file>LayoutEditor/Directives/Popup.js</file>

File diff suppressed because one or more lines are too long

View File

@@ -19,9 +19,6 @@
});
});
};
$scope.updateContent = function (e) {
$scope.element.setHtml(e.target.innerHTML);
};
// Overwrite the setHtml function so that we can use the $sce service to trust the html (and not have the html binding strip certain tags).
$scope.element.setHtml = function (html) {
@@ -33,16 +30,7 @@
}
],
templateUrl: environment.templateUrl("Content"),
replace: true,
link: function (scope, element) {
// Mouse down events must not be intercepted by drag and drop while inline editing is active,
// otherwise clicks in inline editors will have no effect.
element.find(".layout-content-markup").mousedown(function (e) {
if (scope.element.editor.inlineEditingIsActive) {
e.stopPropagation();
}
});
}
replace: true
};
}
]);

View File

@@ -78,7 +78,7 @@
if (!$scope.element.inlineEditingIsActive) {
$scope.element.inlineEditingIsActive = true;
$element.find(".layout-toolbar-container").show();
var selector = "#layout-editor-" + $scope.$id + " .layout-content-h-t-m-l .layout-content-markup[data-templated=false]";
var selector = "#layout-editor-" + $scope.$id + " .layout-html .layout-content-markup[data-templated=false]";
var firstContentEditorId = $(selector).first().attr("id");
tinymce.init({
selector: selector,

View File

@@ -0,0 +1,48 @@
angular
.module("LayoutEditor")
.directive("orcLayoutHtml", ["$sce", "scopeConfigurator", "environment",
function ($sce, scopeConfigurator, environment) {
return {
restrict: "E",
scope: { element: "=" },
controller: ["$scope", "$element",
function ($scope, $element) {
scopeConfigurator.configureForElement($scope, $element);
$scope.edit = function () {
$scope.$root.editElement($scope.element).then(function (args) {
$scope.$apply(function () {
if (args.cancel)
return;
$scope.element.data = args.element.data;
$scope.element.setHtml(args.element.html);
});
});
};
$scope.updateContent = function (e) {
$scope.element.setHtml(e.target.innerHTML);
};
// Overwrite the setHtml function so that we can use the $sce service to trust the html (and not have the html binding strip certain tags).
$scope.element.setHtml = function (html) {
$scope.element.html = html;
$scope.element.htmlUnsafe = $sce.trustAsHtml(html);
};
$scope.element.setHtml($scope.element.html);
}
],
templateUrl: environment.templateUrl("Html"),
replace: true,
link: function (scope, element) {
// Mouse down events must not be intercepted by drag and drop while inline editing is active,
// otherwise clicks in inline editors will have no effect.
element.find(".layout-content-markup").mousedown(function (e) {
if (scope.element.editor.inlineEditingIsActive) {
e.stopPropagation();
}
});
}
};
}
]);

View File

@@ -898,14 +898,6 @@ var LayoutEditor;
return result;
};
var getEditorObject = this.getEditorObject;
this.getEditorObject = function () {
var dto = getEditorObject();
return $.extend(dto, {
Content: this.html
});
}
this.setHtml(html);
};
@@ -926,3 +918,71 @@ var LayoutEditor;
};
})(LayoutEditor || (LayoutEditor = {}));
var LayoutEditor;
(function ($, LayoutEditor) {
LayoutEditor.Html = function (data, htmlId, htmlClass, htmlStyle, isTemplated, contentType, contentTypeLabel, contentTypeClass, html, hasEditor) {
LayoutEditor.Element.call(this, "Html", data, htmlId, htmlClass, htmlStyle, isTemplated);
this.contentType = contentType;
this.contentTypeLabel = contentTypeLabel;
this.contentTypeClass = contentTypeClass;
this.html = html;
this.hasEditor = hasEditor;
this.getInnerText = function () {
return $($.parseHTML("<div>" + this.html + "</div>")).text();
};
// This function will be overwritten by the Content directive.
this.setHtml = function (html) {
this.html = html;
this.htmlUnsafe = html;
}
this.toObject = function () {
return {
"type": "Html"
};
};
this.toObject = function () {
var result = this.elementToObject();
result.contentType = this.contentType;
result.contentTypeLabel = this.contentTypeLabel;
result.contentTypeClass = this.contentTypeClass;
result.html = this.html;
result.hasEditor = hasEditor;
return result;
};
var getEditorObject = this.getEditorObject;
this.getEditorObject = function () {
var dto = getEditorObject();
return $.extend(dto, {
Content: this.html
});
}
this.setHtml(html);
};
LayoutEditor.Html.from = function (value) {
var result = new LayoutEditor.Html(
value.data,
value.htmlId,
value.htmlClass,
value.htmlStyle,
value.isTemplated,
value.contentType,
value.contentTypeLabel,
value.contentTypeClass,
value.html,
value.hasEditor);
return result;
};
LayoutEditor.registerFactory("Html", function(value) { return LayoutEditor.Html.from(value); });
})(jQuery, LayoutEditor || (LayoutEditor = {}));

View File

@@ -19,5 +19,6 @@
<file>Models/Row.js</file>
<file>Models/Column.js</file>
<file>Models/Content.js</file>
<file>Models/Html.js</file>
</files>
</bundle>

File diff suppressed because one or more lines are too long

View File

@@ -36,14 +36,6 @@
return result;
};
var getEditorObject = this.getEditorObject;
this.getEditorObject = function () {
var dto = getEditorObject();
return $.extend(dto, {
Content: this.html
});
}
this.setHtml(html);
};

View File

@@ -0,0 +1,68 @@
var LayoutEditor;
(function ($, LayoutEditor) {
LayoutEditor.Html = function (data, htmlId, htmlClass, htmlStyle, isTemplated, contentType, contentTypeLabel, contentTypeClass, html, hasEditor) {
LayoutEditor.Element.call(this, "Html", data, htmlId, htmlClass, htmlStyle, isTemplated);
this.contentType = contentType;
this.contentTypeLabel = contentTypeLabel;
this.contentTypeClass = contentTypeClass;
this.html = html;
this.hasEditor = hasEditor;
this.getInnerText = function () {
return $($.parseHTML("<div>" + this.html + "</div>")).text();
};
// This function will be overwritten by the Content directive.
this.setHtml = function (html) {
this.html = html;
this.htmlUnsafe = html;
}
this.toObject = function () {
return {
"type": "Html"
};
};
this.toObject = function () {
var result = this.elementToObject();
result.contentType = this.contentType;
result.contentTypeLabel = this.contentTypeLabel;
result.contentTypeClass = this.contentTypeClass;
result.html = this.html;
result.hasEditor = hasEditor;
return result;
};
var getEditorObject = this.getEditorObject;
this.getEditorObject = function () {
var dto = getEditorObject();
return $.extend(dto, {
Content: this.html
});
}
this.setHtml(html);
};
LayoutEditor.Html.from = function (value) {
var result = new LayoutEditor.Html(
value.data,
value.htmlId,
value.htmlClass,
value.htmlStyle,
value.isTemplated,
value.contentType,
value.contentTypeLabel,
value.contentTypeClass,
value.html,
value.hasEditor);
return result;
};
LayoutEditor.registerFactory("Html", function(value) { return LayoutEditor.Html.from(value); });
})(jQuery, LayoutEditor || (LayoutEditor = {}));

View File

@@ -1,5 +1,4 @@
using System.Web.Mvc;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq;
using Orchard.DisplayManagement;
using Orchard.Layouts.Elements;
using Orchard.Layouts.Framework.Display;
@@ -8,7 +7,11 @@ using Orchard.Layouts.Helpers;
using Orchard.Utility.Extensions;
namespace Orchard.Layouts.Services {
public abstract class LayoutModelMapBase<T> : ILayoutModelMap where T:Element {
public abstract class LayoutModelMapBase<T> : ILayoutModelMap where T : Element {
public int Priority {
get { return 10; }
}
public virtual string LayoutElementType { get { return typeof(T).Name; } }
public virtual bool CanMap(Element element) {
@@ -43,9 +46,9 @@ namespace Orchard.Layouts.Services {
}
}
public class CanvasModelMap : LayoutModelMapBase<Canvas> {}
public class GridModelMap : LayoutModelMapBase<Grid> {}
public class RowModelMap : LayoutModelMapBase<Row> {}
public class CanvasModelMap : LayoutModelMapBase<Canvas> { }
public class GridModelMap : LayoutModelMapBase<Grid> { }
public class RowModelMap : LayoutModelMapBase<Row> { }
public class ColumnModelMap : LayoutModelMapBase<Column> {
protected override void ToElement(Column element, JToken node) {
@@ -64,20 +67,22 @@ namespace Orchard.Layouts.Services {
public class ContentModelMap : ILayoutModelMap {
private readonly IShapeDisplay _shapeDisplay;
private readonly IElementDisplay _elementDisplay;
private readonly UrlHelper _urlHelper;
public ContentModelMap(IShapeDisplay shapeDisplay, IElementDisplay elementDisplay, UrlHelper urlHelper) {
public ContentModelMap(IShapeDisplay shapeDisplay, IElementDisplay elementDisplay) {
_shapeDisplay = shapeDisplay;
_elementDisplay = elementDisplay;
_urlHelper = urlHelper;
}
public string LayoutElementType { get { return "Content"; } }
public bool CanMap(Element element) {
public virtual int Priority {
get { return 0; }
}
public virtual string LayoutElementType { get { return "Content"; } }
public virtual bool CanMap(Element element) {
return !(element is Container);
}
public Element ToElement(IElementManager elementManager, DescribeElementsContext describeContext, JToken node) {
public virtual Element ToElement(IElementManager elementManager, DescribeElementsContext describeContext, JToken node) {
var elementTypeName = (string)node["contentType"];
var descriptor = elementManager.GetElementDescriptorByTypeName(describeContext, elementTypeName);
var element = elementManager.ActivateElement(descriptor);
@@ -88,13 +93,6 @@ namespace Orchard.Layouts.Services {
element.HtmlStyle = (string)node["htmlStyle"];
element.IsTemplated = (bool)(node["isTemplated"] ?? false);
// To support inline editing, we need to tell the element to update its content.
var contentElement = element as IContentElement;
if (contentElement != null) {
var html = (string)node["html"];
contentElement.Content = html;
}
return element;
}
@@ -112,4 +110,32 @@ namespace Orchard.Layouts.Services {
node["html"] = _shapeDisplay.Display(_elementDisplay.DisplayElement(element, content: describeContext.Content, displayType: "Design"));
}
}
public class HtmlModelMap : ContentModelMap {
public HtmlModelMap(IShapeDisplay shapeDisplay, IElementDisplay elementDisplay)
: base(shapeDisplay, elementDisplay) {
}
public override int Priority {
get { return 1; }
}
public override string LayoutElementType {
get { return "Html"; }
}
public override bool CanMap(Element element) {
return element is Html;
}
public override Element ToElement(IElementManager elementManager, DescribeElementsContext describeContext, JToken node) {
var html = (string)node["html"];
var element = (Html)base.ToElement(elementManager, describeContext, node);
// To support inline editing, we need to update the element's content.
element.Content = html;
return element;
}
}
}

View File

@@ -3,6 +3,7 @@ using Orchard.Layouts.Framework.Elements;
namespace Orchard.Layouts.Services {
public interface ILayoutModelMap : IDependency {
int Priority { get; }
string LayoutElementType { get; }
bool CanMap(Element element);
Element ToElement(IElementManager elementManager, DescribeElementsContext describeContext, JToken node);

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls.WebParts;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Orchard.ContentManagement;

View File

@@ -59,7 +59,7 @@ namespace Orchard.Layouts.Services {
}
public ILayoutModelMap GetMapFor(Element element) {
return _maps.Value.Single(x => x.CanMap(element));
return SelectMap(x => x.CanMap(element));
}
private Element ParseEditorNode(JToken node, Container parent, int index, DescribeElementsContext describeContext) {
@@ -77,7 +77,7 @@ namespace Orchard.Layouts.Services {
private Element LoadElement(JToken node, Container parent, int index, DescribeElementsContext describeContext) {
var type = (string)node["type"];
var map = _maps.Value.Single(x => x.LayoutElementType == type);
var map = SelectMap(x => x.LayoutElementType == type);
var element = map.ToElement(_elementManager, describeContext, node);
element.Container = parent;
@@ -85,5 +85,9 @@ namespace Orchard.Layouts.Services {
return element;
}
private ILayoutModelMap SelectMap(Func<ILayoutModelMap, bool> predicate) {
return _maps.Value.OrderByDescending(x => x.Priority).FirstOrDefault(predicate);
}
}
}

View File

@@ -8,11 +8,11 @@ using Orchard.Tokens;
namespace Orchard.Layouts.Tokens {
[OrchardFeature("Orchard.Layouts.Tokens")]
public class ElementTokens : Component, ITokenProvider {
private readonly ElementManager _elementManager;
private readonly ElementDisplay _elementDisplay;
private readonly IElementManager _elementManager;
private readonly IElementDisplay _elementDisplay;
private readonly IShapeDisplay _shapeDisplay;
public ElementTokens(ElementManager elementManager, ElementDisplay elementDisplay, IShapeDisplay shapeDisplay) {
public ElementTokens(IElementManager elementManager, IElementDisplay elementDisplay, IShapeDisplay shapeDisplay) {
_elementManager = elementManager;
_elementDisplay = elementDisplay;
_shapeDisplay = shapeDisplay;

View File

@@ -1,6 +1,5 @@
namespace Orchard.Layouts.ViewModels {
public class TextEditorViewModel {
public string Text { get; set; }
public string Flavor { get; set; }
public string Content { get; set; }
}
}

View File

@@ -4,5 +4,6 @@
}
<fieldset class="autofocus">
@Html.LabelFor(m => m.Text, T("Body"))
@Html.TextAreaFor(m => m.Text, new { @class = "text large", rows = 10, autofocus = "autofocus" })
@Html.TextAreaFor(m => m.Text, 25, 80, new { @class = "text large tokenized", autofocus = "autofocus" })
@Html.Hint(T("Note: HTML markup will be rendered unencoded."))
</fieldset>

View File

@@ -3,6 +3,7 @@
Script.Include("AutoFocus.js");
}
<fieldset class="autofocus">
@Html.LabelFor(m => m.Text, T("Body"))
@Display.Body_Editor(EditorFlavor: Model.Flavor, Text: Model.Text, AutoFocus: true)
@Html.LabelFor(m => m.Content, T("Body"))
@Html.TextAreaFor(m => m.Content, 25, 80, new { @class = "text large tokenized", autofocus = "autofocus" })
@Html.Hint(T("Note: HTML markup will be rendered encoded."))
</fieldset>

View File

@@ -40,7 +40,7 @@
typeLabel: "@Model.DisplayText.Text",
typeClass: "@Model.DisplayText.Text.HtmlClassify()",
data: LayoutEditor.decode("@Url.Encode(Model.ElementData)"),
html: "@Url.Encode(Model.ElementHtml)",
html: LayoutEditor.decode("@Url.Encode(Model.ElementHtml)"),
isTemplated: false
},
elementEditorModel: @Html.Raw(Model.ElementEditorModel.ToJson())

View File

@@ -1,11 +1,8 @@
@using Orchard.DisplayManagement.Shapes
@using Orchard.Layouts.Elements
@using Orchard.Layouts.Helpers
@{
var element = (Html)Model.Element;
var tagBuilder = TagBuilderExtensions.AddCommonElementAttributes(new OrchardTagBuilder("div"), Model);
var text = element.Content;
}
@tagBuilder.StartElement
@Html.Raw(text)
@tagBuilder.EndElement
@Html.Raw(Model.ProcessedText)
@tagBuilder.EndElement

View File

@@ -1,10 +1,8 @@
@using Orchard.DisplayManagement.Shapes
@using Orchard.Layouts.Elements
@using Orchard.Layouts.Helpers
@{
var tagBuilder = TagBuilderExtensions.AddCommonElementAttributes(new OrchardTagBuilder("p"), Model);
var element = (Paragraph) Model.Element;
}
@tagBuilder.StartElement
@Html.Raw(element.Content)
@Html.Raw(Model.ProcessedText)
@tagBuilder.EndElement

View File

@@ -1 +1 @@
@Html.Raw((string)Model.ProcessedText)
@Model.Element.Content

View File

@@ -1,5 +1,4 @@
@using Orchard.Layouts.ViewModels;
<div class="layout-element-wrapper">
<div class="layout-element-wrapper">
<ul class="layout-panel layout-panel-main">
<li class="layout-panel-item layout-panel-label">{{::element.contentTypeLabel}}</li>
<li class="layout-panel-item layout-panel-action layout-panel-action-edit" ng-show="{{element.hasEditor}}" title="Edit {{element.contentTypeLabel.toLowerCase()}} content (Enter)" ng-click="edit()"><i class="fa fa-code"></i></li>
@@ -8,5 +7,5 @@
<li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} up (Ctrl+Up)")" ng-click="element.moveUp()" ng-class="{disabled: !element.canMoveUp()}"><i class="fa fa-chevron-up"></i></li>
<li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} down (Ctrl+Down)")" ng-click="element.moveDown()" ng-class="{disabled: !element.canMoveDown()}"><i class="fa fa-chevron-down"></i></li>
</ul>
<div id="layout-content-markup-{{::$id}}" class="layout-content-markup" ng-bind-html="element.htmlUnsafe" ng-blur="updateContent($event)" data-templated="{{element.isTemplated}}"></div>
<div id="layout-content-markup-{{::$id}}" class="layout-content-markup" ng-bind-html="element.htmlUnsafe" data-templated="{{element.isTemplated}}"></div>
</div>

View File

@@ -0,0 +1,11 @@
<div class="layout-element-wrapper">
<ul class="layout-panel layout-panel-main">
<li class="layout-panel-item layout-panel-label">{{::element.contentTypeLabel}}</li>
<li class="layout-panel-item layout-panel-action layout-panel-action-edit" ng-show="{{element.hasEditor}}" title="Edit {{element.contentTypeLabel.toLowerCase()}} content (Enter)" ng-click="edit()"><i class="fa fa-code"></i></li>
@Display(New.LayoutEditor_Template_Properties(ElementTypeName: "{{element.contentTypeLabel.toLowerCase()}}"))
<li class="layout-panel-item layout-panel-action" title="@T("Delete {{element.contentTypeLabel.toLowerCase()}} (Del)")" ng-click="delete(element)"><i class="fa fa-remove"></i></li>
<li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} up (Ctrl+Up)")" ng-click="element.moveUp()" ng-class="{disabled: !element.canMoveUp()}"><i class="fa fa-chevron-up"></i></li>
<li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} down (Ctrl+Down)")" ng-click="element.moveDown()" ng-class="{disabled: !element.canMoveDown()}"><i class="fa fa-chevron-down"></i></li>
</ul>
<div id="layout-content-markup-{{::$id}}" class="layout-content-markup" ng-bind-html="element.htmlUnsafe" ng-blur="updateContent($event)" data-templated="{{element.isTemplated}}"></div>
</div>