A Facebook-like layout offers several innovative features that are designed to give users an enhanced experience. Spread.Views allows users to Like, Comment, or Share their posts just like you can do while using Facebook.
You can create this demo using the following Spread.Views features:
Use the following steps to create a social networking interface using Spread.Views, as shown in the following image.
Sample Code
Add the following references to the project.
<link rel="stylesheet" type="text/css" href="[Your Stylesheet Path]/gc.spread.views.dataview.10.1.1.css"> <script src="[Your Script Path]/gc.spread.common.10.1.1.min.js" type="text/javascript"></script> <script src="[Your Script Path]/gc.spread.views.dataview.10.1.1.min.js" type="text/javascript"></script> <script src="[Your Script Path]/gc.spread.views.gridlayout.10.1.1.min.js" type="text/javascript"></script> <script src="[Your Script Path]/zepto.min.js" type="text/javascript"></script> <script src="[Your Script Path]/license.js" type="text/javascript"></script> <script src="data/comments.js" type="text/javascript"></script>
Add a style tag within the head tag to apply styling to the interface.
* { -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } @font-face { font-family: 'spreadview-demo-icon'; src: url(data:application/font-woff;base64,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) format('woff'); } .demo-icon { font-family: "spreadview-demo-icon"; font-style: normal; display: inline-block; text-align: center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-variant: normal; text-transform: none; } .icon-share:before { content: '\e804'; } .icon-comment:before { content: '\e805'; } .icon-like:before { content: '\e806'; } .gc-grid { padding: 1em; } .gc-cell-border { border: 0; } .post-wrapper { border: 1px solid; border-color: #e5e6e9 #dfe0e4 #d0d1d5; border-radius: 3px; -webkit-border-radius: 3px; -ms-border-radius: 3px; background-color: white; color: #141823; width: 452px; margin: 0 5px 10px 0; } .user-content-wrapper { padding: 12px 12px 0 12px; } .block-wrapper { margin-bottom: 10px; } .user-icon { display: inline-block; margin-right: 10px; } .user-stamp { vertical-align: top; display: inline-block; } .user-stamp-name { display: inline-block; } .user-story { display: inline-block; } .user-stamp-time { display: inline-block; } .comment-link { display: inline-block; margin-top: 10px; font-size: 12px; color: #9197a3; } .comment-link:hover { color: #828793; text-decoration: none; } .interface-icons-wrapper { padding-top: 10px; margin-top: 10px; border-top: 1px solid #e1e2e3; } .interface-icons { display: table-cell; } .comment-icon-link { margin-right: 30px; color: #7f7f7f; cursor: pointer; } .comment-icon-link:hover { text-decoration: underline; } .icon-checked { color: #5890ff; } .comments { border-top: 1px solid #e1e2e3; background-color: #f6f7f8; margin-top: 10px; padding: 0; } .comment-item { padding: 3px 12px 3px 12px; overflow: hidden; word-wrap: break-word; } .small-icon { width: 32px; height: 32px; position: relative; top: 2px; } .comment-item-message { padding-left: 8px; overflow: hidden; } .user-name { font-weight: bold; color: #3b5998; } .gc-cell { white-space: normal; text-overflow: clip; } .gc-row.gc-focused { background-color: inherit; } .gc-focused .post-wrapper { background-color: #E6EFF9; }
Add the div tag within the body tag to include the DOM element as the container in the page.
<body style="margin:0;position:absolute;top:0;bottom:0;left:0;right:0;font-size:14px;user-select:none;-webkit-user-select: none;overflow:hidden;"> <div id="grid1" style="height:100%"></div> <template id='rowTemplate' style="display: none"> <div class="post-wrapper"> <div class="user-content-wrapper"> <div class="block-wrapper"> <div class="user-icon" data-column="icon"></div> <div class="user-stamp"> <div> <span class="user-stamp-name" data-column="name"></span> <span class="user-story" data-column="story"></span> </div> <span class="user-stamp-time" data-column="created_time"></span> </div> </div> <div data-column="message"></div> <div> <div data-column="img"></div> <div data-column="video"></div> </div> <div data-column="comment_link"></div> <div> <div class="interface-icons-wrapper"> <div data-column="like" class="interface-icons"></div> <div class="interface-icons"> <a class="comment-icon-link icon-link-comment"><i class="demo-icon icon-comment"></i> comment</a> </div> <div class="interface-icons"> <a class="comment-icon-link icon-link-share"><i class="demo-icon icon-share"></i> share</a> </div> </div> </div> </div> <div data-column="commentUI" class="comments"></div> </div> </template>
- Add a variable definition and the column definition.
var columns = [{ id: 'icon', name: 'icon', dataField: 'icon', presenter: '<a href="{{=it.icon}}"><img src="{{=it.icon}}" style="width:40px;height:40px;"></a>' }, { id: 'created_time', name: 'created_time', dataField: 'created_time', format: 'mm-dd-yyyy' }, { id: 'story', name: 'story', dataField: 'story' }, { id: 'name', name: 'name', dataField: 'name', presenter: '<a class="user-name">{{=it.name}}</a>' }, { id: 'message', name: 'message', dataField: 'message' }, { id: 'comment_link', name: 'comment_link', dataField: 'comment_link', presenter: '<a class="comment-link">' + '<span>{{=(it.total_likes + (it.like ? 1 : 0))}}{{?(it.total_likes + (it.like ? 1 : 0)) > 1}} likes{{??}} like{{?}}</span>  ' + '<span>{{=it.total_comments}}{{?it.total_comments <= 1}} comment{{??it.total_comments > 1}} comments{{?}}</span>  ' + '<span>{{=it.total_shares}}{{?it.total_shares <= 1}} share{{??it.total_shares > 1}} shares{{?}}</span>' + '</a>' }, { id: 'like', name: 'like', dataField: 'like', presenter: '<a class="comment-icon-link icon-link-like {{?it.like}}icon-checked{{?}}"><i class="demo-icon icon-like"></i> like</a>' }, { id: 'img', name: 'img', dataField: 'img', presenter: '<div>{{~it.img:value:index}}' + '<div class="img-item">' + '<img src="{{=value.url}}" style="width:426px;" alt="{{=value.name}}">' + '</div>' + '{{~}}</div>' }, { id: 'video', name: 'video', dataField: 'video', presenter: '<div>{{~it.video:value:index}}' + '<div class="video-item">' + '<video style="width:426px;height:243px" controls>' + '<source src="{{=value.url}}" type="video/mp4">' + '</video>' + '</div>' + '{{~}}</div>' }, { id: 'commentUI', name: 'commentUI', dataField: 'commentUI', presenter: '{{?it.show_comment}}<div>{{~it.comments:value:index}}' + '<div class="comment-item">' + '<div style="float:left"><img class="small-icon" src="{{=value.icon}}"></div>' + '<div><div class="comment-item-message"><a class="user-name">{{=value.name}}:</a> {{=value.message}}</div></div>' + '</div>' + '{{~}}</div>{{?}}' }, { id: 'total_likes', name: 'total_likes', dataField: 'total_likes', visible: false }, { id: 'total_comments', name: 'total_comments', dataField: 'total_comments', visible: false }, { id: 'total_shares', name: 'total_shares', dataField: 'total_shares', visible: false }, { id: 'comments', name: 'comments', dataField: 'comments', visible: false }, { id: 'show_comment', name: 'show_comment', dataField: 'show_comment', visible: false }];
Initialize the grid followed by a function to handle the click events.
var dataView = new GC.Spread.Views.DataView(document.getElementById('grid1'), data, columns, new GC.Spread.Views.Plugins.GridLayout({ rowTemplate: '#rowTemplate', autoRowHeight: true, showRowHeader: false, showColHeader: false, selectionMode: 'none' })); document.getElementById('grid1').addEventListener('click', handleMouseClick); //focus data.view by default document.querySelector('#grid1').focus(); function handleMouseClick(event) { var grid = dataView; var hitTestInfo = grid.hitTest(event); var row = hitTestInfo.row; var targetList = ['.icon-link-like', '.icon-link-comment']; var i = lookupForElementNames(event, targetList); if (i === 0) { data[row].like = !data[row].like; var cell = document.querySelector('#' + grid.uid + '-r' + row + ' .comment-link span'); var likes = data[row]['total_likes'] + data[row].like; cell.innerHTML = likes > 1 ? likes + ' likes' : likes + ' like'; } else if (i === 1) { if (data[row].video) { return; } data[row].show_comment = !data[row].show_comment; grid.refreshRow_(hitTestInfo); } // return the matched name's index function lookupForElementNames(event, targetNameSet) { var element = event.target; while (element) { // get the first match in the name set for (var i = 0, len = targetNameSet.length; i < len; ++i) { if (matchName(element, targetNameSet[i])) { return i; } } element = element.parentNode; } return -1; } function matchName(element, name) { if (typeof name === 'string') { var initial = name[0]; var str = ''; switch (initial) { case '.': if (!element.classList) { return false; } str = name.slice(1).toLowerCase(); for (var i = 0, len = element.classList.length; i < len; ++i) { if (element.classList[i].toLowerCase() === str) { return true; } } return false; case '#': str = name.slice(1).toLowerCase(); return !!element.id && element.id.toLowerCase() === str; break; default: str = name.toLowerCase(); return element.tagName.toLowerCase() === str; } } } }