Category Archives: Code

Discovering Web Workers

So I wanted to learn about Web Workers, since they are (as far as I have come to understand) the only real way of running javascript in a separate thread. The following post is my explanation of the concept as I have percieved it at the time of learning.

Note: I wrote this post in the process of learning, meaning I’m not an expert. Don’t take my word as the truth. They’re just my interpretation of what others have said, and my own tests.

Web Workers

Web Workers allows running scripts “in the background”, in a separate thread from that of the user interface, allowing tasks to be performed without disturbing the user experience. Since javascript is a single threaded language, only able to simulate multithreading by using for example yield() or setInterval(), workers might be the only option for running javascript in separate threads. At least as far as I know.

Some things to know about web workers

  • Workers have a high start-up performance cost
  • Each worker instance consume a high amount of memory
  • Workers are not intened to be used in large numbers at the same time

A worker should not be something you call frequently to perform small tasks, since the cost of calling the worker will exceed the benefit of running it in a separate thread.

So when do you use Web Workers then? Well, if you want to run something that has a high performance cost, without interfering with the user experience, web workers can be a viable option. Uses can include for example perform heavy calculations, or having a “listener” for notifications running in the background.

So how do you do it?

Simple example

First of all, I have a simple html page, with a span to post my results, and buttons to start and stop my worker.

<html lang="en">
 <head>
[...]
 </head>

 <body>
 <input type="button" onclick="startWorking();" value="Start working!">
 <input type="button" onclick="stopWorking();" value="Stop working!">
 

 

 Results: <span id="resultSpan">...</span>

 <!-- load scripts at the bottom of your page -->
 <script src="javascript/foreman.js"></script>
 </body>
</html>

Next, I have a javascript file being loaded to the page. This is not my worker, but the script responsible for calling the worker. I call it foreman.js.

The first thing I want to do is to get my resultSpan element to present the results of the workers. I also create a variable for storing my worker object.

var result = document.getElementById("resultSpan");
var worker;

Next I create a function for stopping the worker.

function stopWorking() {
 worker.terminate(); // Tell the worker to stop working.
 worker = undefined; // Fire the worker.
}

Not all browsers support workers, so a function to check for worker support might be a good idea.

function browserSupportsWebWorkers() {
 if(typeof(Worker) !== "undefined") {
 // Yes! Web worker support!
 return true;
 } else {
 // Sorry! No Web Worker support..
 return false;
 }
}

And now to the important parts. We want to be able to call our worker, and create a function for doing just that.

function startWorking() {
// Code goes here.
}

The first thing I do is checking if the browser supports workers. If it doesn’t, I can handle it in different ways. This is good if you don’t want your functionality to break due to compatibility issues.

 if (!browserSupportsWebWorkers()) {
 // What to do if browser doesn't support workers.
 return;
 }

Then I instantiate a new worker object, referencing the worker javascript file. And yes, the worker code needs to be located in a separate file.

 worker = new Worker("javascript/worker.js"); // Create a new worker object.

// Code goes here.
}

Now when we have the worker object, we need to define what will happen when we get a response from it.  Communication between the foreman and worker will be passed through messages, and we need to declare what to do with those messages. The code below shows 2 ways of doing the same thing.

 worker.onmessage = function(event) { // Tell the foreman what to do when the worker response comes.
   result.innerHTML = event.data;
 };

 // This is another way of doing the same thing.
 worker.addEventListener("message", function (event) {
   results.innerHTML = event.data;
 }, false);

In the code above, we declare that when we recieve a message from the worker, we will get that message and show it in our resultSpan by setting its innerHTML.

We may also want to handle what happens if an error occurs. In addition to the .onmessage event, we can declare the .onerror event for just this reason.

worker.onerror = function(event) { // Tell the foreman what to do when the worker fails.
   result.innerHTML = "Error: " + event.message;
 };

The last thing is to call the worker. This is done by calling the postMessage function of the worker object.

worker.postMessage(); // Tell the worker to start working.

What will happen now is that the worker javascript will be loaded and executed. The results will depend on what we put in the worker.js file. All we have done in foreman.js is to say that we will present the results of the worker. So let’s take a look at the actual worker: worker.js.

var i = 0;

function timedCount() {
 console.log("Worker says: Counting to " + i);
 i = i + 1;
 postMessage(i);
 setTimeout("timedCount()",500);
}

timedCount();

In this simple example, all I want to do is to illustrate a continuous process being run in the background. The worker runs a recursive function every 500 milliseconds and sends the response back to the foreman. The message is being passed by calling the postMessage function. The object put as a parameter in postMessage will be available in event.data in the foreman script. In this case it’s an integer, but it could just as well be a string or JSON object.

Calling specific worker functions

You cannot call a specific function within a worker directly. When the worker is called, it simply runs the file. However, you can implement your own handling by passing function names as parameters.

In my next example, I have another worker file, skilledWorker.js. It contains three functions. I choose to store these in an object called actions, and you will see why later. This is not required however, and there are many ways of implementing support for calling certain functions.


var actions = {};
actions.count = function (parameters) {
  // Unpack parameters.
  var number = parameters;

  setTimeout(function () { // Call setTimeout to run function each 1000 ms.
    postMessage(number); // Message the foreman of the current number.
    number++; // Increment number.
    actions.count(number); // Recursively call the same function to increment number with each call.
  },100);
}

actions.calculate = function (parameters) {
  // Unpack parameters.
  var a = parameters.a;
  var b = parameters.b;

  var results = a + b;
  postMessage(results);
}

actions.read = function (parameters) {
  // Unpack parameters.
  var results = parameters.text;
  postMessage(results);
}

Next, I need to declare what will happen when my worker receives a message.


self.onmessage = function (event) {
  handleMessage(event);
}

This says that I should call the function handleMessage and pass my event whenever a message is received. All that’s left is implementing the handleMessage function.

function handleMessage(event) {
    var command = event.data.command;
    var parameters = event.data.parameters;
    var action = actions[command];
   
    if (action) {
        action(parameters);
    }
    else {
        postMessage("Unknown command");
    }
}

What happens here is that we retrieve the event.data, and get two properties from it, command and parameters. These has to be passed when calling the worker, and I will show how in a bit.

The next piece of code I got a little help from my friend and colleague Anatoly Mironov who has one of the best SharePoint blogs out there.

Since we store our functions in the object called actions, calling “actions[command]” will return the function matching the command string. If no functions matches, the value will simply be undefined. The simple if-statement allows you to check and handle what happens when trying to call a function that doesn’t exist.

The last thing we need to do is to call the worker passing the correct command and parameters.

Passing parameters

Calling a worker with parameters is still done with postMessage(). You can pass either a string or a JSON object. This example will demonstrate how to pass a JSON object. Passed parameters will be available in the worker in event.data. As you saw above, our workers handleMessage function needed the data to contain .command and .parameters. So when calling postMessage() we simply input a JSON object containing these two values.


worker.postMessage( { 'command': 'count', 'parameters': 1 } ); // Tell the worker to start counting.

worker.postMessage( { 'command': 'calculate', 'parameters': {'a': 5, 'b': 10 } } ); // Tell the worker to calculate.

worker.postMessage( { 'command': 'read', 'parameters': {'text': 'This is text the worker is supposed to read.'} } ); // Tell the worker to read the text.

In the code above, each  line will call the worker, but running different functions, which in turn use different parameters.

In conclusion

Web workers are not very difficult to work with once you understand how they work, and while their use might be limited due to the heavy initial performance cost, being able to running a background thread for large tasks can be quite powerful.

If you want to check the full code I have a GitHub repository for it here: https://github.com/Johesmil/webworkers.

If you want to learn more about Web Workers from people who actually know what they’re talking about, check out the links below. =)

Sources

Web Workers

http://www.htmlgoodies.com/html5/tutorials/introducing-html-5-web-workers-bringing-multi-threading-to-javascript.html
http://www.w3schools.com/html/html5_webworkers.asp
https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers
http://anders.janmyr.com/2013/02/web-workers.html
http://www.html5rocks.com/en/tutorials/workers/basics/

Advertisements

Embedding a PDF file dynamically on a web page

So embedding a PDF to a web page is pretty easy. All you need to do is to add an object or embed element to your HTML.

Actually, you could use only object or embed, depending on browser support. But using both is a safeguard. If object fails to load it’s data, it will render it’s child elements instead, in this case the embed element.

< object data='myPDF.pdf' type='application/pdf'>
 < embed src='myPDF.pdf' type='application/pdf'></embed>
</object>
 

There are spaces between the < and object/embed elements since WordPress doesn’t allow these elements. Remove it if copying this code.

But what if you don’t know what PDF file you want to display, and you want to load it dynamically? This is what I was trying to do, and of course I ran into problems displaying the PDF in Internet Explorer. This is how you should be able to set which file will be loaded using javascript. First, we add the elements to our HTML. To make it easier to get the elements in our javascript, give them a unique id.

< object id='myPdfObject' type='application/pdf'>
 < embed id='myPdfEmbed' type='application/pdf'></embed>
</object>

Then, in javascript, we SHOULD be able to change witch PDF should be shown like this.

// Get the elements.
var pdfViewerObject = document.getElementById("myPdfObject");
var pdfViewerEmbed = document.getElementById("myPdfEmbed");

// Set the elements to reference our PDF file.
pdfViewerObject.setAttribute("data", pdfUrl);
pdfViewerEmbed.setAttribute("src", pdfUrl);

It works perfectly in Chrome, but in IE (tried versions 10 and 11 as well as emulated 8 and 9), you will only see a grey frame with nothing in it. When debugging the javascript the attribute is actually updated, and everything seems to be fine, except you can’t see the PDF. Very frustrating. After a bit of googling i found a solution here (it’s not the marked answer). Instead of using <element>.setAttribute(), which should work, you need to modify the outerHTML attribute of the element.

pdfViewerObject.outerHTML = pdfViewerObject.outerHTML.replace(/data="(.+?)"/, 'data="' + pdfUrl + '"');
pdfViewerEmbed.outerHTML = pdfViewerEmbed.outerHTML.replace(/src="(.+?)"/, 'src="' + pdfUrl + '"');

However, this will only work if you already have the attribute present. So either you need to have a default url in your HTML, or you need to set the attribute first, which both is kind of annoying. Putting it all together it might look something like this.

var pdfUrl = "http://mySite/myPDF.pdf";

var pdfViewerObject = document.getElementById("myPdfObject");
pdfViewerObject.setAttribute("data", pdfUrl);
pdfViewerObject.outerHTML = pdfViewerObject.outerHTML.replace(/data="(.+?)"/, 'data="' + pdfUrl + '"');

var pdfViewerEmbed = document.getElementById("myPdfEmbed");
pdfViewerEmbed.setAttribute("src", pdfUrl);
pdfViewerEmbed.outerHTML = pdfViewerEmbed.outerHTML.replace(/src="(.+?)"/, 'src="' + pdfUrl + '"');

And there you go. Dynamically loading an embedded PDF to a web page, working in IE 8-11 and Chrome, and hopefully other browsers as well.

My main sources/further reading:
http://stackoverflow.com/questions/676705/changing-data-content-on-an-object-tag-in-html
http://stackoverflow.com/questions/1244788/embed-vs-object

Programmatically move a SPListItem to another folder in the same list

I had a hard time finding a good source for this, and therefore decided to write a short post about it.

First of all, I want to say that I am against the use of folders unless you absolutely need them. They add unnecessary complexity, and you can have the benefits of folders without many of the drawbacks by using metadata instead, for example with managed metadata fields. However, as there are no OOTB (out of the box) way of handling permissions for a group of items based in their metadata, folders MIGHT be useful for that purpose. There are other solutions though.

Now to the task at hand, moving a SPListItem based on it’s metadata, and then moving it to a subfolder in the same list. In my example, I will be moving the item in an event receiver.

What we need to do is to check the SPFileSystemObjectType of the SPListItem. This value will actually be File, even it it’s not a document library. Regular list items will also return object type File. This is only needed if you don’t want to move folders the same way.

This code assumes you have already got your SPListItem:

if (item.FileSystemObjectType == SPFileSystemObjectType.File)
{
 // Put the rest of code here.
}

Then we need to get the file object of the item. The file object will exist even if the list is not a library, and this code will work for documents and list items alike.

SPFile file = item.Web.GetFile(item.Url);

Then we want to build the new destination path were the item will be moved to. The path should follow the pattern: “<web url>/<list rootfolder url>/<subfolder>/<item Id>._000”

string filePath = string.Format("{0}/{1}_.000", "My Folder", item.ID);

And lastly, we simply call the SPFile.MoveTo method on our file object, and add the destination path.

file.MoveTo(filePath);

And that’s it. Put this in an ItemAdded function in an event receiver for a list and items will automatically be moved to the correct folder. Below is my complete example where I also make sure the folder exist before moving the item.

public override void ItemAdded(SPItemEventProperties properties)
{
 var item = properties.ListItem;
 var folderName = item["My Column"].ToString();
 var folderUrl = SPUtility.ConcatUrls(SPUtility.ConcatUrls(item.Web.Url, item.ParentList.RootFolder.Url), folderName);

 EnsureFolder(item.ParentList, folderName, folderUrl);

 MoveItemToFolder(item, folderUrl);
}

private static void EnsureFolder(SPList list, string folderName, string folderUrl)
{
 if (!list.ParentWeb.GetFolder(folderUrl).Exists)
 {
 SPListItem newFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, folderName);
 newFolder.Update();
 }
}

private static void MoveItemToFolder(SPListItem item, string folderUrl)
{
 if (item.FileSystemObjectType == SPFileSystemObjectType.File)
 {
 var filePath = string.Format("{0}/{1}_.000", folderUrl, item.ID);
 var file = item.Web.GetFile(item.Url);
 file.MoveTo(filePath);
 }
}

Sources:

http://zhebrun.blogspot.se/2011/06/sharepoint-how-to-move-listitem-or.html

 

Programmatically create, setup and use a custom Site Policy

On a current project I got the task to implement a solution for pushing out Site Policies to team sites. The common way of doing this is by using a Content Type Hub, which there are several blogs and guides available explaining how to do. But in this case this was not an option, and I had to be able to do it programmatically.

Finding examples of how to create a custom Site Policy wasn’t very hard, but what I soon discovered was that hardly any of these actually explained how to setup the schema of the policy the way you wanted. They just explained how to create one and maybe even set it to be used on a given site. And the object model itself isn’t complete enough to let you set everything using code. Eventually I found one single blog post by Dragan Panjkov which showed how to set it up, and managed to get it to work.

Site Policies are actually hidden content types, which you can tell by some parts of the creation process.The creation of the policies are actually pretty simple, and can be done with a few lines of code. First of all, you need reference the InformationPolicy namespace, like so:

using Microsoft.Office.RecordsManagement.InformationPolicy;

The second thing we do is getting the ProjectPolicy content type, which is (according to it’s own description) the “Container content type for Project Policy definitions”.
Note: The code assumes you already have an SPSite object called site.

var projectPolicyContentTypeId = new SPContentTypeId("0x010085EC78BE64F9478aAE3ED069093B9963");
var contentTypes = site.RootWeb.ContentTypes;
var parentContentType = contentTypes[projectPolicyContentTypeId];

The content type id in the code above is always the same, and is the id of the content type “Project Policy”.

Then you can create your own content type using Project Policy as the parent.

var policyContentType = new SPContentType(parentContentType, contentTypes, "My Site Policy");
policyContentType = contentTypes.Add(policyContentType);
policyContentType.Group = parentContentType.Group;
policyContentType.Description = "My Description.";
policyContentType.Hidden = true;
policyContentType.Update();

The next step is to setup the content type with the schema you want to use. For this there is no object model support. You have to write your own xml, which is a real pain. But the great post by Dragan gave a great solution on how to do this.

Setup a Site Policy the way you want it on a site in the browser. Open the site in SharePoint Manager and go to the Content Types collection. There will be a content type with the same name as the policy you just created. Click the content type and scroll down to the XmlDocuments property. Open that collection and copy the value of the <pp:ProjectPolicy> property.

policyschema

You will get an xml string, which you can copy and reuse to create your new policy schema. Doing so is simple. With the same content type object you have created previously, delete the existing project policy XmlDocument using the name from the xml.

policyContentType.XmlDocuments.Delete("http://schemas.microsoft.com/office/server/projectpolicy");

Then load your copied xml string into a new XmlDocument object, and add that to the XmlDocuments collection of your content type, and updated it.

var policySchema = new XmlDocument();
policySchema.LoadXml("Insert policy schema xml here.");
policyContentType.XmlDocuments.Add(policySchema);
policyContentType.Update();

When this is done, all that’s left is to create a Policy, using your content type.

Policy.CreatePolicy(policyContentType, null);

And that’s it. You’ve created your own Site Policy, with a custom schema, and all through code.

To apply the custom policy, simply get the policy object using the ProjectPolicy class, and run the ApplyProjectPolicy method.

var policy = (from projectPolicy in ProjectPolicy.GetProjectPolicies(web)
	where projectPolicy.Name.Equals("My Site Policy")
	select projectPolicy).Single();
ProjectPolicy.ApplyProjectPolicy(web, policy);

I’ve added a simple PolicyService class on GitHub Gist. Feel free to copy and use it if you want. Some tweaks may be necessary. =)

Resources:

http://blog.dragan-panjkov.com/archive/2013/10/27/configuring-site-policy-in-sharepoint-2013-using-server-code.aspx

How to reference nested class or struct etc, in PowerShell

I had a problem trying to reference a struct inside a public class from PowerShell. I tried to do it just like in C#, only with PowerShell syntax, simply adding the nested class or struct in the namespace, separated by a dot.

Doesn’t work:

$myProperty = [MyProject.MyClass.MyClassStruct]::MyProperty

But this didn’t work. Instead I got the following error:
Unable to find type [MyProject.MyClass.MyClassStruct]: make sure that the assembly containing this type is loaded.”

It seems, after fiddling around a bit and doing a quick search, that PowerShell has it’s very own way of calling a nested class or struct. Instead of adding the nested class with a dot, you actually have to use a +, like this:

Works:

$myProperty = [MyProject.MyClass+MyClassStruct]::MyProperty

I don’t know why, but that’s the way you do it. =)

Resources:

http://stackoverflow.com/questions/14141690/special-use-of-plus-sign-in-powershell

Automatic minifying of CSS (and LESS) and javascript using Web Essentials 2013 in Visual Studio 2013

We just recently started upgrading to Visual Studio 2013 in the project I’m currently working on, and with VS 2013 comes Web Essentials 2013, an extension that’s truly essential for web development.

Now, I like to use the LESS framework when writing CSS, and have been using Web Essentials 2012 for some time. One of the nice things about LESS and Web Essentials 2012 was that it automatically generates a minified version of the CSS file for you, and that’s pretty sweet.

Now, one of the first thing we noticed in VS 2013, was that modifying and saving our LESS files no longer generated a minified version of that file.

No mini

At first we thought it might be a bug, but when exploring the toolbar menu for Web Essentials (new to 2013), we found an interresting button:

Toolbar menu

Pressing this created a settings file and added it to the solution. In this file we found a number of awesome stuff. For example, you could turn the automatic generation of CSS files on and off. And even better, there was even an option to do the same for our javascript files!

Settings

Now we were getting our minified CSS files just like before, and also having the same behavior for our javascripts!

Yes mini

Before, we used another VS plugin for generating our minified javascripts, but now we no longer need to. Everything is taken care of using Web Essentials 2013, and modifying the settings file.

Perhaps the best thing about the created settings file is that it is automatically added as a solution file, and picked up by the source controller. So once configurated, we can just check in the file and let everyone in the team get the correct behaviour automatically.

Now, I may be ignorant of what was possible in 2012. Perhaps this settings file was available, and perhaps they had support for minifying javascripts. But since Web Essentials are now more visible than before (having its own toolbar menu), finding these features was easier, and took only a few minutes to figure out, without googling for help or reading any Product Updates info. And to me that’s pretty sweet! =)

Programmatically set navigation settings in SharePoint 2013

When working on a project where I needed to set the navigation for newly created sites programmatically, I had a hard time finding the correct properties and methods in the SharePoint object model to change all the navigation settings. After some researching I found that you need no less than 3 different objects representing the navigation of a website to be able to modify all the settings. These examples apply to SharePoint sites with publishing features enabled (navigation options differ on non-publishing sites), and just using the PublishingWeb.Navigation and WebNavigationSettings objects were sufficient for me. Other properties can be found in the SPWeb.Navigation object however.

These are the objects containing navigation properties:

  • web.Navigation (Namespace: Microsoft.SharePoint)
  • publishingWeb.Navigation (Namespace: Microsoft.SharePoint.Publishing)
  • WebNavigationSettings (Namespace: Microsoft.SharePoint.Publishing.Navigation)

Here are examples of how you instantiate these objects:

// Web Navigation
using (var site = new SPSite("http://somesite"))
using (var web= site.OpenWeb())
{
 var navigation = web.Navigation;
}

// PublishingWeb Navigation
var pubWeb = PublishingWeb.GetPublishingWeb(web);

// WebNavigationSettings
var webNavigationSettings = new WebNavigationSettings(web);

Once instantiated, you will be able to modify the navigation using these objects. I will show some examples of how to set different options on the Navigation settings page on a publishing site through code.

Select type of navigation

GlobalAndCurrent

There are two navigations. The Global navigation (also called Top navigation) and the Current navigation (also called left navigation or quicklaunch). Both of these can be set to different to use different sources. They can inherit from their parent (if a subsite only), use managed navigation, or structural navigation. All you need to do is select the webNavigationSettings object, choose which navigation to set, and select a source for that navigation.

webNavigationSettings.GlobalNavigation.Source = StandardNavigationSource.TaxonomyProvider;
webNavigationSettings.GlobalNavigation.Source = StandardNavigationSource.InheritFromParentWeb;
webNavigationSettings.GlobalNavigation.Source = StandardNavigationSource.PortalProvider;
webNavigationSettings.GlobalNavigation.Source = StandardNavigationSource.Unknown;
webNavigationSettings.CurrentNavigation.Source = StandardNavigationSource.Unknown;

TaxonomyProvider is Managed Metadata Navigation, PortalProvider is structural navigation, InheritFromParentWeb is self-explanatory, and Unknown leaves no radiobutton selected.

Show subsites and pages

To change these options you need to use the PublishingWeb object.

ShowSubsitesAndPages2

pubWeb.Navigation.CurrentIncludeSubSites = false;
pubWeb.Navigation.CurrentIncludePages = false;
pubWeb.Navigation.CurrentDynamicChildLimit = 20;

Managed navigation: Page settings

To change the values of these two checkboxes, use the WebNavigationSettings object again.

DefaultPageSettings

webNavigationSettings.AddNewPagesToNavigation = false;
webNavigationSettings.CreateFriendlyUrlsForNewPages = false;

Managed navigation: Term set

To connect to a term set in code you can do something like this.

MetadataNavigation

// Below code has to be used from within a method of course.
var session = new TaxonomySession(web.Site);
if (session.TermStores.Count != 0)
{
    var termStore = session.TermStores["MyTermStoreName"]; // Standard name is "Managed Metadata Service"
    var group = this.GetTermGroupByName(termStore.Groups, "MyTermGroupName");
    var termSet = this.GetTermSetByName(group.TermSets, "MyTermSetName");
    webNavigationSettings.GlobalNavigation.TermStoreId = termStore.Id;
    webNavigationSettings.GlobalNavigation.TermSetId = termSet.Id;
}

// Support methods
private Group GetTermGroupByName(GroupCollection groupCollection, string name)
{
    foreach (var group in groupCollection)
    {
        if (group.Name == name)
        {
            return group;
        }
    }
    return null;
}

private TermSet GetTermSetByName(TermSetCollection setCollection, string name)
{
    foreach (var set in setCollection
    {
        if (set.Name == name)
        {
            return set;
        }
    }
    return null;
}

Structural navigation: Sorting

Use the PublishingWeb.Navigation to set the ordering of the Structural navigation.

Sorting

pubWeb.Navigation.OrderingMethod = OrderingMethod.Automatic;
pubWeb.Navigation.AutomaticSortingMethod = AutomaticSortingMethod.Title;

Update
Finally, don’t forget to update your objects when you are done with them.

webNavigationSettings.Update();
pubWeb.Update();
web.Update();

These examples are not a complete overview of what you can do with the navigation in SP2013, but the objects I have shown contain most of the properties needed to set the navigation. You just have to look at the object model in Visual Studio to find other options, and most are pretty self-explanatory.