broadcast_progress_event_to_client <- function(session, event, data) {
session$sendCustomMessage("tutorial.progress_event", list(
event = event,
data = data
))
}
broadcast_question_event_to_client <- function(session, label, answer) {
broadcast_progress_event_to_client(session = session,
event = "question_submission",
data = list(label = label, answer = answer))
}
register_default_event_handlers <- function() {
event_register_handler(
"session_start",
function(session, event, data) {
# The observer here needs to be registered at session_start; if it is
# called in initialize_tutorial(), then the "section_viewed" event fire
# too soon, which will cause errors when it calls get_object(), because
# the storage system won't yet be ready.
#
# This observer watches input$`tutorial-visible-sections`, and wraps it
# so that it fires a "section_viewed" event when a new section is added
# to that input value.
last_visible_sections <- character(0)
observe({
visible_sections <- session$input$`tutorial-visible-sections`
new_visible <- setdiff(visible_sections, last_visible_sections)
for (section in new_visible) {
event_trigger(
session,
"section_viewed",
data = list(sectionId = section)
)
}
# Note: `visible_sections` could have more or fewer items from
# `last_visible_sections`; the setdiff() above only detects if it has
# more. Always save the `visible_sections`.
last_visible_sections <<- visible_sections
})
}
)
event_register_handler(
"section_viewed",
function(session, event, data) {
label <- ns_wrap("section_viewed_", data$sectionId)
if (length(get_object(session = session, object_id = label)) == 0) {
first_time <- TRUE
save_object(
session = session,
object_id = label,
data = tutorial_object(
type = "section_viewed",
data = list(sectionId = data$sectionId)
)
)
} else {
first_time <- FALSE
}
if (first_time) {
event_trigger(
session,
"section_viewed_first_time",
data = list(sectionId = data$sectionId)
)
}
}
)
event_register_handler(
"question_submission",
function(session, event, data) {
# notify client side listeners
broadcast_question_event_to_client(
session = session,
label = data$label,
answer = data$answer
)
# store submission for later replay
save_question_submission(
session = session,
label = data$label,
question = data$question,
answer = data$answer
)
}
)
event_register_handler(
"reset_question_submission",
function(session, event, data) {
# notify client side listeners
broadcast_progress_event_to_client(
session,
"question_submission",
list(label = data$label, answer = NULL)
)
# store submission for later replay
save_reset_question_submission(
session = session,
label = data$label,
question = data$question
)
}
)
event_register_handler(
"section_skipped",
function(session, event, data) {
# notify client side listeners
broadcast_progress_event_to_client(
session = session,
event = "section_skipped",
data = data
)
# save for later replay
save_section_skipped(session = session, sectionId = data$sectionId)
}
)
event_register_handler(
"exercise_result",
function(session, event, data) {
# Should this event count towards exercise completion?
ex <- standardize_exercise_code(get_exercise_cache(data$label))
requires_check <- nzchar(ex$check) || nzchar(ex$code_check)
# Only set `correct` on the `exercise_submission` event if a check was required
correct <- if (requires_check && data$checked) data$feedback$correct
# Submission counts for completion when:
# 1. Some code is submitted
# 2. A check is not required OR the submission was checked
# (correctness does not affect completion)
completed <- nzchar(trimws(data$code)) && (!requires_check || data$checked)
# notify client side listeners
broadcast_progress_event_to_client(
session = session,
event = "exercise_submission",
data = list(label = data$label, correct = correct, completed = completed)
)
# save submission for later replay
save_exercise_submission(
session = session,
label = data$label,
code = data$code,
output = data$output,
error_message = data$error_message,
checked = data$checked,
feedback = data$feedback
)
}
)
event_register_handler(
"video_progress",
function(session, event, data) {
# notify client side listeners
broadcast_progress_event_to_client(session, "video_progress", data)
# save for later replay
save_video_progress(session, data$video_url, data$time, data$total_time)
}
)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.