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) {
|
||||
|
||||
/* ChromeVox Ace namespace. */
|
||||
var cvoxAce = {};
|
||||
|
||||
|
|
@ -141,11 +142,12 @@ define(function(require, exports, module) {
|
|||
var KEY_PREFIX = 'CONTROL + SHIFT ';
|
||||
|
||||
/* Globals. */
|
||||
cvoxAce.editor = null;
|
||||
/**
|
||||
* Last cursor position.
|
||||
* @type {!cvoxAce.Cursor}
|
||||
* @type {cvoxAce.Cursor}
|
||||
*/
|
||||
var lastCursor = ace.selection.getCursor();
|
||||
var lastCursor = null;
|
||||
|
||||
/**
|
||||
* Table of annotations.
|
||||
|
|
@ -201,7 +203,8 @@ define(function(require, exports, module) {
|
|||
* @return {boolean} True if in Vim mode.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
var speakLine = function(row, queue) {
|
||||
var tokens = ace.getSession().getTokens(row);
|
||||
var tokens = cvoxAce.editor.getSession().getTokens(row);
|
||||
if (tokens.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -418,7 +421,7 @@ define(function(require, exports, module) {
|
|||
changed = false;
|
||||
return;
|
||||
}
|
||||
var currCursor = ace.selection.getCursor();
|
||||
var currCursor = cvoxAce.editor.selection.getCursor();
|
||||
if (currCursor.row !== lastCursor.row) {
|
||||
onRowChange(currCursor);
|
||||
} else {
|
||||
|
|
@ -482,7 +485,7 @@ define(function(require, exports, module) {
|
|||
* @param {!Event} evt Event.
|
||||
*/
|
||||
var onAnnotationChange = function(evt) {
|
||||
var annotations = ace.getSession().getAnnotations();
|
||||
var annotations = cvoxAce.editor.getSession().getAnnotations();
|
||||
var newAnnotations = annotations.filter(isNewAnnotation);
|
||||
if (newAnnotations.length > 0) {
|
||||
cvox.Api.playEarcon(ERROR_EARCON);
|
||||
|
|
@ -545,7 +548,7 @@ define(function(require, exports, module) {
|
|||
if (!isVimMode()) {
|
||||
return;
|
||||
}
|
||||
switch (ace.keyBinding.$data.state) {
|
||||
switch (cvoxAce.editor.keyBinding.$data.state) {
|
||||
case INSERT_MODE_STATE:
|
||||
cvox.Api.speak('Insert mode');
|
||||
break;
|
||||
|
|
@ -640,7 +643,7 @@ define(function(require, exports, module) {
|
|||
shortcut.func();
|
||||
/* ChromeVox will bring focus to an element near the cursor instead of the
|
||||
* text input. */
|
||||
ace.focus();
|
||||
cvoxAce.editor.focus();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -663,47 +666,13 @@ define(function(require, exports, module) {
|
|||
body.addEventListener('ATCustomEvent', contextMenuHandler, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a mutations handler where f is applied to each mutation.
|
||||
* @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 {
|
||||
var onFindSearchbox = function(evt) {
|
||||
if (evt.match) {
|
||||
/* There is still a match! Speak the line. */
|
||||
speakLine(lastCursor.row, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
} else {
|
||||
/* No match, give auditory feedback! */
|
||||
cvox.Api.playEarcon(NO_MATCH_EARCON);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -711,7 +680,7 @@ define(function(require, exports, module) {
|
|||
* Focus to text input.
|
||||
*/
|
||||
var focus = function() {
|
||||
ace.focus();
|
||||
cvoxAce.editor.focus();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -774,7 +743,9 @@ define(function(require, exports, module) {
|
|||
/**
|
||||
* Initialize the theme.
|
||||
*/
|
||||
var init = function() {
|
||||
var init = function(editor) {
|
||||
cvoxAce.editor = editor;
|
||||
lastCursor = editor.selection.getCursor();
|
||||
/* Construct maps. */
|
||||
SHORTCUTS.forEach(function(shortcut) {
|
||||
keyCodeToShortcutMap[shortcut.keyCode] = shortcut;
|
||||
|
|
@ -782,10 +753,11 @@ define(function(require, exports, module) {
|
|||
});
|
||||
|
||||
/* Set up listeners. */
|
||||
ace.getSession().selection.on('changeCursor', onCursorChange);
|
||||
ace.getSession().on('change', onChange);
|
||||
ace.getSession().on('changeAnnotation', onAnnotationChange);
|
||||
ace.on('changeStatus', onChangeStatus);
|
||||
cvoxAce.editor.getSession().selection.on('changeCursor', onCursorChange);
|
||||
cvoxAce.editor.getSession().on('change', onChange);
|
||||
cvoxAce.editor.getSession().on('changeAnnotation', onAnnotationChange);
|
||||
cvoxAce.editor.on('changeStatus', onChangeStatus);
|
||||
cvoxAce.editor.on('findSearchBox', onFindSearchbox);
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
|
||||
/* Assume we start in command mode if vim. */
|
||||
|
|
@ -794,13 +766,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
initContextMenu();
|
||||
|
||||
var target = document.querySelector('.ace_editor');
|
||||
var mutationHandler = getMutationHandler(watchForStartSearch);
|
||||
var observer = new MutationObserver(mutationHandler);
|
||||
|
||||
observer.observe(target, MO_CONFIG);
|
||||
|
||||
ace.focus();
|
||||
cvoxAce.editor.focus();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -825,19 +791,30 @@ define(function(require, exports, module) {
|
|||
|
||||
/**
|
||||
* Check for ChromeVox load.
|
||||
* @param {Object} editor Editor to use.
|
||||
*/
|
||||
function watchForCvoxLoad() {
|
||||
function watchForCvoxLoad(editor) {
|
||||
if (cvoxApiExists()) {
|
||||
init();
|
||||
init(editor);
|
||||
} else {
|
||||
tries++;
|
||||
if (tries >= MAX_TRIES) {
|
||||
return;
|
||||
}
|
||||
window.setTimeout(watchForCvoxLoad, 500);
|
||||
window.setTimeout(watchForCvoxLoad, 500, editor);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize everything when ChromeVox has loaded. */
|
||||
watchForCvoxLoad();
|
||||
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
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -214,7 +214,9 @@ var SearchBox = function(editor, range, showReplaceForm) {
|
|||
caseSensitive: this.caseSensitiveOption.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.findNext = function() {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ module.exports.themes = [
|
|||
"kr_theme",
|
||||
"merbivore",
|
||||
"merbivore_soft",
|
||||
"monokai",
|
||||
"mono_industrial",
|
||||
"monokai",
|
||||
"pastel_on_dark",
|
||||
"solarized_dark",
|
||||
"solarized_light",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue