Custom Tiles With Custom Sorting In SharePoint

This article explains how to create custom promoted links/tiles in SharePoint with custom sorting.

Technologies Used

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

Prerequisite

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

Below is the screenshot of the application with some random data.

SharePoint
SharePoint

HTML

Add the following HTML with required files in HTML file.

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">  
  2. <html>  
  3.   
  4. <head>  
  5.     <title>Custom Promoted Links</title>  
  6.     <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>  
  7.     <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>  
  8.     <script src="/SiteAssets/JS/getTilesData.js"></script>  
  9.     <link rel="stylesheet" href=" /SiteAssets/CSS/customTiles.css" /> </head>  
  10.   
  11. <body>  
  12.     <!--HTML Content--><input type="button" value="Sort By Title" data-bind="click: sortedtilesByTitle()">  <input type="button" value="Sort By Order" data-bind="click: sortedtilesByOrder()"><br/><br/>  
  13.     <div class="mainContainer" data-bind="foreach:tiles">  
  14.         <div class='card slide-up'>  
  15.             <div><img class='image' data-bind="attr:{src: backImage}"> </div>  
  16.             <div class='caption'>  
  17.                 <h2 class='caption-title' data-bind="text:title"></h2>  
  18.                 <p class='caption-content' data-bind="text:desc"> </p>  
  19.             </div>  
  20.         </div>  
  21.     </div>  
  22. </body>  
  23.   
  24. </html>  

CSS

Content of customTiles.css file is as below.

  1. .card {  
  2.     position: relative;  
  3.     width: 200 px;  
  4.     height: 200 px;  
  5.     float: left;  
  6.     margin: 0 10 px 10 px 0;  
  7.     cursor: pointer;  
  8.     background - color: #ffffff;  
  9.     overflow: hidden;  
  10.     box - shadow: 0 3 px 6 px rgba(0, 0, 0, 0.16),  
  11.     0 3 px 6 px rgba(0, 0, 0, 0.23);  
  12. }.image {  
  13.     width: 200 px;  
  14.     height: 200 px;  
  15.     background - position: center;  
  16.     background - size: cover;  
  17.     background - repeat: no - repeat; - webkit - transition - property: -webkit - transform;  
  18.     transition - property: -webkit - transform;  
  19.     transition - property: transform;  
  20.     transition - property: transform,  
  21.     -webkit - transform; - webkit - transition - duration: 0.4 s;  
  22.     transition - duration: 0.4 s;  
  23. }.caption {  
  24.     position: absolute;  
  25.     top: auto;  
  26.     bottom: 0;  
  27.     opacity: 0;  
  28.     left: 0;  
  29.     width: 100 % ;  
  30.     height: 100 px;  
  31.     background - color: #ffffff;  
  32.     padding: 15 px; - webkit - transform: translateY(100 % );  
  33.     transform: translateY(100 % ); - webkit - backface - visibility: hidden;  
  34.     backface - visibility: hidden; - webkit - transition: opacity 0.1 s 0.3 s,  
  35.     -webkit - transform 0.4 s;  
  36.     transition: opacity 0.1 s 0.3 s,  
  37.     -webkit - transform 0.4 s;  
  38.     transition: transform 0.4 s,  
  39.     opacity 0.1 s 0.3 s;  
  40.     transition: transform 0.4 s,  
  41.     opacity 0.1 s 0.3 s,  
  42.     -webkit - transform 0.4 s;  
  43. }.caption - title {  
  44.         margin - top: 0;  
  45.         margin - bottom: 10 px;  
  46.     }.caption - content {  
  47.         margin: 0;  
  48.     }.caption - link {  
  49.         color: #724b31;  
  50.   
  51. text - decoration: none;  
  52. opacity: 1; - webkit - transition - property: opacity;  
  53. transition - property: opacity; - webkit - transition - duration: 0.15 s;  
  54. transition - duration: 0.15 s; - webkit - transition - timing - function: cubic - bezier(0.39, 0.58, 0.57, 1);  
  55. transition - timing - function: cubic - bezier(0.39, 0.58, 0.57, 1);  
  56. }.caption - link: hover {  
  57.     opacity: 0.65;  
  58. }.slide - up: hover.image {  
  59.     -webkit - transform: translateY(-50 px);  
  60.     transform: translateY(-50 px);  
  61. }.slide - up: hover.caption {  
  62.     opacity: 1; - webkit - transform: translateY(0 px);  
  63.     transform: translateY(0 px); - webkit - transition: opacity 0.1 s,  
  64.     -webkit - transform 0.4 s;  
  65.     transition: opacity 0.1 s,  
  66.     -webkit - transform 0.4 s;  
  67.     transition: transform 0.4 s,  
  68.     opacity 0.1 s;  
  69.     transition: transform 0.4 s,  
  70.     opacity 0.1 s,  
  71.     -webkit - transform 0.4 s;  
  72. }  

JavaScript (gettilesData.js)

I have used knockout.js for binding the logic. This is a self-explanatory JavaScript file.

  1. //declare variables  
  2. var completeListItems = null;  
  3. var listName = 'CustomTiles';  
  4. $(document).ready(function() {  
  5.     //fetch items from list on page load  
  6.     SP.SOD.executeFunc('sp.js''SP.ClientContext'function() {  
  7.         mainFunction();  
  8.     });  
  9. });  
  10. //main function to activate knockout  
  11. function mainFunction() {  
  12.     completeListItems = new tilesListViewModel();  
  13.     retrivelistItems();  
  14.     ko.applyBindings(completeListItems);  
  15. }  
  16.   
  17. function tilesList(title, desc, tileOrder, backImage, linkLocation) {  
  18.     var self = this;  
  19.     self.title = title;  
  20.     self.desc = desc;  
  21.     self.tileOrder = tileOrder;  
  22.     self.backImage = backImage;  
  23.     self.linkLocation = linkLocation;  
  24. }  
  25. //view model  
  26. function tilesListViewModel() {  
  27.     var self = this;  
  28.     self.tiles = ko.observableArray([]); //observable array  
  29.     //to add tiles data  
  30.     self.AddTiles = function(title, desc, tileOrder, backImage, linkLocation) {  
  31.         self.tiles.push(new tilesList(title, desc, tileOrder, backImage, linkLocation));  
  32.     }  
  33.     //sort tiles by order  
  34.     self.sortedtilesByOrder = function() {  
  35.         self.tiles.sort(function(left, right) {  
  36.             return left.tileOrder == right.tileOrder ? 0 : (left.tileOrder < right.tileOrder ? -1 : 1)  
  37.         });  
  38.     }  
  39.     //sort tiles by title  
  40.     self.sortedtilesByTitle = function() {  
  41.         self.tiles.sort(function(left, right) {  
  42.             return left.title == right.title ? 0 : (left.title < right.title ? -1 : 1)  
  43.         });  
  44.     }  
  45. //End view model  
  46. //function to get list items from sharepoint using CSOM  
  47. function retrivelistItems() {  
  48.     var clientContext = new SP.ClientContext.get_current();  
  49.     var oList = clientContext.get_web().get_lists().getByTitle(listName);  
  50.     var camlQuery = new SP.CamlQuery();  
  51.     camlQuery.set_viewXml("<View><RowLimit>20</RowLimit></View>");  
  52.     this.collListItem = oList.getItems(camlQuery);  
  53.     clientContext.load(collListItem);  
  54.     clientContext.executeQueryAsync(Function.createDelegate(thisthis.querySuccess), Function.createDelegate(thisthis.queryFail));  
  55. }  
  56. //success callback  
  57. function querySuccess(sender, args) {  
  58.     var listItemEnumerator = collListItem.getEnumerator();  
  59.     while (listItemEnumerator.moveNext()) {  
  60.         var oListItem = listItemEnumerator.get_current();  
  61.         var tileTitle = oListItem.get_item('Title');  
  62.         var tileDesc = oListItem.get_item('Description');  
  63.         var tileOrder = oListItem.get_item('TileOrder');  
  64.         var tileBackImage = oListItem.get_item('BackgroundImageLocation').get_url();  
  65.         var linkLoc = oListItem.get_item('LinkLocation').get_url();  
  66.         //fill the data from list  
  67.         completeListItems.AddTiles(tileTitle, tileDesc, tileOrder, tileBackImage, linkLoc);  
  68.     }  
  69. }  
  70. //failure function callback  
  71. function queryFail(sender, args) {  
  72.     alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());  
  73. }  

Add a Content Editor to SharePoint page and refer to the HTML file. The end result will be something like below.

 SharePoint

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

 SharePoint

Clicking on the "sort by title" or "sort by order" option will sort the tiles accord the ng to title (A-Z) or order provided in the list (1-onwards sequentially).

You can customize the CSS for more transition effects.