Category Archives: HTML and JavaScript

Creating a picture library slideshow using jQuery Cycle2 and the SharePoint framework

In this post, I wanted to show how you can modify the SharePoint framework Hello World web part and add other custom JavaScript libraries to create a simple slideshow.

spfx

Prerequisites

I’m going to start my tutorial after following these steps:

Setup SharePoint Tenant
Setup your machine
HelloWorld WebPart
HelloWorld, Talking to SharePoint

Once that is all working fine, you should have something that looks like this:

spfx-slideshow01

Note: In the solution below, I have removed some of the HTML rendered in the SolutionNameWebPart.ts file (optional):

this.domElement.innerHTML = `
<div class="${styles.solutionName}">
  <div class="${styles.container}">
    <div id="spListContainer" />
  </div>
</div>`;

Pull in images from SharePoint picture library

Create a picture library in your SharePoint site called “Slideshow”. Upload a couple of images into this library for testing purposes.

Inside your project, open up SolutionNameWebPart.ts (found inside your WebPart folder). Change the REST API call so that the picture library item URLs are fetched. Currently the REST query (found in the _getListData function) is pulling list and library names, change it to:

this.context.pageContext.web.absoluteUrl + "/_api/web/lists/GetByTitle('slideshow')/Items?$select=EncodedAbsUrl"

This will return the picture library item URLs.

Add the EncodedAbsUrl as a string to the ISPList object:

export interface ISPList {
  Title: string;
  Id: string;
  EncodedAbsUrl: string;
}

In the “_renderList” function, change the item loop to this:

items.forEach((item: ISPList) => {
   html += `<img src="${item.EncodedAbsUrl}" alt="image" />`;
});

This will now use the EncodedAbsUrl as the image location. Running this using gulp serve should now show the images from the picture library. You may want to add in some mock data for local tests.

spfx-slideshow02

Making it responsive

The images are rendered at their actual size. Some CSS is required to make the images responsive. Add the class ${styles.cdbImage} to the image tag.

html += `<img src="${item.EncodedAbsUrl}" class="${styles.cdbImage}" alt="image" />`;

Open the SolutionName.module.scss file and add the following code inside the last brace.

.cdbImage{width:100%;height:auto;}

Serve the files again and the images will now be responsive.

spfx-slideshow03

Adding jQuery and Cycle2

Download using Node Package Manager

When adding common JavaScript libraries to projects, Node Package Manager is an excellent tool to quickly bundle items. Run the following nodeJS package manager commands:

npm install jquery

npm install jquery-cycle-2

Two extra folders are now created under “node_modules”.

Install TypeScript definitions

In order to use these libraries in TypeScript, a definition file is required for IntelliSense and compilation. jQuery can be added via the TypeScript definition tool in the nodeJS command line:

tsd install jquery –save

jQuery Cycle2 is not available via this command line but can be downloaded from here:

Github jQuery TypeScript

Download it and add it to a new folder called jquerycycle under the “typings” folder. The typings folder contains all the TypeScript definition files. jQuery has automatically been added here. However we need to manually add the Cycle2 definition.

In the root of the typings folder, open the file named tsd.d.ts. This file controls all the definitions which are used in the project. jQuery has already been added, manually add a new line for jQuery Cycle2.

/// <reference path="jquery/jquery.d.ts" />
/// <reference path="jquerycycle/jquery.cycle.d.ts" />

Add libraries to project

Open the config.json file (under the config folder) in the project. This lists all the external references. jQuery and Cycle2 need to be added here so they can be used in the project. In the “externals” section, add:

 "jquery": "node_modules/jquery/dist/jquery.js",
 "jquery-cycle": "node_modules/jquery-cycle-2/src/jquery.cycle.all.js"
 

The libraries can now be included in the project. Go back to the solutionNameWebPart.ts file and add:

import * as myjQuery from 'jquery';
require('jquery-cycle');
 

The object myjQuery should be a unique name for your project to avoid conflicts. jQuery cycle is added using require as it has a dependency on jQuery.

At the end of the _renderList function in the web part class, add the following code to initialise the slideshow:

myjQuery( document ).ready(function() {
    myjQuery('#spListContainer').cycle();
});
 

Refreshing the page, should now give you a responsive slideshow.

spfx

Issues with the new SharePoint interface for document and picture libraries

Let’s start with the positive aspects of this new interface. It’s responsive and integrates really well into the OneDrive app for mobile devices. However there are currently a number of setbacks for users when switching to the new look interface. Users should consider it carefully before turning the new interface on at tenancy level or on a per user basis.

New Document and Picture Library

No JS Link property

Microsoft have mentioned that there is still some functionality to roll out, however they have not been specific about what that will include. A large number of businesses use JS Link to highlight data in a list or library and to add some custom actions at the item level. This is done using the Microsoft best practices of using client side JavaScript, however we are still awaiting this functionality in the new interface. New features are being added to the new interface such as content types and custom columns so we can only hope that this will also be added before the full implementation of the new interface in 2017.

No JS actions to brand the interface

A while ago I blogged about using JS instead of custom master pages to brand the look and feel. Again this is client side code and was Microsoft best practice, however this doesn’t seem to apply to the new view. The new look interface despite being modern and minimalist is bland and unbranded. Most companies/schools want branded intranets, they are always keen to get away from the “SharePoint” look. Although the new interface is modern and responsive, all of the pages look the same and it is possible that we will fall into the trap of looking like SharePoint again. Theming engines do not offer the bespoke customisation that most users require. The future of SharePoint event and videos did mention a chrome as part of the SharePoint framework so we can only hope that this is exposed to JS developers.

No image link in picture libraries

On occasions users require a link to a document or image inside a library. This used to be easy for users to do, open it up and copy the URL. This is no longer possible for an image library as each image opens up in a lightbox view. There are no options to get a link to the exact image, in fact there is an option called “get a link” but this shares the image and changes the permissions rather than giving a URL link (for users to use on a site or email).

These are the initial issues I have found with the new look interface. It seems to be have been rushed out to tenancies without investigation into how customers use library views within SharePoint. Although there is a benefit having a similar interface to OneDrive and having it work as a single page application, the fact that it is part of a SharePoint site and has that extra SharePoint functionality makes it usable to end users. The new views will run side by side until 2017, hopefully by then Microsoft will have resolved the issues and released the new SharePoint framework for Microsoft partners (due to go live in autumn 2016) to get developing branding and custom JS solutions.

UPDATE: 08/07/2016

Microsoft have released this update confirming that there is still functionality to be added to the new user experience. Looks very positive for JS links and other missing functionality: http://dev.office.com/blogs/update-on-modern-document-libraries-and-extensiblity

The future of SharePoint

The future of SharePoint event took place last night live from San Francisco. It was a live online event open to all which was watched by thousands of SharePoint fans across the globe. Microsoft renewed its commitment to SharePoint and the SharePoint brand by announcing the renaming of the sites tile in Office 365 to SharePoint and the release of a new SharePoint mobile app.

SP2016mobileteamsite

It was a very exciting glimpse into the future of SharePoint (both on-premises and online). A completely new revamped UI for team and publishing sites and a slick editing experience. One of the flaws with the current SharePoint experience is the inheritance of older SharePoint site templates and libraries which has only incrementally improved over time. Frustratingly this has left users with a poor mobile experience and a clunky, more complex editing process. Even the current SharePoint 2013 mobile site looks more like an ancient WAP site designed for a Nokia 7110. Below is a sneak peak as to what the new team site may look like. Above is a preview of the new SharePoint app.

SP2016teamsite

New document library experience

This has already rolled out to some tenancies. It gives a fresh look to document libraries which puts them in-line with the OneDrive experience and the SharePoint mobile view. The classic view will still be supported if you are using JS client side rendering, workflows or specific custom views. One downside to the new experience is the loss of any branding, however you could add document libraries to pages if you wanted to keep this. Users can pin files to the top of the page and get really nice previews of documents. Administrators can override end users to choose either the classic or new view of document libraries (see details here).

Design and development

The new improvements in the interface mean not only a fully responsive design but also a mobile app experience on iOS, Android and Windows. SharePoint is also moving away from the iframe app part model allowing more fluid and responsive web parts. For designers and developers there is now a new SharePoint framework (to be released later this year) which doesn’t depend on Visual Studio or any server-side development. Using JavaScript open source libraries we will soon be able to create design experiences which apply to both the browser and mobile apps.

There was several indications that design was moving this way over the last few years. Check out my earlier posts on moving from custom master pages to JS actions and client side rendering. Using these client side technologies was the first step in preparing ourselves for the new client side rendering experience for the next generation of SharePoint portals. I’m very excited to get stuck into the new SharePoint framework technologies (please release it soon Microsoft!). If you can’t wait to get started, you can start by learning the new technologies which will be used to develop against the SharePoint framework such as nodejs, Yeoman, Gruntjs and all the open source JavaScript frameworks which interest you. There is a good post on how to get hold of all these applications and packages on this blog post by Stefan Bauer. You can also view the full development lifecycle processes that Microsoft recommend in their latest video previewing the new framework below.



Microsoft Flow

Microsoft Flow is a new tool in the SharePoint toolbox. It’s a new way to get data into SharePoint and perform workflows using custom logic. It doesn’t replace InfoPath or SharePoint Designer but I can see many uses for it in a business process environment and sales. It extends workflow functionality out of SharePoint using templates or custom written apps. For examples you can have a flow which picks up tweets from Twitter and puts them into a SharePoint list. Very interesting to see how this product develops with SharePoint. You can find out more on the flow website.

Microsoft PowerApps

Create your own mobile apps in a few simple steps from lists and libraries in SharePoint without having to write any code. This could be a mobile app or just a web app. In fact you can do this from the browser from any list in a few simple steps. This could be a SharePoint list view or a web part. The PowerApps will be available from within the SharePoint app. I’m assuming you will be able to pin these apps to your start screen like you can with OneNote notebooks and pages. You can find out more about Power Apps on the website.

More updates to come…

How to stop using custom master pages when branding SharePoint



With the rise of Office 365 and SharePoint online, the ancient practice of using a custom master page to brand a SharePoint site is coming to an end. SharePoint online has many incremental changes, bug fixes and improvements to the Seattle master page meaning that if you have taken a copy of this Master Page to apply your branding, you could be missing out on the constant evolution of SharePoint online.

Custom Master Pages can still be used but Microsoft recommend against this now. The good news is that we can make exactly the same branding changes without having to use a custom master page.

I will briefly mention that you can create themes for SharePoint very quickly using Microsoft’s free tool which can be downloaded from here. Great for quick colour palettes and background images but not great if you want a responsive or more custom design.

Custom master pages (for branding purposes) tended to have a small number of adjustments such as:

  • Custom HTML (maybe for a menu container)
  • Links to CSS files (for responsive styling and branding)
  • Links to JavaScript files (for use of jQuery and additional libraries)

Link to custom CSS file

A link to a custom CSS file is recommended for advanced branding changes. This won’t affect any improvements to the default Seattle master page however you may need to update the CSS from time to time to reflect any interface changes. The alternative CSS link can be set via the GUI on a publishing site or by CSOM on any site.

As a designer, you will be aware that you can’t do everything in CSS such as placeholders for menus or other interactive content or run JavaScript.

Inject JavaScript

JavaScript and HTML plays a big role in most branding exercises. It could be DOM manipulation, a responsive menu, sliding effects or responsive background slideshows and JavaScript tends to be a requirement on most projects. Luckily there is some more good news, JavaScript can be added to a site without editing the Master Page by adding custom actions.

You should already be storing JavaScript in external files (in the Style Library) rather than embedding on the master page. So the only change is to inject these JavaScript files rather than reference them on the MasterPage. This can be done via CSOM (I use the PowerShell method).

#Run all of your lines to load the context of the site collection
$context.Load($site)

#add custom js injection action
$customJSAction = $site.UsercustomJSActions.Add();
$customJSAction.Location = “ScriptLink”;
#reference to JS file
$customJSAction.ScriptSrc = “~SiteCollection/Style Library/JS Display Templates/test.js”;
#load it last
$customJSAction.Sequence = 1000;
#make the changes
$customJSAction.Update();
$context.ExecuteQuery();

You can use the same objects to remove all the custom actions and list them. You can find out more information and the C# examples here.

Conclusion

Although this is a different way of thinking about branding, in the long run, it’s cleaner and more reusable than custom master pages. Your customers will have a better experience in Office 365 but even CSS and DOM manipulation may need updating as SharePoint evolves.

Some really useful examples and more detailed explanations can be found on Vesa Juvonen’s Ignite talk. In Vesa’s example he uses Visual Studio and Apps to deploy the CSS and JS.

In the video at the top of the post, I quickly go through the process of setting alternative CSS and JavaScript custom actions.

How to embed a Twitter widget on a SharePoint page

Many schools and businesses are using twitter as a social communication platform to send out news and information to users. How to embed twitter feeds on SharePoint intranets and public sites has been a popular question recently so thought I would share with you how it is done. I’ve also created a video guide on YouTube to talk through the process.

First login to your twitter account in a browser on a desktop computer (it doesn’t have to be the same account as the one that you want to display in your widget).

Click on your profile picture in the top right of the screen and select “Settings” from the drop down menu.

Twitter

Select “Widgets” from the left side menu.

Twitter

Create a new widget.

Twitter

Choose your design and configuration. More options are available via the customisation documentation link on the page. Click “Create Widget” to generate the code.

Twitter

Copy and paste the code into a Script Editor web part. The Script Editor web part can be found under the “Media and Content” category.

Twitter

I go through the process in more detail in the video below. Hope you find it useful. For SharePoint support and consultancy please contact me at Cloud Design Box.



How to render display template on a list view

This blog post is a bit more technical than my previous entries. Just recently, I was required to show two different views of a list on the same page (both styled with JS Display Templates). It’s relatively straight forward when you know how to quickly get the view GUID from the web part.

JS Display template only applying to one web part

You may have seen in other posts that you can get the GUID of a view by going to the edit view page and grabbing it from the URL encoded string. However this doesn’t always work for web parts added to the page as they tend to get thier own unique “current view”.

There is a really easy and quick way of finding this GUID using an alert in your JavaScript Display Template. When you are working with the current list object, in my example below “ctx”, you can get the view GUID from this object by calling “ctx.view”. Wrap that up in an alert and the alerts will render from top to bottom on the page and display each web part view GUID.

alert(ctx.view);

Once you have the GUID, use another if statement in your code to set the base view id. Now your JavaScript only applies to that one view for the list.

if (ctx.view === "{07BC665B-0274-42D2-97BF-8EBEA8B72436}") {
	//Override the BaseViewID if it's the one we want.
	ctx.BaseViewID = 722;                
}


List subsites using the JavaScript client object model in SharePoint 2013

SharePoint Office 365 Site Creation JavaScript

To do this, use the script editor web part or the page viewer web part (and put the HTML file in a document library).

To start off, setup the HTML to include jQuery and sp.js (see below).

SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
 //alert('loaded');
});

JQuery functions are used to populate HTML containers on the page.

<div id="tonycontent">
	<!-- Dashboard -->
	<div id="tonydashboard" class="tonycontenttable">
	</div>
</div>

The first function loads the current site. The get_current function returns the current context of the user from which the subsites can be retrieved (see below).

function getSubWebs(){
	clientContext = new SP.ClientContext.get_current();
	web = clientContext.get_web();
    	webCollection = web.getSubwebsForCurrentUser(null);
    	clientContext.load(webCollection);
    	clientContext.executeQueryAsync(onGetSubwebsSuccess, onGetSubwebsFail);
}

If the query is successful it will load the onGetSubwebsSuccess function, otherwise it will run onGetSubwebsFail function.

In the success function, the webCollection variable is looped through to retrieve the URL and the title of each subsite. JQuery functions are then used to append the HTML containers.

function onGetSubwebsSuccess(sender, args){
	jQuery("#tonydashboard").empty();
	var html4 ="<div class='tonycontenttablerow'><div class='tonycontenttabletitle'>Site Name</div><div class='tonycontenttabletitle'>Site URL</div></div>";
	jQuery("#tonydashboard").append(html4);
    var webEnumerator = webCollection.getEnumerator();	
    while (webEnumerator.moveNext()){
        var web = webEnumerator.get_current();
		var webtitle = web.get_title();
		var weburl = web.get_serverRelativeUrl();
        var html3="<div class='tonycontenttablerow'><div class='tonycontenttablecolumn'>" + webtitle + "</div><div class='tonycontenttablecolumn'>" + weburl + "</div></div>";
		jQuery("#tonydashboard").append(html3);
    }
}

Download the full code here

The client object model can also be used to create subsites from templates, permission sites, create lists and much more! This method works on both 365 SharePoint Online and SharePoint 2010 and SharePoint 2013 on-premises.

SharePoint 2013 JavaScript Client Object Model

JavaScript Client Object Model in SharePoint 2013

SharePoint 2013 has a new and more complete JavaScript Client Object Model API. Some of the additional functionality is using social networking.

Using the JS COM, followers can be pulled from SharePoint for the current user or a specific user. This might be used for creating a new social networking interface

My Followers

First load JQuery and the SharePoint 2013 JavaScript functions. The JavaScript functions are loaded on the page so it is just a case of waiting for specific functions to be loaded before the script will work correctly (see below):

SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
	SP.SOD.executeFunc('userprofile', 'SP.UserProfiles', function () {
		tonyishereGetUserProfileProperties();
	});
});

Once the functions are loaded, the People manager object can be created. The example below was taken from the Micrsoft site and modified, this is a great resource if you are starting out with the client object model.

http://msdn.microsoft.com/en-us/library/office/jj679673.aspx

function tonyishereGetUserProfileProperties() {
    // Get the current client context.
    var clientContext = SP.ClientContext.get_current();
    // Get the PeopleManager instance.
    var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
    // Get the people who are following the current user.
    Followers = peopleManager.getMyFollowers();
    clientContext.load(Followers);
    // Send the request to the server.
    clientContext.executeQueryAsync(displayFollowers, requestFailed)
}

Once the object has been loaded successfully, functions can be run to pull out the required data. In the example below, the data is stored in a string which is then displayed as HTML in a div using JQuery.

function displayFollowers() {
    var results = Followers.getEnumerator();
	var myFollowers = "Followers<br />";
    while (results.moveNext()) {
    var person = results.get_current();
		myFollowers = myFollowers + "<br />" + person.get_displayName();
    }
	jQuery("#MyFollowers").html(myFollowers);
}

The script was added to the page without the use of Visual Studio or SharePoint Designer 2013. The script was inserted using the Script Editor web part. This web part runs client side code such as HTML and JavaScript.

Script Editor

The same methods can be used to pull out a whole host of data from the social aspects of SharePoint 2013 including the profile picture, display name, hash tags and trending topics.

Profile web part

Client-side RSS feed viewer using JavaScript

There are plenty of server-side RSS feed viewers out there but very little in the case of client-side JavaScript based viewers. Below I will go through the steps of creating a simple JavaScript based RSS feed viewer. Please note that this will only work with RSS feeds on the same domain. JavaScript does not allow cross domain scripting. You may find ways round this by using some of the Google API.

RSS Viewer
Create HTML Container

First begin by creating a HTML div container with a unique ID.

<div id="myDiv"></div>

Make a XML HTTP Request

The following function returns the data from an RSS (XML) page. As far as I am aware there is no way to use this cross domain, so you will have to look for a server-side script to work cross domains.

function httpGet(theUrl) {
			var xmlHttp = null;
			xmlHttp = new XMLHttpRequest();
			xmlHttp.open("GET", theUrl, false);
			xmlHttp.send();
			return xmlHttp.responseXML;
		}
var rssFeedData = httpGet('http://www.tonyishere.co.uk/RSSExample/rss.xml');

Loop through the data and retrieve tags by name

Once this data has been stored in the variable as an object, we can use the “getElementsByTagName” function to pull out a particular tag (title in this case). Looping through all the tags called “title” will go through all of the XML from top to bottom. While looping through the tags, we can store the title and description in arrays to use later.

			var i=0;
			var allTitles = [];
		var allDescriptions = [];
			// loop through all of the items and put them in arrays
			while (rssFeedData.getElementsByTagName("title")[i])
			{
					allTitles[i] = rssFeedData.getElementsByTagName("title")[i];
					allDescriptions[i] = rssFeedData.getElementsByTagName("description")[i];
					flag=i;
					i=i+1;
			}

Loop through the arrays and render the data

Looking at the structure of the XML, you should be able to pick out the child nodes. In this case, each item is the first node (numbering starts from 0).

This can then be rendered as HTML and inserted into the div created earlier. In the example below I have decided to store the description and call an onclick function to show the description.

for (i=0;i<flag;i++){
				titles[i]=allTitles[i].childNodes[0].nodeValue;
				descriptions[i]=allDescriptions[i].childNodes[0].nodeValue;
				document.getElementById('myDiv').innerHTML = newHTML;
				newHTML = document.getElementById('myDiv').innerHTML;
				newHTML = newHTML + "<div class=\"titlearea\" id=\"title" + i + "\" onclick=\"showdesc('" + i + "');\">" + titles[i] +"</div><div id=\"desc" + i + "\"></div>";
				document.getElementById('myDiv').innerHTML = newHTML;
			}

Show the description

When the onclick function to display the description is run, the function below inserts the description stored in the array into the desc div. The array position was called as an argument to the function. This enables us to display the correct description in the div.

function showdesc(idc){
			var idcdesc = "desc" + idc;
			document.getElementById(idcdesc).innerHTML = descriptions[(idc-1)];
		}

Starting point for RSS feed viewer

Click on the link below to see the full code working. This is a very simple example of what can be done with RSS feeds using client-side scripting only. Hope this is of interest, please contact me on twitter for feedback and questions.

RSS Viewer Example

Fixing SharePoint 2010 dynamic menus on the iPad

When using an iPad with the default v4 Master Page in SharePoint 2010, the dynamic drop down menus do not function as expected. When using a mouse, a simple hover over the menu item will drop down the dynamic menu child items (as shown below).

SharePoint 2010 menu on ipad

When using an iPad, iPhone and most other smart phone/tablets device, there is no mouse and no hover over action. When clicking on the parent menu item, the user is taken to that link instead of showing the child items.

To solve this issue (partially), I created some jQuery code to allow the first tap to drop down the menu items and the second tap to take the user to the chosen page.

First I use the jQuery ready function to load my script when the page has fully loaded.

jQuery(document).ready(function() {
});

When the page has finished loading, the type of device needs to be detected. In the example below I have used the iPhone, iPad and iPod devices. There are alternative devices!

if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
}

This solution involves using a counter to detect the first tap of a dynamic menu item as a hover over and the second tap as the actual click. First, set the counter to 0.

var countipad=0;

Another handy jQuery function is used to detect when a dynamic menu item is clicked. Using this class “dynamic-children” ensures that only the first click of a drop down menu is cancelled.

jQuery("a.dynamic-children").click(function() {
}

If the click is the first click, the default action (redirect) is prevented. The counter is then incremented ready for the next click.

if(countipad==0){
	event.preventDefault();
	countipad=countipad+1;
}

The full solution is as follows:

jQuery(document).ready(function() {
	if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
		var countipad=0;
 		jQuery("a.dynamic-children").click(function() {
			if(countipad==0){
				event.preventDefault();
				countipad=countipad+1;
			}
		});
	}
});

This isn’t a great solution as the second click will always take you to the link. A better solution would detect which link is selected and only redirect on the second click of that particular menu item.

ipad menu SharePoint 2010