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
- 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.
- Add a picture library for background images of the promoted links. (Given name as “picsForTiles”).
- 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.
- <!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()"> <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 is as below.
- .card {
- position: relative;
- width: 200 px;
- height: 200 px;
- float: left;
- margin: 0 10 px 10 px 0;
- cursor: pointer;
- background - color: #ffffff;
- overflow: hidden;
- box - shadow: 0 3 px 6 px rgba(0, 0, 0, 0.16),
- 0 3 px 6 px rgba(0, 0, 0, 0.23);
- }.image {
- width: 200 px;
- height: 200 px;
- 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.4 s;
- transition - duration: 0.4 s;
- }.caption {
- position: absolute;
- top: auto;
- bottom: 0;
- opacity: 0;
- left: 0;
- width: 100 % ;
- height: 100 px;
- background - color: #ffffff;
- padding: 15 px; - webkit - transform: translateY(100 % );
- transform: translateY(100 % ); - webkit - backface - visibility: hidden;
- backface - visibility: hidden; - webkit - transition: opacity 0.1 s 0.3 s,
- -webkit - transform 0.4 s;
- transition: opacity 0.1 s 0.3 s,
- -webkit - transform 0.4 s;
- transition: transform 0.4 s,
- opacity 0.1 s 0.3 s;
- transition: transform 0.4 s,
- opacity 0.1 s 0.3 s,
- -webkit - transform 0.4 s;
- }.caption - title {
- margin - top: 0;
- margin - bottom: 10 px;
- }.caption - content {
- margin: 0;
- }.caption - link {
- color: #724b31;
-
- text - decoration: none;
- opacity: 1; - webkit - transition - property: opacity;
- transition - property: opacity; - webkit - transition - duration: 0.15 s;
- transition - duration: 0.15 s; - 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(-50 px);
- transform: translateY(-50 px);
- }.slide - up: hover.caption {
- opacity: 1; - webkit - transform: translateY(0 px);
- transform: translateY(0 px); - webkit - transition: opacity 0.1 s,
- -webkit - transform 0.4 s;
- transition: opacity 0.1 s,
- -webkit - transform 0.4 s;
- transition: transform 0.4 s,
- opacity 0.1 s;
- transition: transform 0.4 s,
- opacity 0.1 s,
- -webkit - transform 0.4 s;
- }
JavaScript (gettilesData.js)
I have used knockout.js for binding the logic. This is a self-explanatory JavaScript file.
-
- var completeListItems = null;
- var listName = 'CustomTiles';
- $(document).ready(function() {
-
- SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function() {
- mainFunction();
- });
- });
-
- 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;
- }
-
- function tilesListViewModel() {
- var self = this;
- self.tiles = ko.observableArray([]);
-
- self.AddTiles = function(title, desc, tileOrder, backImage, linkLocation) {
- self.tiles.push(new tilesList(title, desc, tileOrder, backImage, linkLocation));
- }
-
- self.sortedtilesByOrder = function() {
- self.tiles.sort(function(left, right) {
- return left.tileOrder == right.tileOrder ? 0 : (left.tileOrder < right.tileOrder ? -1 : 1)
- });
- }
-
- self.sortedtilesByTitle = function() {
- self.tiles.sort(function(left, right) {
- return left.title == right.title ? 0 : (left.title < right.title ? -1 : 1)
- });
- }
- }
-
- 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));
- }
-
- 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();
-
- completeListItems.AddTiles(tileTitle, tileDesc, tileOrder, tileBackImage, linkLoc);
- }
- }
-
- function queryFail(sender, args) {
- alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
- }
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.