Google Speech Recognizer - define 2 optional languages - javascript
I developed a web application base on JavaScript, with Google Speech Recognizer API.
The main language should be Hebrew, and supposed to help doctors to write medical diagnosis.
The problem is that if I say medical word in English like C.T or Diabetes that in professional language should be say in English, it writes the English word in Hebrew.
My question is, if there is any option to define multi languages option or define languages priorities that when it detect unfamiliar word it will try the second choice????
Please help me Thank you!
This is my JavaScript Code:
var langs =
[['Afrikaans', ['af-ZA']],
['Hebrew', ['he-IL']],
['Bahasa Melayu', ['ms-MY']],
['Català', ['ca-ES']],
['Čeština', ['cs-CZ']],
['Deutsch', ['de-DE']],
['English', ['en-AU', 'Australia'],
['en-CA', 'Canada'],
['en-IN', 'India'],
['en-NZ', 'New Zealand'],
['en-ZA', 'South Africa'],
['en-GB', 'United Kingdom'],
['en-US', 'United States']],
['Español', ['es-AR', 'Argentina'],
['es-BO', 'Bolivia'],
['es-CL', 'Chile'],
['es-CO', 'Colombia'],
['es-CR', 'Costa Rica'],
['es-EC', 'Ecuador'],
['es-SV', 'El Salvador'],
['es-ES', 'España'],
['es-US', 'Estados Unidos'],
['es-GT', 'Guatemala'],
['es-HN', 'Honduras'],
['es-MX', 'México'],
['es-NI', 'Nicaragua'],
['es-PA', 'Panamá'],
['es-PY', 'Paraguay'],
['es-PE', 'Perú'],
['es-PR', 'Puerto Rico'],
['es-DO', 'República Dominicana'],
['es-UY', 'Uruguay'],
['es-VE', 'Venezuela']],
['Euskara', ['eu-ES']],
['Français', ['fr-FR']],
['Galego', ['gl-ES']],
['Hrvatski', ['hr_HR']],
['IsiZulu', ['zu-ZA']],
['Íslenska', ['is-IS']],
['Italiano', ['it-IT', 'Italia'],
['it-CH', 'Svizzera']],
['Magyar', ['hu-HU']],
['Nederlands', ['nl-NL']],
['Norsk bokmål', ['nb-NO']],
['Polski', ['pl-PL']],
['Português', ['pt-BR', 'Brasil'],
['pt-PT', 'Portugal']],
['Română', ['ro-RO']],
['Slovenčina', ['sk-SK']],
['Suomi', ['fi-FI']],
['Svenska', ['sv-SE']],
['Türkçe', ['tr-TR']],
['български', ['bg-BG']],
['Pусский', ['ru-RU']],
['Српски', ['sr-RS']],
['한국어', ['ko-KR']],
['中文', ['cmn-Hans-CN', '普通话 (中国大陆)'],
['cmn-Hans-HK', '普通话 (香港)'],
['cmn-Hant-TW', '中文 (台灣)'],
['yue-Hant-HK', '粵語 (香港)']],
['日本語', ['ja-JP']],
['Lingua latīna', ['la']]];
for (var i = 0; i < langs.length; i++) {
select_language.options[i] = new Option(langs[i][0], i);
}
select_language.selectedIndex = 1;
updateCountry();
select_dialect.selectedIndex = 1;
showInfo('info_start');
function updateCountry() {
for (var i = select_dialect.options.length - 1; i >= 0; i--) {
select_dialect.remove(i);
}
var list = langs[select_language.selectedIndex];
for (var i = 1; i < list.length; i++) {
select_dialect.options.add(new Option(list[i][1], list[i][0]));
}
select_dialect.style.visibility = list[1].length == 1 ? 'hidden' : 'visible';
}
var create_email = false;
var final_transcript = '';
var recognizing = false;
var ignore_onend;
var start_timestamp;
if (!('webkitSpeechRecognition' in window)) {
console.log("before upgrade")
upgrade();
} else {
start_button.style.display = 'inline-block';
var recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.interimResults = true;
recognition.onstart = function() {
recognizing = true;
showInfo('info_speak_now');
console.log("webkitSpeechRecognition")
start_img.src = '/static/Mic_MicroPhone_Mute.PNG';
start_pic=document.getElementById("start_img")
start_pic.style.height="59px";
start_pic.style.width="43px";
};
recognition.onerror = function(event) {
if (event.error == 'no-speech') {
console.log("event error");
start_img.src = '/static/mic.png';
showInfo('info_no_speech');
ignore_onend = true;
}
if (event.error == 'audio-capture') {
console.log("event caputre");
start_img.src = '/static/mic.png';
showInfo('info_no_microphone');
ignore_onend = true;
}
if (event.error == 'not-allowed') {
console.log("even not allowed");
if (event.timeStamp - start_timestamp < 100) {
showInfo('info_blocked');
} else {
showInfo('info_denied');
}
ignore_onend = true;
}
};
recognition.onend = function() {
recognizing = false;
if (ignore_onend) {
return;
}
console.log("init mic image");
start_img.src = '/static/mic.png';
if (!final_transcript) {
showInfo('info_start');
return;
}
showInfo('');
// if (window.getSelection) {
// window.getSelection().removeAllRanges();
// var range = document.createRange();
// range.selectNode(document.getElementById('final_span'));
// window.getSelection().addRange(range);
// }
if (create_email) {
create_email = false;
createEmail();
}
};
recognition.onresult = function(event) {
var interim_transcript = '';
for (var i = event.resultIndex; i < event.results.length; ++i) {
if (event.results[i].isFinal) {
console.log("Final!!!!!!!!!!!!")
console.log(final_span.value+event.results[i][0].transcript);
final_transcript = final_span.value+event.results[i][0].transcript;
final_span.value=final_transcript;
} else {
interim_transcript += event.results[i][0].transcript;
}
}
final_transcript = capitalize(final_transcript);
console.log("interim_transcript :");
console.log(interim_transcript);
console.log("final_transcript :");
console.log(final_transcript);
// final_span.value = linebreak(interim_transcript);
if (final_transcript) {
console.log("final transcript true");
// final_span.value= linebreak(final_transcript);
}
if (final_transcript || interim_transcript) {
showButtons('inline-block');
}
};
}
function upgrade() {
start_button.style.visibility = 'hidden';
showInfo('info_upgrade');
}
var two_line = /\n\n/g;
var one_line = /\n/g;
function linebreak(s) {
return s.replace(two_line, '<p></p>').replace(one_line, '<br>');
}
var first_char = /\S/;
function capitalize(s) {
return s.replace(first_char, function(m) { return m.toUpperCase(); });
}
function createEmail() {
var n = final_transcript.indexOf('\n');
if (n < 0 || n >= 80) {
n = 40 + final_transcript.substring(40).indexOf(' ');
}
var subject = encodeURI(final_transcript.substring(0, n));
var body = encodeURI(final_transcript.substring(n + 1));
textarea_value=document.getElementById("final_span").value;
window.location.href = 'mailto:?subject=' + "Puzzle-Soft Telemedicine - Speech Recognizer " + '&body=' + textarea_value;
}
function copyButton() {
if (recognizing) {
recognizing = false;
recognition.stop();
}
copy_button.style.display = 'none';
copy_info.style.display = 'inline-block';
showInfo('');
}
function emailButton() {
if (recognizing) {
create_email = true;
recognizing = false;
recognition.stop();
} else {
createEmail();
}
email_button.style.display = 'none';
email_info.style.display = 'inline-block';
showInfo('');
}
function startButton(event) {
if (recognizing) {
recognition.stop();
console.log("StartButton if")
return;
}
console.log("StartButton else")
final_transcript = '';
recognition.lang = select_dialect.value;
recognition.start();
ignore_onend = false;
// final_span.innerHTML = '';
// interim_span.innerHTML = '';
start_img.src = '/static/mic.png';
showInfo('info_allow');
showButtons('none');
start_timestamp = event.timeStamp;
}
function showInfo(s) {
if (s) {
for (var child = info.firstChild; child; child = child.nextSibling) {
if (child.style) {
child.style.display = child.id == s ? 'inline' : 'none';
}
}
info.style.visibility = 'visible';
} else {
info.style.visibility = 'hidden';
}
}
var current_style;
function showButtons(style) {
if (style == current_style) {
return;
}
current_style = style;
copy_button.style.display = style;
email_button.style.display = style;
copy_info.style.display = 'none';
email_info.style.display = 'none';
}
function ClearText() {
console.log("clear");
text_area_value=document.getElementById("final_span");
console.log(text_area_value);
console.log(text_area_value.value);
text_area_value.value='';
}
//var givevalue = function (my_key) {
// return dict[my_key];
//
// }
//
//js_json={'אדרנלypr': 'Olanzapine Teva', 'זיפאדהרה': 'Zypadhera', 'אומפראזול': 'Omeprazole', 'אומפרדקס': 'Omepradex', 'לוסק': 'Losec', 'אומפריקס': 'Omeprix', 'אומפרדקס Z': 'Omepradex Z', 'אומפרה': 'Omepra', 'אונדאנסטרון': 'Ondansetron', 'זופרן': 'Zofran', 'אודנטרון': 'Odnatron', 'אונדאנסטרון - פרזניוס': 'Ondansetron - Fresenius', 'אונדנסטרון אינובמד': 'Ondansetron Inovamed'}
//function replaceTextAreaDict() {
//textarea_result=document.getElementById("final_span");
// textarea_words=textarea_result.split(' ') ;
// for (var i = 0; i < textarea_result.length; i++) {
//
// }
//
//
//
// givevalue()
//
//}
//
//replaceTextAreaDict();
You cannot mix language.
Speech Recognition roughly contains 3 part -> Accoustic model, Language model, and dictionary.
Accoustic model is the result of data training contains relationship between audio signal and phonetic
Dictionary contains words and how they pronounced, for e.g, word TOP are pronounced "T AH P" on the general speech recognition dictionary.
Language model is the connection between words to create sentences, for e.g. the word "I" is connected with "am", so the speech recognizer will very rarely (or never) give the result of "I are" or "I is".
Every Language have their own Accoustic Model (phonetic), Dictionary (words), and Language Model (sentences), so we can just mix them up.
The Question is : Is it still possible?
The Answer is : YES!
You can build your own language (in this case Medical language) using many tools, one I already tried called CMU Sphinx / Pocket Sphinx. You can build your own model, train it, and make a dictionary out of it. It will be alot work to do, but you can configure anything you will need for speech recognition.
Link for any platform implementation : https://github.com/cmusphinx
Related
create a typing and deleting effect animation of placeholder in an input box
I'm trying to create an animated placeholder for an input box which looks like the placeholder is typed and deleted again (like in https://www.squarespace.com/templates ). I tried for a single string but failed to do so for an array, I have commented the part I tried to change. I am new to Javascript: const words = [ "Injection", "Broken Authentication", "Sensitive Data Exposure", "XML External Entities (XXE)", "Broken Access Control", "Security Misconfiguration", "Cross-Site Scripting (XSS)", "Insecure Deserialization", "Using Components with Known Vulnerabilities", "Insufficient Logging&Monitoring" ]; let i = 0; let timer; function typingEffect() { let word = words[i].split(""); var loopTyping = function () { if (word.length > 0) { document.getElementById('word').innerHTML += word.shift(); } else { deletingEffect(); return false; }; timer = setTimeout(loopTyping, 200); }; loopTyping(); }; function deletingEffect() { let word = words[i].split(""); var loopDeleting = function () { if (word.length > 0) { word.pop(); // document.getElementById('word').style.font = inherit; document.getElementById('word').innerHTML = word.join(""); } else { if (words.length > (i + 1)) { i++; } else { i = 0; }; typingEffect(); return false; }; timer = setTimeout(loopDeleting, 100); }; loopDeleting(); }; typingEffect(); I wanted this to happen in the placeholder of the input tag. Can you help me please?
You can use .setAttribute() and .getAttribute() to set and append to the placeholder text: typingEffect(): let elem = document.getElementById('typer'); elem.setAttribute('placeholder', elem.getAttribute('placeholder') + word.shift()); deletingEffect(): document.getElementById('typer').setAttribute('placeholder', word.join("")); See example below: const words = ["Injection", "Broken Authentication", "Sensitive Data Exposure", "XML External Entities (XXE)", "Broken Access Control", "Security Misconfiguration", "Cross-Site Scripting (XSS)", "Insecure Deserialization", "Using Components with Known Vulnerabilities", "Insufficient Logging&Monitoring" ]; let i = 0; let timer; function typingEffect() { let word = words[i].split(""); var loopTyping = function() { if (word.length > 0) { let elem = document.getElementById('typer'); elem.setAttribute('placeholder', elem.getAttribute('placeholder') + word.shift()); } else { deletingEffect(); return false; }; timer = setTimeout(loopTyping, 200); }; loopTyping(); }; function deletingEffect() { let word = words[i].split(""); var loopDeleting = function() { if (word.length > 0) { word.pop(); document.getElementById('typer').setAttribute('placeholder', word.join("")); } else { if (words.length > (i + 1)) { i++; } else { i = 0; }; typingEffect(); return false; }; timer = setTimeout(loopDeleting, 100); }; loopDeleting(); }; typingEffect(); #typer { font-size: 30px; } <input type="text" id="typer" placeholder=""></div>
how to update a class property in the function of event handler?
Please help to how to access the property of class in the event handler function. I want to update property of class in a handle function of web speech API, while it always fail, I do not know how to transfer the class object to the event handler function. The error code is "Cannot read property 'resultIndex' of undefined" in following code class SpeechToText { constructor() { this.recognition = null; this.text = 'original'; this.getDataFromRecognition = this.getDataFromRecognition.bind(this); } getDataFromRecognition(event){ console.log(this.text); var final_transcript = ''; var interim_transcript = ''; for (var i = event.resultIndex; i < event.results.length; ++i) { if (event.results[i].isFinal) { final_transcript += event.results[i][0].transcript; console.log('result is Final' + final_transcript); } else { interim_transcript += event.results[i][0].transcript; console.log('interim transcript' + interim_transcript); } } this.text = final_transcript; } listening() { let recognition = new window.webkitSpeechRecognition(); recognition.lang = 'zh-CN'; recognition.interimResults = false; recognition.continuous = false; recognition.start(); recognition.onresult = this.getDataFromRecognition(event); recognition.onspeechend = function() { this.stop(); } recognition.onnomatch = function(event) { console.log( "It is no match."); } recognition.onerror = function(event) { console.log('Error occurred in recognition: ' + event.error); } } } # on following code, this.text in the function "this.onresult = function(event)" will create a new property of SpeechRecognition. class SpeechToText { constructor() { this.text = 'original'; this.recognition = null; } setText(str){ this.text = str; return this.text; console.log('this in on setText ' + this); } getText(){ return this.text; } listening() { this.recognition = new window.webkitSpeechRecognition(); this.recognition.lang = 'zh-CN'; //this.recognition.lang = 'en-GB'; this.recognition.interimResults = false; this.recognition.continuous = false; this.recognition.start(); console.log("this under class" + this); this.recognition.onresult = function(event) { // The SpeechRecognitionEvent results property returns a SpeechRecognitionResultList object // The SpeechRecognitionResultList object contains SpeechRecognitionResult objects. // It has a getter so it can be accessed like an array // The [last] returns the SpeechRecognitionResult at the last position. // Each SpeechRecognitionResult object contains SpeechRecognitionAlternative objects that contain individual results. // These also have getters so they can be accessed like arrays. // The [0] returns the SpeechRecognitionAlternative at position 0. // We then return the transcript property of the SpeechRecognitionAlternative object this.recognition = new window.webkitSpeechRecognition(); var final_transcript = ''; var interim_transcript = ''; for (var i = event.resultIndex; i < event.results.length; ++i) { if (event.results[i].isFinal) { final_transcript += event.results[i][0].transcript; console.log('result is Final' + final_transcript); } else { interim_transcript += event.results[i][0].transcript; console.log('interim transcript' + interim_transcript); } } //_utteranceForEdgeTrigger = final_transcript; //final_transcript = capitalize(final_transcript); console.log('final_transcript' + final_transcript); //this.setText(final_transcript); this.text = final_transcript; console.log('the text is in listening function :' + this.text); console.log('the this in on result is ' + this); //window.SpeechToText.getText(); } this.recognition.onspeechend = function() { console.log('this in function onspeechend' + this); this.stop(); console.log('speech end') } this.recognition.onnomatch = function(event) { console.log( "I didn't recognise that color."); } this.recognition.onerror = function(event) { console.log('Error occurred in recognition: ' + event.error); } } } var speech = new SpeechToText(); //speech.getbx(); speech.listening(); }
Why isn't localStorage saving my variables?
My game is an idle one where you click protons, neutrons, and electrons and when you have enough of some, you can build hydrogen and so forth. I kind of got my local variables to work but now I am having issues with the buying stage. Basically hydrogen costs 1 proton and one electron, when you click on the button, it runs the function SetHydrogen(), when it does that, it is supposed to run based off of the variable HydrogenCost. I am not sure if any of this is feasible. var protons = Number(localStorage.setItem("ProtonS", Pcount)); var neutrons = Number(localStorage.NeutronS); var electrons = Number(localStorage.ElectronS); var hydrogens = Number(localStorage.HydrogenS); function SaveVariables(){ if (localStorage.getItem("ProtonS")){ localStorage.setItem("ProtonS", Pcount); protons = Number(localStorage.ProtonS); } else { localStorage.ProtonS = Number(localStorage.ProtonS); } if (localStorage.NeutronS){ localStorage.NeutronS = neutrons; neutrons = Number(localStorage.NeutronS); } else { neutrons = Number(localStorage.NeutronS); } if (localStorage.ElectronS){ localStorage.ElectronS = electrons; electrons = Number(localStorage.ElectronS); } else { electrons = Number(localStorage.ElectronS); } if (localStorage.HydrogenS){ localStorage.HydrogenS = document.getElementByID("HydrogenTotal").innerHTML; hydrogens = Number(localStorage.HydrogenS); } else { hydrogens = 0; } } function LoadVariables(){ buying = 0; CanUBuy = false; protons = Number(localStorage.ProtonS); neutrons = Number(localStorage.NeutronS); electrons = Number(localStorage.ElectronS); hydrogens = Number(localStorage.HydrogenS); } function update(){ protonTap.onmousedown = function() {protons = protons + 1}; neutronTap.onmousedown = function() {neutrons = neutrons + 1}; electronTap.onmousedown = function() {electrons = electrons + 1}; }; function draw(){ ProtonsTotal.value = protons.toFixed(0); NeutronsTotal.value = neutrons.toFixed(0); ElectronsTotal.value = electrons.toFixed(0); console.log(hydrogens); console.log(CanUBuy); console.log(Pcount); }; var mainloop = function() {update(), draw(), SaveVariables()}; var buying = 0; function SetHydrogen(){ buying = 1; HydrogenCost.buy; if (CanUBuy = true){ HydrogenTotal.value ++; buying = 0; CanUBuy = false; } else { buying = 0; } } function reset(){ CanUBuy = false; protons = 0; neutrons = 0; electrons = 0; hydrogens = 0; buying = 0; } setInterval(mainloop, 16); var CanUBuy = false; var HydrogenCost = new buy(1,0,1); function buy(ProtonCost, NeutronCost, ElectronCost){ if (buying = 1){ this.pCost = ProtonCost; this.nCost = NeutronCost; this.eCost = ElectronCost; if (protons >= ProtonCost && neutrons >= NeutronCost && electrons >= ElectronCost) { CanUBuy = true; protons = protons - this.pCost; neutrons = neutrons - this.nCost; electrons = electrons - this.eCost; } else{ CanUBuy = false; alert("You don't have enough money"); } } else if (buying = 0) { buying = 0; } } if(!localStorage.getItem('start')){ localStorage.setItem('start', Date.now()); } var start = parseInt(localStorage.getItem('start')); setInterval(function(){ ffs.value = ~~((Date.now() - start)/1e3); }, 1e3);
At first, i think you should rethink your overall structure. You could shorten your code and make it reusable through OOP: function stored(name,startvalue){ this.name=name; this.value=+localStorage.getItem(name) || startvalue || 0; } stored.prototype={ change:function(by){ this.value+=by; localStorage.setItem(this.name,this.value); }, set:function(to){ this.value=to; localStorage.setItem(this.name,this.value); }, valueOf:function(){ return this.value;}, }; So you can do: var neutrons=new stored("neutrons"); alert(+neutrons);//0, 5 on reload neutrons.set(5); alert(+neutrons);//5 Note the + to convert the stored object to its value. A hydrogen function could look like this: var protons=new stored("protons",10); var electrons=new stored("electrons",10); var hydrogens=new stored("hydrogens"); hydrogens.buy=function(){ if(+protons && +neutrons){ protons.change(-1); neutrons.change(-1); this.change(1); }else{ alert("impossible. Sorry :("); } } hydrogens.buy();//test http://jsbin.com/pozinotida/1/edit?js
How do I store a range into a database
I want to store user selection in a database in order to highlight them the next time user visits the page. Here is the code I am using to add a span around the selected text. window.rangeIntersectsNode = function(range, node) { var nodeRange; if (range.intersectsNode) { return range.intersectsNode(node); } else { nodeRange = node.ownerDocument.createRange(); try { nodeRange.selectNode(node); } catch (e) { nodeRange.selectNodeContents(node); } return range.compareBoundaryPoints(Range.END_TO_START, nodeRange) == -1 && range.compareBoundaryPoints(Range.START_TO_END, nodeRange) == 1; } } window.getSelectedElementTags = function(win) { var range, sel, elmlist, treeWalker, containerElement; sel = win.getSelection(); if (sel.rangeCount > 0) { range = sel.getRangeAt(0); } if (range) { containerElement = range.commonAncestorContainer; if (containerElement.nodeType != 1) { containerElement = containerElement.parentNode; } treeWalker = win.document.createTreeWalker( containerElement, NodeFilter.SHOW_TEXT, function(node) { return rangeIntersectsNode(range, node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; }, false); elmlist = [treeWalker.currentNode]; while (treeWalker.nextNode()) { elmlist.push(treeWalker.currentNode); } return (elmlist); } } window.wrapInSpan = function(range) { var tempElement; var selectedArr = getSelectedElementTags(window); for (var i = 2; i < (selectedArr.length - 1); i++) { tempElement = document.createElement("span"); tempElement.innerHTML = selectedArr[i].nodeValue; selectedArr[i].parentElement.replaceChild(tempElement, selectedArr[i]) } var sC = range.startContainer; if (selectedArr.length == 2) { if (sC.nodeType == 3) { tempElement = document.createElement("span"); tempElement.innerHTML = sC.nodeValue.substring(range.startOffset, range.endOffset); var anc1 = sC.splitText(range.startOffset); var anc2 = (anc1.splitText(range.endOffset)).previousSibling; anc2.parentElement.replaceChild(tempElement, anc2); } } else { if (sC.nodeType == 3) { tempElement = document.createElement("span"); tempElement.innerHTML = sC.nodeValue.substring(range.startOffset); sC.parentElement.insertBefore(tempElement, sC.nextSibling); sC.nodeValue = sC.nodeValue.replace(sC.nodeValue.substring(range.startOffset), ""); } var eC = range.endContainer; if (eC.nodeType == 3) { tempElement = document.createElement("span"); tempElement.innerHTML = eC.nodeValue.substring(0, range.endOffset); eC.parentElement.insertBefore(tempElement, eC); eC.nodeValue = eC.nodeValue.replace(eC.nodeValue.substring(0, range.endOffset), ""); } } } i am using the following code to get the details of the selection, but it in the console I get always get the variables as undefined. var startNode=range.anchorNode; var endNode=range.focusNode; var startoffset=range.anchorOffset; var endoffset=range.focusOffset; var location=[startNode,endNode,startoffset,endoffset]; console.log(startNode); return location; I would greatly appreciate if some one can help me figure out how to store the range and to reload it. I am not looking to use rangy's library unless it is essentials. Also i am not sure if it will work in a chrome extension
XML Javascript undefined error in ie9
I have a 'jargon buster' on my site that uses an xml file to load an A-Z of words which when clicked display a brief short explanation of each word. This works fine in all browsers bar the latest ie's which i get an 'undefined' error with. The jscript im using is below Jargon = { xmlfile: 'http://www.mysite.com/jargon.xml', xml: null, wordHolder: 'words', defHolder: 'definition', idprefix: 'jargon_', selected: null, init: function () { var con = Jargon.xhcon(); Jargon.wordHolder = $(Jargon.wordHolder); Jargon.defHolder = $(Jargon.defHolder); if (!con || !Jargon.wordHolder || !Jargon.defHolder) { return; } function conComplete(oXML) { Jargon.xml = oXML.responseXML; //Jargon.showWords('a'); } con.connect(Jargon.xmlfile, 'GET', Math.random(), conComplete); }, showWords: function (c) { if (Jargon.selected) { Jargon.selected.className = ''; } var words = Jargon.getWords(c); while (Jargon.wordHolder.childNodes.length > 0) { Jargon.wordHolder.removeChild(Jargon.wordHolder.childNodes[0]); } while (Jargon.defHolder.childNodes.length > 0) { Jargon.defHolder.removeChild(Jargon.defHolder.childNodes[0]); } for (var i = 0; i < words.length; i++) { var o = document.createElement('a'); o.href = 'javascript:Jargon.showDef(\'' + words[i].id + '\');'; o.id = Jargon.idprefix + words[i].id; //o.onclick = Jargon.showDef; o.appendChild($t(words[i].name)); Jargon.wordHolder.appendChild(o); Jargon.wordHolder.appendChild(document.createElement('br')); } if (!words.length) { var o = document.createElement('p'); var s = 'There are no words for the letter ' + c.toUpperCase(); Jargon.wordHolder.appendChild(o.appendChild($t(s))); } }, showDef: function (id) { var o = $(Jargon.idprefix + id); if (Jargon.selected) { Jargon.selected.className = ''; } if (o) { o.className = 'selected'; Jargon.selected = o; } var defobjs = Jargon.getDef(id); while (Jargon.defHolder.childNodes.length > 0) { Jargon.defHolder.removeChild(Jargon.defHolder.childNodes[0]); } var heading = document.createElement('span'); heading.className = "jargtitle"; heading.appendChild(document.createTextNode(defobjs[1][0].textContent)); Jargon.defHolder.appendChild(heading); var definition = document.createElement('span'); definition.className = "jargdefinition"; definition.appendChild(document.createTextNode(defobjs[0][0].textContent)); Jargon.defHolder.appendChild(definition); }, getWords: function(c) { var x = Jargon.xml; var letters = x.getElementsByTagName('letter'); var oLetter = null; for (var i = 0; i < letters.length; i++) { if (letters[i].getAttribute('id') == c) { oLetter = letters[i]; break; } } if (!oLetter) { return []; } var words = []; for (i = 0; i < oLetter.childNodes.length; i++) { var oJargon = oLetter.childNodes[i]; if (oJargon.nodeName == 'jargon') { var s = Jargon.getName(oJargon); words[words.length] = { id: oLetter.childNodes[i].getAttribute('id'), name: s }; } } return words; }, getDef: function (id) { var x = Jargon.xml; var j = null; var temp = new Array(2); var jargons = x.getElementsByTagName('jargon'); for (var i = 0; i < jargons.length; i++) { if (jargons[i].getAttribute('id') == id) { j = jargons[i]; break; } } if (!j) { return []; } //return []; for (i = 0; i < j.childNodes.length; i++) { if (j.childNodes[i].nodeName == 'name') { temp[1] = j.childNodes[i].childNodes; } } for (i = 0; i < j.childNodes.length; i++) { if (j.childNodes[i].nodeName == 'desc') { temp[0] = j.childNodes[i].childNodes; } } //return []; return temp; }, cloneNode: function (oldNode, deep) { deep = (deep) ? true : false; // a replacement to the normal dom clone node // this will copy xml nodes to html nodes // which can then be inserted into the document // scope in all browsers // See for for the bug http://www.quirksmode.org/blog/archives/2005/12/xmlhttp_notes_c.html var newNode = null; if (oldNode.nodeType == '3') { // textnode newNode = $t(oldNode.nodeValue); } else if (oldNode.nodeType == '1') { // element node newNode = document.createElement(oldNode.nodeName); if (deep) { for (var i = 0; i < oldNode.childNodes.length; i++) { newNode.appendChild(Jargon.cloneNode(oldNode.childNodes[i], true)); } } } return newNode; }, getName: function (oJargon) { for (var i = 0; i < oJargon.childNodes.length; i++) { if (oJargon.childNodes[i].nodeName == 'name') { var oName = oJargon.childNodes[i]; var s = ''; for (var j = 0; j < oName.childNodes.length; j++) { if (oName.childNodes[j].nodeType == 3) { // text node s += oName.childNodes[j].nodeValue; } } return s; } } return ''; }, xhcon: function () { var xmlhttp, bComplete = false; try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp = false; }}} if (!xmlhttp) { return null; } this.connect = function(sURL, sMethod, sVars, fnDone) { if (!xmlhttp) { return false; } bComplete = false; sMethod = sMethod.toUpperCase(); try { if (sMethod == "GET") { xmlhttp.open(sMethod, sURL+"?"+sVars, true); sVars = ""; } else { xmlhttp.open(sMethod, sURL, true); xmlhttp.setRequestHeader("Method", "POST "+sURL+" HTTP/1.1"); xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && !bComplete) { bComplete = true; fnDone(xmlhttp); } }; xmlhttp.send(sVars); } catch(z) { return false; } return true; }; return this; } } In terms of how im calling the jscript im using <li>a</li> which loads a list of all items that begin with f then when i click one of items from that list say "Fiduciary" it triggers javascript:Jargon.showDef('f1'); which in turns loads the and into a definition div however in ie9 it displays "undefined" . It works in all other browers Example of the XML below: <letter id="f"> -<jargon id="f1"> <name>Fiduciary</name> <desc>in a position of trust. This includes people such as trustees looking after trust assets for the beneficiaries and company directors running a company for the shareholders' benefit.</desc> </jargon> -<jargon id="f2"> <name>Forfeiture</name> <desc>the loss of possession of a property because the tenancy conditions have not been met by the tenant.</desc> </jargon> -<jargon id="f3"> <name>Freehold</name> <desc>describing land that only the owner has any rights over.</desc> </jargon> -<jargon id="f4"> <name>Free of encumbrances</name> <desc>no one else having any rights over something. When property is owned by someone and nobody else has any rights over it, it is owned free of encumbrances.</desc> </jargon> </letter>