Building a Communication Center for your users Part 3

coding

In this final installment on building a custom communication center, I will go over the code required to make all of this work. There is a total of four different JavaScript functions, but only a single function is called on document load. The other three are associated with the process to add, update, and delete the item. However, they are the center for how all of these scripts work. You can take what I have below and shape them for what you want. The list that I have used may or may not work for you, so feel free to customize the calls to whatever you need. The solutions must center around your work.

Document Ready Call

1
2
3
4
5
6
7
8
9
$(document).ready(function() {
retrieveNewsItems();
$('#addNewsBtn').click(function(){
$('#addNewsModal').removeClass("modal-hidden").addClass("modal");
});
$(".close").click(function(){
$("#addNewsModal").removeClass("modal").addClass("modal-hidden");
});
});

The retrieveNewsItems(); function is the only function that gets loaded on document load. What this function does, as you would guess, is place an AJAX call, retrieve the items, build the table and the display it. There is also logic built into the code that will set the drop down menu to the proper setting depending on if the news item has been promoted to the top or ‘Headline News.’

Here is the code:

retrievenewsitems();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
function retrieveNewsItems() {
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "_api/web/lists/GetByTitle('News')/items?$Select=Id,Title,headlineNews,NewsSubTitle,newsBody,newsImage&$orderby=Created desc",
type: "GET",
headers: {
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"IF-MATCH": "*",
"X-HTTP-Method": null
},
cache: false,
success: function(data) {
$("#eventsTableResults").empty();
$('#eventsTableResults').append(`
<table id="addEventsTable" class="tg">
<tbody>
<tr>
<th class="tg-yw41">Title</th>
<th class="tg-yw41">Event Description</th>
<th class="tg-yw41">Start Date/Time</th>
<th class="tg-yw41">End Date/Time</th>
<th class="tg-yw41">Event Day</th>
<th class="tg-yw41">Event Month</th>
<th class="tg-yw41">EventYear</th>
<th class="tg-yw41">EventTime</th>
</tr>
<tr>
<td class="tg-yw41"></td>
<td class="tg-yw41"></td>
<td class="tg-yw41"><input id="newStartDateTime" style="width: 150px;" type="datetime-local" /></td>
<td class="tg-yw41"><input id="newEndDateTime" style="width: 150px;" type="datetime-local" /></td>
<td class="tg-yw41"></td>
<td class="tg-yw41"></td>
<td class="tg-yw41"></td>
<td class="tg-yw41"></td>
</tr>
</tbody>
</table>
`);
for (var i = 0; i &lt; data.d.results.length; i++) {
var item = data.d.results[i];
if (item.headlineNews == "Yes") {
$('#newsTable').append(`

<input name="&#96; + item.Id + &#96;" type="checkbox" value="&#96; + item.Id + &#96;" />
<input id="&#96; + item.Id + &#96;-newsitem" class="newsItemNumber" style="display: none;" type="textbox" value="&#96; + item.Id + &#96;" /><textarea id="&#96; + item.Id + &#96;-newsTitle" cols="20" rows="5">` + item.Title + `</textarea>

<select id="&#96; + item.Id + &#96;-newsHeadlineNews">
<option value="Yes">Yes</option>
<option value="No">No</option>
</select><textarea id="&#96; + item.Id + &#96;-newsSubTitle" cols="20" rows="5">` + item.NewsSubTitle + `</textarea><textarea id="&#96; + item.Id + &#96;-newsBodyText" cols="30" rows="5">` + item.newsBody + `</textarea><textarea id="&#96; + item.Id + &#96;-newsImgUrl" cols="20" rows="5">` + item.newsImage + `</textarea>

`);
} else {
$('#newsTable').append(`

<input name="&#96; + item.Id + &#96;" type="checkbox" value="&#96; + item.Id + &#96;" />
<input id="&#96; + item.Id + &#96;-newsitem" class="newsItemNumber" style="display: none;" type="textbox" value="&#96; + item.Id + &#96;" /><textarea id="&#96; + item.Id + &#96;-newsTitle" cols="20" rows="5">` + item.Title + `</textarea>

<select id="&#96; + item.Id + &#96;-newsHeadlineNews">
<option value="No">No</option>
<option value="Yes">Yes</option>
</select><textarea id="&#96; + item.Id + &#96;-newsSubTitle" cols="20" rows="5">` + item.NewsSubTitle + `</textarea><textarea id="&#96; + item.Id + &#96;-newsBodyText" cols="30" rows="5">` + item.newsBody + `</textarea><textarea id="&#96; + item.Id + &#96;-newsImgUrl" cols="20" rows="5">` + item.newsImage + `</textarea>

`);
}
}
},
error: function(data) {
$("#newsTableResults").empty().text(data.responseJSON.error);
}
});
}

As you can see, when the AJAX call returns the data and builds each item, there is a check box that is created before each list item.  This checkbox is the center data point for other functions. This checkbox stores the value of the list item’s Id. Each time the update or delete functions are executed, the first thing those functions do is look for which check boxes are selected.

addnewsitem();

The next function we’ll look at is the addNewsItem(); function. This function has some extra logic steps that it runs. When an item is added, the function will store the information passed into variables. If the article is selected to be ‘headline news’ the code checks if there are any checkboxes selected (which there should not be). For each item that is currently marked ‘Yes’ for the headline news, the script will execute an AJAX call and pass an updated value changing it to ‘No.’ This will prevent more than one item being marked ‘Headline News.’ Then, the script will make another AJAX call submitting the new list item. If there are no other items that are marked ‘headline news’ then the script bypasses the previous logic and executes the AJAX call submitting the new item to the list. Some items to note, the type of AJAX call needs to be set to POST, in the headers of the AJAX call make sure that the ‘X-HTTP-Method’ is set to POST, the X-RequestDigest needs to be set to $(‘#__REQUESTDIGEST’).val(); (those are double underscores in the beginning).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
function addNewsItem() {
var newNewsTitle = $("#newNewsTitle").val();
var newHeadlineNews = $("#newHeadlineNews").val();
var newSubTitle = $('#newSubTitle').val();
var newNewsBody = $('#newNewsBody').val();
var newImgURL = $('#newImgURL').val();
if (newHeadlineNews == "Yes") {
$('input:checkbox').each(function() {
if ($(this).not(':checked')) {
var newsId = $(this).val();
}

$('#' + newsId + '-newsHeadlineNews').each(function() {
if ($(this).val() == "Yes") {
/* var newText = newsId + "text";
var titleText = $("#newNewsTitle").val();*/

var unPublish = 'No';

$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('News')/items(" + newsId + ")", // list item ID
type: "POST",
data: JSON.stringify({
__metadata: {
type: "SP.Data.NewsListItem"
},
headlineNews: unPublish
}),
headers: {
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"IF-MATCH": "*",
"X-HTTP-Method": "MERGE"
},
success: function(data, status, xhr) {

},
error: function(xhr, status, error) {
$("#ResultDiv").empty().text(error);
}
});
}
});
});

$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('News')/items",
type: "POST",
data: JSON.stringify({
__metadata: {
type: "SP.Data.NewsListItem"
},
Title: newNewsTitle,
NewsSubTitle: newSubTitle,
newsBody: newNewsBody,
newsImage: newImgURL,
headlineNews: newHeadlineNews
}),
headers: {
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"X-HTTP-Method": "POST"
},
success: function(data, status, xhr) {
retrieveNewsItems();
},
error: function(xhr, status, error) {
$("#ResultDiv").empty().text(data.responseJSON.error);
}
});
} else {
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('News')/items",
type: "POST",
data: JSON.stringify({
__metadata: {
type: "SP.Data.NewsListItem"
},
Title: newNewsTitle,
NewsSubTitle: newSubTitle,
newsBody: newNewsBody,
newsImage: newImgURL,
headlineNews: newHeadlineNews
}),
headers: {
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"X-HTTP-Method": "POST"
},
success: function(data, status, xhr) {
retrieveNewsItems();
},
error: function(xhr, status, error) {
$("#ResultDiv").empty().text(data.responseJSON.error);
}
});
}
}

updatenewsitem();

The next function gives us the ability to update the current items. When this function is run, the first thing that it does is check to see which items have the checkbox selected (remember how I mentioned that the checkbox is important?). For each item that is selected, the script stores the checkbox value as the itemId variable. It then stores the rest of the information as variables as well, regardless if it was actually updated. It then conducts an AJAX call that includes the itemId variable in the call (to make sure we’re hitting the right item). Once that is done, it passes the updated information. Some items to note, in the headers of the AJAX call, make sure that the ‘X-HTTP-Method’ is set to MERGE, the X-RequestDigest needs to be set to $(‘#__REQUESTDIGEST’).val(); (those are double underscores in the beginning) to get the digest value for security, and set the ‘if-match’ to *.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function updateNewsItem() {
$('input[type="checkbox"').each(function() {
if ($(this).is(':checked')) {
var itemId = $(this).val();
var titleText = $('#' + itemId + '-newsTitle').val();
var updatedHeadlineNews = $('#' + itemId + '-newsHeadlineNews').val();
var updatedNewsSubTitle = $('#' + itemId + '-newsSubTitle').val();
var updatedNewsBody = $('#' + itemId + '-newsBodyText').val();
var updatedNewsImage = $('#' + itemId + '-newsImgUrl').val();
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('News')/items(" + itemId + ")", // list item ID
type: "POST",
data: JSON.stringify({
__metadata: {
type: "SP.Data.NewsListItem"
},
Title: titleText,
headlineNews: updatedHeadlineNews,
NewsSubTitle: updatedNewsSubTitle,
newsBody: updatedNewsBody,
newsImage: updatedNewsImage
}),
headers: {
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"IF-MATCH": "*",
"X-HTTP-Method": "MERGE"
},
success: function(data, status, xhr) {
retrieveNewsItems();
},
error: function(xhr, status, error) {
$("#ResultDiv").empty().text(data.responseJSON.error);
}
});
}
});

}

DELETENEWSITEM();

This final function is a more simple one. The script, when executed, looks for which checkboxes are selected and for each one, it records the value in the itemId variable. Then the script will conduct an AJAX call passing the itemId in url string. It is set as a POST type, in the headers you still need to make sure that the ‘X-HTTP-Method’ is set to DELETE, IF-MATCH is set to *, and the X-RequestDigest needs to be set to $(‘#__REQUESTDIGEST’).val(); (those are double underscores in the beginning) to get the digest value for security.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function deleteNewsItem() {
$('input[type="checkbox"').each(function() {
if ($(this).is(':checked')) {
var itemId = $(this).val();
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('News')/items(" + itemId + ")",
type: "POST",
headers: {
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"IF-MATCH": "*",
"X-HTTP-Method": "DELETE"
},
success: function(data, status, xhr) {
retrieveNewsItems();
},
error: function(xhr, status, error) {
alert(data.responseJSON.error);
}
});
}
});
}

HTML

I want to include the HTML for the displays as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!-- NEWS MANAGEMENT -->

<section id="newsManagement">
<div id="addNewsItems">

<!-- The Modal -->
<div id="addNewsModal" class="modal-hidden">

<!-- Modal content -->
<div class="modal-content">
<div class="modal-header"></div>
<div class="modal-body">
<p class="headlineHeader">Add News Item</p>
Title

&nbsp;

Subtitle

&nbsp;

Body

&nbsp;

Image

&nbsp;

Promote to top?

<select id="newHeadlineNews">
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>

<button class="button orange-button">Add Item</button>

</div>
<div class="modal-footer"><center><a class="button orange-button close" href="#">Close</a></center></div>
</div>
</div>
</div>
<div id="editNewsItems">
<div id="newsTableResults" class="tg-wrap">
<table id="newsTable" class="tg">
<tbody>
<tr>
<th class="tg-yw41"></th>
<th class="tg-yw41">Title</th>
<th class="tg-yw41">Headline?</th>
<th class="tg-yw41">SubTitle</th>
<th class="tg-yw41">Body</th>
<th class="tg-yw41">Image Link</th>
</tr>
</tbody>
</table>
<div style="width: max-content; margin: 0px auto;"><a id="addNewsBtn" class="button orange-button" style="cursor: pointer; display: inline-block; padding-top: 10px; height: 22px;"></a>Add News
<button id="updateNewsBtn" class="button orange-button" style="cursor: pointer; display: inline-block;">Update</button>
<button id="deleteNewsBtn" class="button red-button" style="cursor: pointer; display: inline-block;">Delete</button></div>
</div>
</div>
</section>

As for the styling, I’ll leave that all up to you. Each site and implementation is different and can be set to, however, you would like. Get creative! Remember, the right answer is the one that works for your client or company. Center the development around the requirements and you will build an awesome solution.

Need help with SharePoint? Feel free to contact me.

Have a bigger project? Check out my company, UDig, LLC.