Skip to content

Instantly share code, notes, and snippets.

@nadavkav
Last active March 12, 2022 13:15
Show Gist options
  • Save nadavkav/009a275dc636bffb58662cd82f7b203d to your computer and use it in GitHub Desktop.
Save nadavkav/009a275dc636bffb58662cd82f7b203d to your computer and use it in GitHub Desktop.
Count user's timeonpage (only when it is focused)
function local_petel_before_footer() {
global $PAGE, $USER, $CFG;
$sesskey = sesskey();
// Save data as event into Moodle logstore_standard_log DB table.
$logurl = $CFG->wwwroot. '/local/petel/timeonpage.php';
// Count the time a user was looking at the page (page was in focus)
// TODO: https://stackoverflow.com/questions/33859522/how-much-of-an-element-is-visible-in-viewport
// TODO: refactore JS code to: https://usefulangle.com/post/62/javascript-send-data-to-server-on-page-exit-reload-redirect
// to avoide any delay on the user, when he/she navigate to a new page.
//
$PAGE->requires->js_amd_inline("
require(['jquery'], function($) {
$(document).ready(function() {
var start = new Date();
// Save user's focus time on page.
// end - start = all the time the page was visible, but not necessarily focused.
/*
// This method pause user navigation, it is sync.
$(window).on('beforeunload', function(e) {
console.log('Total focus time on page = ' + window.timercounter + ' sec.');
var end = new Date();
$.ajax({
url: '{$logurl}',
data: {'timespent': window.timercounter,
'contextid': {$PAGE->context->id},
'userid': {$USER->id},
'sesskey': '{$sesskey}'},
async: false
})
});
*/
// https://usefulangle.com/post/62/javascript-send-data-to-server-on-page-exit-reload-redirect
// This method does not pause user navigation, it is async.
$(window).on('beforeunload', function(e) {
var fd = new FormData();
fd.append('timespent', window.timercounter);
fd.append('contextid', {$PAGE->context->id});
fd.append('userid', {$USER->id});
fd.append('sesskey', '{$sesskey}');
navigator.sendBeacon('$logurl', fd);
});
// Let's start counting user focus on page, immediately after it fully loads
startTimer();
});
window.timercounter = 0;
var myInterval;
// Active
window.addEventListener('focus', startTimer);
// Inactive
window.addEventListener('blur', stopTimer);
function timerHandler() {
window.timercounter++;
//document.getElementById('seconds').innerHTML = timercounter;
}
// Start timer
function startTimer() {
console.log('focus (timer on) @ ' + window.timercounter + ' sec.');
myInterval = window.setInterval(timerHandler, 1000);
}
// Stop timer
function stopTimer() {
console.log('lost focus (time off) @ ' + window.timercounter + ' sec.');
window.clearInterval(myInterval);
}
});
");
}
<?php
define('AJAX_SCRIPT', true);
ignore_user_abort(true);
require(__DIR__ . '/../../config.php');
$contextid = required_param('contextid', PARAM_INT);
$timespent = required_param('timespent', PARAM_INT);
$userid = required_param('userid', PARAM_INT);
if (isguestuser()) {
die;
}
// Security. (WIP)
list($context, $course, $cm) = get_context_info_array($contextid);
require_login($course->id, false, $cm);
//require_capability('moodle/role:review', $context);
//require_sesskey();
//$preftimings = json_decode($preftiming);
//echo json_encode($preftiming['domContentLoadedEventEnd']);
//var_dump($preftimings);
$eventdata = array();
$eventdata['context'] = $context;
$eventdata['other']['timespent'] = $timespent;
$eventdata['courseid'] = $course->id;
$eventdata['userid'] = $userid;
//$eventdata['action'] = 'timespent';
$eventdata['objectid'] = $context->instanceid;
$event = \local_petel\event\timeonpage_viewed::create($eventdata)->trigger();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment