diff --git a/.gitignore b/.gitignore index 3151c335..6ba72d89 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,4 @@ -.Rproj.user -.Rhistory -.RData -tools/DataTables* -tools/Plugins -rsconnect/ -large.txt -inst/examples/random.R -.*.Rnb.cached -revdep/ +.Rproj.user +.Rhistory +.RData +.DS_Store diff --git a/inst/examples/DT-edit/app.R b/inst/examples/DT-edit/app.R index 36db1cd5..116dd425 100644 --- a/inst/examples/DT-edit/app.R +++ b/inst/examples/DT-edit/app.R @@ -3,43 +3,29 @@ library(DT) shinyApp( ui = fluidPage( title = 'Double-click to edit table cells', - fluidRow(column(12, h1('Client-side processing'), hr(), DTOutput('x1'))), - fluidRow(column(12, h1('Server-side processing'), hr(), DTOutput('x2'))), - fluidRow(column(12, h1('Server-side processing (no row names)'), hr(), DTOutput('x3'))) + titlePanel('Double-click to edit table cells'), + DTOutput('x1') ), server = function(input, output, session) { d1 = iris - d1$Date = Sys.time() + seq_len(nrow(d1)) - d2 = d3 = d1 - options(DT.options = list(pageLength = 5)) + output$x1 = renderDT(d1, selection = "none", editable = T, rownames = T, options = list( + editType = list("0" = "text", "1" = "text", "2" = "text", "3" = "text", "4" = "select"), + editAttribs = list("0" = list(placeholder = "Length"), "1" = list(placeholder = "Width"), + "2" = list(placeholder = "Length"), "3" = list(placeholder = "Width"), + "4" = list(options = c("setosa", "versicolor", "virginica"))) + )) - output$x1 = renderDT(d1, selection = 'none', server = FALSE, editable = TRUE) - output$x2 = renderDT(d2, selection = 'none', editable = TRUE) - output$x3 = renderDT(d3, selection = 'none', rownames = FALSE, editable = TRUE) - - proxy2 = dataTableProxy('x2') - - observeEvent(input$x2_cell_edit, { - info = input$x2_cell_edit + proxy1 = dataTableProxy('x1') + + observeEvent(input$x1_cell_edit, { + info = input$x1_cell_edit str(info) i = info$row j = info$col v = info$value - d2[i, j] <<- DT::coerceValue(v, d2[i, j]) - replaceData(proxy2, d2, resetPaging = FALSE) # important - }) - - proxy3 = dataTableProxy('x3') - - observeEvent(input$x3_cell_edit, { - info = input$x3_cell_edit - str(info) - i = info$row - j = info$col + 1 # column index offset by 1 - v = info$value - d3[i, j] <<- DT::coerceValue(v, d3[i, j]) - replaceData(proxy3, d3, resetPaging = FALSE, rownames = FALSE) + d1[i, j] <<- DT::coerceValue(v, d1[i, j]) + replaceData(proxy1, d1, resetPaging = FALSE) # important }) } ) diff --git a/inst/htmlwidgets/datatables.js b/inst/htmlwidgets/datatables.js index d66752c9..7ff11415 100644 --- a/inst/htmlwidgets/datatables.js +++ b/inst/htmlwidgets/datatables.js @@ -682,29 +682,136 @@ HTMLWidgets.widget({ // run the callback function on the table instance if (typeof data.callback === 'function') data.callback(table); - // double click to edit the cell - if (data.editable) table.on('dblclick.dt', 'tbody td', function() { - var $input = $(''); - var $this = $(this), value = table.cell(this).data(), html = $this.html(); - var changed = false; - $input.val(value); - $this.empty().append($input); - $input.css('width', '100%').focus().on('change', function() { - changed = true; - var valueNew = $input.val(); - if (valueNew != value) { - table.cell($this).data(valueNew); - if (HTMLWidgets.shinyMode) changeInput('cell_edit', cellInfo($this)); - // for server-side processing, users have to call replaceData() to update the table - if (!server) table.draw(false); - } else { - $this.html(html); + // editor is enabled + if (data.editable) { + var editorNextCell = null; // declare variable for next cell to be acivated by the tab key + var options = table.init(); // load table options + if ('editType' in options) { + for (var key in options.editType) { + colIndex = parseInt(key); + if (table.column(0).header().innerHTML == ' ') + colIndex = colIndex + 1; + $(table.column(colIndex).header()).attr('data-editortype', options.editType[key]).attr('data-editoroptions', JSON.stringify(options.editAttribs[key])); // set column editor attributes + } + } else { + table.columns().every(function() { + if (this.header().innerHTML != ' ') + $(this.header()).attr('data-editortype', 'text').attr('data-editoroptions', JSON.stringify({placeholder: this.header().innerHTML})); // set column editor attributes + }); + } + + // double click to edit the cell + table.on('dblclick.dt', 'tbody td', function() { + if (table.column(this).header().hasAttribute('data-editortype')) { // cell is marked as editable + var $this = $(this), value = table.cell(this).data(), html = $this.html(); + var changed = false; + if (table.column(this).header().getAttribute('data-editortype') == 'text') { // cell shall display a textinput + var $input = $(''); + $input.val(value); + $input.attr('placeholder', JSON.parse(table.column(this).header().getAttribute('data-editoroptions')).placeholder); + } else if (table.column(this).header().getAttribute('data-editortype') == 'select') { // cell shall display a selectinput + var $input = $('