Skip to content

Commit f81c49e

Browse files
nathancdaylionel-
authored andcommitted
Add keyboard shortcuts
Closes #13 Closes #64
1 parent ef37e2b commit f81c49e

File tree

3 files changed

+85
-24
lines changed

3 files changed

+85
-24
lines changed

R/shiny-server.R

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ vdiffrServer <- function(cases) {
3030
output$case_context <- renderCaseContext(input, cases)
3131

3232
toggleValidateBtns(input, session)
33+
listenToKeys(input, session, cases)
3334

3435
quitApp(input)
3536
})
@@ -49,8 +50,9 @@ prettify_types <- function(x) {
4950
renderTypeInput <- function(input, reactive_cases) {
5051
shiny::renderUI({
5152
cases <- reactive_cases$all
52-
53+
5354
types <- unique(map_chr(cases, function(case) class(case)[[1]]))
55+
5456
if (length(types) == 0) {
5557
return(NULL)
5658
}
@@ -152,34 +154,33 @@ withdraw_cases <- function(cases) {
152154
}
153155

154156
validateSingleCase <- function(input, reactive_cases) {
155-
shiny::observe({
156-
if (input$case_validation_button > 0) {
157-
cases <- shiny::isolate(reactive_cases$all)
158-
case <- shiny::isolate(input$case)
157+
shiny::observeEvent(c(input$case_validation_button, input[["validateCase"]]), {
158+
159+
cases <- shiny::isolate(reactive_cases$all)
160+
case <- shiny::isolate(input$case)
161+
shiny::req(input$case)
159162

160-
withdraw_cases(cases[case])
161-
cases[[case]] <- success_case(cases[[case]])
163+
withdraw_cases(cases[case])
164+
cases[[case]] <- success_case(cases[[case]])
162165

163-
shiny::isolate(reactive_cases$all <- cases)
164-
}
165-
})
166+
shiny::isolate(reactive_cases$all <- cases)
167+
})
166168
}
167169

168-
validateGroupCases <- function(input, reactive_cases) {
169-
shiny::observe({
170-
if (input$group_validation_button > 0) {
171-
active_cases <- shiny::isolate(reactive_cases$active())
172-
cases <- shiny::isolate(reactive_cases$all)
173-
174-
if (length(cases) > 0) {
175-
type <- shiny::isolate(input$type)
170+
validateGroupCases <- function(input, reactive_cases, session) {
171+
shiny::observeEvent(c(input$group_validation_button, input[["validateGroup"]]), {
172+
active_cases <- shiny::isolate(reactive_cases$active())
173+
cases <- shiny::isolate(reactive_cases$all)
174+
175+
if (length(cases) > 0) {
176+
shiny::req(input$type)
177+
type <- shiny::isolate(input$type)
176178

177-
withdraw_cases(active_cases)
178-
idx <- sapply(cases, inherits, type)
179-
cases[idx] <- lapply(cases[idx], success_case)
179+
withdraw_cases(active_cases)
180+
idx <- sapply(cases, inherits, type)
181+
cases[idx] <- lapply(cases[idx], success_case)
180182

181-
shiny::isolate(reactive_cases$all <- cases)
182-
}
183+
shiny::isolate(reactive_cases$all <- cases)
183184
}
184185
})
185186
}
@@ -230,6 +231,29 @@ toggleValidateBtns <- function(input, session) {
230231
})
231232
}
232233

234+
listenToKeys <- function(input, session, reactive_cases) {
235+
shiny::observeEvent(input[["nextCase"]], {
236+
names <- unique(names(reactive_cases$active()))
237+
shiny::updateSelectInput(session, "case",
238+
selected = next_element(input$case, names))
239+
})
240+
shiny::observeEvent(input[["prevCase"]], {
241+
names <- unique(names(reactive_cases$active()))
242+
shiny::updateSelectInput(session, "case",
243+
selected = next_element(input$case, names, direction = -1))
244+
})
245+
shiny::observeEvent(input[["nextType"]], {
246+
types <- unique(map_chr(reactive_cases$all, function(case) class(case)[[1]]))
247+
shiny::updateSelectInput(session, "type",
248+
selected = next_element(input$type, types))
249+
})
250+
shiny::observeEvent(input[["prevType"]], {
251+
types <- unique(map_chr(reactive_cases$all, function(case) class(case)[[1]]))
252+
shiny::updateSelectInput(session, "type",
253+
selected = next_element(input$type, types, direction = -1))
254+
})
255+
}
256+
233257
quitApp <- function(input) {
234258
shiny::observe({
235259
if (input$quit_button > 0) {

R/utils.R

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,17 @@ is_ci <- function() {
187187
is_bool <- function(x) {
188188
is_logical(x, n = 1) && !is.na(x)
189189
}
190+
191+
next_element <- function(element, group, direction = 1) {
192+
if (element == "") {
193+
return(NULL) # if a type is empty
194+
} else {
195+
next_position <- match(element, group) + direction
196+
if (next_position > length(group)) {
197+
next_position <- next_position - length(group)
198+
} else if (next_position < 1) {
199+
next_position <- length(group)
200+
}
201+
return(group[next_position])
202+
}
203+
}

inst/www/toggle.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,27 @@ Shiny.addCustomMessageHandler('toggle-validate-btns-handler', toggleBtns);
1313
function toggleBtns(message) {
1414
document.getElementById('group_validation_button').disabled = message;
1515
document.getElementById('case_validation_button').disabled = message;
16-
}
16+
}
17+
18+
//Keyboard shortcuts
19+
document.onkeydown = function(e) {
20+
if (e.shiftKey) { // using e.shiftKey && e.which == 86 simultaneously doesn't work?
21+
if (e.which == 39) { // down-arrow
22+
Shiny.onInputChange("nextType", Math.random());
23+
} else if (e.which == 37) { //up-arrow
24+
Shiny.onInputChange("prevType", Math.random());
25+
} else if (e.which == 86) { // v
26+
Shiny.onInputChange("validateGroup", Math.random());
27+
}
28+
} else {
29+
if (e.which == 39) { // right-arrow
30+
Shiny.onInputChange("nextCase", Math.random());
31+
} else if (e.which == 37) { // left-arrow
32+
Shiny.onInputChange("prevCase", Math.random());
33+
} else if (e.which == 86) { // v
34+
Shiny.onInputChange("validateCase", Math.random());
35+
} else if (e.which == 27) { //esc, q = 81
36+
Shiny.onInputChange("quit_button", Math.random());
37+
}
38+
}
39+
};

0 commit comments

Comments
 (0)