Display Templates – Colour Picker

Following on from my recent post which explores the potential of using Display Templates with Site Columns I wanted to expand on that concept with another idea that has proved a challenge in SharePoint – a colour picker.

There are several times in the past I have wanted to allow a user to choose a colour – perhaps for a particular category in a list driven menu. Display Templates let me do just this.

Site Column
Name: ColourPicker
Type: Single line of text

As usual, you can give this a friendly display name by editing after it has been created, but that is all you need to do for the site column. It is ready to be added to any list or library and will hold the hex value of the selected colour.

Display Template
You can get the full Display Template . Note that I have extended the basic concept to also display the RGB values just in case you need them. As is my usual approach I have saved my file into a custom folder inside my Style Library.

The invertColour function simply lets me show the hex value in display mode using a contrasting colour to the background which is my selected colour.

paylord.colourPicker.invertColour = function(hexTripletColor) {
    var color = hexTripletColor;
    //color = color.substring(1);         // remove #
    color = parseInt(color, 16);          // convert to integer
    color = 0xFFFFFF ^ color;             // invert three bytes
    color = color.toString(16);           // convert to hex
    color = ("000000" + color).slice(-6); // pad with leading zeros
    //color = "#" + color;                // prepend #
    return color;
}

To be able to show the RGB values of my selected colour, I also need to convert from hex:

paylord.colourPicker.hexToRgb = function(hex) {
    // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
    var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
    hex = hex.replace(shorthandRegex, function(m, r, g, b) {
        return r + r + g + g + b + b;
    });

    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
    } : null;
}

So now I bring those together with a template to display the selected value in view mode:

paylord.colourPicker.colourViewTemplate = function(ctx) {
	var colour = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
	if (colour == "") {
		colour = "353535";
	}
	
	if (colour[0] == "#") {
		colour = colour.substring(1);
	}
	
	var rgb = paylord.colourPicker.hexToRgb(colour);
	var title = "";
	title = "R:" + rgb.r + " G: " + rgb.g + " B:" + rgb.b;
	
	var fontColour = paylord.colourPicker.invertColour(colour);

	var ret = "<div title='" + title + "' style='background-color: #" + colour + ";color:#" + fontColour + ";padding: 0px 5px;'>" + colour + "</div>";
	return ret;
}

So now to focus on setting the colour. What I want to do is grab the current value or set a default if it is blank then ensure I set the class so my field is recognised by the colour picker:

paylord.colourPicker.colourEditTemplate = function(ctx) {
	var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx); 
	formCtx.registerGetValueCallback(formCtx.fieldName, paylord.colourPicker.getFieldValue.bind(null, formCtx.fieldName));
	var elId = "paylord-" + formCtx.fieldName;
	
	var colour = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
	if (colour == "") {
		colour = "#353535";
	}
	var ret = "<input id='" + elId + "' class='color' value='" + colour + "'>";
	return ret;
};

And finally, I register my templates:

(function () {
	var colourCtx = {};
	colourCtx.Templates = {};
	colourCtx.Templates.Fields = {
		"Colour": {
			"View": paylord.colourPicker.colourViewTemplate,
			"DisplayForm": paylord.colourPicker.colourViewTemplate,
			"EditForm": paylord.colourPicker.colourEditTemplate,
			"NewForm": paylord.colourPicker.colourEditTemplate
		}
	};
	
	SPClientTemplates.TemplateManager.RegisterTemplateOverrides(colourCtx);

})();

Colour Picker Script
For the purposes of this example, I decided to go with a pure JavaScript colour picker rather than one dependent on jQuery. There are many to choose from out there so feel free to experiment and find one you like. I went with which is really easy to interface with as all I had to do was give the input field a class of “color”.

PowerShell
In this case, our template needs both the Display Template and the JSColor script so this introduces the ability to add multiple scripts to our Site Column. It is just the same as before but we separate each script we want to reference with a pipe ¦ character:

$web = Get-SPWeb "http://sitename"
$field = $web.Fields["ColourPicker"]
$field.JSLink = "~sitecollection/Style Library/custom/jscolor.js¦~sitecollection/Style Library/custom/ColourPicker.js"
$field.Update($true)
$web.Dispose()

The Resulting Column in Action

Colour Picker showing RGB hover text

Colour Picker showing RGB hover text

Colour Picker Showing Picker

Colour Picker Showing Picker

So here is the resulting column in display mode and edit mode. When you click on the input in edit mode then the colour picker appears and lets you choose the colour you like which then stores the hex value in the text field.

JSLink Property
Being able to add the JSLink through the standard browser interface settings for the site column would make this whole approach so much more flexible so I have raised it as a suggestion on User Voice – please add your vote.

Posted in SharePoint | Tagged , , , , | Leave a comment

Display Templates for Site Columns – Harvey Balls

So one of the little things with XSL that has bugged me is that it seems harder to change just one column than it should be – and of course, you have to apply the XSL every time you want a view to be changed. I have recently managed to spend a bit of time taking a look at 2013 Display Templates and I was very excited to find that this resolves both of these issues by allowing a Display Template to be attached to a Site Column.

This means that every time that Site Column is added to a list, your custom Display Template will be applied to it – very nice.

But the goodness does not stop there. Within the Display Template you can also change how the column appears depending on what you are doing with it – so in create or edit mode it can look completely different to view or display mode. This opens up a whole range of exciting possibilities.

Sitting at Auckland airport after the New Zealand SharePoint Conference last month I had the pleasure to sit and discuss this with Marc Anderson who wondered if it was possible to show Harvey Balls in this way. Well that seemed like an opportunity too good to miss so here we go.

Site Column
Firstly we need to create our Site Column. I am going to assume you know how to create a site column but the properties we need are below:
Column Name: HarveyBalls
Type: Choice
Choices: 0, 1, 2, 3, 4
Display Using: Radio Buttons

Good start. What I usually do is then edit the Site Column and change the Name to a more friendly display name – in this case: Harvey Balls.

So, our column at this point is ready to be added to any list or library but will simply display as a radio button offering the choices from 0-4.

Display Template
Again, there are some great blogs and articles out there on the basics of creating Display Templates so I am not going to go into too much background.

My first attempt used Unicode characters which was nice and simple but did not look great. A CSS version of Harvey Balls added a tiny bit more complexity to the script but looked much better.

My Display Template can be found on GitHub and that is definitely the best way to grab a copy for your own use. I will also not try quoting the full script here as it never seems to play nicely!

First we define our namespace and a function to display our field. Within this function we have an array with 5 options to match our choices (0-4) which are actually the CSS classes we want.

var balls = ["harvey", "upper-right", "harvey half-right", "three-quarters", "harvey black"];

We then get the current selected value of our field which will be 0-4 and just to be safe set it to 0 if it is empty:

var ball = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
if (ball == "") {
	ball = 0;
}

A string is then constructed containing a DIV with the class set to the value from our array which matches the choice value:

var ret = "";
switch (ball) {
	case "1":
		ret = "<div class='harvey'><div class='" + balls[ball] + "'><i></i></div></div>";
		break;
	case "3":
		ret = "<div class='harvey black'><div class='" + balls[ball] + "'><i></i></div></div>";
		break;
	default:
		ret = "<div class='" + balls[ball] + "'><i></i></div>";
		break;
};

Our string is then returned and this HTML is what is put on the page to represent our Site Column.

I chose to make the Display Template completely standalone so the next section in the script adds the required CSS to the page to present our Harvey Balls. This could also just be added to a standard CSS file.

Finally, we define template object and register it with SharePoint:

var fieldCtx = {};
fieldCtx.Templates = {};
fieldCtx.Templates.Fields = {
	"HarveyBalls": {
		"View": paylord.harveyBalls.viewFieldTemplate,
		"DisplayForm": paylord.harveyBalls.viewFieldTemplate
	}
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(fieldCtx);

Note that in this case we are only changing the way the field looks in view and display modes.

These scripts can be saved anywhere but I usually add them to a custom folder in my Style Library.

PowerShell
Now, unfortunately Microsoft seem to have forgotten to add the JSLink property to the UI of Site Columns so the simplest way to link our script to our Site Column is a few lines of PowerShell:

$web = Get-SPWeb "http://sitename"
$field = $web.Fields["Harvey Balls"]
$field.JSLink = "~sitecollection/Style Library/custom/HarveyBalls.js"
$field.Update($true)
$web.Dispose()

I have simplified the PowerShell here but the GitHub version linked above will prompt for the values it needs. Main thing to note here is the “~sitecollection” element as part of the path – make sure you include this or one of the other alternatives depending upon where you have saved the file. Relative paths and even full paths do not seem to work well.

Summary
That is it! You can now add your Site Column as usual to any list or library, be able to choose 0-4 from the radio button and this will then be displayed as the related Harvey Balls icon when in view or display mode.

Harvey Balls

I will definitely being doing some more of these so watch this space!

Posted in SharePoint | Tagged , , , , | 1 Comment

SharePoint Conference Australia and Auckland

I did some work recently with a client who had really embraced social technologies and made excellent use of them, particularly Yammer, within the organisation. They had a number of different groups in Yammer including one that was used for non-work related content such as sales and wants, team BBQs etc – what a great idea!

However, when we came to integrate such social feeds into their SharePoint intranet homepage it raised a whole collection of interesting challenges.

This will be the topic I am presenting at the SharePoint Conferences in Sydney and Auckland coming up in July 2013. If you are there then do come along and say hello. I will also make sure to add my slides here after the conferences just in case there are any who are interested but cannot make it.

Hope to see you there :)

Posted in SharePoint | Tagged , , , , , , | Leave a comment

Power View and Marine Rescue on SP24

I will be presenting a session at SP24 on Power View using Marine Rescue Data.

https://www.sp24conf.com/2014-1/Conf/SP24S026/ConfPages/SessionRoom.aspx

The presentation is available here

Hope to see you online.

Posted in SharePoint | Tagged | 2 Comments

Office 365 at Marine Rescue Queensland

Read more about how Marine Rescue are using Office 365 to share documents and training materials to improve safety across Queensland – http://www.obs.com.au/AboutUs/Hot-Topics/Pages/Can-Office-365-Assist-Marine-Rescue-Queensland.aspx

Posted in SharePoint | Tagged , , | Leave a comment

Content Types and Hidden Columns

When working with list or libraries, it is often a requirement to have a column that can be set automatically, perhaps by a workflow, but which you do not want users to be able to manually change. When creating a content type, each site column can be set to Required, Optional or Hidden. This can be set at the content type level or at the library level.

If the site column is left as Optional and then the content type is added to the library, the column is correctly added to the library and can be used as required and set to Hidden through the content type within the library settings. This ensures it does not appear in forms so applies a degree of protection against users changing it manually.

If this content type is added to one or more lists or libraries and then the site column is set to hidden at the content type level then this setting will be inherited by all the lists or libraries using that content type.

However, if the site column is set to hidden at the content type level before the content type is added to the library then this is where a problem arises. The column is not visible from the list settings, nor in the content types in the list settings. It is not available in views nor in filters nor sorts. However, if you try to add the site column manually then you will find it is not available to be added – because it has actually been added already as part of the content type.

A logical thought at this point would be to go back to the content type level and change the site column to Optional or Required. Sadly changing this does not seem to be inherited by the list.

My response at this stage was to resort to PowerShell – because that can do anything right?

$web = Get-SPWeb
$list = $web.Lists["List Name"]
$col = $list.Fields["Column Name"]
$col.Hidden

This will show True – so our problem is that the column has been added as hidden. You may think this is what we wanted but in fact the problem is that the column is hidden at the list level rather than at the content type level.

The easy option seemed to be:
$col.Hidden = $false

Sadly this fails as it is not allowed.

Another thought was to try changing the content type within the list through PowerShell:

$ct = $list.ContentTypes["Content Type Name"]
$field = $ct.FieldLinks["Column Name"]
$field.Hidden = $false

This succeeds – but sadly makes no difference.

So what about deleting the offending column?

$col.Delete()

Nope – this fails too as you cannot delete a column which is hidden – but you cannot unhide it . . .

So we now have a column in our list that we cannot use as we want to and we cannot even delete using PowerShell – or can we?

After a bit of fiddling and some suggestions from Microsoft we finally found a way to get rid of the column:

$col.AllowDeletion = $true
$col.Sealed = $false
$col.Delete()
$list.Update()

Phew! Note that even though the column will say Sealed is False, you must set it to false as above – no idea why so if you have suggestions please let me know.

Microsoft has managed to reproduce this and is deciding whether or not it is a bug – I will keep you informed.

Posted in SharePoint | Tagged , , , , , , , , , | 1 Comment

Granular Permissions on SharePoint Libraries

In most circumstances the standard “Contribute” permission level hits the spot. It allows users to add new documents, edit existing ones and delete any no longer needed.

However, there are times when you may need something else. Perhaps you do not want users to be able to delete documents?

In SharePoint it is easy enough to create new permissions levels – I usually copy the Contribute and then delete the options I no longer want. CRUD is the acronym often associated with permission levels:

C = Create
R = Read
U = Update
D = Delete

Read will always be granted for one of the other levels so I generally just go for Create, Delete and Edit – edit being a more SharePoint consistent term than update.

All good so far, but what happens when you apply these different levels on a library?

You will hopefully already be familiar with the process of uploading a document into SharePoint; the way you select or drag the document, watch it whir away for a moment then get the form prompting you for any metadata, such as the Title column. Usually you fill this in and click save and hey presto there is your document in the library. Great!

If you grant a user Create permission only, you would probably expect that process to remain the same. Wrong!

The first bit all goes well and the form pops up. If the user then types in a Title for example, when they click save they get a permission error – but the document is actually in the library . . .

It seems this is actually a two stage process. The Create permission allows you to load the document into the library and it is only after this point that the form pops up – so at this stage you now need Edit permissions. This means that if you have required metadata fields, users who only have Create permissions will never be able to check them in, and users who only have Edit permissions will never be able to upload them.

There is another oddity that you should also be aware of related to the Delete permission level.

When you upload a document through the standard browser interface, if it has a trailing space in the file name eg ‘FILE .DOCX’ then SharePoint will automatically trim out that space and all will be fine. If you use the Save As method to get the above document into the library then it does not trim it. Now when a user who does not have Delete permissions tries to edit the metadata, SharePoint tries to automatically remove that offending space character – but for some reason it seems to try to delete the old document and replace it with the new one – so again that permission error comes up – though somewhat confusingly for the user, assuming they have edit permissions any metadata changes have been saved. Note that in this circumstance, SharePoint does not let you delete the trailing space through the standard form interface – essentially renaming the document. In fact you will not even be able to tell it is there. The easiest way around this seems to be to open the library in Explorer mode and from there you can see the trailing space and rename the document – always assuming you have permissions of course.

Have fun.

Posted in SharePoint | Tagged , , , , , , | 2 Comments