/CVox/res/raw/basic.user.js

http://eyes-free.googlecode.com/ · JavaScript · 226 lines · 192 code · 18 blank · 16 comment · 69 complexity · 8dbea4d9b53a7ddd8e230f7070b7b3a6 MD5 · raw file

  1. // ==UserScript==
  2. // @name CVOX
  3. // @description Generic CVOX Script
  4. // @author Charles L. Chen
  5. // @include http://*
  6. // ==/UserScript==
  7. var currentElem = null;
  8. var prevElem = null;
  9. var inputFocused = false;
  10. function getNextLeafNode(){
  11. prevElem = currentElem;
  12. if (currentElem == null){
  13. currentElem = document.body;
  14. } else {
  15. while (!currentElem.nextSibling){
  16. currentElem = currentElem.parentNode;
  17. if (currentElem == document.body){
  18. currentElem = null;
  19. return currentElem;
  20. }
  21. }
  22. currentElem = currentElem.nextSibling;
  23. }
  24. while (currentElem.firstChild){
  25. currentElem = currentElem.firstChild;
  26. }
  27. return currentElem;
  28. }
  29. function getPrevLeafNode(){
  30. prevElem = currentElem;
  31. if (currentElem == null){
  32. currentElem = document.body;
  33. } else {
  34. while (!currentElem.previousSibling){
  35. currentElem = currentElem.parentNode;
  36. if (currentElem == document.body){
  37. currentElem = null;
  38. return currentElem;
  39. }
  40. }
  41. currentElem = currentElem.previousSibling;
  42. }
  43. while (currentElem.lastChild){
  44. currentElem = currentElem.lastChild;
  45. }
  46. return currentElem;
  47. }
  48. function containsText(textStr){
  49. if (textStr === null){
  50. return false;
  51. }
  52. if (textStr.length < 1){
  53. return false;
  54. }
  55. var myregexp = new RegExp("[a-zA-Z0-9]");
  56. return myregexp.test(textStr);
  57. }
  58. function getLineage(targetNode){
  59. var lineage = new Array();
  60. while (targetNode){
  61. lineage.push(targetNode);
  62. targetNode = targetNode.parentNode;
  63. }
  64. lineage.reverse();
  65. while(lineage.length && !lineage[0].tagName && !lineage[0].nodeValue){
  66. lineage.shift();
  67. }
  68. return lineage;
  69. }
  70. //Compares Lineage A with Lineage B and returns
  71. //the index value in B at which B diverges from A.
  72. //If there is no divergence, the result will be -1.
  73. //Note that if B is the same as A except B has more nodes
  74. //even after A has ended, that is considered a divergence.
  75. //The first node that B has which A does not have will
  76. //be treated as the divergence point.
  77. //
  78. function compareLineages(lina, linb){
  79. var i = 0;
  80. while( lina[i] && linb[i] && (lina[i] == linb[i]) ){
  81. i++;
  82. }
  83. if ( !lina[i] && !linb[i] ){
  84. i = -1;
  85. }
  86. return i;
  87. }
  88. function getInfoOnCurrentElem(){
  89. var currentLineage = getLineage(currentElem);
  90. var divergence = compareLineages(getLineage(prevElem), currentLineage);
  91. var infoStr = "";
  92. for (var i=divergence, elem; elem = currentLineage[i]; i++){
  93. if (elem.tagName){
  94. if (elem.tagName == 'H1'){
  95. infoStr = infoStr + 'H 1. ';
  96. } else if (elem.tagName == 'H2'){
  97. infoStr = infoStr + 'H 2. ';
  98. } else if (elem.tagName == 'H3'){
  99. infoStr = infoStr + 'H 3. ';
  100. } else if (elem.tagName == 'H4'){
  101. infoStr = infoStr + 'H 4. ';
  102. } else if (elem.tagName == 'H5'){
  103. infoStr = infoStr + 'H 5. ';
  104. } else if (elem.tagName == 'H6'){
  105. infoStr = infoStr + 'H 6. ';
  106. } else if (elem.tagName == 'A'){
  107. infoStr = infoStr + 'Link. ';
  108. }
  109. }
  110. }
  111. return infoStr;
  112. }
  113. function readNext(){
  114. getNextLeafNode();
  115. while (!containsText(currentElem.textContent)){
  116. getNextLeafNode();
  117. if (currentElem === null){
  118. speak("End of document", 0, null);
  119. return;
  120. }
  121. }
  122. speak(getInfoOnCurrentElem() + ' ' + currentElem.textContent, 0, null);
  123. scrollToElem(currentElem);
  124. }
  125. function readPrev(){
  126. getPrevLeafNode();
  127. while (!containsText(currentElem.textContent)){
  128. getPrevLeafNode();
  129. if (currentElem === null){
  130. speak("Beginning of document", 0, null);
  131. return;
  132. }
  133. }
  134. speak(getInfoOnCurrentElem() + ' ' + currentElem.textContent, 0, null);
  135. scrollToElem(currentElem);
  136. }
  137. function scrollToElem(targetNode){
  138. while (!targetNode.offsetParent){
  139. targetNode = targetNode.parentNode;
  140. }
  141. var left = 0;
  142. var top = 0;
  143. while (targetNode.offsetParent) {
  144. left += targetNode.offsetLeft;
  145. top += targetNode.offsetTop;
  146. targetNode = targetNode.offsetParent;
  147. }
  148. left += targetNode.offsetLeft;
  149. top += targetNode.offsetTop;
  150. window.scrollTo(left, top);
  151. }
  152. function speak(textStr, queueMode, paramsArray){
  153. window.ttsHelper.speak(textStr, queueMode);
  154. //alert(textStr);
  155. }
  156. //TODO: Come up with a working escape sequence!
  157. function keyPressHandler(evt){
  158. var keyCode = evt.keyCode;
  159. if (inputFocused){
  160. return true;
  161. }
  162. if (keyCode == 106) { // j
  163. readNext();
  164. return false;
  165. }
  166. if (keyCode == 107) { // k
  167. readPrev();
  168. return false;
  169. }
  170. return true;
  171. }
  172. function keyDownHandler(evt){
  173. window.ttsHelper.stop();
  174. var keyCode = evt.keyCode;
  175. if (inputFocused){
  176. return true;
  177. }
  178. if ((keyCode == 32) || (keyCode == 13)) { // space or Enter (G1 enter key does not work)
  179. var targetElem = currentElem;
  180. while (targetElem){
  181. if (targetElem.tagName == 'A'){
  182. document.location = targetElem.href;
  183. return false;
  184. }
  185. targetElem = targetElem.parentNode;
  186. }
  187. return true;
  188. }
  189. return true;
  190. }
  191. function focusHandler(evt){
  192. if (evt.target.tagName &&
  193. evt.target.tagName == 'INPUT'){
  194. inputFocused = true;
  195. }
  196. return true;
  197. }
  198. function blurHandler(evt){
  199. inputFocused = false;
  200. return true;
  201. }
  202. if (document.location.toString().indexOf('http://www.google.com/search?') != 0){
  203. document.addEventListener('keypress', keyPressHandler, true);
  204. document.addEventListener('keydown', keyDownHandler, true);
  205. document.addEventListener('focus', focusHandler, true);
  206. document.addEventListener('blur', blurHandler, true);
  207. speak(document.title, 0, null);
  208. }