Create Custom Tiles using HTML CSS and KnockoutJS in SharePoint 2013

knockout js tutorial sharepoint 2013.png
InfoPath alternatives for form designing SharePoint

This article explains how to create custom promoted links or Tiles in SharePoint 2013 with custom sorting using Knockout JS and csom.

Technologies Used:
HTML CSS for building tile like structure.
CSOM to get data from SharePoint list.
Knockout JS for binding list data with UI

Pre-Requisite:
1. Add Promoted links app in your site.(I have given it name as “CustomTiles”). You can use custom list as well with same columns as in promoted links.
2. Add picture library for background images of promoted links. (Given name as “picsForTiles”).
3. Add some data in promoted links app i.e “CustomTiles” list.

SharePoint online: Ultimate tutorial guide PDF download

Below is screenshot with some random data:

knockout js tutorial sharepoint 2013
knockout js tutorial sharepoint 2013
knockout js tutorial sharepoint 2013 examples
knockout js tutorial sharepoint 2013 examples




HTML:
Add following HTML with required files in html file.

<!DOCTYPE HTML PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”>

<html>

<head>

<title>Custom Promoted Links</title>

<script src=”https://code.jquery.com/jquery-3.3.1.min.js”></script>

<script src=”https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js”></script>

<script src=”/SiteAssets/JS/getTilesData.js”></script>

<link rel=”stylesheet” href=” /SiteAssets/CSS/customTiles.css”/>

</head>

<body>

<!–HTML Content–>

<input type=”button” value=”Sort By Title” data-bind=”click: sortedtilesByTitle()”>&nbsp; <input type=”button” value=”Sort By Order” data-bind=”click: sortedtilesByOrder()”><br/><br/>

<div class=”mainContainer” data-bind=”foreach:tiles”>

<div class=’card slide-up’>

<div ><img class=’image’ data-bind=”attr:{src: backImage}”> </div>

<div class=’caption’> <h2 class=’caption-title’ data-bind=”text:title”></h2>

<p class=’caption-content’ data-bind=”text:desc”> </p>

</div> </div> </div>

</body> </html>




CSS:
Content of customTiles.css file:
.card {
position: relative;
width: 200px;
height: 200px;
float:left;
margin:0 10px 10px 0;
cursor:pointer;
background-color: #ffffff;
overflow: hidden;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
}
.image {
width:200px;
height:200px;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
-webkit-transition-property: -webkit-transform;
transition-property: -webkit-transform;
transition-property: transform;
transition-property: transform, -webkit-transform;
-webkit-transition-duration: 0.4s;
transition-duration: 0.4s;
}
.caption {
position: absolute;
top: auto;
bottom: 0;
opacity: 0;
left: 0;
width: 100%;
height: 100px;
background-color: #ffffff;
padding: 15px;
-webkit-transform: translateY(100%);
transform: translateY(100%);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transition: opacity 0.1s 0.3s, -webkit-transform 0.4s;
transition: opacity 0.1s 0.3s, -webkit-transform 0.4s;
transition: transform 0.4s, opacity 0.1s 0.3s;
transition: transform 0.4s, opacity 0.1s 0.3s, -webkit-transform 0.4s;
}
.caption-title {
margin-top: 0;
margin-bottom: 10px;
}
.caption-content {
margin: 0;
}
.caption-link {
color: #724b31;
text-decoration: none;
opacity: 1;
-webkit-transition-property: opacity;
transition-property: opacity;
-webkit-transition-duration: 0.15s;
transition-duration: 0.15s;
-webkit-transition-timing-function: cubic-bezier(0.39, 0.58, 0.57, 1);
transition-timing-function: cubic-bezier(0.39, 0.58, 0.57, 1);
}
.caption-link:hover {
opacity: 0.65;
}
.slide-up:hover .image {
-webkit-transform: translateY(-50px);
transform: translateY(-50px);
}
.slide-up:hover .caption {
opacity: 1;
-webkit-transform: translateY(0px);
transform: translateY(0px);
-webkit-transition: opacity 0.1s, -webkit-transform 0.4s;
transition: opacity 0.1s, -webkit-transform 0.4s;
transition: transform 0.4s, opacity 0.1s;
transition: transform 0.4s, opacity 0.1s, -webkit-transform 0.4s;
}

JavaScript (gettilesData.js):



I have used knockout js for binding and logic as follows which is self-explanatory.

//declare variables
var completeListItems=null;
var listName=’CustomTiles’;
$(document).ready(function ()
{
//fetch items from list on page load
SP.SOD.executeFunc(‘sp.js’, ‘SP.ClientContext’, function () { mainFunction(); });
});

//main function to activate knockout
function mainFunction(){
completeListItems=new tilesListViewModel();
retrivelistItems();
ko.applyBindings(completeListItems);
}

function tilesList(title,desc,tileOrder, backImage, linkLocation) {
var self = this;
self.title = title;
self.desc = desc;
self.tileOrder = tileOrder;
self.backImage = backImage;
self.linkLocation=linkLocation;
}

//view model
function tilesListViewModel() {
var self = this;
self.tiles = ko.observableArray([]); //observable array
//to add tiles data
self.AddTiles = function (title,desc,tileOrder, backImage, linkLocation) {
self.tiles.push(new tilesList(title,desc,tileOrder, backImage, linkLocation));}
//sort tiles by order
self.sortedtilesByOrder = function() {
self.tiles.sort(function (left, right) {
return left.tileOrder == right.tileOrder ? 0 : (left.tileOrder < right.tileOrder ? -1 : 1) });
}
//sort tiles by title
self.sortedtilesByTitle = function() {
self.tiles.sort(function (left, right) {
return left.title == right.title ? 0 : (left.title < right.title ? -1 : 1) });
}

}//End view model

//function to get list items from sharepoint using CSOM
function retrivelistItems(){
var clientContext=new SP.ClientContext.get_current();
var oList=clientContext.get_web().get_lists().getByTitle(listName);
var camlQuery= new SP.CamlQuery();
camlQuery.set_viewXml(“<View><RowLimit>20</RowLimit></View>”);
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(Function.createDelegate(this,this.querySuccess),Function.createDelegate(this,this.queryFail));
}

//success callback
function querySuccess(sender,args){

var listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
var tileTitle=oListItem.get_item(‘Title’);
var tileDesc=oListItem.get_item(‘Description’);
var tileOrder=oListItem.get_item(‘TileOrder’);
var tileBackImage=oListItem.get_item(‘BackgroundImageLocation’).get_url();
var linkLoc=oListItem.get_item(‘LinkLocation’).get_url();
//fill the data from list
completeListItems.AddTiles(tileTitle,tileDesc,tileOrder,tileBackImage,linkLoc);
}
}

//failure function callback
function queryFail(sender,args){
alert(‘Request failed. ‘ + args.get_message() + ‘\n’ + args.get_stackTrace());
}

Add Content editor to SharePoint page and refer html file. End result will be as follows:

knockout js tutorial sharepoint online
knockout js tutorial sharepoint online

On mouse hover tile displays Title and description. You can add more data from list if required.

knockout js tutorial sharepoint
knockout js tutorial sharepoint

Clicking on sort by title or sort by order will sort the tiles according to title (A-Z) or order provided in list (1-onwards sequentially). You can customize css for more transition effects.

Similar SharePoint 2013 Tutorials


About Prajkta Patil

I am a SharePoint Developer with 6+ years of experience working on a range of projects like building intranet, migrating SharePoint environment from older to latest versions,building Nintex/Designer workflows to develop business process. My skills and knowledge include: • SharePoint Development • Designer/Nintex workflows- design, development and support • C# and ASP.net development • HTML, CSS, jQuery • REST,spservices • PnP Powershell •knockout,angular frameworks • Sitecore development My current role is to develop intranet sites,workflows design,powerapp development. It allows me to deliver best solutions to business users.

View all posts by Prajkta Patil →

Leave a Reply