Skip to content

Instantly share code, notes, and snippets.

@MayaGans
Forked from gadenbuie/app.R
Last active January 3, 2020 16:10
Show Gist options
  • Save MayaGans/ec7255dbc3d3241f1f591ac1a79194dd to your computer and use it in GitHub Desktop.
Save MayaGans/ec7255dbc3d3241f1f591ac1a79194dd to your computer and use it in GitHub Desktop.
drag and drop a new element
library(shiny)
library(tidyverse)
ui <- fluidPage(
tags$head(
tags$link(rel = "//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"),
tags$script(src = "https://code.jquery.com/ui/1.12.1/jquery-ui.js"),
tags$link(href = "styles.css", rel = "stylesheet")
),
fluidRow(
tableOutput("debug")
),
fluidRow(
div(
class = "col-xs-12 col-sm-3",
h4("Add Input"),
tags$ul(
id = "sortable",
tags$li(
id = "ttest",
class = "ui-state-default",
"T-Test"
),
tags$li(
id = "chg",
class = "ui-state-default",
"CHG"
),
tags$li(
id = "mean",
"Mean"
),
tags$li(
id = "freq",
"Freq"
)
)
),
div(
class = "col-xs-12 col-sm-9",
h4("Drop Here"),
div(
id = "droppable",
# I want to use sortTxtbox to be able to re-arrange the list
# I added to JS:
# $(".sortTxtbox").sortable();
# $(".sortTxtbox").disableSelection();
class = "ui-widget-header sortTxtbox"
)
)),
div(
class = "col-xs-12 col-sm-3",
id = "inside_drop_zone", style="background:lightgrey;"),
tags$script(src = "script.js")
)
server <- function(input, output, session) {
# How do I get this to also print Mean and Freq blocks I add?
output$debug <- renderTable({
as.data.frame(read_html(input$drop_zone) %>% html_table(fill=TRUE)) %>%
separate(1, into = c("Aggregate", "Select"), sep=":")
})
}
shinyApp(ui, server)
$(function () {
$("#sortable").sortable();
$("#sortable").disableSelection();
$(".sortTxtbox").sortable();
$(".sortTxtbox").disableSelection();
});
// remove the item from the list
$("#droppable").on('click', '.delete', function() {
$(this).parent().remove();
});
// get the length every select in the droppable div
// create unique ids for each
function getNewId(type) {
var newId;
newId = $('#droppable').find('select').length
return type + (newId + 1);
}
// How can we expand this function to re-run everytime there's a change in the droppable zone
// so that the inputs reflect when a block is deleted or rearranged?
$(function () {
$(".draggable").draggable();
$("#droppable").droppable({
drop: function (event, ui) {
var draggableId = ui.draggable.attr("id");
var newid = getNewId(draggableId);
// selectInput('${newid}', "${newid}", choices = c("Volvo", "Saab", "Fiat", "Audi"))
if (draggableId.includes("ttest")) {
$(this).append(`<div class="form-group drop_area">
<label class="control-label" for="${newid}">T-TEST</label>
<select id="${newid}">
<option value="week1" selected>Week 1</option>
<option value="week2">Week 2</option>
<option value="week3">Week 3</option>
<option value="week4">Week 4</option></select>
<script type="application/json" data-for="${newid}" data-nonempty="">{}</script>
<button class="delete">Delete</button>
</div>`)
} else if (draggableId.includes("chg")) {
$(this).append(`<div class="form-group drop_area">
<label class="control-label" for="${newid}">CHG</label>
<select id="${newid}">
<option value="week1" selected>Week 1</option>
<option value="week2">Week 2</option>
<option value="week3">Week 3</option>
<option value="week4">Week 4</option></select>
<script type="application/json" data-for="${newid}" data-nonempty="">{}</script>
<button class="delete">Delete</button>
</div>`)
} else {
$(this).append(`
<div>
<div>
<div class="form-group drop_area">
<label class="control-label" for="${newid}">${newid.replace(/[0-9]/g, '').toUpperCase()}</label>
<script type="application/json" data-for="${newid}" data-nonempty="">{}</script>
<button class="delete">Delete</button>
</div>
</div>
</div>`)
}
}
});
});
// this doesn't update when option:selected changes
// maybe turn this function into a callback to be used
var target = document.querySelector('#droppable')
var observer = new MutationObserver(function(mutations) {
var str = "";
$('#droppable label').each(function() {
const txt = $(this).text() // changed
const val = $(this).parent().find("select").children("option:selected").val()
str += "<tr><td>" + txt + (val ? ": " + val : "") + "</td></tr>";
})
document.getElementById("inside_drop_zone").innerHTML = '<table>' + str + '</table>'
let str_to_table = '<table>' + str + '</table>'
Shiny.setInputValue('drop_zone', str_to_table)
})
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };
// pass in the target node, as well as the observer options
observer.observe(target, config);
#sortable, #sortable1 {
list-style-type: none;
margin: 0;
padding: 0;
width: 60%;
}
li {
list-style-type: none;
}
#sortable li {
margin: 5px;
padding: 0.4em;
padding-left: 1.5em;
font-size: 1.4em;
width: 146px;
border: 1px solid lightgray;
}
#sortable li:hover {
cursor: grab;
}
#sortable .ui-sortable-helper {
background-color: #ddd;
border-color: black;
}
#sortable .ui-sortable-helper:hover {
cursor: grabbing;
}
#droppable {
border: 2px dashed #466683;
padding: 1em;
min-height: 200px;
}
#droppable.ui-droppable-hover {
background: #bad4ed;
}
#droppable select {
margin: 5px;
}
.drop_area {
border: 1px solid lightgray;
padding: 3px;
margin-bottom: 3px;
width: 100%;
}
.delete {
background: none;
border: 0px;
color: #888;
font-size: 15px;
width: 60px;
margin: 0px 0 0;
font-family: Lato, sans-serif;
cursor: pointer;
float: right;
display: inline-block;
}
button:hover {
color: #CF2323;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment