This was a triumph.
I'm making a note here: HUGE SUCCESS.

Search This Blog

Tuesday, January 28, 2014

IT'S OVER ONE THOUSAAAAAAAAAAND!!!!

My blog just got over one thousand views!!! 

 

Hurray!!! 

 

Confetti for everyone!!!

 

I probably just viewed my own blog so many times that I'm now up to one thousand. Although I did set it so that my own views wouldn't count. But meh, /care, one thousand views!

Also, someone actually clicked on the advertisement box on the right. Which gave me a very tiny small amount of eurocents, but still money nonetheless!
So if you happen to stumble upon this post, could you like... Just... Do a tiny click on that advertisement box on your right? Yeah. That one, right underneath the "Subscribe to" thingy. It won't cost you a thing, it won't do any harm either, but it will give me a (once again) very tiny small amount of money, which in return makes me a very tiny bit more happier each time someone clicks it.

And who knows, it might even be interesting! I have no idea what the advertisement box tells you, it is supposed to show you advertisements that are relevant to whatever business you searched for on Google. In my case it shows me something in French about becoming a florist, although I have absolutely no idea why it would show something like that since I never even searched for flowers online. Peculiar.


I think I'll keep making posts like these every time my views increase by a thousand. Eventually, I'll get to 9000. And you should know what that means. Oh boy, do I look forward to that moment... That will be one heck of a post.

Friday, January 24, 2014

My new favourite syntax highlighter: Prism!

The past few days, I noticed some parts of my code were missing in the Syntax Highlighter and that sometimes, the code wasn't shown in the highlighter at all (it was just dull text). When I edited the affected blog posts however, the missing pieces of code were there and so were the elements for the highlighter. So I figured it might have had to do something with the Syntax Highlighter.

I decided to search for a new highlighter, and came across Prism. This is a very neat highlighter, it is lightweight and extensible, offers six different styles, has various plugins and is supported by most browsers.
For my blog, I'm using the Prism highlighter with the Okaidia theme and I also included the Line Numbers plugin. 

How to use Prism on Blogger/Blogspot

First of all, I discovered that I couldn't host JavaScript files on Blogger/Blogspot. Secondly, I didn't like the idea of hosting scripts elsewhere. I tried hosting it on Google Drive and that sort of worked, but still I wanted to find an easier way.
So I checked the source of prismjs.com and its pages, searched for the scripts and found them there. Not quite sure if I'm allowed to do that... But it was easier for me and I think those will always be the most up-to-date scripts. 
This is the core JavaScript code of Prism. 
This is the JavaScript code for the line numbers plugin.
This is the CSS code for the line numbers plugin.
And this is the CSS code for the Okaidia theme.

I'm not going to provide the link to all the scripts, plugins and themes for Prism since you can probably find most of them yourself by changing the URLs a bit or by doing a search through the source code of the site. 

Now that we have the necessary files, we need to include them to the template. 
To add them, you need to edit the HTML of your template. You can do so by going to the settings of your blog, select "Template" from the left hand side navigation, and then choose "Edit HTML". 

Right before the </head> tag, you paste the following code (source of the scripts may be different depending on which plugins or styles you use):
<script src='http://prismjs.com/prism.js' type='text/javascript'/>
<script src='http://prismjs.com/plugins/line-numbers/prism-line-numbers.js' 
type='text/javascript'/>
<link 
href='http://prismjs.com/themes/prism-okaidia.css' rel='stylesheet'/>
<link 
href='http://prismjs.com/plugins/line-numbers/prism-line-numbers.css' 
rel='stylesheet'/>

Now, when you create a new blog post and you wish to add code to it, you can use the following to highlight your code:
<pre class="line-numbers"><code class="language-javascript">
// Your code here.
</code></pre>

Do note that depending on which plugins you have, you can change the class in the pre tag. You can read more about the different plugins and how to use them here. Also, depending on what kind of code you will be highlighting, you can change the class in the code tag.
To highlight CSS, use language-css class for the code tag.
To highlight HTML, use language-markup class for the code tag.
To highlight JavaScript, use language-javascript class for the code tag.

Got code that's not showing up? No problem. We can fix this. 

I noticed that if you want to use HTML code inside JavaScript (or even script tags in JavaScript), the code will likely not show. I think this might be related to HTML being stripped off. For example, see the following code:
var site = "www.prismjs.com";
var title = "PrismJS";
var text = "" + title + "";

Noticed anything strange? I surely did. I added an anchor tag to that code, yet it is not showing.
Let me show you the same code, but now I changed the "less than" character ("<") with "&lt;" and this is the result:
var site = "www.prismjs.com";
var title = "PrismJS";
var text = "<a href='" + site + "'>" + title + "</a>";

Bam! Suddenly the code works. Just to give you an idea, this is how it looks like (and how I write it in order for it to show up properly) when I edit the blog post with the code:
var site = "www.prismjs.com";
var title = "PrismJS";
var text = "&lt;a href='" + site + "'>" + title + "&lt;/a>";

So when you use HTML inside JavaScript, or even when you use "<script></script>" tags or regular expressions, always make sure to replace the "less than" character with "<". That way, no code will be missing from the highlighter and visitors will be able to correctly copy and use your code.

All done! Let's start making more blog posts now!

Now that I finally have a syntax highlighter that does what I want it to do, I can continue writing blog posts about my SharePoint experiences without having to worry about visitors not seeing my code. ^_^

I would like to thank Lea Verou and all these people who created Prism, without them I would probably still struggle with highlighting stuff. Please do check out Prism, I highly recommend it for Blogger/Blogspot or any other site.

Thursday, January 23, 2014

How to get a term-driven breadcrumb trail with full hierarchy in SharePoint 2013

On the 6th of May, 2013, I had asked a question on Stack Overflow on how one could create a term-driven hierarchical breadcrumb trail in SharePoint 2013. Alas, never really got an answer that suited my needs.

Yesterday, I suddenly had the idea to just try and find a solution with JavaScript. The idea was to loop through the subsite navigation and see which list item resembled the current page, then find all the parent elements of that list item and fetch their values. And in case I was on a page that wasn't part of a subsite (but rather just a page at the top site collection), I would just fetch the title of the page and add that to the breadcrumb trail.

Here's a screenshot of how my breadcrumb looked like earlier:



And here's a screenshot of how it looks like now:



Pretty nice, huh?

Let's just get started, I'll give you the code.

The code

// Just add the following line.
SP.SOD.executeOrDelayUntilScriptLoaded("SP.UserProfiles.js", 
   "~sitecollection/Style Library/Scripts/jquery.SPServices-2013.01.js");

var siteCollection = "Your site collection name";
var siteCollectionUrl = "/";     
var pageName; 
var subsite;
// Fetch the name of the subsite you're currently on.
$().SPServices({
    operation: "SiteDataGetWeb",
    async: false,
  completefunc: function (xData, Status) {
   subsite = $(xData.responseXML).SPFilterNode("Title").text();
  }
});
// Fetch the url of the subsite you're currently on.
var subsiteUrl = $().SPServices.SPGetCurrentSite();
// Fetch the title of the page, remove a piece of text from the title
// (in my case, "Pages - "), then remove any white spaces before and 
// after the title.
var pageTitle = document.getElementsByTagName("title")[0].innerHTML
   .replace("Pages - ", "").replace(/^\s\s*/, "").replace(/\s\s*$/, "");

// If the current site is the same as the site collection (meaning it is
// not a subsite), then use the url of the current page.
if (subsite == siteCollection) {
 // Create the string that will contain the breadcrumb trail.
 var text = "<a href='" + siteCollectionUrl + "'>" + siteCollection 
 + "</a> > <a href='" + document.URL + "'>" + pageTitle + "</a>";
}
// In any other case, use the url of the subsite. 
else {
 // Create the string that will contain the breadcrumb trail.
 var text = "<a href='" + siteCollectionUrl + "'>" + siteCollection 
 + "</a> > <a href='" + subsiteUrl + "'>" + subsite + "</a>";
}

$(function runMe() {
 // Set the ID of your subsite navigation. 
 var $this = $("#NavRootAspMenu");
 if($this != null) {
  // Remove the class "static" from the last item in the navigation 
  // (because it(s a link to edit the navigation) and remove the last
  // child element (since this doesn't have a href attribute).
  $(".ms-listMenu-editLink").removeClass("static");
  $("ul[id*='RootAspMenu'] li.ms-navedit-editArea:last-child").remove();
  $this.find("li").each(function(i){
   var elem = $($this).find("li.static")[i]; 
   // If elem finds an anchor tag that contains the following class, then
   // add a new class. We'll use this class for the parent elements.
   if ($(elem).find("a").hasClass("ms-core-listMenu-selected")) {
    $(elem).addClass("parentSelected");
   }  
  });  
  // If the subsite navigation contains elements with the class 
  // "parentSelected" and that element contains an anchor, a span and
  // another span with the class "menu-item-text", then for each of those
  // elements do the following. 
  $this.find(".parentSelected > a span span.menu-item-text")
   .each(function(j) { 
   $(this).addClass("bcn");  //bcn = breadcrumbnode
   var crumbLink = $($this).find(".parentSelected > a")[j].href;
   var crumbName = $("span.bcn")[j].innerHTML;
   // If the link equals the url of the site collection, then this list
   // item is a category and it does not require an anchor tag.
   if (crumbLink == "https://your-site-collection.com/") {
    text = text + " > " + crumbName;
   }
   // In any other case, this list item has a page and we will add an
   // anchor tag to the breadcrumb trail. 
   else {
   text = text + " > <a href='" + crumbLink + "'>" + crumbName + "</a>";
   }
  });
 }
// When we ran through the navigation, apply the new breadcrumb trail to
// the element in the master page. 
document.getElementById("customBreadcrumb").innerHTML = text;
});

You'll also need to have the jQuery library for SharePoint Web Services, you can find it here.
In order for our code to work properly, we will need to replace some code from the master page and add a reference to the breadcrumb script on the master page. Be sure to read the JavaScript code first, you will need to fill in a name for your site collection (var siteCollection) and give the url of your site collection followed by a slash (var crumbLink).

Adding a reference to the master page

If we want to apply this code on the site collection and all subsites, then we should add a reference to our script in the master page. Please do note that I'm using a HTML master page. This is the code you should add:
<!--SPM:<SharePoint:ScriptLink language="javascript" ID="scriptLink1"
runat="server" name="~sitecollection/Style Library/Scripts/breadcrumb.js"
OnDemand="false" Localizable="false"/>-->

Do note that the ID might be different. You must make sure that you do not already have a scriptlink with the same ID, so change the number of the ID and make it unique.
Also, the name (path to your script) might be different. Make sure that it matches the path of where your script is located.

Replacing code in the master page

Next, we need to replace some code in the master page. In my HTML master page, I replaced any piece of code that had to do with the breadcrumb. Just to give you an idea, the following pieces of code are the ones that I REMOVED from my master page:
<!--SPM:<asp:sitemappath runat="server" 
 sitemapproviders="SPSiteMapProvider,SPXmlContentMapProvider" 
 rendercurrentnodeaslink="true" 
 nodestyle-cssclass="breadcrumbNode" 
 currentnodestyle-cssclass="breadcrumbCurrentNode" 
 rootnodestyle-cssclass="breadcrumbRootNode" 
 hideinteriorrootnodes="false"
 SkipLinkText=""/>-->
<!--SPM:<SharePoint:AjaxDelta id="DeltaPlaceHolderPageTitleInTitleArea" 
 runat="server">-->
<!--SPM:</SharePoint:AjaxDelta>-->
<!--SPM:<SharePoint:AjaxDelta BlockElement="true" 
 id="DeltaPlaceHolderPageDescription" CssClass="ms-displayInlineBlock 
 ms-normalWrap" runat="server">-->
 <a href="javascript:;" id="ms-pageDescriptionDiv" 
  style="display: none;">
  <span id="ms-pageDescriptionImage"></span>
 </a>
 <span class="ms-accessible" id="ms-pageDescription">
  <!--SPM:<asp:ContentPlaceHolder id="PlaceHolderPageDescription" 
   runat="server"/>-->
 </span>
 <!--SPM:<SharePoint:ScriptBlock runat="server">-->
  <!--SPM:_spBodyOnLoadFunctionNames.push("setupPageDescriptionCallout");-->
 <!--SPM:</SharePoint:ScriptBlock>-->
<!--SPM:</SharePoint:AjaxDelta>-->

It is very important that you keep the following code in your master page, but wrap something around it with a class. Like so:
<span class="hideDefaultBreadcrumb">
 <!--SPM:<asp:ContentPlaceHolder id="PlaceHolderPageTitleInTitleArea" 
  runat="server">-->
  <!--SPM:<SharePoint:SPTitleBreadcrumb runat="server"
   RenderCurrentNodeAsLink="true"
   SiteMapProvider="SPContentMapProvider"
   CentralAdminSiteMapProvider="SPXmlAdminContentMapProvider">-->
   <!--SPM:<pathseparatortemplate>-->
    <!--SPM:<SharePoint:ClusteredDirectionalSeparatorArrow 
     runat="server"/>-->
   <!--SPM:</PATHSEPARATORTEMPLATE>-->
  <!--SPM:</SharePoint:SPTitleBreadcrumb>-->
 <!--SPM:</asp:ContentPlaceHolder>-->
</span>

Then add the class to your style sheet:
.hideDefaultBreadcrumb {
 display: none;
}

The reason that we must keep this content placeholder, is that otherwise you'll suddenly miss a great portion of the "Apps you can add". I forgot about this at first and then suddenly had only three apps left, but after reading about it here I learned that I should have left in the content placeholder with ID PlaceHolderPageTitleInTitleArea. So that's fixed now.

I also removed a span with the ID "ctl00_DeltaPlaceHolderPageTitleInTitleArea" in the master page.

Bear in mind that your code might be different from mine, so always check your site with source view in your browser, to see the ID's and classes of the elements in the breadcrumb.
Now, ADD the following code to the location of where you just removed the piece of code that was previously your breadcrumb:
<span id="customBreadcrumb"></span>

In that tiny span, your breadcrumb trail will appear. This will be dynamically filled with text and links once your script is running.

Make sure your master page and your script are checked in. Now you can finally see the full breadcrumb trail, with the correct hierarchy!
No need to deploy solutions, no need to find a workaround or use webparts to do the trick, just some simple JavaScript is all you need. ;)

Enjoy!