Chromevox theme now an extension, added demo file, added findSearchBox event.
This commit is contained in:
parent
304b27954b
commit
38b42d20d3
4 changed files with 809 additions and 786 deletions
44
demo/chromevox.html
Normal file
44
demo/chromevox.html
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>ACE Autocompletion demo</title>
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<pre id="editor"></pre>
|
||||||
|
|
||||||
|
<!-- load ace -->
|
||||||
|
<script src="../build/src/ace.js"></script>
|
||||||
|
<!-- load ace language tools -->
|
||||||
|
<script src="../build/src/ext-chromevox.js"></script>
|
||||||
|
<script>
|
||||||
|
// trigger extension
|
||||||
|
ace.require("ace/ext/chromevox");
|
||||||
|
var editor = ace.edit("editor");
|
||||||
|
editor.session.setMode("ace/mode/html");
|
||||||
|
editor.setTheme("ace/theme/tomorrow");
|
||||||
|
// enable autocompletion and snippets
|
||||||
|
editor.setOptions({
|
||||||
|
enableBasicAutocompletion: true,
|
||||||
|
enableSnippets: true
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="./show_own_source.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
/* ChromeVox Ace namespace. */
|
|
||||||
var cvoxAce = {};
|
|
||||||
|
|
||||||
/* Typedefs for Closure compiler. */
|
/* ChromeVox Ace namespace. */
|
||||||
/**
|
var cvoxAce = {};
|
||||||
|
|
||||||
|
/* Typedefs for Closure compiler. */
|
||||||
|
/**
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
rate: number,
|
rate: number,
|
||||||
pitch: number,
|
pitch: number,
|
||||||
|
|
@ -12,27 +13,27 @@ define(function(require, exports, module) {
|
||||||
punctuationEcho: string
|
punctuationEcho: string
|
||||||
}}
|
}}
|
||||||
*/
|
*/
|
||||||
/* TODO(peterxiao): Export this typedef through cvox.Api. */
|
/* TODO(peterxiao): Export this typedef through cvox.Api. */
|
||||||
cvoxAce.SpeechProperty;
|
cvoxAce.SpeechProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* row: number,
|
* row: number,
|
||||||
* column: number
|
* column: number
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
cvoxAce.Cursor;
|
cvoxAce.Cursor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
type: string,
|
type: string,
|
||||||
value: string
|
value: string
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
cvoxAce.Token;
|
cvoxAce.Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These are errors and information that Ace will display in the gutter.
|
* These are errors and information that Ace will display in the gutter.
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
row: number,
|
row: number,
|
||||||
|
|
@ -41,91 +42,91 @@ define(function(require, exports, module) {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
cvoxAce.Annotation;
|
cvoxAce.Annotation;
|
||||||
|
|
||||||
/* Speech Properties. */
|
/* Speech Properties. */
|
||||||
/**
|
/**
|
||||||
* Speech property for speaking constant tokens.
|
* Speech property for speaking constant tokens.
|
||||||
* @type {cvoxAce.SpeechProperty}
|
* @type {cvoxAce.SpeechProperty}
|
||||||
*/
|
*/
|
||||||
var CONSTANT_PROP = {
|
var CONSTANT_PROP = {
|
||||||
'rate': 0.8,
|
'rate': 0.8,
|
||||||
'pitch': 0.4,
|
'pitch': 0.4,
|
||||||
'volume': 0.9
|
'volume': 0.9
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default speech property for speaking tokens.
|
* Default speech property for speaking tokens.
|
||||||
* @type {cvoxAce.SpeechProperty}
|
* @type {cvoxAce.SpeechProperty}
|
||||||
*/
|
*/
|
||||||
var DEFAULT_PROP = {
|
var DEFAULT_PROP = {
|
||||||
'rate': 1,
|
'rate': 1,
|
||||||
'pitch': 0.5,
|
'pitch': 0.5,
|
||||||
'volume': 0.9
|
'volume': 0.9
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speech property for speaking entity tokens.
|
* Speech property for speaking entity tokens.
|
||||||
* @type {cvoxAce.SpeechProperty}
|
* @type {cvoxAce.SpeechProperty}
|
||||||
*/
|
*/
|
||||||
var ENTITY_PROP = {
|
var ENTITY_PROP = {
|
||||||
'rate': 0.8,
|
'rate': 0.8,
|
||||||
'pitch': 0.8,
|
'pitch': 0.8,
|
||||||
'volume': 0.9
|
'volume': 0.9
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speech property for speaking keywords.
|
* Speech property for speaking keywords.
|
||||||
* @type {cvoxAce.SpeechProperty}
|
* @type {cvoxAce.SpeechProperty}
|
||||||
*/
|
*/
|
||||||
var KEYWORD_PROP = {
|
var KEYWORD_PROP = {
|
||||||
'rate': 0.8,
|
'rate': 0.8,
|
||||||
'pitch': 0.3,
|
'pitch': 0.3,
|
||||||
'volume': 0.9
|
'volume': 0.9
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speech property for speaking storage tokens.
|
* Speech property for speaking storage tokens.
|
||||||
* @type {cvoxAce.SpeechProperty}
|
* @type {cvoxAce.SpeechProperty}
|
||||||
*/
|
*/
|
||||||
var STORAGE_PROP = {
|
var STORAGE_PROP = {
|
||||||
'rate': 0.8,
|
'rate': 0.8,
|
||||||
'pitch': 0.7,
|
'pitch': 0.7,
|
||||||
'volume': 0.9
|
'volume': 0.9
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speech property for speaking variable tokens.
|
* Speech property for speaking variable tokens.
|
||||||
* @type {cvoxAce.SpeechProperty}
|
* @type {cvoxAce.SpeechProperty}
|
||||||
*/
|
*/
|
||||||
var VARIABLE_PROP = {
|
var VARIABLE_PROP = {
|
||||||
'rate': 0.8,
|
'rate': 0.8,
|
||||||
'pitch': 0.8,
|
'pitch': 0.8,
|
||||||
'volume': 0.9
|
'volume': 0.9
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speech property for speaking deleted text.
|
* Speech property for speaking deleted text.
|
||||||
* @type {cvoxAce.SpeechProperty}
|
* @type {cvoxAce.SpeechProperty}
|
||||||
*/
|
*/
|
||||||
var DELETED_PROP = {
|
var DELETED_PROP = {
|
||||||
'punctuationEcho': 'none',
|
'punctuationEcho': 'none',
|
||||||
'relativePitch': -0.6
|
'relativePitch': -0.6
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Constants for Earcons. */
|
/* Constants for Earcons. */
|
||||||
var ERROR_EARCON = 'ALERT_NONMODAL';
|
var ERROR_EARCON = 'ALERT_NONMODAL';
|
||||||
var MODE_SWITCH_EARCON = 'ALERT_MODAL';
|
var MODE_SWITCH_EARCON = 'ALERT_MODAL';
|
||||||
var NO_MATCH_EARCON = 'INVALID_KEYPRESS';
|
var NO_MATCH_EARCON = 'INVALID_KEYPRESS';
|
||||||
|
|
||||||
/* Constants for vim state. */
|
/* Constants for vim state. */
|
||||||
var INSERT_MODE_STATE = 'insertMode';
|
var INSERT_MODE_STATE = 'insertMode';
|
||||||
var COMMAND_MODE_STATE = 'start';
|
var COMMAND_MODE_STATE = 'start';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context menu commands.
|
* Context menu commands.
|
||||||
*/
|
*/
|
||||||
var Command = {
|
var Command = {
|
||||||
SPEAK_ANNOT: 'annots',
|
SPEAK_ANNOT: 'annots',
|
||||||
SPEAK_ALL_ANNOTS: 'all_annots',
|
SPEAK_ALL_ANNOTS: 'all_annots',
|
||||||
TOGGLE_LOCATION: 'toggle_location',
|
TOGGLE_LOCATION: 'toggle_location',
|
||||||
|
|
@ -133,102 +134,104 @@ define(function(require, exports, module) {
|
||||||
SPEAK_ROW_COL: 'row_col',
|
SPEAK_ROW_COL: 'row_col',
|
||||||
TOGGLE_DISPLACEMENT: 'toggle_displacement',
|
TOGGLE_DISPLACEMENT: 'toggle_displacement',
|
||||||
FOCUS_TEXT: 'focus_text'
|
FOCUS_TEXT: 'focus_text'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key prefix for each shortcut.
|
* Key prefix for each shortcut.
|
||||||
*/
|
*/
|
||||||
var KEY_PREFIX = 'CONTROL + SHIFT ';
|
var KEY_PREFIX = 'CONTROL + SHIFT ';
|
||||||
|
|
||||||
/* Globals. */
|
/* Globals. */
|
||||||
/**
|
cvoxAce.editor = null;
|
||||||
|
/**
|
||||||
* Last cursor position.
|
* Last cursor position.
|
||||||
* @type {!cvoxAce.Cursor}
|
* @type {cvoxAce.Cursor}
|
||||||
*/
|
*/
|
||||||
var lastCursor = ace.selection.getCursor();
|
var lastCursor = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table of annotations.
|
* Table of annotations.
|
||||||
* @typedef {!Object.<number, Object<number, cvoxAce.Annotation>>}
|
* @typedef {!Object.<number, Object<number, cvoxAce.Annotation>>}
|
||||||
*/
|
*/
|
||||||
var annotTable = {};
|
var annotTable = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to speak character, word, and then line. This allows blind users
|
* Whether to speak character, word, and then line. This allows blind users
|
||||||
* to know the location of the cursor when they change lines.
|
* to know the location of the cursor when they change lines.
|
||||||
* @typedef {boolean}
|
* @typedef {boolean}
|
||||||
*/
|
*/
|
||||||
var shouldSpeakRowLocation = false;
|
var shouldSpeakRowLocation = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to speak displacement.
|
* Whether to speak displacement.
|
||||||
* @typedef {boolean}
|
* @typedef {boolean}
|
||||||
*/
|
*/
|
||||||
var shouldSpeakDisplacement = false;
|
var shouldSpeakDisplacement = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether text was changed to cause a cursor change event.
|
* Whether text was changed to cause a cursor change event.
|
||||||
* @typedef {boolean}
|
* @typedef {boolean}
|
||||||
*/
|
*/
|
||||||
var changed = false;
|
var changed = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current state vim is in.
|
* Current state vim is in.
|
||||||
*/
|
*/
|
||||||
var vimState = null;
|
var vimState = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping from key code to shortcut.
|
* Mapping from key code to shortcut.
|
||||||
*/
|
*/
|
||||||
var keyCodeToShortcutMap = {};
|
var keyCodeToShortcutMap = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping from command to shortcut.
|
* Mapping from command to shortcut.
|
||||||
*/
|
*/
|
||||||
var cmdToShortcutMap = {};
|
var cmdToShortcutMap = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get shortcut string from keyCode.
|
* Get shortcut string from keyCode.
|
||||||
* @param {number} keyCode Key code of shortcut.
|
* @param {number} keyCode Key code of shortcut.
|
||||||
* @return {string} String representation of shortcut.
|
* @return {string} String representation of shortcut.
|
||||||
*/
|
*/
|
||||||
var getKeyShortcutString = function(keyCode) {
|
var getKeyShortcutString = function(keyCode) {
|
||||||
return KEY_PREFIX + String.fromCharCode(keyCode);
|
return KEY_PREFIX + String.fromCharCode(keyCode);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if in vim mode.
|
* Return if in vim mode.
|
||||||
* @return {boolean} True if in Vim mode.
|
* @return {boolean} True if in Vim mode.
|
||||||
*/
|
*/
|
||||||
var isVimMode = function() {
|
var isVimMode = function() {
|
||||||
return ace.keyBinding.getKeyboardHandler().$id === 'ace/keyboard/vim';
|
var keyboardHandler = cvoxAce.editor.keyBinding.getKeyboardHandler();
|
||||||
};
|
return keyboardHandler.$id === 'ace/keyboard/vim';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current token.
|
* Gets the current token.
|
||||||
* @param {!cvoxAce.Cursor} cursor Current position of the cursor.
|
* @param {!cvoxAce.Cursor} cursor Current position of the cursor.
|
||||||
* @return {!cvoxAce.Token} Token at the current position.
|
* @return {!cvoxAce.Token} Token at the current position.
|
||||||
*/
|
*/
|
||||||
var getCurrentToken = function(cursor) {
|
var getCurrentToken = function(cursor) {
|
||||||
return ace.getSession().getTokenAt(cursor.row, cursor.column + 1);
|
return cvoxAce.editor.getSession().getTokenAt(cursor.row, cursor.column + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current line the cursor is under.
|
* Gets the current line the cursor is under.
|
||||||
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
||||||
*/
|
*/
|
||||||
var getCurrentLine = function(cursor) {
|
var getCurrentLine = function(cursor) {
|
||||||
return ace.getSession().getLine(cursor.row);
|
return cvoxAce.editor.getSession().getLine(cursor.row);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for row changes. When the user changes rows we want to speak
|
* Event handler for row changes. When the user changes rows we want to speak
|
||||||
* the line so the user can work on this line. If shouldSpeakRowLocation is on
|
* the line so the user can work on this line. If shouldSpeakRowLocation is on
|
||||||
* then we speak the character, then the row, then the line so the user knows
|
* then we speak the character, then the row, then the line so the user knows
|
||||||
* where the cursor is.
|
* where the cursor is.
|
||||||
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
||||||
*/
|
*/
|
||||||
var onRowChange = function(currCursor) {
|
var onRowChange = function(currCursor) {
|
||||||
/* Notify that this line has an annotation. */
|
/* Notify that this line has an annotation. */
|
||||||
if (annotTable[currCursor.row]) {
|
if (annotTable[currCursor.row]) {
|
||||||
cvox.Api.playEarcon(ERROR_EARCON);
|
cvox.Api.playEarcon(ERROR_EARCON);
|
||||||
|
|
@ -241,15 +244,15 @@ define(function(require, exports, module) {
|
||||||
} else {
|
} else {
|
||||||
speakLine(currCursor.row, 0);
|
speakLine(currCursor.row, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the cursor is at the beginning of a word. A word is
|
* Returns whether the cursor is at the beginning of a word. A word is
|
||||||
* a grouping of alphanumeric characters including underscores.
|
* a grouping of alphanumeric characters including underscores.
|
||||||
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
||||||
* @return {boolean} Whether there is word.
|
* @return {boolean} Whether there is word.
|
||||||
*/
|
*/
|
||||||
var isWord = function(cursor) {
|
var isWord = function(cursor) {
|
||||||
var line = getCurrentLine(cursor);
|
var line = getCurrentLine(cursor);
|
||||||
var lineSuffix = line.substr(cursor.column - 1);
|
var lineSuffix = line.substr(cursor.column - 1);
|
||||||
if (cursor.column === 0) {
|
if (cursor.column === 0) {
|
||||||
|
|
@ -259,26 +262,26 @@ define(function(require, exports, module) {
|
||||||
var firstWordRegExp = /^\W(\w+)/;
|
var firstWordRegExp = /^\W(\w+)/;
|
||||||
var words = firstWordRegExp.exec(lineSuffix);
|
var words = firstWordRegExp.exec(lineSuffix);
|
||||||
return words !== null;
|
return words !== null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapping of syntax type to speech properties.
|
* A mapping of syntax type to speech properties.
|
||||||
*/
|
*/
|
||||||
var rules = {
|
var rules = {
|
||||||
'constant': CONSTANT_PROP,
|
'constant': CONSTANT_PROP,
|
||||||
'entity': ENTITY_PROP,
|
'entity': ENTITY_PROP,
|
||||||
'keyword': KEYWORD_PROP,
|
'keyword': KEYWORD_PROP,
|
||||||
'storage': STORAGE_PROP,
|
'storage': STORAGE_PROP,
|
||||||
'variable': VARIABLE_PROP
|
'variable': VARIABLE_PROP
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speak the line with syntax properties.
|
* Speak the line with syntax properties.
|
||||||
* @param {number} row Row to speak.
|
* @param {number} row Row to speak.
|
||||||
* @param {number} queue Queue mode to speak.
|
* @param {number} queue Queue mode to speak.
|
||||||
*/
|
*/
|
||||||
var speakLine = function(row, queue) {
|
var speakLine = function(row, queue) {
|
||||||
var tokens = ace.getSession().getTokens(row);
|
var tokens = cvoxAce.editor.getSession().getTokens(row);
|
||||||
if (tokens.length === 0) {
|
if (tokens.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -291,33 +294,33 @@ define(function(require, exports, module) {
|
||||||
speakToken_(firstToken, queue);
|
speakToken_(firstToken, queue);
|
||||||
/* Speak rest of tokens. */
|
/* Speak rest of tokens. */
|
||||||
tokens.forEach(speakTokenQueue);
|
tokens.forEach(speakTokenQueue);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speak the token based on the syntax of the token, flushing.
|
* Speak the token based on the syntax of the token, flushing.
|
||||||
* @param {!cvoxAce.Token} token Token to speak.
|
* @param {!cvoxAce.Token} token Token to speak.
|
||||||
* @param {number} queue Queue mode.
|
* @param {number} queue Queue mode.
|
||||||
*/
|
*/
|
||||||
var speakTokenFlush = function(token) {
|
var speakTokenFlush = function(token) {
|
||||||
speakToken_(token, 0);
|
speakToken_(token, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speak the token based on the syntax of the token, queueing.
|
* Speak the token based on the syntax of the token, queueing.
|
||||||
* @param {!cvoxAce.Token} token Token to speak.
|
* @param {!cvoxAce.Token} token Token to speak.
|
||||||
* @param {number} queue Queue mode.
|
* @param {number} queue Queue mode.
|
||||||
*/
|
*/
|
||||||
var speakTokenQueue = function(token) {
|
var speakTokenQueue = function(token) {
|
||||||
speakToken_(token, 1);
|
speakToken_(token, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speak the token based on the syntax of the token.
|
* Speak the token based on the syntax of the token.
|
||||||
* @private
|
* @private
|
||||||
* @param {!cvoxAce.Token} token Token to speak.
|
* @param {!cvoxAce.Token} token Token to speak.
|
||||||
* @param {number} queue Queue mode.
|
* @param {number} queue Queue mode.
|
||||||
*/
|
*/
|
||||||
var speakToken_ = function(token, queue) {
|
var speakToken_ = function(token, queue) {
|
||||||
/* Types are period delimited. In this case, we only syntax speak the outer
|
/* Types are period delimited. In this case, we only syntax speak the outer
|
||||||
* most type of token. */
|
* most type of token. */
|
||||||
if (!token || !token.type) {
|
if (!token || !token.type) {
|
||||||
|
|
@ -333,25 +336,25 @@ define(function(require, exports, module) {
|
||||||
prop = DEFAULT_PROP;
|
prop = DEFAULT_PROP;
|
||||||
}
|
}
|
||||||
cvox.Api.speak(token.value, queue, prop);
|
cvox.Api.speak(token.value, queue, prop);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speaks the character under the cursor. This is queued.
|
* Speaks the character under the cursor. This is queued.
|
||||||
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
* @param {!cvoxAce.Cursor} cursor Current cursor position.
|
||||||
* @return {string} Character.
|
* @return {string} Character.
|
||||||
*/
|
*/
|
||||||
var speakChar = function(cursor) {
|
var speakChar = function(cursor) {
|
||||||
var line = getCurrentLine(cursor);
|
var line = getCurrentLine(cursor);
|
||||||
cvox.Api.speak(line[cursor.column], 1);
|
cvox.Api.speak(line[cursor.column], 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speaks the jump from lastCursor to currCursor. This function assumes the
|
* Speaks the jump from lastCursor to currCursor. This function assumes the
|
||||||
* jump takes place on the current line.
|
* jump takes place on the current line.
|
||||||
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
||||||
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
||||||
*/
|
*/
|
||||||
var speakDisplacement = function(lastCursor, currCursor) {
|
var speakDisplacement = function(lastCursor, currCursor) {
|
||||||
cvox.Api.stop();
|
cvox.Api.stop();
|
||||||
var line = getCurrentLine(currCursor);
|
var line = getCurrentLine(currCursor);
|
||||||
|
|
||||||
|
|
@ -364,15 +367,15 @@ define(function(require, exports, module) {
|
||||||
/* Speak out loud spaces. */
|
/* Speak out loud spaces. */
|
||||||
displace = displace.replace(/ /g, ' space ');
|
displace = displace.replace(/ /g, ' space ');
|
||||||
cvox.Api.speak(displace, 1);
|
cvox.Api.speak(displace, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speaks the word if the cursor jumped to a new word or to the beginning
|
* Speaks the word if the cursor jumped to a new word or to the beginning
|
||||||
* of the line. Otherwise speak the charactor.
|
* of the line. Otherwise speak the charactor.
|
||||||
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
||||||
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
||||||
*/
|
*/
|
||||||
var speakCharOrWordOrLine = function(lastCursor, currCursor) {
|
var speakCharOrWordOrLine = function(lastCursor, currCursor) {
|
||||||
/* Say word only if jump. */
|
/* Say word only if jump. */
|
||||||
if (Math.abs(lastCursor.column - currCursor.column) !== 1) {
|
if (Math.abs(lastCursor.column - currCursor.column) !== 1) {
|
||||||
var currLineLength = getCurrentLine(currCursor).length;
|
var currLineLength = getCurrentLine(currCursor).length;
|
||||||
|
|
@ -388,9 +391,9 @@ define(function(require, exports, module) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
speakChar(currCursor);
|
speakChar(currCursor);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for column changes. If shouldSpeakDisplacement is on, then
|
* Event handler for column changes. If shouldSpeakDisplacement is on, then
|
||||||
* we just speak displacements in row changes. Otherwise, we either speak
|
* we just speak displacements in row changes. Otherwise, we either speak
|
||||||
* the character for single character movements, the word when jumping to the
|
* the character for single character movements, the word when jumping to the
|
||||||
|
|
@ -398,41 +401,41 @@ define(function(require, exports, module) {
|
||||||
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
|
||||||
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
|
||||||
*/
|
*/
|
||||||
var onColumnChange = function(lastCursor, currCursor) {
|
var onColumnChange = function(lastCursor, currCursor) {
|
||||||
if (shouldSpeakDisplacement) {
|
if (shouldSpeakDisplacement) {
|
||||||
speakDisplacement(lastCursor, currCursor);
|
speakDisplacement(lastCursor, currCursor);
|
||||||
} else {
|
} else {
|
||||||
speakCharOrWordOrLine(lastCursor, currCursor);
|
speakCharOrWordOrLine(lastCursor, currCursor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for cursor changes. Classify cursor changes as either row or
|
* Event handler for cursor changes. Classify cursor changes as either row or
|
||||||
* column changes, then delegate accordingly.
|
* column changes, then delegate accordingly.
|
||||||
* @param {!Event} evt The event.
|
* @param {!Event} evt The event.
|
||||||
*/
|
*/
|
||||||
var onCursorChange = function(evt) {
|
var onCursorChange = function(evt) {
|
||||||
/* Do not speak if cursor change was a result of text insertion. We want to
|
/* Do not speak if cursor change was a result of text insertion. We want to
|
||||||
* speak the text that was inserted and not where the cursor lands. */
|
* speak the text that was inserted and not where the cursor lands. */
|
||||||
if (changed) {
|
if (changed) {
|
||||||
changed = false;
|
changed = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var currCursor = ace.selection.getCursor();
|
var currCursor = cvoxAce.editor.selection.getCursor();
|
||||||
if (currCursor.row !== lastCursor.row) {
|
if (currCursor.row !== lastCursor.row) {
|
||||||
onRowChange(currCursor);
|
onRowChange(currCursor);
|
||||||
} else {
|
} else {
|
||||||
onColumnChange(lastCursor, currCursor);
|
onColumnChange(lastCursor, currCursor);
|
||||||
}
|
}
|
||||||
lastCursor = currCursor;
|
lastCursor = currCursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for source changes. We want auditory feedback for inserting
|
* Event handler for source changes. We want auditory feedback for inserting
|
||||||
* and deleting text.
|
* and deleting text.
|
||||||
* @param {!Event} evt The event.
|
* @param {!Event} evt The event.
|
||||||
*/
|
*/
|
||||||
var onChange = function(evt) {
|
var onChange = function(evt) {
|
||||||
var data = evt.data;
|
var data = evt.data;
|
||||||
switch (data.action) {
|
switch (data.action) {
|
||||||
case 'removeText':
|
case 'removeText':
|
||||||
|
|
@ -446,24 +449,24 @@ define(function(require, exports, module) {
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not the annotation is new.
|
* Returns whether or not the annotation is new.
|
||||||
* @param {!cvoxAce.Annotation} annot Annotation in question.
|
* @param {!cvoxAce.Annotation} annot Annotation in question.
|
||||||
* @return {boolean} Whether annot is new.
|
* @return {boolean} Whether annot is new.
|
||||||
*/
|
*/
|
||||||
var isNewAnnotation = function(annot) {
|
var isNewAnnotation = function(annot) {
|
||||||
var row = annot.row;
|
var row = annot.row;
|
||||||
var col = annot.column;
|
var col = annot.column;
|
||||||
return !annotTable[row] || !annotTable[row][col];
|
return !annotTable[row] || !annotTable[row][col];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the annotation table.
|
* Populates the annotation table.
|
||||||
* @param {!Array.<cvoxAce.Annotation>} annotations Array of annotations.
|
* @param {!Array.<cvoxAce.Annotation>} annotations Array of annotations.
|
||||||
*/
|
*/
|
||||||
var populateAnnotations = function(annotations) {
|
var populateAnnotations = function(annotations) {
|
||||||
annotTable = {};
|
annotTable = {};
|
||||||
for (var i = 0; i < annotations.length; i++) {
|
for (var i = 0; i < annotations.length; i++) {
|
||||||
var annotation = annotations[i];
|
var annotation = annotations[i];
|
||||||
|
|
@ -474,78 +477,78 @@ define(function(require, exports, module) {
|
||||||
}
|
}
|
||||||
annotTable[row][col] = annotation;
|
annotTable[row][col] = annotation;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for annotation changes. We want to notify the user when an
|
* Event handler for annotation changes. We want to notify the user when an
|
||||||
* a new annotation appears.
|
* a new annotation appears.
|
||||||
* @param {!Event} evt Event.
|
* @param {!Event} evt Event.
|
||||||
*/
|
*/
|
||||||
var onAnnotationChange = function(evt) {
|
var onAnnotationChange = function(evt) {
|
||||||
var annotations = ace.getSession().getAnnotations();
|
var annotations = cvoxAce.editor.getSession().getAnnotations();
|
||||||
var newAnnotations = annotations.filter(isNewAnnotation);
|
var newAnnotations = annotations.filter(isNewAnnotation);
|
||||||
if (newAnnotations.length > 0) {
|
if (newAnnotations.length > 0) {
|
||||||
cvox.Api.playEarcon(ERROR_EARCON);
|
cvox.Api.playEarcon(ERROR_EARCON);
|
||||||
}
|
}
|
||||||
populateAnnotations(annotations);
|
populateAnnotations(annotations);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speak annotation.
|
* Speak annotation.
|
||||||
* @param {!cvoxAce.Annotation} annot Annotation to speak.
|
* @param {!cvoxAce.Annotation} annot Annotation to speak.
|
||||||
*/
|
*/
|
||||||
var speakAnnot = function(annot) {
|
var speakAnnot = function(annot) {
|
||||||
var annotText = annot.type + ' ' + annot.text + ' on ' +
|
var annotText = annot.type + ' ' + annot.text + ' on ' +
|
||||||
rowColToString(annot.row, annot.column);
|
rowColToString(annot.row, annot.column);
|
||||||
annotText = annotText.replace(';', 'semicolon');
|
annotText = annotText.replace(';', 'semicolon');
|
||||||
cvox.Api.speak(annotText, 1);
|
cvox.Api.speak(annotText, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speak annotations in a row.
|
* Speak annotations in a row.
|
||||||
* @param {number} row Row of annotations to speak.
|
* @param {number} row Row of annotations to speak.
|
||||||
*/
|
*/
|
||||||
var speakAnnotsByRow = function(row) {
|
var speakAnnotsByRow = function(row) {
|
||||||
var annots = annotTable[row];
|
var annots = annotTable[row];
|
||||||
for (var col in annots) {
|
for (var col in annots) {
|
||||||
speakAnnot(annots[col]);
|
speakAnnot(annots[col]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a string representation of a row and column.
|
* Get a string representation of a row and column.
|
||||||
* @param {boolean} row Zero indexed row.
|
* @param {boolean} row Zero indexed row.
|
||||||
* @param {boolean} col Zero indexed column.
|
* @param {boolean} col Zero indexed column.
|
||||||
* @return {string} Row and column to be spoken.
|
* @return {string} Row and column to be spoken.
|
||||||
*/
|
*/
|
||||||
var rowColToString = function(row, col) {
|
var rowColToString = function(row, col) {
|
||||||
return 'row ' + (row + 1) + ' column ' + (col + 1);
|
return 'row ' + (row + 1) + ' column ' + (col + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speaks the row and column.
|
* Speaks the row and column.
|
||||||
*/
|
*/
|
||||||
var speakCurrRowAndCol = function() {
|
var speakCurrRowAndCol = function() {
|
||||||
cvox.Api.speak(rowColToString(lastCursor.row, lastCursor.column));
|
cvox.Api.speak(rowColToString(lastCursor.row, lastCursor.column));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speaks all annotations.
|
* Speaks all annotations.
|
||||||
*/
|
*/
|
||||||
var speakAllAnnots = function() {
|
var speakAllAnnots = function() {
|
||||||
for (var row in annotTable) {
|
for (var row in annotTable) {
|
||||||
speakAnnotsByRow(row);
|
speakAnnotsByRow(row);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speak the vim mode. If no vim mode, this function does nothing.
|
* Speak the vim mode. If no vim mode, this function does nothing.
|
||||||
*/
|
*/
|
||||||
var speakMode = function() {
|
var speakMode = function() {
|
||||||
if (!isVimMode()) {
|
if (!isVimMode()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (ace.keyBinding.$data.state) {
|
switch (cvoxAce.editor.keyBinding.$data.state) {
|
||||||
case INSERT_MODE_STATE:
|
case INSERT_MODE_STATE:
|
||||||
cvox.Api.speak('Insert mode');
|
cvox.Api.speak('Insert mode');
|
||||||
break;
|
break;
|
||||||
|
|
@ -553,12 +556,12 @@ define(function(require, exports, module) {
|
||||||
cvox.Api.speak('Command mode');
|
cvox.Api.speak('Command mode');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle speak location.
|
* Toggle speak location.
|
||||||
*/
|
*/
|
||||||
var toggleSpeakRowLocation = function() {
|
var toggleSpeakRowLocation = function() {
|
||||||
shouldSpeakRowLocation = !shouldSpeakRowLocation;
|
shouldSpeakRowLocation = !shouldSpeakRowLocation;
|
||||||
/* Auditory feedback of the change. */
|
/* Auditory feedback of the change. */
|
||||||
if (shouldSpeakRowLocation) {
|
if (shouldSpeakRowLocation) {
|
||||||
|
|
@ -566,12 +569,12 @@ define(function(require, exports, module) {
|
||||||
} else {
|
} else {
|
||||||
cvox.Api.speak('Speak location on row change disabled.');
|
cvox.Api.speak('Speak location on row change disabled.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle speak displacement.
|
* Toggle speak displacement.
|
||||||
*/
|
*/
|
||||||
var toggleSpeakDisplacement = function() {
|
var toggleSpeakDisplacement = function() {
|
||||||
speakDisplacement = !speakDisplacement;
|
speakDisplacement = !speakDisplacement;
|
||||||
/* Auditory feedback of the change. */
|
/* Auditory feedback of the change. */
|
||||||
if (speakDisplacement) {
|
if (speakDisplacement) {
|
||||||
|
|
@ -579,29 +582,29 @@ define(function(require, exports, module) {
|
||||||
} else {
|
} else {
|
||||||
cvox.Api.speak('Speak current character or word on column changes.');
|
cvox.Api.speak('Speak current character or word on column changes.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for key down events. Gets the right shortcut from the map,
|
* Event handler for key down events. Gets the right shortcut from the map,
|
||||||
* and calls the associated function.
|
* and calls the associated function.
|
||||||
* @param {!Event} evt Keyboard event.
|
* @param {!Event} evt Keyboard event.
|
||||||
*/
|
*/
|
||||||
var onKeyDown = function(evt) {
|
var onKeyDown = function(evt) {
|
||||||
if (evt.ctrlKey && evt.shiftKey) {
|
if (evt.ctrlKey && evt.shiftKey) {
|
||||||
var shortcut = keyCodeToShortcutMap[evt.keyCode];
|
var shortcut = keyCodeToShortcutMap[evt.keyCode];
|
||||||
if (shortcut) {
|
if (shortcut) {
|
||||||
shortcut.func();
|
shortcut.func();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for status change events. Auditory feedback of changing
|
* Event handler for status change events. Auditory feedback of changing
|
||||||
* between vim states.
|
* between vim states.
|
||||||
* @param {!Event} evt Change status event.
|
* @param {!Event} evt Change status event.
|
||||||
* @param {!Object} editor Editor state.
|
* @param {!Object} editor Editor state.
|
||||||
*/
|
*/
|
||||||
var onChangeStatus = function(evt, editor) {
|
var onChangeStatus = function(evt, editor) {
|
||||||
if (!isVimMode()) {
|
if (!isVimMode()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -624,30 +627,30 @@ define(function(require, exports, module) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vimState = state;
|
vimState = state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles context menu events. This is a ChromeVox feature where hitting
|
* Handles context menu events. This is a ChromeVox feature where hitting
|
||||||
* the shortcut ChromeVox + comma will open up a search bar where you can
|
* the shortcut ChromeVox + comma will open up a search bar where you can
|
||||||
* type in various commands. All keyboard shortcuts are also commands that
|
* type in various commands. All keyboard shortcuts are also commands that
|
||||||
* can be invoked. This handles the event that ChromeVox sends to the page.
|
* can be invoked. This handles the event that ChromeVox sends to the page.
|
||||||
* @param {Event} evt Event received.
|
* @param {Event} evt Event received.
|
||||||
*/
|
*/
|
||||||
var contextMenuHandler = function(evt) {
|
var contextMenuHandler = function(evt) {
|
||||||
var cmd = evt.detail['customCommand'];
|
var cmd = evt.detail['customCommand'];
|
||||||
var shortcut = cmdToShortcutMap[cmd];
|
var shortcut = cmdToShortcutMap[cmd];
|
||||||
if (shortcut) {
|
if (shortcut) {
|
||||||
shortcut.func();
|
shortcut.func();
|
||||||
/* ChromeVox will bring focus to an element near the cursor instead of the
|
/* ChromeVox will bring focus to an element near the cursor instead of the
|
||||||
* text input. */
|
* text input. */
|
||||||
ace.focus();
|
cvoxAce.editor.focus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the ChromeVox context menu.
|
* Initialize the ChromeVox context menu.
|
||||||
*/
|
*/
|
||||||
var initContextMenu = function() {
|
var initContextMenu = function() {
|
||||||
var ACTIONS = SHORTCUTS.map(function(shortcut) {
|
var ACTIONS = SHORTCUTS.map(function(shortcut) {
|
||||||
return {
|
return {
|
||||||
desc: shortcut.desc + getKeyShortcutString(shortcut.keyCode),
|
desc: shortcut.desc + getKeyShortcutString(shortcut.keyCode),
|
||||||
|
|
@ -661,63 +664,29 @@ define(function(require, exports, module) {
|
||||||
|
|
||||||
/* Listen for ContextMenu events. */
|
/* Listen for ContextMenu events. */
|
||||||
body.addEventListener('ATCustomEvent', contextMenuHandler, true);
|
body.addEventListener('ATCustomEvent', contextMenuHandler, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
var onFindSearchbox = function(evt) {
|
||||||
* Returns a mutations handler where f is applied to each mutation.
|
if (evt.match) {
|
||||||
* @param {function} f Function to be applied to mutations.
|
|
||||||
*/
|
|
||||||
var getMutationHandler = function(f) {
|
|
||||||
return function(mutations) {
|
|
||||||
mutations.forEach(f);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Watches and handles the mutation that is a result of a search.
|
|
||||||
* @param {Mutation} m Mutation.
|
|
||||||
*/
|
|
||||||
var watchForSearch = function(m) {
|
|
||||||
if (m.attributeName === 'class' &&
|
|
||||||
m.target.className === 'ace_search_form ace_nomatch') {
|
|
||||||
/* No match, give auditory feedback! */
|
|
||||||
cvox.Api.playEarcon(NO_MATCH_EARCON);
|
|
||||||
} else {
|
|
||||||
/* There is still a match! Speak the line. */
|
/* There is still a match! Speak the line. */
|
||||||
speakLine(lastCursor.row, 0);
|
speakLine(lastCursor.row, 0);
|
||||||
|
} else {
|
||||||
|
/* No match, give auditory feedback! */
|
||||||
|
cvox.Api.playEarcon(NO_MATCH_EARCON);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for mutation observer.
|
|
||||||
*/
|
|
||||||
var MO_CONFIG = { attributes: true, childList: true, characterData: true};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Watches and handles the mutation that adds the search bar to the DOM.
|
|
||||||
*/
|
|
||||||
var watchForStartSearch = function(m) {
|
|
||||||
for (var i = 0; i < m.addedNodes.length; i++) {
|
|
||||||
if (m.addedNodes.item(i).className === 'ace_search right') {
|
|
||||||
var mutationHandler = getMutationHandler(watchForSearch);
|
|
||||||
var searchObs = new MutationObserver(mutationHandler);
|
|
||||||
var target = m.addedNodes.item(i).querySelector('.ace_search_form');
|
|
||||||
searchObs.observe(target, MO_CONFIG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Focus to text input.
|
* Focus to text input.
|
||||||
*/
|
*/
|
||||||
var focus = function() {
|
var focus = function() {
|
||||||
ace.focus();
|
cvoxAce.editor.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut definitions.
|
* Shortcut definitions.
|
||||||
*/
|
*/
|
||||||
var SHORTCUTS = [
|
var SHORTCUTS = [
|
||||||
{
|
{
|
||||||
/* 1 key. */
|
/* 1 key. */
|
||||||
keyCode: 49,
|
keyCode: 49,
|
||||||
|
|
@ -769,12 +738,14 @@ define(function(require, exports, module) {
|
||||||
cmd: Command.FOCUS_TEXT,
|
cmd: Command.FOCUS_TEXT,
|
||||||
desc: 'Focus text'
|
desc: 'Focus text'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the theme.
|
* Initialize the theme.
|
||||||
*/
|
*/
|
||||||
var init = function() {
|
var init = function(editor) {
|
||||||
|
cvoxAce.editor = editor;
|
||||||
|
lastCursor = editor.selection.getCursor();
|
||||||
/* Construct maps. */
|
/* Construct maps. */
|
||||||
SHORTCUTS.forEach(function(shortcut) {
|
SHORTCUTS.forEach(function(shortcut) {
|
||||||
keyCodeToShortcutMap[shortcut.keyCode] = shortcut;
|
keyCodeToShortcutMap[shortcut.keyCode] = shortcut;
|
||||||
|
|
@ -782,10 +753,11 @@ define(function(require, exports, module) {
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Set up listeners. */
|
/* Set up listeners. */
|
||||||
ace.getSession().selection.on('changeCursor', onCursorChange);
|
cvoxAce.editor.getSession().selection.on('changeCursor', onCursorChange);
|
||||||
ace.getSession().on('change', onChange);
|
cvoxAce.editor.getSession().on('change', onChange);
|
||||||
ace.getSession().on('changeAnnotation', onAnnotationChange);
|
cvoxAce.editor.getSession().on('changeAnnotation', onAnnotationChange);
|
||||||
ace.on('changeStatus', onChangeStatus);
|
cvoxAce.editor.on('changeStatus', onChangeStatus);
|
||||||
|
cvoxAce.editor.on('findSearchBox', onFindSearchbox);
|
||||||
window.addEventListener('keydown', onKeyDown);
|
window.addEventListener('keydown', onKeyDown);
|
||||||
|
|
||||||
/* Assume we start in command mode if vim. */
|
/* Assume we start in command mode if vim. */
|
||||||
|
|
@ -794,50 +766,55 @@ define(function(require, exports, module) {
|
||||||
}
|
}
|
||||||
initContextMenu();
|
initContextMenu();
|
||||||
|
|
||||||
var target = document.querySelector('.ace_editor');
|
cvoxAce.editor.focus();
|
||||||
var mutationHandler = getMutationHandler(watchForStartSearch);
|
};
|
||||||
var observer = new MutationObserver(mutationHandler);
|
|
||||||
|
|
||||||
observer.observe(target, MO_CONFIG);
|
/**
|
||||||
|
|
||||||
ace.focus();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if cvox exists, and the api exists.
|
* Returns if cvox exists, and the api exists.
|
||||||
* @return {boolean} Whether not Cvox Api exists.
|
* @return {boolean} Whether not Cvox Api exists.
|
||||||
*/
|
*/
|
||||||
function cvoxApiExists() {
|
function cvoxApiExists() {
|
||||||
return (typeof(cvox) !== 'undefined') && cvox && cvox.Api;
|
return (typeof(cvox) !== 'undefined') && cvox && cvox.Api;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of tries for Cvox loading.
|
* Number of tries for Cvox loading.
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
var tries = 0;
|
var tries = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Max number of tries to watch for Cvox loading.
|
* Max number of tries to watch for Cvox loading.
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
var MAX_TRIES = 15;
|
var MAX_TRIES = 15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for ChromeVox load.
|
* Check for ChromeVox load.
|
||||||
|
* @param {Object} editor Editor to use.
|
||||||
*/
|
*/
|
||||||
function watchForCvoxLoad() {
|
function watchForCvoxLoad(editor) {
|
||||||
if (cvoxApiExists()) {
|
if (cvoxApiExists()) {
|
||||||
init();
|
init(editor);
|
||||||
} else {
|
} else {
|
||||||
tries++;
|
tries++;
|
||||||
if (tries >= MAX_TRIES) {
|
if (tries >= MAX_TRIES) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window.setTimeout(watchForCvoxLoad, 500);
|
window.setTimeout(watchForCvoxLoad, 500, editor);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var Editor = require('../editor').Editor;
|
||||||
|
require('../config').defineOptions(Editor.prototype, 'editor', {
|
||||||
|
enableChromevoxEnhancements: {
|
||||||
|
set: function(val) {
|
||||||
|
if (val) {
|
||||||
|
watchForCvoxLoad(this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: true // turn it on by default or check for window.cvox
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* Initialize everything when ChromeVox has loaded. */
|
|
||||||
watchForCvoxLoad();
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,9 @@ var SearchBox = function(editor, range, showReplaceForm) {
|
||||||
caseSensitive: this.caseSensitiveOption.checked,
|
caseSensitive: this.caseSensitiveOption.checked,
|
||||||
wholeWord: this.wholeWordOption.checked
|
wholeWord: this.wholeWordOption.checked
|
||||||
});
|
});
|
||||||
dom.setCssClass(this.searchBox, "ace_nomatch", !range && this.searchInput.value);
|
var noMatch = !range && this.searchInput.value;
|
||||||
|
dom.setCssClass(this.searchBox, "ace_nomatch", noMatch);
|
||||||
|
this.editor._emit("findSearchBox", { match: !noMatch });
|
||||||
this.highlight();
|
this.highlight();
|
||||||
};
|
};
|
||||||
this.findNext = function() {
|
this.findNext = function() {
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ module.exports.themes = [
|
||||||
"kr_theme",
|
"kr_theme",
|
||||||
"merbivore",
|
"merbivore",
|
||||||
"merbivore_soft",
|
"merbivore_soft",
|
||||||
"monokai",
|
|
||||||
"mono_industrial",
|
"mono_industrial",
|
||||||
|
"monokai",
|
||||||
"pastel_on_dark",
|
"pastel_on_dark",
|
||||||
"solarized_dark",
|
"solarized_dark",
|
||||||
"solarized_light",
|
"solarized_light",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue