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
Jump to file or symbol
Failed to load files and symbols.
+110 −30
Diff settings

Always

Just for now

View
@@ -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
View
@@ -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)){
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

This comment has been minimized.

@trestletech

trestletech Oct 15, 2014

Owner

Shouldn't this block still be in there?

@trestletech

trestletech Oct 15, 2014

Owner

Shouldn't this block still be in there?

# 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))
)
}
View
@@ -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{
View
@@ -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}
View
@@ -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}
View
@@ -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}
View
@@ -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
View
@@ -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.