Merge pull request #3243 from edx/dcs/pdfbook-logging
Added analytics event logging to PDF book viewer
This commit is contained in:
@@ -80,25 +80,46 @@ def pdf_index(request, course_id, book_index, chapter=None, page=None):
|
||||
raise Http404("Invalid book index value: {0}".format(book_index))
|
||||
textbook = course.pdf_textbooks[book_index]
|
||||
|
||||
if request.GET.get('viewer','') == 'true':
|
||||
return render_to_response('pdf_viewer.html')
|
||||
viewer_params = '&file='
|
||||
current_url = ''
|
||||
|
||||
if 'url' in textbook:
|
||||
textbook['url'] = remap_static_url(textbook['url'], course)
|
||||
viewer_params += textbook['url']
|
||||
current_url = textbook['url']
|
||||
|
||||
# then remap all the chapter URLs as well, if they are provided.
|
||||
current_chapter = None
|
||||
if 'chapters' in textbook:
|
||||
for entry in textbook['chapters']:
|
||||
entry['url'] = remap_static_url(entry['url'], course)
|
||||
if chapter is not None:
|
||||
current_chapter = textbook['chapters'][int(chapter) - 1]
|
||||
else:
|
||||
current_chapter = textbook['chapters'][0]
|
||||
viewer_params += current_chapter['url']
|
||||
current_url = current_chapter['url']
|
||||
|
||||
if page is not None:
|
||||
viewer_params += '&page={}'.format(page)
|
||||
|
||||
if request.GET.get('viewer','') == 'true':
|
||||
template = 'pdf_viewer.html'
|
||||
else:
|
||||
template = 'static_pdfbook.html'
|
||||
|
||||
return render_to_response(
|
||||
'static_pdfbook.html',
|
||||
template,
|
||||
{
|
||||
'book_index': book_index,
|
||||
'course': course,
|
||||
'textbook': textbook,
|
||||
'chapter': chapter,
|
||||
'page': page,
|
||||
'viewer_params': viewer_params,
|
||||
'current_chapter': current_chapter,
|
||||
'staff_access': staff_access,
|
||||
'current_url': current_url,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
102
lms/static/js/pdf-analytics.js
Normal file
102
lms/static/js/pdf-analytics.js
Normal file
@@ -0,0 +1,102 @@
|
||||
function sendLog(name, data, event_type) {
|
||||
var message = data || {};
|
||||
message.chapter = PDF_URL || '';
|
||||
message.name = "textbook.pdf." + name;
|
||||
Logger.log(event_type ? event_type : message.name, message);
|
||||
};
|
||||
|
||||
// this event is loaded after the others to accurately represent the order of events:
|
||||
// click next -> pagechange
|
||||
$(function() {
|
||||
var first_page = true;
|
||||
var scroll = {timeStamp: 0, direction: null};
|
||||
|
||||
$(window).bind("pagechange", function(event) {
|
||||
// log every page render
|
||||
var page = event.originalEvent.pageNumber;
|
||||
var old_page = PDFView.previousPageNumber;
|
||||
// pagechange is called many times per viewing.
|
||||
if (PDFView.previousPageNumber !== page || first_page) {
|
||||
first_page = false;
|
||||
if ((event.timeStamp - scroll.timeStamp) < 50) {
|
||||
sendLog("page.scrolled", {"page": page, "direction": scroll.direction});
|
||||
}
|
||||
sendLog("page.loaded", {"type": "gotopage", "old": old_page, "new": page}, "book");
|
||||
scroll.timeStamp = 0;
|
||||
}
|
||||
});
|
||||
|
||||
$('#viewerContainer').bind('DOMMouseScroll mousewheel', function(event) {
|
||||
scroll.timeStamp = event.timeStamp;
|
||||
scroll.direction = PDFView.pageViewScroll.down ? "down" : "up";
|
||||
});
|
||||
});
|
||||
|
||||
$('#viewThumbnail,#sidebarToggle').on('click', function() {
|
||||
sendLog("thumbnails.toggled", {"page": PDFView.page});
|
||||
});
|
||||
|
||||
$('#thumbnailView a').live('click', function(){
|
||||
sendLog("thumbnail.navigated", {"page": $('#thumbnailView a').index(this) + 1, "thumbnail_title": $(this).attr('title')});
|
||||
});
|
||||
|
||||
$('#viewOutline').on('click', function() {
|
||||
sendLog("outline.toggled", {"page": PDFView.page});
|
||||
});
|
||||
|
||||
$('#previous').on('click', function() {
|
||||
sendLog("page.navigatednext", {"type": "prevpage", "new": PDFView.page - 1}, "book");
|
||||
});
|
||||
|
||||
$('#next').on('click', function() {
|
||||
sendLog("page.navigatednext", {"type": "nextpage", "new": PDFView.page + 1}, "book");
|
||||
});
|
||||
|
||||
$('#zoomIn,#zoomOut').on('click', function() {
|
||||
sendLog("zoom.buttons.changed", {"direction": $(this).attr("id") == "zoomIn" ? "in" : "out", "page": PDFView.page});
|
||||
});
|
||||
|
||||
$('#pageNumber').on('change', function() {
|
||||
sendLog("page.navigated", {"page": $(this).val()});
|
||||
});
|
||||
|
||||
var old_amount = 1;
|
||||
$(window).bind('scalechange', function(evt) {
|
||||
var amount = evt.originalEvent.scale;
|
||||
if (amount !== old_amount) {
|
||||
sendLog("display.scaled", {"amount": amount, "page": PDFView.page});
|
||||
old_amount = amount;
|
||||
}
|
||||
});
|
||||
|
||||
$('#scaleSelect').on('change', function() {
|
||||
sendLog("zoom.menu.changed", {"amount": $("#scaleSelect").val(), "page": PDFView.page});
|
||||
});
|
||||
|
||||
var search_event = null;
|
||||
$(window).bind("find findhighlightallchange findagain findcasesensitivitychange", function(event) {
|
||||
if (search_event && event.type == 'find') {
|
||||
clearTimeout(search_event);
|
||||
}
|
||||
search_event = setTimeout(function(){
|
||||
var message = event.originalEvent.detail;
|
||||
message.status = $('#findMsg').text();
|
||||
message.page = PDFView.page;
|
||||
var event_name = "search";
|
||||
switch (event.type) {
|
||||
case "find":
|
||||
event_name += ".executed";
|
||||
break;
|
||||
case "findhighlightallchange":
|
||||
event_name += ".highlight.toggled";
|
||||
break;
|
||||
case "findagain":
|
||||
event_name += ".navigatednext";
|
||||
break;
|
||||
case "findcasesensitivitychange":
|
||||
event_name += "casesensitivity.toggled";
|
||||
break;
|
||||
}
|
||||
sendLog(event_name, message);
|
||||
}, 500);
|
||||
});
|
||||
@@ -23,15 +23,13 @@ http://sourceforge.net/adobe/cmap/wiki/License/
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<meta name="google" content="notranslate">
|
||||
<title>PDF.js viewer</title>
|
||||
<title>${current_chapter['title'] if current_chapter else '' |h}</title>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="${static.url('/static/css/vendor/pdfjs/viewer.css')}"/>
|
||||
|
||||
<script type="text/javascript" src="${static.url('/static/js/vendor/pdfjs/compatibility.js')}"></script>
|
||||
|
||||
|
||||
|
||||
<!-- This snippet is used in production, see Makefile -->
|
||||
<link rel="resource" type="application/l10n" href="${static.url('/static/js/vendor/pdfjs/locale/locale.properties')}"/>
|
||||
<script type="text/javascript" src="${static.url('/static/js/vendor/pdfjs/l10n.js')}"></script>
|
||||
@@ -41,8 +39,11 @@ http://sourceforge.net/adobe/cmap/wiki/License/
|
||||
PDFJS.imageResourcesPath = '${static.url('/static/css/vendor/pdfjs/images/')}';
|
||||
PDFJS.workerSrc = '${static.url('/static/js/vendor/pdfjs/pdf.worker.js')}';
|
||||
PDFJS.cMapUrl = '${static.url('/static/css/vendor/pdfjs/cmaps/')}';
|
||||
PDF_URL = '${current_url | h}';
|
||||
</script>
|
||||
<script type="text/javascript" src="${static.url('/static/js/vendor/pdfjs/viewer.js')}"></script>
|
||||
<%static:js group='main_vendor'/>
|
||||
<%static:js group='application'/>
|
||||
<%static:js group='courseware'/>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -401,7 +402,8 @@ PDFJS.cMapUrl = '${static.url('/static/css/vendor/pdfjs/cmaps/')}';
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="${static.url('/static/js/pdf-analytics.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('/static/js/vendor/pdfjs/viewer.js')}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ $(function(){
|
||||
'title': $(this).text()
|
||||
});
|
||||
$('#viewer-frame').focus();
|
||||
Logger.log("textbook.pdf.chapter.navigated", {"name": "textbook.pdf.chapter.navigated", "chapter": url, "chapter_title": $(this).text()});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -39,26 +40,11 @@ $(function(){
|
||||
</section>
|
||||
%endif
|
||||
|
||||
<%
|
||||
params = '&file='
|
||||
label = ""
|
||||
if 'url' in textbook:
|
||||
params += textbook['url']
|
||||
elif chapter is not None:
|
||||
chap = textbook['chapters'][int(chapter) - 1]
|
||||
else:
|
||||
chap = textbook['chapters'][0]
|
||||
params += chap['url']
|
||||
label = chap['title']
|
||||
|
||||
if page is not None:
|
||||
params += '&page={}'.format(page)
|
||||
%>
|
||||
<div class="book">
|
||||
<iframe
|
||||
title="${label}"
|
||||
title="${current_chapter['title']|h}"
|
||||
id="viewer-frame"
|
||||
src="${request.path}?viewer=true${params}#zoom=page-fit"
|
||||
src="${request.path}?viewer=true${viewer_params}#zoom=page-fit"
|
||||
width="856"
|
||||
height="1108"
|
||||
frameborder="0"
|
||||
|
||||
Reference in New Issue
Block a user