<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>Bootstrap 101 Template</title>
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
<!-- Bootstrap -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
</head>
<body ng-controller="baseController as cntrl">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 col-xs-12">
<ul class="timeline-v2">
<li ng-repeat="(key, value) in cntrl.notifications" data-date="{{key}}">
<div ng-repeat="notification in value">
<div class="media">
<div class="media-left">
<a href="javascript:void(0);">
<img class="media-object img-circle"
src="{{notification.img}}" alt="Image">
</a>
</div>
<div class="media-body media-middle" data-time="{{notification.time}}" ng-bind-html="notification.text | sanitize"></div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<!-- AngularJS -->
<script src="https://code.angularjs.org/1.5.7/angular.min.js"></script>
</body>
</html>
body {
background-color: #f5f5f5 !important;
font-family: 'Roboto', sans-serif !important;
}
.container {
padding-top: 40px;
padding-bottom: 40px;
}
.timeline-v2 {
margin-bottom: 0;
list-style: none;
padding-left: 140px;
padding-right: 20px;
position: relative;
.media {
padding: 20px;
background-color: #fff;
-webkit-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.025);
box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.025);
}
.media-object {
width: 45px;
height: 45px;
}
.media-body {
&[data-time]::after {
content: attr(data-time);
position: absolute;
top: 0;
right: -10px;
padding: 5px 10px;
font-size: 10px;
color: #fff;
background-color: #2196f3;
-webkit-border-radius: 3px;
border-radius: 3px;
-webkit-transition: background-color 0.2s;
transition: background-color 0.2s;
}
p:last-child {
margin-bottom: 0;
}
}
> li {
position: relative;
&[data-date]::before {
content: attr(data-date);
position: absolute;
top: 44px;
right: 100%;
margin-right: 20px;
white-space: nowrap;
font-weight: 300;
font-size: 12px;
color: #777;
}
&[data-date] {
> div .media::before {
content: '';
position: absolute;
top: 47px;
left: -25px;
width: 12px;
height: 12px;
background-color: #f5f5f5;
border: 2px solid #2196f3;
z-index: 1;
-webkit-border-radius: 50%;
border-radius: 50%;
-webkit-transition-property: top, left, width, height, border-color;
transition-property: top, left, width, height, border-color;
-webkit-transition-duration: 0.2s;
transition-duration: 0.2s;
}
> div + div .media::before {
border-color: #4caf50;
}
> div,
> div + div {
.media:hover::before {
border-color: #f44336;
}
}
}
&:not(:last-child) > div:before,
&:last-child > div:not(:last-child)::before {
content: '';
position: absolute;
top: 53px;
left: -20px;
height: 100%;
border: 1px solid #e8e8e8;
}
&:not(:last-child) > div:not(:last-child):before,
&:last-child > div:not(:last-child)::before {
border-style: dashed;
}
> div {
margin-left: 20px;
padding-top: 10px;
padding-bottom: 10px;
position: relative;
&::after {
content: '';
position: absolute;
top: 47px;
left: -6px;
border-style: solid;
border-width: 6px 6px 6px 0;
border-color: transparent #fff transparent transparent;
}
&:hover .media-body[data-time]::after {
background-color: #f44336;
}
}
}
}
@media (max-width: 767px) {
.timeline-v2 {
padding-left: 30px;
> li[data-date]::before {
margin-right: auto;
-webkit-transform: rotate(-90deg) translate(50%, -20px);
transform: rotate(-90deg) translate(50%, -20px);
-webkit-transform-origin: right;
transform-origin: right;
}
}
}
View Compiled
angular.module('app', [])
.filter('sanitize', function($sce) {
return function(htmlCode){
return $sce.trustAsHtml(htmlCode);
}
})
.controller('baseController', function() {
this.notifications = {
'May 21, 2015': [
{
img: 'https://s3.amazonaws.com/uifaces/faces/twitter/_everaldo/128.jpg',
text: '<strong>Mad Jack</strong> added you to the board <a href="javascript:void(0);">The treasure of the three witches</a>',
time: '9:40 PM'
}
],
'May 20, 2015': [
{
img: 'https://s3.amazonaws.com/uifaces/faces/twitter/fffabs/128.jpg',
text: '<p><strong>Snuck</strong> commented on <a href="javascript:void(0);">Adventures of the high sees</a></p><p>Can\'t wait to go on this adventure with you, captain. it\'s a honor and a privilege to serve as your first mate..."</p>',
time: '4:42 PM'
},
{
img: 'https://s3.amazonaws.com/uifaces/faces/twitter/alexcican/128.jpg',
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vehicula posuere ligula at aliquet. Sed ornare, lacus quis hendrerit fringilla, augue quam tincidunt ante, laoreet fringilla elit odio non eros. Sed aliquam augue vitae leo cursus, ut facilisis metus fringilla. Aliquam nisi ipsum, tincidunt a orci ac, fermentum cursus purus. Nunc commodo, odio quis faucibus imperdiet, ante arcu aliquet odio, nec tincidunt sapien tortor quis nisi. Duis rhoncus sapien dolor, sed efficitur orci viverra a. Etiam eget mollis mi. Donec sagittis vulputate enim.',
time: '1:22 AM'
},
],
'April 8, 2015': [
{
img: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
text: '<p><strong>Angus Dagnabbit</strong> moved <a href="javascript:void(0);">Pirate\'s treasure from</a> <span class="label label-warning">In progress</span> to <span class="label label-success">Done</span></p>',
time: '2:09 PM'
}
],
'April 6, 2015': [
{
img: 'https://s3.amazonaws.com/uifaces/faces/twitter/alexcican/128.jpg',
text: '<p><strong>Flash Dashing</strong> uploaded 4 new screenshots to the board <a href="javascript:void(0);">Steal Mad Jack\'s treasure again</a></p>',
time: '4:22 PM'
},
{
img: 'https://s3.amazonaws.com/uifaces/faces/twitter/_everaldo/128.jpg',
text: 'Aliquam faucibus mauris sit amet blandit placerat. Maecenas interdum sapien ante, ut sollicitudin ex semper convallis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam id maximus est. Vestibulum ullamcorper semper ante, quis tristique odio aliquam eget. Sed ut luctus augue. Mauris sollicitudin tellus a malesuada ultricies. Fusce purus est, dapibus quis ex ac, egestas ornare orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at consequat lectus.',
time: '12:20 PM'
}
]
};
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.