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,4 +1,5 @@
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
|
|
||||||
/* ChromeVox Ace namespace. */
|
/* ChromeVox Ace namespace. */
|
||||||
var cvoxAce = {};
|
var cvoxAce = {};
|
||||||
|
|
||||||
|
|
@ -141,11 +142,12 @@ define(function(require, exports, module) {
|
||||||
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.
|
||||||
|
|
@ -201,7 +203,8 @@ define(function(require, exports, module) {
|
||||||
* @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';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -210,7 +213,7 @@ define(function(require, exports, module) {
|
||||||
* @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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -218,7 +221,7 @@ define(function(require, exports, module) {
|
||||||
* @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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -278,7 +281,7 @@ define(function(require, exports, module) {
|
||||||
* @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;
|
||||||
}
|
}
|
||||||
|
|
@ -418,7 +421,7 @@ define(function(require, exports, module) {
|
||||||
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 {
|
||||||
|
|
@ -482,7 +485,7 @@ define(function(require, exports, module) {
|
||||||
* @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);
|
||||||
|
|
@ -545,7 +548,7 @@ define(function(require, exports, module) {
|
||||||
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;
|
||||||
|
|
@ -640,7 +643,7 @@ define(function(require, exports, module) {
|
||||||
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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -663,47 +666,13 @@ define(function(require, exports, module) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -711,7 +680,7 @@ define(function(require, exports, module) {
|
||||||
* Focus to text input.
|
* Focus to text input.
|
||||||
*/
|
*/
|
||||||
var focus = function() {
|
var focus = function() {
|
||||||
ace.focus();
|
cvoxAce.editor.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -774,7 +743,9 @@ define(function(require, exports, module) {
|
||||||
/**
|
/**
|
||||||
* 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,13 +766,7 @@ 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();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -825,19 +791,30 @@ define(function(require, exports, module) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize everything when ChromeVox has loaded. */
|
var Editor = require('../editor').Editor;
|
||||||
watchForCvoxLoad();
|
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
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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