Sitecore MVC Custom Link - asp.net-mvc-4

I am trying to create a custom link from sitecore into my view
#Html.Sitecore().Field("CTA display", Model.Item, new { text = "<span>" + + "</span>"})
I am not 100% sure what the correct way to do this is, but I want to wrap the text from the link into a for styling. I've tried to put the Model.Rendering.Item.Fields["CTA display"] into there with .Text and it doesn't work.
Any help would be appreciated.

First, I'd start by creating a SitecoreHelper extension method that allows you to modify the inner html of the element you're rendering:
public static HtmlString Field(this SitecoreHelper helper, string fieldName, Item item, object parameters, string innerHtml)
{
if (helper == null)
{
throw new ArgumentNullException("helper");
}
if (innerHtml.IsNullOrEmpty())
{
return helper.Field(fieldName, item, parameters);
}
return new HtmlString(helper.BeginField(fieldName, item, parameters).ToString() + innerHtml + helper.EndField().ToString());
}
This will allow you to pass an optional innerHtml string that will be inserted between opening and closing tags of your element (in this case, an <a> tag).
From here, pass your html string containing your CTA label to the above method, or modify the method to output the field's Text value wrapped in a <span>.

I used the solution posted above by computerjules which worked a treat. You can then called the extended method like follows
#Html.Sitecore().Field("Link", Html.Sitecore().CurrentItem, new {Class = "some-class"}, "<span class='some-other-class'></span>")
and the span is rendered within the anchor tabs

Related

Remove "MIME type" column from Filent Content List

I am Using a Script Adapter by passing payload to get contend for a Content List from "Search with values" event
When Contend get loaded to content list , i have a custom view to preview them. But if i clicked on MIME type column , It opens a separate view with the mapped viewer
So I need to remove this column or make it un-clickable
1) I am passing search values to content list's "Search with values" event , from where can i handle Content List's contend loading ,any Dojo Event i can use ?
2) With Script Adapter can i do this without going for a "response filter"
Edit :
As Nicely explained by "Ivo Jonker" (in his answer - "or try to specifically locate the widgets on your page" and with his example code)
responsed = page.ContentList8.ecmContentList.getResultSet();
var cols = responsed.structure.cells[0];
for (i=cols.length-1; i>0; i--){
var col = cols[i];
if (col.field=="mimeTypeIcon")
cols.splice(i,1);
}
page.ContentList78.ecmContentList.setResultSet(responsed);
I simply remove this row. Thanks Again and lovely blog , hope you keep posting more great articles.
The values passed through the Search With Values event will eventually be handled by the icm.pgwidget.contentlist.dijit.DocumentSearchHandler
that in turn creates a SearchTemplate to execute the search (ecm.model.SearchTemplate.prototype.search). One option would be to aspect/before/around the DocumentSearchHandler#query to manipulat the searchresults and by that way to remove the column.
The wiring however does not provide any handles to achieve this for a specific query-resultset combination leaving you to either fix this on a global scale (icm.pgwidget.contentlist.dijit.DocumentSearchHandler.prototype#query), or try to specifically locate the widgets on your page.
Personally, taking into account #2, i'd go for the responsefilter-option if you feel the global solution wouldn't be a problem, or alternatively i'd personally prefer to create a simple ICM widget that instantiates/implements a "plain" ecm.widget.listView.ContentList and exposes a wire to set the ecm.model.Resultset.
You'd then be able to create your own Searchquery in a scriptadapter, remove the column, and pass the resultset.
The script adapter could be something like:
var scriptadapter=this;
var queryParams={};
queryParams.query = "SELECT * FROM Document where id in /*your list*/";
queryParams.retrieveAllVersions = false;
queryParams.retrieveLatestVersion = true;
queryParams.repository = ecm.model.desktop.repositories[0];
queryParams.resultsDisplay = {
"sortBy": "{NAME}",
"sortAsc": true,
"columns": ["{NAME}"],
"honorNameProperty": true};
var searchQuery = new ecm.model.SearchQuery(queryParams);
searchQuery.search(function(response/*ecm.model.Resultset*/){
//remove the mimeTypeIcon
var cols = response.structure.cells[0];
for (i=cols.length-1; i>0; i--){
var col = cols[i];
if (col.field=="mimeTypeIcon")
cols.splice(i,1);
}
//emit the resultset to your new contentlist, be sure to block the regular synchrounous output of the scriptadapter
scriptadapter.onPublishEvent("icm.SendEventPayload",response);
//The contentlist wire would simply do contentlist.setResultSet(response);
});

Html.LabelFor not rendering HTML

I am binding a model to view.
public class Validation
{
[Display("Please enter in <h5>day(s)</h5>")]
public string Message { get; set; }
}
Here Message property will be set as Please enter in <h5>day(s)</h5>.
In view am binding model property to LabelFor.
#Html.LabelFor(m => m.Message)
Expecting output as
Please enter in day(s)
But actual output is
Please enter in <h5>day(s)</h5>
I want part of the string to vary in size and cosmetics, so applying CSS to the entire label is not what I'm looking for.
Your display string "<h5>some text</h5>" will be rendered as text, not HTML. MVC will encode the < > characters to < >, causing them to be displayed as-is.
You shouldn't want to do this like this anyway.
The proper way would be to apply the display string to contain the text you want:
[Display("some text")]
Then create a CSS class:
label.fancyLabel {
/* your style here that makes a label look like a h5 */
}
Then apply that class to the label (from .NET MVC - How to assign a class to Html.LabelFor?):
#Html.LabelFor(m => m.Message, new { #class= "fancyLabel" })
As for your edit, if you want to just render the Display attribute's text as literal HTML, you'll have to:
Introduce your own HTML helper.
In there, write a label (and make sure to set the for= attribute).
Read the DisplayAttribute's value.
#Html.Raw() that value as the label text.
Use #Html.YourLabelHelper(m => m.Message) to render it.
But using HTML on your models like that isn't really advisable. Views and templates should decide how to render a model, not the other way around.

How do you automate DevExpress Combo Boxes with Selenuim/Watir?

DevExpress builds combo boxes in a very odd way. The standard identification built in to Selenuim and Watir (including Page Objects) does not see it as a Select List.
So how can you automate these successfully?
So as it turns out, DevExpress builds combo boxes as a text box with several layered tables associated with it but not under the text box in the HTML tree.
interactions are all done via embedded scripts.
I found the simplest way to automate this object is to identify the text box and the lowest table containing the list of items (3rd table down).
for example (using Watir and Page Objects)
table(:list,:id => 'ComboBoxValue_DDD_L_LBT')
text_field(:state, :id => 'ComboBoxValue_I') #:name => 'State')
I have not found a way to get better IDs at these levels, but we are working that issue.
Then your select code looks like this:
self.state_element.click
row = list_element.find { |row| row[0].text == value }
row.click
Note that with Selenium, you can execute arbitrary javascript in the client to query and set the control's state (if the client-side is enabled for the control). Here's how I did so to extract (and set) the selected text from a combobox named localeSelectList:
// unit test code, c#
[TestMethod]
public void SomeTestMethod()
{
IWebDriver ff = new FirefoxDriver();
ff.Navigate().GoToUrl(homeUrl);
// find the element as an iWebElement
IWebElement localeBox = ff.FindElement(By.CssSelector("#localeSelectList"));
Assert.IsTrue(localeBox.Enabled);
// get the text from the control via javascript
var locale = Util.GetControlText(ff, localeSelectList);
Assert.IsTrue(locale == "English");
// set the text in the control via javascript
Util.SetControlText(ff, localeSelectList, "German");
// verify the text was set
locale = Util.GetControlText(ff, localeSelectList);
Assert.IsTrue(locale == "German");
}
// helper methods, Util class
static public string GetControlText(IWebDriver driver, string controlName)
{
string script = string.Format("return {0}.GetText();", controlName);
var controlText = ((IJavaScriptExecutor)driver).ExecuteScript(script);
return controlText.ToString();
}
static public void SetControlText(IWebDriver driver, string controlName, string controlText)
{
string script = string.Format("{0}.SetValue('{1}');", controlName, controlText);
((IJavaScriptExecutor)driver).ExecuteScript(script);
}
It's not quite the same thing as interacting with the extensions via primitives (clicks, keystrokes, etc) as it won't fire the event handlers for these events, but if your extension uses 'valueChanged' events instead of primitive handlers it's pretty close to the same.
Also note: you can use client-side javascript to find and return elements using jquery/css selectors and ids, as follows:
IWebElement element = (IWebElement) ((IJavaScriptExecutor)driver).ExecuteScript("return $('#.myElementId');")
That's right with several layered tables, but I would like to add that they are only visible when combobox is clicked. First
var cmbParameterGruppen = webDriver.FindElement(By.Id("phContent_ParameterGruppenComboBox_I"));
cmbParameterGruppen.Click();
and then
var tblItems = webDriver.FindElement(By.Id("phContent_ParameterGruppenComboBox_DDD_L_LBT"));
var parameterGruppen = tblItems.FindElements(By.XPath(".//*"));
var count = parameterGruppen.Count;
Debug.WriteLine($"Count = {count}");
if(count > 0)
parameterGruppen[count - 1].Click();
I select hier last row.

Using Rich Text Editor in Orchard CMS Custom Module

I am creating a custom module in Orchard CMS 1.7.1
So far all is going well (ish)
One of my properties is a string (called InfoBubbleHtml).
I would like to utilise the rich text edit for this input on my modules create/edit form.
Is there a helper already in place that would render my property as a rich text area rather than just a textarea or input field?
If not, what would i need to do to be able to have this property render the rich text editor?
Thanks in advance.
Update
As an update/addition to this question... Any HTML that I enter into my current text area is being ignored; guessing to do with request validation. how is this disabled for my controller so i can allow html in the admin?
Update 2
Ok, so i have figured out how to add this to my view by using:
#Display.Body_Editor(Text:Model.InfoBubbleHtml,EditorFlavor:"html")
Any idea how to set the ID of the editor?
#Display.Body_Editor(Text:Model.InfoBubbleHtml,EditorFlavor:"html") is rendering a shape named Body.Editor.cshtml.
This file lives in : Orchard.Web\Core\Common\Views\Body.Editor.cshtml
And it's content is
#using Orchard.Utility.Extensions;
#{
string editorFlavor = Model.EditorFlavor;
}
#Html.TextArea("Text", (string)Model.Text, 25, 80, new { #class = editorFlavor.HtmlClassify() })
So using this Shape you cannot set Id, Model is the anon that you send on the Display (Text and EditorFlavor).
Shapes.cs on Orchard.Core/Common is hooking an alternate using the EditoFlavor string.
public void Discover(ShapeTableBuilder builder) {
builder.Describe("Body_Editor")
.OnDisplaying(displaying => {
string flavor = displaying.Shape.EditorFlavor;
displaying.ShapeMetadata.Alternates.Add("Body_Editor__" + flavor);
});
}
So the final file that is rendered : TinyMVC\Views\Body-Html.Editor.cshtml
using Orchard.Environment.Descriptor.Models
#{
var shellDescriptor = WorkContext.Resolve<ShellDescriptor>();
}
<script type="text/javascript">
var mediaPickerEnabled = #(shellDescriptor.Features.Any(x => x.Name == "Orchard.MediaPicker") ? "true" : "false");
var mediaLibraryEnabled = #(shellDescriptor.Features.Any(x => x.Name == "Orchard.MediaLibrary") ? "true" : "false");
</script>
#{
Script.Require("OrchardTinyMce");
Script.Require("jQueryColorBox");
Style.Require("jQueryColorBox");
}
#Html.TextArea("Text", (string)Model.Text, 25, 80,
new Dictionary<string,object> {
{"class", "html tinymce"},
{"data-mediapicker-uploadpath",Model.AddMediaPath},
{"data-mediapicker-title",T("Insert/Update Media")},
{"style", "width:100%"}
})
You need to add this to the template and include another parameter in the TextArea Dictionary parameter named : {"id", "THE ID YOU LIKE"}.
Take a look at the docs about Shapes if you want to learn more Docs
You can patch the TinyMVC\Views\Body-Html.Editor.cshtml file to enable it to use custom Name/ID for the text area. The modification is quite simple - replace
#Html.TextArea("Text", (string)Model.Text, 25, 80,
with
#Html.TextArea((string)Model.PropertyName ?? "Text", (string)Model.Text, 25, 80,
Now you can use additional parameter PropertyName in your call:
#Display.Body_Editor(PropertyName:"InfoBubbleHtml", Text:Model.InfoBubbleHtml, EditorFlavor:"html")
The downside is that you are patching a foreign code and have to reapply this patch every time this file in TinyMVC module is updated.

Selenium: Getting the value of elements in the dom when they are hidden

I am iterating a list of elements found ByClassName(). For each item in that list, I need to extract the text value of their child elements. I have seen some solutions for using javascript to get at the values, but I must be missing something. In this specific instance I have a span, and I need the text or innerhtml from it. I have verified with Firebug that there is text in it.
If all you want is to access the children elements you can also use xpath's //div[#class='Class']/child::div where you can change the classname and the child type. If you are wanting to access all children of the parent element you can return a list of elements that match your selector as below:
ReadOnlyCollection<IWebElement> elements = _driver.FindElements(By.XPath("//div[#class='ClassName']/child::div"));
At this point, yes, if you can access the element you should be able to access the innerHTML. Note that I have written my code in C#, which I believe is what your code is in too.
It turns out GetAttribute("innerHTML") is not inhibited by hidden html.
public string GetChildElementTextByClassName(IWebElement element, string className)
{
string returnValue = string.Empty;
try
{
IWebElement childElement = element.FindElement((By.ClassName(className)));
if (childElement != null)
{
returnValue = childElement.GetAttribute("innerHTML").Replace(Environment.NewLine, "").Trim();
}
}
catch (Exception)
{
//throw;
}
return returnValue;
}