Aspose Wordsfor .NET: replace link contents keeping (setting) it's style - aspose

There is much info over internet telling how to change link contents with Aspose Wordsfor .NET. Also, there is enough info about setting link style after insertion.
But I have a problem: I need to modify existed link (from template) keeping (or just setting) it's visual style (underlined blue text). By defaul, after link change (se code below) it's style is broken.
foreach (Field field in docTemplate.Range.Fields)
{
if (field.Type == FieldType.FieldHyperlink)
{
var hyperlink = (FieldHyperlink)field;
if (hyperlink.Result.Equals("<<[model.Id]>>"))
{
hyperlink.Address = model.IdUrl;
hyperlink.Result = model.Id;
}
}
}
Does any solution for this case exist? Will appreciate any help.

I have tested your scenario with Aspose.Words for .NET 17.4 and unable to notice hyperlink style issue, it remains intact after modification. If you are using some old version of Aspose.Words for .NET then please upgrade to latest version, hopefully it will resolve the issue.
However, if your issue persists then please share your complete code along with your input,output and expected documents. It will help to understand your issue exactly.
I'm Tilal, developer evangelist at Aspose.
Document doc = new Document("Hyperlink.docx");
//You may change the color of Hyperlink style, if required.
//doc.Styles[StyleIdentifier.Hyperlink].Font.Color = Color.Blue;
//doc.Styles[StyleIdentifier.FollowedHyperlink].Font.Color = Color.Blue;
foreach (Field field in doc.Range.Fields){
if (field.Type == FieldType.FieldHyperlink){
FieldHyperlink link = (FieldHyperlink) field;
if (link.Result.Equals("aspose.com"))
{
link.Result = "google";
link.Target = "www.google.com";
}
}
}
doc.Save("Hyperlink_174.docx");
Edit: If you want to modify a specific hyperlink then use following code snippet.
Document doc = new Document("E:/Data/Hyperlink.docx");
DocumentBuilder builder = new DocumentBuilder(doc);
foreach (Field field in doc.Range.Fields)
{
if (field.Type == FieldType.FieldHyperlink)
{
FieldHyperlink link = (FieldHyperlink)field;
if (link.Result.Equals("aspose.com"))
{
builder.MoveToField(link, false);
builder.Font.ClearFormatting();
// Specify font formatting for the hyperlink.
builder.Font.Color = Color.Blue;
builder.Font.Underline = Underline.Single;
// Insert the link.
builder.InsertHyperlink("google", "http://www.google.com", false);
link.Remove();
}
}
}
doc.Save("UpdatedHyperlink.docx");

Related

How to make an Action that opens a page that is filtered after multiple option values in AL?

I'm pretty new to business central so excuse me if this is a rather stupid question. I have been trying to make a button that sends the user to a page where he can see products that are new or old.
A product has a field named "Status" which can have the values "New", "Old", "SoldOut" or "BeingDelivered".
So my question is how do I set the filter to only show products that are either "New" or "Old". I got this so far which only shows products that are "New" but I can't figure out how to show "New" OR "Old" ones.
Group(group1)
{
Action(testAction)
{
ApplicationArea = All;
Caption = 'TestAction';
RunObject = page Products;
RunPageLink = Status = const("New");
}
}
I have been trying to find a solution and tried a bunch of different approaches but couldn't figure much out. Any help is really appreciated.
Little Edit:
Here is an example of what I would ideally want which obviously doesnt work though.
Group(group1)
{
Action(testAction)
{
ApplicationArea = All;
Caption = 'TestAction';
RunObject = page Products;
RunPageLink = Status = const("New|Old");
}
}
Thanks for your time and effort!
Use filter instead of const
Cheers

Sharepoint 2013 - Open search result in new window/tab

Ok, so I've been struggling with this problem for a few hours now...
I need to modify the links in the search results, so that they open in a new window/tab.
Specifically it's the search results that links to a "off-site"-hit.
I've created a copy of Item_WebPage.html, but I just can't get it to work.
I guess that there are some kind of async loads that screws it all up.
My js-code is as follows:
var anchors = document.getElementsByClassName('ms-srch-item-link');
for (var i = 0; i < anchors.length; i++) {
anchors[i].setAttribute("target", "_blank");
}
}
However, "anchors" always is "0".
Is there a "sharepoint-document-ready-as-h*ll"-function I can use?
My guess is that my problem is that not all content is loaded into the DOM before I run my code...
A custom display template is a good way of changing the behavior of the search results. I've used JQuery code to make sure that external links always load in a new window :
<script type="text/javascript">
if (window.jQuery) {
$(window).load(function () {
// Open external links in a new tab
var url = '://' + window.location.hostname;
// get the current website name, and i add :// to make sure we're looking at the right name //
url = url.toLowerCase(); // lowercase everything to compare apples to apples
$("a").each(function () {
var link = this; // assign the link object to another variable for easier managability
var linkHref = link.href.toLowerCase(); // lower case it
if (linkHref.indexOf(url) < 0 && linkHref.indexOf('javascript:') < 0) { // check to see if this A object has this domain in it and make sure it's not a javascript call
link.target = '_blank'; // change the target to be in the new window
} if (linkHref.indexOf('.pdf') > 0) { // check to see if this is a PDF
link.target = '_blank'; // change the target to be in the new window
$(link).removeAttr("onclick"); //remove the SP click event
} if (linkHref.indexOf('/forms/') > 0 && linkHref.indexOf(').aspx') > 0) { //check for links in the forms library
link.target = '_blank'; // change the target to be in the new window
$(link).removeAttr("onclick"); //remove the SP click event
}
});
});
}
</script>
It's way too long and you may have resolved it.
I was looking for the same and added - target="_blank" to the anchor tag in a custom display template
In SharePoint online, this worked perfectly for me, applies to all results though.
Using SharePoint Designer, update the Item_CommonItem_Body.html Display Template from within _catalogs/masterpage/display templates/search.
Search for below line :
var titleHtml = String.format('<a clicktype="{0}" id="{1}" href="{2}" class="ms-srch-item-link" title="{3}" onfocus="{4}" {5} >{6}</a>',
and replace it with :
var titleHtml = String.format('<a clicktype="{0}" id="{1}" href="{2}" class="ms-srch-item-link" title="{3}" onfocus="{4}" {5} target="_blank">{6}</a>',
Save the change and, from the browser master page library, publish a major version. When you search now the results should open in new tabs although you may need to load the page cache again (CTRL+F5).
From https://social.technet.microsoft.com/Forums/ie/en-US/a7db8389-3740-4ff6-ac52-645776b29a56/search-results-in-new-tabwindow-in-sharepoint-2013

Can Glass.Mapper V3 support language fallback (field-level and item-level)?

We just updated our project to use Glass.Mapper V3. We LOVE it. But we've encountered an issue. It doesn't seem to respect language fallback.
We have our site set up so that if a user picks a non-default language, they will see the item of that language if it exists. If not, they will see the default ("fallback") language version. We have also set this up at the field level, so that if there is a non-default version of an item but not all the fields are changed, any unchanged fields will fall back to the default language version's value for that field.
Is there anything we can do to enable Glass to use language fallback?
I am updating this with a bit of background on why we do the check. If you ask for a Sitecore item that doesn't exist you get a null value, so that is simple to handle. However if you ask for a Sitecore item that doesn't exist in that particular language returns an item with no versions. This means we have to do this check because otherwise Glass would end up returning empty class which I don't think makes much sense.
This answer will get a little experimental.
First in the the Spherical.cs file you need to disable the check:
protected void Application_BeginRequest()
{
Sitecore.Context.Items["Disable"] = new VersionCountDisabler();
}
We can then move the check to later on to the Object Construction pipeline. First create a task:
public class FallbackCheckTask : IObjectConstructionTask
{
public void Execute(ObjectConstructionArgs args)
{
if (args.Result == null)
{
var scContext = args.AbstractTypeCreationContext as SitecoreTypeCreationContext;
if (scContext.Item == null)
{
args.AbortPipeline();
return;
}
//this checks to see if the item was created by the fallback module
if (scContext.Item is Sitecore.Data.Managers.StubItem)
{
return;
}
// we could be trying to convert rendering parameters to a glass model, and if so, just return.
if (String.Compare(scContext.Item.Paths.FullPath, "[orphan]/renderingParameters", true) == 0)
{
return;
}
if (scContext.Item.Versions.Count == 0)
{
args.AbortPipeline();
return;
}
}
}
}
Then finally register this task in the GlassMapperScCustom class:
public static void CastleConfig(IWindsorContainer container){
var config = new Config();
container.Register(
Component.For<IObjectConstructionTask>().ImplementedBy<FallbackCheckTask>().LifestyleTransient()
);
container.Install(new SitecoreInstaller(config));
}
I haven't tested this but it should in theory work <- disclaimer ;-)
There are few potential issues with provided solution when sitecore 7 (7.2) + IoC + solr + mvc is used.
When using IoC ex Winsdor please make sure that your Global.asax looks like this one <%# Application Codebehind="Global.asax.cs" Inherits="Sitecore.ContentSearch.SolrProvider.CastleWindsorIntegration.WindsorApplication" Language="C#" %>. Once, by mistake this file has been changed to <%# Application Codebehind="Global.asax.cs" Inherits="Merck.Manuals.Web.Global" Language="C#" %> and language fallback was not working. Also the errors we were getting wasn't descriptive as we thought that solr schema is incorrect.
Code Sitecore.Context.Items["Disable"] = new VersionCountDisabler(); can be added to PreprocessRequestProcessor and it works fine which is better solution that modifying global.asax.

How to generate media item link with id instead of path in Sitecore

Anyone knows how to generate links in sitecore with ID instead of item path?
If you use GetMediaUrl method from the API, I can get this URL:
/~/media/Images/Archive/content/News and Events/News_and_Events_Level2/20070419162739/iwhiz3.jpg
The problem with this approach is that if someone changes the media item name, removes it somewhere or deletes it, the above link will break.
I notice if I insert a media link from rich text editor, I get the link as below:
/~/media/14BDED00E4D64DFD8F74019AED4D74EB.ashx
The second link is better because it's using the item id, so if the actual media item is renamed, removed, or deleted, all related links will be updated too. On top of that, when Sitecore renders the page, it will actually convert the above link and display the item path so it's readable.
I'm using Sitecore 6.5 and currently doing content migration so I need to make sure all internal links are updated properly.
May I know if there is a method to generate the second link by using sitecore API?
Thanks!
The GetMediaItemUrl extension method seems to give you what you want.
public static class ItemExtensions
{
public static string GetMediaItemUrl(this Item item)
{
var mediaUrlOptions = new MediaUrlOptions() { UseItemPath = false, AbsolutePath = true };
return Sitecore.Resources.Media.MediaManager.GetMediaUrl(item, mediaUrlOptions);
}
}
[TestFixture]
public class when_using_items_extensions
{
[Test]
public void a_url_based_on_media_item_id_can_be_generated()
{
// Arrange
Database db = global::Sitecore.Configuration.Factory.GetDatabase("master");
Item item = db.GetItem("/sitecore/media library/Images/MyImage");
// Act
var mediaUrl = item.GetMediaItemUrl();
// Assert
Assert.That(mediaUrl, Is.EqualTo("/~/media/17A1341ABEEC46788F2159843DCEAB03.ashx"));
}
}
These are called dynamic links and you can normally generate them using the LinkManager e.g:
Sitecore.Links.LinkManager.GetDynamicUrl(item)
.. but I'm not sure of the method to do this with Media links (there probably is one but I cant seem to find it and its not on MediaManager) but the basic syntax is:
"/~/media/" + item.ID.ToShortID() + ".ashx"
If you always want to use ID's instead of paths, you can change this setting in webconfig to false (like this):
<setting name="Media.UseItemPaths" value="false"/>`
Here is what the webconfig describes about it:
MEDIA - USE ITEM PATHS FOR URLS
This setting controls if item paths are used for constructing media URLs.
If false, short ids will be used.
Default value: true
Then you can use the default implementation (without additional parameters):
Sitecore.Resources.Media.MediaManager.GetMediaUrl(item);
This is what I use:
var imgField = ((Sitecore.Data.Fields.ImageField)currentItem.Fields["Icon"]);
MediaUrlOptions opt = new MediaUrlOptions();
opt.AlwaysIncludeServerUrl = true;
// Absolute Path works as well. So either use AbsolutePath or AlwaysIncludeServerUrl
opt.AbsolutePath = true;
string mediaUrl = MediaManager.GetMediaUrl(imgField.MediaItem, opt);

Check if items exist in the current language?

I have a Sitecore solution where there are 3 different languages enabled. On top of the page, there is a link to each language. When you click this link, you get the current page you are standing on, in the selected language.
But not all pages are translated into all languages. So if I am standing on page x in English language, and this page is only available in English and German but not Chinese, then the Chinese link should not be shown.
So the question is - How do I check if the current item has a version of a specific language?
To see if there is a version of the current item you can do this: Sitecore.Context.Item.Versions.Count > 0
[updated for comment]
I don't claim that this is the most efficient way to determine if an item has a version in a language, but this will work:
bool hasVersion = HasLanguageVersion(Sitecore.Context.Item, "en");
private bool HasLanguageVersion(Sitecore.Data.Items.Item item, string languageName)
{
var language = item.Languages.FirstOrDefault(l => l.Name == languageName);
if (language != null)
{
var languageSpecificItem = global::Sitecore.Context.Database.GetItem(item.ID, language);
if (languageSpecificItem != null && languageSpecificItem.Versions.Count > 0)
{
return true;
}
}
return false;
}
You can retrieve a collection (LanguageCollection) of an items content languages (ie. the languages for which the item has content).
LanguageCollection collection = ItemManager.GetContentLanguages(Sitecore.Context.Item);
foreach (var lang in collection)
{
var itm = Sitecore.Context.Database.GetItem(Sitecore.Context.Item.ID,lang);
if(itm.Versions.Count > 0)
{
Response.Write("Found language " + lang + "<br />");
}
}
Hope this helps :)
NB: Add a comment dude.. please dont just make random edits to my answer. This is the height of rudeness.
Edit: Correcting .. Turns out the method doesn't take into account versions of that language existing.---
to clarify, ItemManager.GetContentLanguages does not get you the list of languages on a given item. It gives the list of all languages you have opted to include in your environment. Under the hood, it does 2 things (based on decompiled code for sitecore 7.2):
it calls LanguageManager.GetLanguages(item.Database));
it adds to this any languages not already added by step 1 by calling item.Database.DataManager.DataSource.GetLanguages(item.ID);
If you have the context items in a list, use a Linq expression:
List<Item> languageContentItems =
contentItems.Where(x=> x.Version != null && x.Versions.Count > 0).ToList();
I'm thoroughly confused as to why x.Version.Number wouldn't be the correct syntax vs. using x.Versions.Count because the x.Versions inline-documentation states that it returns all language versions of the item, which would mean that x.Versions.Count should return a count of all versions in all languages, when we really only want to see if the item has a version for the current context language.
This works like charm for me:
item.Versions.GetVersions(false).Any();
don't forget about Fallback option sometimes
if (item.Versions.Count > 0 && !item.IsFallback)
would work better
have a look at this post for a method which returns a list of languages an item has versions in: https://stackoverflow.com/a/31351810/551811
I use the following extension method on Item. This assumes you have an item to start from of course.
public static bool HasVersionInLanguage(this Item item, Sitecore.Globalization.Language lang)
{
return ItemManager.GetVersions(item, lang).Any();
}
If you don't have the item in memory you could change this to a 'normal' method and pass the ID of the item as a second parameter..
public bool HasVersionInLanguage(ID itemId, Sitecore.Globalization.Language lang)
{
return ItemManager.GetVersions(item, lang).Any();
}