Skip to content

Commit 4b8b50a

Browse files
committed
Add document and message link detection to message view. Allow navigation based on back/forward
1 parent bc45d61 commit 4b8b50a

File tree

4 files changed

+257
-110
lines changed

4 files changed

+257
-110
lines changed

js/custom.js

Lines changed: 192 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,32 @@ var msgModal;
3030
var msgModalTitle;
3131
var msgModalBody;
3232
var msgModalShare;
33+
var msgModalHistoryDepth = 0;
34+
35+
function validateAndUseURLParams(url) {
36+
urlParamMsgType = stringToMsgType(getUrlParameter(url, 'type'));
37+
urlParamMsgYear = parseInt(getUrlParameter(url, 'year'));
38+
urlParamMsgNumber = parseInt(getUrlParameter(url, 'number'));
39+
40+
//Use url parameter msg type as the default selected msg type in the UI filter.
41+
if (urlParamMsgType != MsgType.UNKNOWN) {
42+
userSelectedMsgType = urlParamMsgType;
43+
//Only prefill url param msg year if the url param msg type is valid.
44+
if (urlParamMsgYear > -1) {
45+
userSelectedMsgYear = urlParamMsgYear;
46+
47+
if (urlParamMsgNumber > -1) {
48+
userSelectedMsgNumber = urlParamMsgNumber;
49+
} else {
50+
userSelectedMsgNumber = -1
51+
}
52+
} else {
53+
userSelectedMsgYear = -1
54+
}
55+
} else {
56+
userSelectedMsgType = MsgType.NAVADMIN
57+
}
58+
}
3359

3460
$(document).ready(function() {
3561
//Set callback for setting wait cursor
@@ -45,18 +71,7 @@ $(document).ready(function() {
4571
msgModalBody = $('#msg-body-modal .modal-body');
4672
msgModalShare = $('#msg-body-modal .modal-share-link');
4773

48-
urlParamMsgType = stringToMsgType(getUrlParameter(window.location.href, 'type'));
49-
urlParamMsgYear = parseInt(getUrlParameter(window.location.href, 'year'));
50-
urlParamMsgNumber = parseInt(getUrlParameter(window.location.href, 'number'));
51-
52-
//Use url parameter msg type as the default selected msg type in the UI filter.
53-
if (urlParamMsgType != MsgType.UNKNOWN) {
54-
userSelectedMsgType = urlParamMsgType;
55-
//Only prefill url param msg year if the url param msg type is valid.
56-
if (urlParamMsgYear > -1) {
57-
userSelectedMsgYear = urlParamMsgYear;
58-
}
59-
}
74+
validateAndUseURLParams(window.location.href)
6075

6176
//Load previously stored messages from local storage
6277
if (isLocalStorageSupported()) {
@@ -84,47 +99,40 @@ $(document).ready(function() {
8499
console.log('Could not add event listener for visibilitychange', e);
85100
}
86101

102+
setUIInLoadingStatus(true, "Getting available messages");
87103
setFilterMsgTypeDropdown(availableMsgTypes);
88104
setFilterMsgYearDropdown(userSelectedMsgType, userSelectedMsgYear);
89105
setTableMessages(userSelectedMsgType, userSelectedMsgYear);
90-
setUIInLoadingStatus(true, "Getting available messages");
91-
92-
93-
function getMessageYearsAndMetadata() {
94-
return function() {
95-
getYearsForMsgType( // Get years for message type
96-
userSelectedMsgType,
97-
[],
98-
userSelectedMsgYear == -1,
99-
function() {
100-
if (!setFilterMsgYearDropdown(userSelectedMsgType, userSelectedMsgYear)) { console.log("getMessageYearsAndMetadata > fetch > completionHandler > setFilterMsgYearDropdown did not have data to complete.") }
101-
102-
getYearsForMsgType( //Get message metadata for the user selected year or latest year
103-
userSelectedMsgType,
104-
[userSelectedMsgYear > -1 ? userSelectedMsgYear : latestYearForMsgType(userSelectedMsgType)],
105-
false,
106-
function() {
107-
if (!setTableMessages(userSelectedMsgType, userSelectedMsgYear)) { console.log("getMessageYearsAndMetadata > fetch > completionHandler > fetch > completionHandler > setTableMessages did not have data to complete.")}
108-
}
109-
)
110-
}
111-
);
112-
}
113-
}
114106

115107
//Use url params to start loading a message to view if the url params are valid.
116-
if (urlParamMsgType != MsgType.UNKNOWN && urlParamMsgYear > -1 && urlParamMsgNumber > -1) {
117-
getMsgBody(urlParamMsgType, urlParamMsgYear, urlParamMsgNumber, getMessageYearsAndMetadata());
108+
if (userSelectedMsgType != MsgType.UNKNOWN && userSelectedMsgYear > -1 && userSelectedMsgNumber > -1) {
109+
getMessageYearsAndMetadata(
110+
null,
111+
function() {
112+
prepareAndShowMessageModal(userSelectedMsgType, userSelectedMsgYear, userSelectedMsgNumber, null)
113+
})
114+
118115

119116
//Log launch with parameter
120117
if (typeof analytics !== 'undefined') {
121118
analytics.logEvent('LaunchParameter', {
122-
messageNumber: msgTypeToString(urlParamMsgType) + ' ' + pad(m.number, 3) + '/' + pad((m.year % 1000), 2)
119+
messageNumber: msgTypeToString(userSelectedMsgType) + ' ' + pad(m.number, 3) + '/' + pad((m.year % 1000), 2)
123120
});
124121
}
125122
} else {
126123
//No completely prefilled message selector found in url parameters.
127-
getMessageYearsAndMetadata()();
124+
getMessageYearsAndMetadata(
125+
function() {
126+
//debugger
127+
setFilterMsgTypeDropdown(availableMsgTypes);
128+
setFilterMsgYearDropdown(userSelectedMsgType, userSelectedMsgYear);
129+
130+
},
131+
function() {
132+
//debugger
133+
setTableMessages(userSelectedMsgType, userSelectedMsgYear);
134+
}
135+
);
128136
}
129137

130138
$("#msg-search-input").on('keyup paste', msgFilterSearchInputChanged);
@@ -147,12 +155,39 @@ $(document).ready(function() {
147155
getBroadcast(null)
148156
});
149157

158+
function getMessageYearsAndMetadata(yearsCompletionHandler, metadataCompletionHandler) {
159+
getYearsForMsgType( // Get years for message type
160+
userSelectedMsgType,
161+
[],
162+
false,
163+
function() {
164+
if (!setFilterMsgYearDropdown(userSelectedMsgType, userSelectedMsgYear)) { console.log("getMessageYearsAndMetadata > fetch > completionHandler > setFilterMsgYearDropdown did not have data to complete.") }
165+
166+
getYearsForMsgType( //Get message metadata for the user selected year or latest year
167+
userSelectedMsgType,
168+
[userSelectedMsgYear > -1 ? userSelectedMsgYear : latestYearForMsgType(userSelectedMsgType)],
169+
false,
170+
function() {
171+
//debugger
172+
if (!setTableMessages(userSelectedMsgType, userSelectedMsgYear)) { console.log("getMessageYearsAndMetadata > fetch > completionHandler > fetch > completionHandler > setTableMessages did not have data to complete.")}
173+
if (metadataCompletionHandler)
174+
metadataCompletionHandler()
175+
}
176+
)
177+
178+
if (yearsCompletionHandler)
179+
yearsCompletionHandler()
180+
}
181+
);
182+
}
183+
150184
/**
151185
* Set UI loading status
152186
* @param {boolean} disable Show UI as loading.
153187
* @param {string} statusText Status text.
154188
*/
155189
function setUIInLoadingStatus(disable, statusText) {
190+
//console.trace()
156191
console.log(disable, statusText)
157192
if (disable) {
158193
loadingProgress.removeClass('bg-warning');
@@ -350,7 +385,7 @@ function setTableMessages(msgType, msgYear) {
350385
console.log('setTableMessages' + msgTypeToString(msgType) + ' ' + msgYear);
351386

352387
document.title = shortNameForMessage(msgType, msgYear) + ' - ' + NAVADMIN_VIEWER_TITLE;
353-
window.history.replaceState(document.title, NAVADMIN_VIEWER_TITLE, createURLParameters(msgType, msgYear));
388+
window.history.pushState(document.title, NAVADMIN_VIEWER_TITLE, createURLParameters(msgType, msgYear));
354389

355390
//If msgYear is -1, set the msgYear to the latest year for the message type.
356391
if (msgYear == -1) {
@@ -433,45 +468,13 @@ function setTableMessages(msgType, msgYear) {
433468
tr.attr('msg-type', msgTypeToString(m.type));
434469

435470
//Create click handler for table row
436-
function createHandler(msgType, msgYear, msgNumber) {
471+
function createHandler(msgType, msgYear, msgNumber, row) {
437472
return function(e) {
438473
e.preventDefault(); // cancel the link behaviour
439-
//tr.css('cursor', 'progress');
440-
userSelectedMsgType = msgType;
441-
userSelectedMsgYear = msgYear;
442-
userSelectedMsgNumber = msgNumber;
443-
444-
//Create completion handler to reset table row progress indicator when done
445-
function createCompletionHandler(tr) {
446-
return function() {
447-
tr.css('cursor', 'pointer');
448-
}
449-
}
450-
451-
//Check if current message exists in cache
452-
var cachedMsg = cachedMessages ? cachedMessages.get(msgType).get(msgYear)[msgNumber - 1] : null;
453-
if (cachedMsg && cachedMsg.Body && cachedMsg.Body.length > 0)
454-
showMessageModal(msgType, msgYear, msgNumber, cachedMsg.title, cachedMsg.Body);
455-
else
456-
getMsgBody(msgType, msgYear, msgNumber, function() {
457-
createCompletionHandler(tr)
458-
$('#'+shortNameForMessage(-1, msgYear, msgNumber).replace('/','\\/')).addClass('offline-enabled')
459-
if (
460-
(userSelectedMsgType == msgType && userSelectedMsgYear == msgYear && userSelectedMsgNumber == msgNumber) ||
461-
(urlParamMsgType == msgType && urlParamMsgYear == msgYear && urlParamMsgNumber == msgNumber)
462-
) {
463-
showMessageModal(
464-
msgType,
465-
msgYear,
466-
msgNumber,
467-
(cachedMsg && cachedMsg.title.length > 0 ? cachedMsg.title : ''),
468-
cachedMsg.Body
469-
);
470-
}
471-
} );
474+
prepareAndShowMessageModal(msgType, msgYear, msgNumber, row)
472475
};
473476
}
474-
tr.click(createHandler(m.type, m.year, m.number));
477+
tr.click(createHandler(m.type, m.year, m.number, tr));
475478

476479
$('#msg-list-table-body').append(tr);
477480

@@ -483,46 +486,94 @@ function setTableMessages(msgType, msgYear) {
483486
return true;
484487
}
485488

486-
function msgFilterSearchInputChanged(e) {
487-
var searchTerm = $(this).val().toUpperCase();
488-
var searchRE = new RegExp('.*?' + searchTerm + '.*?\\s?', 'g');
489-
var currentSearchArray = cachedMessages.get(userSelectedMsgType).get(userSelectedMsgYear);
490-
currentSearchArray.forEach(function(v) {
491-
if (!searchRE.test(v.title))
492-
v.tr.hide();
493-
else
494-
v.tr.show();
495-
});
496-
}
489+
/**
490+
* Prepare data for and show Message Modal. This is a standalone function so that it can be called from anywhere.
491+
* @param {MsgType} msgType The message type to show.
492+
* @param {number} msgYear The message year to show.
493+
* @param {number} msgNumber The message number to show.
494+
* @param {Element} row The message row to effect
495+
*/
496+
function prepareAndShowMessageModal(msgType, msgYear, msgNumber, row) {
497+
if (row)
498+
row.css('cursor', 'progress');
499+
userSelectedMsgType = msgType;
500+
userSelectedMsgYear = msgYear;
501+
userSelectedMsgNumber = msgNumber;
497502

498-
function navigateToAppStore(e) {
499-
e.preventDefault(); // cancel the link behaviour
500-
var appLink;
501-
var detectedOS = getMobileOperatingSystem();
502-
if (detectedOS == 'android') {
503-
appLink = 'https://play.google.com/store/apps/details?id=com.ansonliu.navadmin';
504-
} else {
505-
appLink = 'https://apps.apple.com/us/app/navadmin-viewer/id1345135985';
503+
//Check if current message exists in cache
504+
var cachedMsg = (cachedMessages && cachedMessages.get(msgType) && cachedMessages.get(msgType).get(msgYear)) ? cachedMessages.get(msgType).get(msgYear)[msgNumber - 1] : null;
505+
506+
function fetchAndShowMessage() {
507+
getMsgBody(msgType, msgYear, msgNumber, function() {
508+
if (row)
509+
row.css('cursor', 'pointer');
510+
$('#'+shortNameForMessage(-1, msgYear, msgNumber).replace('/','\\/')).addClass('offline-enabled')
511+
if (
512+
(userSelectedMsgType == msgType && userSelectedMsgYear == msgYear && userSelectedMsgNumber == msgNumber) ||
513+
(urlParamMsgType == msgType && urlParamMsgYear == msgYear && urlParamMsgNumber == msgNumber)
514+
) {
515+
var cachedMsg = (cachedMessages && cachedMessages.get(msgType) && cachedMessages.get(msgType).get(msgYear)) ? cachedMessages.get(msgType).get(msgYear)[msgNumber - 1] : null;
516+
setUIInLoadingStatus(false, null)
517+
showMessageModal(
518+
msgType,
519+
msgYear,
520+
msgNumber,
521+
(cachedMsg && cachedMsg.title.length > 0 ? cachedMsg.title : 'No message data'),
522+
(cachedMsg ? cachedMsg.Body : 'Error getting message data')
523+
);
524+
}
525+
} );
526+
}
527+
528+
if (!cachedMessages || !cachedMessages.get(msgType) || !cachedMessages.get(msgType).get(msgYear)) { // We don't have the cache structure for the msg type or msg year
529+
getYearsForMsgType(msgType, [msgYear], true, function() {fetchAndShowMessage()})
530+
} else if (cachedMsg && cachedMsg.Body && cachedMsg.Body.length > 0) { // We have the full message already
531+
showMessageModal(msgType, msgYear, msgNumber, cachedMsg.title, cachedMsg.Body);
532+
} else { //We have the cache structure ready but not the message
533+
fetchAndShowMessage();
506534
}
507-
location.assign(appLink);
508535
}
509536

537+
/**
538+
* Show Message Modal.
539+
* @param {MsgType} msgType The message type to show.
540+
* @param {number} msgYear The message year to show.
541+
* @param {number} msgNumber The message number to show.
542+
* @param {string} title The modal title
543+
* @param {string} body The modal body text
544+
*/
510545
function showMessageModal(msgType, msgYear, msgNumber, title, body) {
511546
var messageViewText = shortNameForMessage(msgType, msgYear, msgNumber);
512547
msgModalTitle.text(messageViewText + (title ? ' - ' + title : '')); //TODO: Do regex search in message body to find SUBJ if not metadata not downloaded from server
513-
msgModalBody.text(body);
548+
549+
//body = linkDocumentAndMessageReferences(body, messageViewText)
550+
//msgModalBody.html(body);
551+
try {
552+
body = linkDocumentAndMessageReferences(body, messageViewText)
553+
msgModalBody.html(body);
554+
} catch (e) {
555+
console.log('Linking document and message references had error ' + e)
556+
msgModalBody.text(body);
557+
}
558+
514559
msgModal.modal('show');
560+
msgModalHistoryDepth += 1;
515561

516562
//Set page title to reflect current contents
517563
document.title = msgModalTitle.text() + ' - ' + NAVADMIN_VIEWER_TITLE;
518564

519565
//Set window url to new message direct link parameters
520-
window.history.replaceState(document.title, title, createURLParameters(msgType, msgYear, msgNumber));
521-
522-
msgModal.on('hide.bs.modal', function (e) {
523-
document.title = shortNameForMessage(userSelectedMsgType, userSelectedMsgYear) + ' - ' + NAVADMIN_VIEWER_TITLE;
524-
window.history.replaceState(document.title, NAVADMIN_VIEWER_TITLE, createURLParameters(userSelectedMsgType, userSelectedMsgYear, -1));
525-
})
566+
window.history.pushState(document.title, title, createURLParameters(msgType, msgYear, msgNumber));
567+
568+
if (msgModalHistoryDepth == 1) {
569+
msgModal.on('hide.bs.modal', function (e) {
570+
console.log('message modal hidden')
571+
document.title = shortNameForMessage(userSelectedMsgType, userSelectedMsgYear) + ' - ' + NAVADMIN_VIEWER_TITLE;
572+
window.history.go(-msgModalHistoryDepth)
573+
msgModalHistoryDepth = 0
574+
console.log(window.location.href)
575+
})
576+
}
526577

527578
if (typeof analytics !== 'undefined') {
528579
//Log Viewed Message event
@@ -542,7 +593,41 @@ function shareUserSelectedMessageLink(e) {
542593
window.prompt("Copy the below share link to clipboard (\u229e Ctrl+C / \uf8ff \u2318+C)", shareLink);
543594
}
544595

545-
// $(window).on('popstate',function(event) {
546-
// console.log("pop location: " + document.location);
547-
// console.log(getUrlParameter(window.location.href, 'type'))
548-
// });
596+
function msgFilterSearchInputChanged(e) {
597+
var searchTerm = $(this).val().toUpperCase();
598+
var searchRE = new RegExp('.*?' + searchTerm + '.*?\\s?', 'g');
599+
var currentSearchArray = cachedMessages.get(userSelectedMsgType).get(userSelectedMsgYear);
600+
currentSearchArray.forEach(function(v) {
601+
if (!searchRE.test(v.title))
602+
v.tr.hide();
603+
else
604+
v.tr.show();
605+
});
606+
}
607+
608+
function navigateToAppStore(e) {
609+
e.preventDefault(); // cancel the link behaviour
610+
var appLink;
611+
var detectedOS = getMobileOperatingSystem();
612+
if (detectedOS == 'android') {
613+
appLink = 'https://play.google.com/store/apps/details?id=com.ansonliu.navadmin';
614+
} else {
615+
appLink = 'https://apps.apple.com/us/app/navadmin-viewer/id1345135985';
616+
}
617+
location.assign(appLink);
618+
}
619+
620+
$(window).on('popstate',function(event) {
621+
console.log('popstate' + window.location.href)
622+
oldUserSelectedMsgType = userSelectedMsgType
623+
oldUserSelectedMsgYear = userSelectedMsgYear
624+
validateAndUseURLParams(window.location.href)
625+
if (oldUserSelectedMsgType != userSelectedMsgType || oldUserSelectedMsgYear != userSelectedMsgYear) {
626+
getMessageYearsAndMetadata()
627+
}
628+
629+
if (userSelectedMsgType != MsgType.UNKNOWN && userSelectedMsgYear > -1 && userSelectedMsgNumber > -1) {
630+
prepareAndShowMessageModal(userSelectedMsgType, userSelectedMsgYear, userSelectedMsgNumber, null)
631+
}
632+
633+
});

0 commit comments

Comments
 (0)