Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shortcut and cursor listeners #16

Merged
merged 3 commits into from Oct 23, 2014
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -1,8 +1,8 @@
Package: shinyAce
Type: Package
Title: Ace editor bindings for Shiny
Version: 0.1.0
Date: 2013-10-10
Version: 0.1.1
Date: 2014-08-25
Author: Trestle Technology, LLC.
Maintainer: Jeff Allen <jeff@trestletech.com>
Description: Ace editor bindings to enable a rich text editing environment
@@ -23,67 +23,128 @@
#' of every keystroke as it happens.
#' @param wordWrap If set to \code{TRUE}, Ace will enable word wrapping.
#' Default value is \code{FALSE}.
#' @param cursorId The ID associated with a cursor change.
#' @param selectionId The ID associated with a change of selected text
#' @param hotkeys A list whose names are ID names and whose elements are the shortcuts of keys. Shortcuts can either be a simple string or a list with elements 'win' and 'mac' that that specifies different shortcuts for win and mac (see example).
#' @import shiny
#' @examples \dontrun{
#' aceEditor("myEditor", "Initial text for editor here", mode="r",
#' theme="ambiance")
#'
#' aceEditor("myCodeEditor", "# Enter code", mode="r",
#' hotkeys = list(helpKey="F1",
#' runKey=list(win="Ctrl-R|Ctrl-Shift-Enter",
#' mac="CMD-ENTER|CMD-SHIFT-ENTER")
#' ),
#' wordWrap=TRUE, debounce=10)
#' }
#' @author Jeff Allen \email{jeff@@trestletech.com}
#' @export
aceEditor <- function(outputId, value, mode, theme, vimKeyBinding = FALSE,
readOnly=FALSE, height="400px",
fontSize=12, debounce=1000, wordWrap=FALSE, selectionId=NULL){
js <- paste("var editor = ace.edit('",outputId,"');",sep="")
fontSize=12, debounce=1000, wordWrap=FALSE,
showLineNumbers = TRUE,highlightActiveLine=TRUE,
selectionId=NULL, cursorId=NULL, hotkeys=NULL){
editorVar = paste0("editor__",outputId)
#editorVar = "editor"
#editorIdVar = paste0("$('#", outputId, "')")
js <- paste("var ", editorVar," = ace.edit('",outputId,"');",sep="")
if (!missing(theme)){
js <- paste(js, "editor.setTheme('ace/theme/",theme,"');",sep="")
js <- paste(js, "", editorVar,".setTheme('ace/theme/",theme,"');",sep="")
}
if (vimKeyBinding){
js <- paste(js, "editor.setKeyboardHandler('ace/keyboard/vim');",sep="")
js <- paste(js, "", editorVar,".setKeyboardHandler('ace/keyboard/vim');",sep="")
}
if (!missing(mode)){

This comment has been minimized.

@trestletech

trestletech Oct 15, 2014
Owner

Shouldn't this block still be in there?

js <- paste(js, "editor.getSession().setMode('ace/mode/",mode,"');", sep="")
js <- paste(js, "", editorVar,".getSession().setMode('ace/mode/",mode,"');", sep="")
}
if (!missing(value)){
js <- paste(js, "editor.setValue(", jsQuote(value), ", -1);", sep="")
js <- paste(js, "", editorVar,".setValue(", jsQuote(value), ", -1);", sep="")
}
if (!showLineNumbers) {
js <- paste(js, "", editorVar,".renderer.setShowGutter(false);", sep="")
}
if (!highlightActiveLine) {
js <- paste(js, "", editorVar,".setHighlightActiveLine(false);", sep="")
}

if (readOnly){
js <- paste(js, "editor.setReadOnly(", jsQuote(readOnly), ");", sep="")
js <- paste(js, "", editorVar,".setReadOnly(", jsQuote(readOnly), ");", sep="")
}
if (!is.null(fontSize) && !is.na(as.numeric(fontSize))){
js <- paste(js, "document.getElementById('",outputId,"').style.fontSize='",
as.numeric(fontSize), "px'; ", sep="")
}

if (!is.null(debounce) && !is.na(as.numeric(debounce))){
# I certainly hope there's a more reasonable way to compare versions with an
# extra field in them...
# I certainly hope there's a more reasonable way to compare
# versions with an extra field in them...
re <- regexpr("^\\d+\\.\\d+\\.\\d+", packageVersion("shiny"))
shinyVer <- substr(packageVersion("shiny"), 0, attr(re, "match.length"))

minorVer <- as.integer(substr(packageVersion("shiny"),
attr(re, "match.length")+2,
nchar(packageVersion("shiny"))))
minorVer <- as.integer(substr(packageVersion("shiny"),
attr(re, "match.length")+2,
nchar(packageVersion("shiny"))))
comp <- compareVersion(shinyVer, "0.9.1")
if (comp < 0 || (comp == 0 && minorVer < 9004)){
warning(
"Shiny version 0.9.1.9004 required to use input debouncing in shinyAce.")
"Shiny version 0.9.1.9004 required to use input debouncing in shinyAce.")
}
js <- paste(js, "$('#",outputId,"').data('debounce',",debounce,");", sep="")

js <- paste(js, "$('#",outputId,"').data('debounce',",debounce,");",
sep="")
}

if (wordWrap){
js <- paste(js, "editor.getSession().setUseWrapMode(true);", sep="")
js <- paste(js, "", editorVar,".getSession().setUseWrapMode(true);", sep="")
}

js <- paste(js, "$('#", outputId, "').data('aceEditor',editor);", sep="")
js <- paste(js, "$('#", outputId, "').data('aceEditor',", editorVar,");", sep="")

if (!is.null(selectionId)){
selectJS <- paste("editor.getSelection().on(\"changeSelection\", function(){
selectJS <- paste("", editorVar,".getSelection().on(\"changeSelection\", function(){
Shiny.onInputChange(\"",selectionId,
"\",editor.getCopyText());})",
"\",", editorVar,".getCopyText());})",
sep="")
js <- paste(js, selectJS, sep="")
}

if (!is.null(cursorId)){
curJS <- paste("\n", editorVar,".getSelection().on(\"changeCursor\", function(){
Shiny.onInputChange(\"",cursorId,
"\",", editorVar,".selection.getCursor() );}\n);",
sep="")
js <- paste(js, curJS, sep="")
}

for (i in seq_along(hotkeys)) {
shortcut = hotkeys[[i]]
if (is.list(shortcut)) {
shortcut = paste0(names(shortcut),": '", shortcut,"'", collapse=", ")
} else {
shortcut = paste0("win: '",shortcut,"', mac: '",shortcut,"'")
}

id = names(hotkeys)[i]
code = paste0("
",editorVar,".commands.addCommand({
name: '",id,"',
bindKey: {", shortcut,"},
exec: function(",editorVar,") {
Shiny.onInputChange(\"",id,
"\",{
editorId : '",outputId,"',
selection: ", editorVar,".session.getTextRange(",editorVar,".getSelectionRange()),
cursor : ", editorVar,".selection.getCursor(),
randNum : Math.random()
});
},
readOnly: true // false if this command should not apply in readOnly mode
});
")
js = paste0(js, code)
}



tagList(
singleton(tags$head(
initResourcePaths(),
@@ -101,4 +162,3 @@ aceEditor <- function(outputId, value, mode, theme, vimKeyBinding = FALSE,
tags$script(type="text/javascript", HTML(js))
)
}

@@ -1,11 +1,12 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{aceEditor}
\alias{aceEditor}
\title{Render Ace}
\usage{
aceEditor(outputId, value, mode, theme, vimKeyBinding = FALSE,
readOnly = FALSE, height = "400px", fontSize = 12, debounce = 1000,
wordWrap = FALSE)
wordWrap = FALSE, showLineNumbers = TRUE, highlightActiveLine = TRUE,
selectionId = NULL, cursorId = NULL, keyId = NULL)
}
\arguments{
\item{outputId}{The ID associated with this element}
@@ -45,6 +46,17 @@ aceEditor(outputId, value, mode, theme, vimKeyBinding = FALSE,
\item{wordWrap}{If set to \code{TRUE}, Ace will enable
word wrapping. Default value is \code{FALSE}.}
\item{cursorId}{The ID associated with a cursor change.}
\item{selectionId}{The ID associated with a change of
selected text}
\item{keyId}{A list whose names are ID names and whose
elements are the shortcuts of keys. Shortcuts can either
be a simple string or a list with elements 'win' and
'mac' that that specifies different shortcuts for win and
mac (see example).}
}
\description{
Render an Ace editor on an application page.
@@ -53,6 +65,13 @@ Render an Ace editor on an application page.
\dontrun{
aceEditor("myEditor", "Initial text for editor here", mode="r",
theme="ambiance")
aceEditor("myCodeEditor", "# Enter code", mode="r",
keyId = list(helpKey="F1",
runKey=list(win="Ctrl-R|Ctrl-Shift-Enter",
mac="CMD-ENTER|CMD-SHIFT-ENTER")
),
wordWrap=TRUE, debounce=10)
}
}
\author{
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{getAceModes}
\alias{getAceModes}
\title{Get available modes}
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{getAceThemes}
\alias{getAceThemes}
\title{Get available themes}
@@ -1,4 +1,4 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{jsQuote}
\alias{jsQuote}
\title{Escape a JS String}
@@ -1,10 +1,10 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
% Generated by roxygen2 (4.0.1): do not edit by hand
\name{updateAceEditor}
\alias{updateAceEditor}
\title{Update Ace Editor}
\usage{
updateAceEditor(session, editorId, value, theme, readOnly, mode, fontSize,
wordWrap)
wordWrap, border = c("normal", "alert", "flash"))
}
\arguments{
\item{session}{The Shiny session to whom the editor
@@ -14,3 +14,4 @@ LaTeX: pdfLaTeX

BuildType: Package
PackageInstallArgs: --no-multiarch --with-keep.source
PackageRoxygenize: rd
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.