function MessageCtrl($scope, MessageService) {
function resetInbox() {
$scope.messageIndex = {};
$scope.messageList = [];
$scope.messageIds = [];
resetSelection();
}
function resetSelection() {
$scope.selection = {};
allSelected = $scope.allSelected = false;
}
function updateList() {
resetInbox();
// load our messages
MessageService.getListMessages().then(function(response) {
var list = response.data,
ids = [],
index = {};
list.forEach(function(message) {
if (message) {
ids.push(String(message.id));
index[message.id] = message;
}
});
// store object references by id for faster access
$scope.messageIndex = index;
$scope.messageList = list;
$scope.messageIds = ids;
});
}
function getSelectedIds() {
var selectedIds = [],
selection = $scope.selection;
$scope.messageIds.forEach(function(id) {
if (selection[id] === true) {
selectedIds.push(id);
}
});
return selectedIds;
}
function markAllAsRead(ids) {
var index = $scope.messageIndex;
ids.forEach(function(id) {
index[id].wasRead = true;
});
}
$scope.toggleSelectedId = function(id) {
$scope.selection[id] = !$scope.selection[id];
};
var allSelected = false;
$scope.toggleSelectAll = function() {
var ids = $scope.messageIds,
selection = $scope.selection;
if (!ids.length) return;
allSelected = !allSelected;
ids.forEach(function(id) {
selection[id] = allSelected;
});
$scope.allSelected = allSelected;
};
$scope.markAsRead = function() {
var selectedIds = getSelectedIds();
console.log('mark as read', selectedIds);
if (!selectedIds.length) return;
MessageService.markAsRead(selectedIds).then(function() {
markAllAsRead(selectedIds);
resetSelection();
});
};
$scope.updateList = updateList;
$scope.hasSelection = function() {
return getSelectedIds().length !== 0;
};
resetInbox();
updateList();
}
function MessageServiceFactory($http) {
/**
* Mark messages as read
* @param {String|String[]} ids Can be either a single ID or a list of IDs
*/
function markAsRead(ids) {
if (ids instanceof Array === false) {
ids = [ids];
}
ids = ids.join(',');
return $http.get('/inbox/mark-as-read/' + ids);
}
/**
* Load a list of messages from server
*/
function loadList() {
return $http.get('/inbox/messages');
}
return {
markAsRead: markAsRead,
getListMessages: loadList
};
}
angular.module('inbox', ['ngMockE2E'])
.controller('MessageCtrl', MessageCtrl)
.service('MessageService', MessageServiceFactory);
<!DOCTYPE html>
<html ng-app="inbox">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.0.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js" data-semver="1.0.8"></script>
<script src="http://code.angularjs.org/1.0.8/angular-mocks.js"></script>
<script src="app.js"></script>
<script src="mocks.js"></script>
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" />
</head>
<body ng-controller="MessageCtrl">
<div class="inbox">
<h1>Inbox app</h1>
<div class="toolbar">
<button ng-click="updateList()">Update list</button>
<button class="btn-primary" ng-disabled="!hasSelection()" ng-click="markAsRead()">Mark as read</button>
</div>
<table>
<thead>
<tr ng-class="{selected: allSelected}">
<th><span class="selection-mark" ng-click="toggleSelectAll()"> </span>
</th>
<th>Message</th>
<th>From</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="message in messageList" ng-class="{unread: !message.wasRead, selected: selection[message.id]}" ng-click="toggleSelectedId(message.id)">
<td><span class="selection-mark"> </span>
</td>
<td class="title">{{ message.title }}</td>
<td>{{ message.from }}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
* {
margin: 0;
padding: 0;
font-size: 1em;
font-family: inherit;
}
body {
font-family: sans-serif;
}
.inbox {
font-size: 12px;
padding: 20px;
}
.inbox h1 {
margin-bottom: .5em;
border-bottom: 1px solid #ddd;
font-size: 2em;
}
.inbox table {
width: 100%;
}
.inbox .unread td {
background: #ffe;
}
.inbox .unread .title {
font-weight: bold;
}
.toolbar {
padding-bottom: 1em;
}
.toolbar button {
padding: 7px;
border-radius: 3px;
background: whiteSmoke;
color: #666;
border: none;
font-weight: bold;
}
.toolbar button[disabled="disabled"] {
background: #fafafa;
color: #aaa;
font-weight: normal;
}
.toolbar .btn-primary {
background: #4387FD;
color: white;
}
.inbox table {
border-collapse: collapse;
}
.inbox th {
font-weight: bold;
}
.inbox th,
.inbox td {
padding: 7px;
}
.inbox th {
background-color: whiteSmoke;
text-align: left;
}
.inbox td {
cursor: pointer;
}
.selection-mark {
display: inline-block;
box-sizing: border-box;
width: 1em;
height: 1em;
border: 1px solid #ddd;
cursor: pointer;
}
.selected .selection-mark {
background: #4387FD;
border-color: #4387FD;
}
angular.module('inbox').run(function($httpBackend) {
// mark message(s) as read
// e.g.: /inbox/mark-as-read/1,2,3
$httpBackend.whenGET(/\/inbox\/mark-as-read\/.+/).respond(function() {
return [200];
});
// load message list
$httpBackend.whenGET('/inbox/messages').respond(function() {
var list = [], i = 10;
while (i--) {
list.push(makeMessage());
}
return [200, list];
});
$httpBackend.whenGET(/.*/).passThrough();
$httpBackend.whenPOST(/.*/).passThrough();
var $uid = 0;
function makeUid() {
return ++$uid;
}
var words = 'lorem ipsum dolor sit amet consecteur'.split(' ');
function makeText(numWords) {
var text = [''], word, wordsLen = words.length;
for (var i = 0; i < numWords; i++) {
word = words[Math.floor(Math.random() * wordsLen)];
text.push(word);
}
return text.join(' ');
}
function makeMessage() {
var wasRead = (Math.random() * 10 > 5);
return {
id: makeUid(),
title: makeText(10),
from: makeText(3),
wasRead: wasRead
}
}
});