I'm building an (open source) online tool for users with NO speech who are also blind. The program steps through a list of utterances in a female 'thinking' voice, and when one is selected, speaks it in a male 'speaking' voice (switch genders for a female target users).  I've written a demo of the 'display' half of the code in javascript and I'm about to write the editing code in python (it will parse a specification and create JSON). I've never formally learned javascript, and I feel very much like I'm unaware of 'good' practice. I would like some feedback on general coding style (there's lots to change in the GUI and other aspects, I'm interested in style and safety). There is a demo here, and the github is here.  The main code is below.  Any feedback welcomed.  I'm particularly interested in things that will increase reuse - am I naming things according to expected patterns and so on?window.comscan = window.comscan || {};var speech_voices;if ('speechSynthesis' in window) {    speech_voices = window.speechSynthesis.getVoices();    window.speechSynthesis.onvoiceschanged = function() {        speech_voices = window.speechSynthesis.getVoices();    };}function think(message) {    voiceOutput(message, Fiona)}function say(message) {    voiceOutput(message, Daniel)}function voiceOutput(message, inVoice) {    var utterance = new SpeechSynthesisUtterance(message);    if (utterance.voice == null) {        utterance.voice = speech_voices.filter(function(voice) {            return voice.name == inVoice;        })[0];    }    window.speechSynthesis.speak(utterance);}function MenuItem(inid, inlabel, inlink, inUtterance) {    //Holds the information for a single unit that can be activated.     this.id = inid    this.label = inlabel    this.link = inlink    this.utterance = inUtterance || inlabel} //end MenuItem classfunction PagesIterator(targetGraph) {    this.rootNodeID = 0    this.childIndex = 0; //initialisation    this.graph = targetGraph; //currently a dictionary of node IDs to MenuItem objects    this.currentNode = this.graph[this.rootNodeID]    this.backStack = []; //stores breadcrumbs to work a multi-level 'back' button.     this.getHighlightedItem = function() {        return this.currentNode[this.childIndex]; //returns a MenuItem    }    this.getHighlightedItemLabel = function() {        return this.getHighlightedItem().label;    };    this.getHighlightedItemID = function() {        return this.getHighlightedItem().id;    };    this.refreshHTML = function() {        var listtable = document.getElementById('listtable');        listtable.innerHTML =         for (child = 0; child < this.currentNode.length; child++) {            html = <td>            if (child == this.childIndex) {                html = <td style= \color:red\>;            }            listtable.innerHTML += <tr> + html + this.currentNode[child].label + </tr></td>;        }    }    this.next = function() {        this.childIndex++;        if (this.childIndex == this.currentNode.length) {            this.childIndex = 0;        }        think(this.currentNode[this.childIndex].utterance);        this.refreshHTML()    }    this.jump = function(dest) {        this.currentNode = this.graph[dest]        this.childIndex = 0; //start the new page at the begining        this.refreshHTML() //new page    }    this.processOVF = function(dest) {        if (dest.indexOf(back) != -1) {            this.backStack.pop() //this will be the current page we pop off            dest = this.backStack[this.backStack.length - 1] //this the the page below that we peek at:            if (dest == undefined) {                dest = this.rootNodeID            }            this.jump(dest)            return        } //a different OVF command        alert(stub!);    }    this.activate = function() {        var dest = this.getHighlightedItem().link        if (dest == ) { //then it's a speech activatation            say(this.getHighlightedItem().utterance)            return        }        if (dest in this.graph) {            this.jump(dest)            this.backStack.push(dest)        } else if (dest.indexOf(ovf() != -1) {            this.processOVF(dest)        } else { //some failed linkk            alert(Stub!);        }    }} //end Board class
Tool for blind users who also have NO speech
javascript;git
Joe, here's some quick comments based on a cursory inspection. Note you are in danger of starting bike shedding with your question. :) My comments are really personal opinion.So this is Browser code using the Speech Synthesis API which has good support. it's good you that you are doing feature testing, but might you like to think about fallback if features are missing.You have chosen a classic class based style using JavaScript style in ES5 and the code is small. You don't give an example of use though.Given that I'd say the code is good and easy to understand. You have used good naming and formatting. You have mixed using semicolons and no-semicolons (probably as you are used to python) Either are safe but stick to one or the other as there are dangers if you mix. Use a lint tool like ESLint to check for this and enforce other styles. You don't need to go for a crazy workflow or build set up to use these tools - just command line or npm scripts if you use node for development. Pick a coding style and stick to it.You have no exception handling. Are you sure it is not needed?Be carefull with x == null and x == undefined. There be dragons. Null and undefined are not the same. This is an entire topic to itself. Add in truthy and falsey values and !. Is all fine if you are sure what you are doing but javascript gets really messy around these due to type coercions. Many people stick to using === for comparisons, but that is not totally necessary if you are careful. I'd personally not use null ever, just undefined.I suggest reading Crockford's - JavaScript the good Parts for these sort of issues. It's small and easy to read, though the newer versions of JavaScript are moving the target. You really aught to have some unit tests and there are many opinions and tools on this. Personally I keep it simple and use tape. Mocha and their ilk add quite a bit of complexity. see Eric Elliot on Tape and he has many other opinionated but excellent articles.Finally as your code gets larger you might wanted to explore other patterns that separate logic from state management and side effects like events and DOM updates. As it is you are rather are mixing concerns which will impact testability. There are many, options not just React + Redux which are very popular these days. The add predictability and testability, but these frameworks bring complexity not to mention learning curve. The are very much solving problems of large codebases and teams. I personally like cyclejs but that's a big leap into reactive programming and a functional coding style (rather than classes)I hope that helps you write awesome AT software! :)