comparison test_create/test_create.html @ 444:9c9fd68693b1

Merge. Pull of revision info from dev_main.
author Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk>
date Wed, 23 Dec 2015 14:36:00 +0000
parents db353cc479b8
children 9a8ede168aba
comparison
equal deleted inserted replaced
442:1081368deed7 444:9c9fd68693b1
102 text.textContent = "Thank you for downloading the Web Audio Evaluation Toolbox. This page will help guide you through creating the documents required to run a test. If you have an existing XML file you wish to edit, please drag and drop it into the box below"; 102 text.textContent = "Thank you for downloading the Web Audio Evaluation Toolbox. This page will help guide you through creating the documents required to run a test. If you have an existing XML file you wish to edit, please drag and drop it into the box below";
103 var dnd = document.createElement('div'); 103 var dnd = document.createElement('div');
104 dnd.style.width = "100%"; 104 dnd.style.width = "100%";
105 dnd.style.height = "50px"; 105 dnd.style.height = "50px";
106 dnd.className = "dragndrop"; 106 dnd.className = "dragndrop";
107 dnd.ondragover = function(e) {
108 e.stopPropagation();
109 e.preventDefault();
110 };
111 dnd.ondragenter = function(e) {
112 e.stopPropagation();
113 e.preventDefault();
114 this.style.backgroundColor = '#AAFFAA';
115 };
116 dnd.ondragleave = function(e) {
117 e.stopPropagation();
118 e.preventDefault();
119 this.style.backgroundColor = "#FFFFFF";
120 };
121 dnd.ondrop = function(e) {
122 e.stopPropagation();
123 e.preventDefault();
124
125 var file = e.dataTransfer.files[0];
126
127 // Uses HTML5 FileAPI - https://w3c.github.io/FileAPI/#filereader-interface
128 var reader = new FileReader();
129 reader.onload = function() {
130 var parse = new DOMParser();
131 var xml = parse.parseFromString(reader.result,'text/xml');
132 specificationNode.decode(xml);
133 popupInstance.hidePopup();
134 SpecificationToHTML();
135 };
136 reader.readAsText(file);
137
138 };
107 this.popupBody.appendChild(text); 139 this.popupBody.appendChild(text);
108 this.popupBody.appendChild(dnd); 140 this.popupBody.appendChild(dnd);
109 this.showPopup(); 141 this.showPopup();
110 142
111 var button = document.createElement('button'); 143 var button = document.createElement('button');
1509 this.popupFooter.appendChild(button); 1541 this.popupFooter.appendChild(button);
1510 break; 1542 break;
1511 case 8: 1543 case 8:
1512 this.hidePopup(); 1544 this.hidePopup();
1513 this.state = 0; 1545 this.state = 0;
1514 SpecficationToHTML(); 1546 SpecificationToHTML ();
1515 } 1547 }
1516 this.state++; 1548 this.state++;
1517 }; 1549 };
1518 }; 1550 };
1519 1551
1583 { 1615 {
1584 this.check = input.id; 1616 this.check = input.id;
1585 } 1617 }
1586 }; 1618 };
1587 }; 1619 };
1620
1621 this.randomiseOrder = function(input)
1622 {
1623 // This takes an array of information and randomises the order
1624 var N = input.length;
1625
1626 var inputSequence = []; // For safety purposes: keep track of randomisation
1627 for (var counter = 0; counter < N; ++counter)
1628 inputSequence.push(counter) // Fill array
1629 var inputSequenceClone = inputSequence.slice(0);
1630
1631 var holdArr = [];
1632 var outputSequence = [];
1633 for (var n=0; n<N; n++)
1634 {
1635 // First pick a random number
1636 var r = Math.random();
1637 // Multiply and floor by the number of elements left
1638 r = Math.floor(r*input.length);
1639 // Pick out that element and delete from the array
1640 holdArr.push(input.splice(r,1)[0]);
1641 // Do the same with sequence
1642 outputSequence.push(inputSequence.splice(r,1)[0]);
1643 }
1644 console.log(inputSequenceClone.toString()); // print original array to console
1645 console.log(outputSequence.toString()); // print randomised array to console
1646 return holdArr;
1647 };
1588 this.projectReturn = null; 1648 this.projectReturn = null;
1589 this.randomiseOrder = null; 1649 this.randomiseOrder = null;
1590 this.collectMetrics = null; 1650 this.collectMetrics = null;
1591 this.testPages = null; 1651 this.testPages = null;
1592 this.audioHolders = []; 1652 this.audioHolders = [];
1593 this.metrics = []; 1653 this.metrics = [];
1594 1654
1595 this.decode = function() { 1655 this.decode = function(projectXML) {
1596 // projectXML - DOM Parsed document 1656 // projectXML - DOM Parsed document
1597 this.projectXML = projectXML.childNodes[0]; 1657 this.projectXML = projectXML.childNodes[0];
1598 var setupNode = projectXML.getElementsByTagName('setup')[0]; 1658 var setupNode = projectXML.getElementsByTagName('setup')[0];
1599 this.interfaceType = setupNode.getAttribute('interface'); 1659 this.interfaceType = setupNode.getAttribute('interface');
1600 this.projectReturn = setupNode.getAttribute('projectReturn'); 1660 this.projectReturn = setupNode.getAttribute('projectReturn');
1612 this.testPages = Number(this.testPages); 1672 this.testPages = Number(this.testPages);
1613 if (this.testPages == 0) {this.testPages = null;} 1673 if (this.testPages == 0) {this.testPages = null;}
1614 } 1674 }
1615 var metricCollection = setupNode.getElementsByTagName('Metric'); 1675 var metricCollection = setupNode.getElementsByTagName('Metric');
1616 1676
1617 this.preTest = new this.prepostNode('pretest',setupNode.getElementsByTagName('PreTest')); 1677 var setupPreTestNode = setupNode.getElementsByTagName('PreTest');
1618 this.postTest = new this.prepostNode('posttest',setupNode.getElementsByTagName('PostTest')); 1678 if (setupPreTestNode.length != 0)
1679 {
1680 setupPreTestNode = setupPreTestNode[0];
1681 this.preTest.construct(setupPreTestNode);
1682 }
1683
1684 var setupPostTestNode = setupNode.getElementsByTagName('PostTest');
1685 if (setupPostTestNode.length != 0)
1686 {
1687 setupPostTestNode = setupPostTestNode[0];
1688 this.postTest.construct(setupPostTestNode);
1689 }
1619 1690
1620 if (metricCollection.length > 0) { 1691 if (metricCollection.length > 0) {
1621 metricCollection = metricCollection[0].getElementsByTagName('metricEnable'); 1692 metricCollection = metricCollection[0].getElementsByTagName('metricEnable');
1622 for (var i=0; i<metricCollection.length; i++) { 1693 for (var i=0; i<metricCollection.length; i++) {
1623 this.metrics.push(new this.metricNode(metricCollection[i].textContent)); 1694 this.metrics.push(new this.metricNode(metricCollection[i].textContent));
1673 } 1744 }
1674 }; 1745 };
1675 1746
1676 var audioHolders = projectXML.getElementsByTagName('audioHolder'); 1747 var audioHolders = projectXML.getElementsByTagName('audioHolder');
1677 for (var i=0; i<audioHolders.length; i++) { 1748 for (var i=0; i<audioHolders.length; i++) {
1678 this.audioHolders.push(new this.audioHolderNode(this,audioHolders[i])); 1749 var node = new this.audioHolderNode(this);
1750 node.decode(this,audioHolders[i]);
1751 this.audioHolders.push(node);
1679 } 1752 }
1680 1753
1681 // New check if we need to randomise the test order 1754 // New check if we need to randomise the test order
1682 if (this.randomiseOrder) 1755 if (this.randomiseOrder && typeof randomiseOrder === "function")
1683 { 1756 {
1684 this.audioHolders = randomiseOrder(this.audioHolders); 1757 this.audioHolders = randomiseOrder(this.audioHolders);
1685 for (var i=0; i<this.audioHolders.length; i++) 1758 for (var i=0; i<this.audioHolders.length; i++)
1686 { 1759 {
1687 this.audioHolders[i].presentedId = i; 1760 this.audioHolders[i].presentedId = i;
1716 setupNode.setAttribute('testPages',this.testPages); 1789 setupNode.setAttribute('testPages',this.testPages);
1717 1790
1718 var setupPreTest = root.createElement("PreTest"); 1791 var setupPreTest = root.createElement("PreTest");
1719 for (var i=0; i<this.preTest.options.length; i++) 1792 for (var i=0; i<this.preTest.options.length; i++)
1720 { 1793 {
1721 setupPreTest.appendChild(this.preTest.options.exportXML(root)); 1794 setupPreTest.appendChild(this.preTest.options[i].exportXML(root));
1722 } 1795 }
1723 1796
1724 var setupPostTest = root.createElement("PostTest"); 1797 var setupPostTest = root.createElement("PostTest");
1725 for (var i=0; i<this.preTest.options.length; i++) 1798 for (var i=0; i<this.postTest.options.length; i++)
1726 { 1799 {
1727 setupPostTest.appendChild(this.postTest.options.exportXML(root)); 1800 setupPostTest.appendChild(this.postTest.options[i].exportXML(root));
1728 } 1801 }
1729 1802
1730 setupNode.appendChild(setupPreTest); 1803 setupNode.appendChild(setupPreTest);
1731 setupNode.appendChild(setupPostTest); 1804 setupNode.appendChild(setupPostTest);
1732 1805
1733 // <Metric> tag 1806 // <Metric> tag
1734 var Metric = root.createElement("Metric"); 1807 var Metric = root.createElement("Metric");
1735 for (var i=0; i<this.metrics.length; i++) 1808 for (var i=0; i<this.metrics.length; i++)
1736 { 1809 {
1737 var metricEnable = document.createElement("metricEnable"); 1810 var metricEnable = root.createElement("metricEnable");
1738 metricEnable.textContent = this.metrics[i].enabled; 1811 metricEnable.textContent = this.metrics[i].enabled;
1739 Metric.appendChild(metricEnable); 1812 Metric.appendChild(metricEnable);
1740 } 1813 }
1741 setupNode.appendChild(Metric); 1814 setupNode.appendChild(Metric);
1742 1815
1743 // <interface> tag 1816 // <interface> tag
1744 var CommonInterface = root.createElement("interface"); 1817 var CommonInterface = root.createElement("interface");
1745 for (var i=0; i<this.commonInterface.options.length; i++) 1818 for (var i=0; i<this.commonInterface.options.length; i++)
1746 { 1819 {
1747 var CIObj = this.commonInterface.options[i]; 1820 var CIObj = this.commonInterface.options[i];
1748 var CINode = document.createElement(CIObj.type); 1821 var CINode = root.createElement(CIObj.type);
1749 if (CIObj.type == "check") {CINode.setAttribute("name",CIObj.check);} 1822 if (CIObj.type == "check") {CINode.setAttribute("name",CIObj.check);}
1750 else {CINode.setAttribute("name",CIObj.name);} 1823 else {CINode.setAttribute("name",CIObj.name);}
1751 CommonInterface.appendChild(CINode); 1824 CommonInterface.appendChild(CINode);
1752 } 1825 }
1753 setupNode.appendChild(CommonInterface); 1826 setupNode.appendChild(CommonInterface);
1754 1827
1755 root.getElementsByTagName("BrowserEvalProjectDocument")[0].appendChild(setupNode); 1828 root.getElementsByTagName("BrowserEvalProjectDocument")[0].appendChild(setupNode);
1756 // Time for the <audioHolder> tags 1829 // Time for the <audioHolder> tags
1757 for (var ahIndex = 0; ahIndex < this.audioHolders.length; ahIndex++) 1830 for (var ahIndex = 0; ahIndex < this.audioHolders.length; ahIndex++)
1758 { 1831 {
1759 var AHObj = this.audioHolders[ahIndex]; 1832 var node = this.audioHolders[ahIndex].encode(root);
1760 var AHNode = root.createElement("audioHolder"); 1833 root.getElementsByTagName("BrowserEvalProjectDocument")[0].appendChild(node);
1761 AHNode.id = AHObj.id;
1762 AHNode.setAttribute("hostURL",AHObj.hostURL);
1763 AHNode.setAttribute("sampleRate",AHObj.samplerate);
1764 AHNode.setAttribute("randomiseOrder",AHObj.randomiseOrder);
1765 AHNode.setAttribute("repeatCount",AHObj.repeatCount);
1766 AHNode.setAttribute("loop",AHObj.loop);
1767 AHNode.setAttribute("elementComments",AHObj.elementComments);
1768
1769 // Create <interface> tag
1770 for (var i=0; i<AHObj.interfaces.length; i++)
1771 {
1772 var AHObjInterface = AHObj.interfaces[i];
1773 var AHinterface = root.createElement("interface");
1774 if (AHObjInterface.title != undefined)
1775 {
1776 var title = root.createElement("title");
1777 title.textContent = AHObjInterface.title;
1778 AHinterface.appendChild(title);
1779 }
1780 for (var j=0; j<AHObjInterface.options.length; j++)
1781 {
1782 var CIObj = AHObjInterface.options[j];
1783 var CINode = root.createElement(CIObj.type);
1784 if (CIObj.type == "check") {CINode.setAttribute("name",CIObj.check);}
1785 else {CINode.setAttribute("name",CIObj.name);}
1786 AHinterface.appendChild(CINode);
1787 }
1788 if (AHObjInterface.scale != undefined)
1789 {
1790 for (var j=0; j<AHObjInterface.scale.length; j++)
1791 {
1792 var CIObj = AHObjInterface.scale[j];
1793 var CINode = root.createElement("scale");
1794 CINode.setAttribute("position",CIObj[0]);
1795 CINode.textContent = CIObj[1];
1796 AHinterface.appendChild(CINode);
1797 }
1798 }
1799 AHNode.appendChild(AHinterface);
1800 }
1801
1802 // Create <audioElements>
1803 for (var aeIndex = 0; aeIndex < AHObj.audioElements.length; aeIndex++)
1804 {
1805 var AEObj = AHObj.audioElements[aeIndex];
1806 var AENode = root.createElement("audioElements");
1807 AENode.id = AEObj.id;
1808 AENode.setAttribute("url",AEObj.url);
1809 AENode.setAttribute("type",AEObj.type);
1810 if (AEObj.marker != undefined && AEObj.enforce)
1811 {
1812 AENode.setAttribute("marker",AEObj.marker*100);
1813 }
1814 AHNode.appendChild(AENode);
1815 }
1816
1817 // Create <CommentQuestion>
1818 for (var i=0; i<AHObj.commentQuestions.length; i++)
1819 {
1820 AHNode.appendChild(AHObj.commentQuestions[i].exportXML(root));
1821 }
1822
1823 // Create <PreTest>
1824 var AHPreTest = document.createElement("PreTest");
1825 for (var i=0; i<AHObj.preTest.options.length; i++)
1826 {
1827 AHPreTest.appendChild(AHObj.preTest.options.exportXML(root));
1828 }
1829
1830 var AHPostTest = document.createElement("PostTest");
1831 for (var i=0; i<AHObj.preTest.options.length; i++)
1832 {
1833 AHPostTest.appendChild(AHObj.postTest.options.exportXML(root));
1834 }
1835 AHNode.appendChild(AHPreTest);
1836 AHNode.appendChild(AHPostTest);
1837 root.getElementsByTagName("BrowserEvalProjectDocument")[0].appendChild(AHNode);
1838 } 1834 }
1839 return root; 1835 return root;
1840 }; 1836 };
1841 1837
1842 this.prepostNode = function(type) { 1838 this.prepostNode = function(type) {
1845 1841
1846 this.OptionNode = function() { 1842 this.OptionNode = function() {
1847 1843
1848 this.childOption = function() { 1844 this.childOption = function() {
1849 this.type = 'option'; 1845 this.type = 'option';
1850 this.id = element.id; 1846 this.id = null;
1851 this.name = element.getAttribute('name'); 1847 this.name = undefined;
1852 this.text = element.textContent; 1848 this.text = null;
1853 }; 1849 };
1854 1850
1855 this.type = undefined; 1851 this.type = undefined;
1856 this.id = undefined; 1852 this.id = undefined;
1857 this.mandatory = undefined; 1853 this.mandatory = undefined;
1861 this.options = []; 1857 this.options = [];
1862 this.min = undefined; 1858 this.min = undefined;
1863 this.max = undefined; 1859 this.max = undefined;
1864 this.step = undefined; 1860 this.step = undefined;
1865 1861
1862 this.decode = function(child)
1863 {
1864 this.type = child.nodeName;
1865 if (child.nodeName == "question") {
1866 this.id = child.id;
1867 this.mandatory;
1868 if (child.getAttribute('mandatory') == "true") {this.mandatory = true;}
1869 else {this.mandatory = false;}
1870 this.question = child.textContent;
1871 if (child.getAttribute('boxsize') == null) {
1872 this.boxsize = 'normal';
1873 } else {
1874 this.boxsize = child.getAttribute('boxsize');
1875 }
1876 } else if (child.nodeName == "statement") {
1877 this.statement = child.textContent;
1878 } else if (child.nodeName == "checkbox" || child.nodeName == "radio") {
1879 var element = child.firstElementChild;
1880 this.id = child.id;
1881 if (element == null) {
1882 console.log('Malformed' +child.nodeName+ 'entry');
1883 this.statement = 'Malformed' +child.nodeName+ 'entry';
1884 this.type = 'statement';
1885 } else {
1886 this.options = [];
1887 while (element != null) {
1888 if (element.nodeName == 'statement' && this.statement == undefined){
1889 this.statement = element.textContent;
1890 } else if (element.nodeName == 'option') {
1891 var node = new this.childOption();
1892 node.id = element.id;
1893 node.name = element.getAttribute('name');
1894 node.text = element.textContent;
1895 this.options.push(node);
1896 }
1897 element = element.nextElementSibling;
1898 }
1899 }
1900 } else if (child.nodeName == "number") {
1901 this.statement = child.textContent;
1902 this.id = child.id;
1903 this.min = child.getAttribute('min');
1904 this.max = child.getAttribute('max');
1905 this.step = child.getAttribute('step');
1906 }
1907 };
1908
1866 this.exportXML = function(root) 1909 this.exportXML = function(root)
1867 { 1910 {
1868 var node = root.createElement(this.type); 1911 var node = root.createElement(this.type);
1869 switch(this.type) 1912 switch(this.type)
1870 { 1913 {
1878 node.textContent = this.question; 1921 node.textContent = this.question;
1879 break; 1922 break;
1880 case "number": 1923 case "number":
1881 node.id = this.id; 1924 node.id = this.id;
1882 node.setAttribute("mandatory",this.mandatory); 1925 node.setAttribute("mandatory",this.mandatory);
1883 node.setAttribute("min"), this.min; 1926 node.setAttribute("min", this.min);
1884 node.setAttribute("max"), this.max; 1927 node.setAttribute("max", this.max);
1885 node.setAttribute("step"), this.step; 1928 node.setAttribute("step", this.step);
1929 node.textContent = this.statement;
1886 break; 1930 break;
1887 case "checkbox": 1931 case "checkbox":
1888 node.id = this.id; 1932 node.id = this.id;
1889 var statement = document.createElement("statement"); 1933 var statement = root.createElement("statement");
1890 statement.textContent = this.statement; 1934 statement.textContent = this.statement;
1891 node.appendChild(statement); 1935 node.appendChild(statement);
1892 for (var i=0; i<this.options.length; i++) 1936 for (var i=0; i<this.options.length; i++)
1893 { 1937 {
1894 var option = this.option[i]; 1938 var option = this.options[i];
1895 var optionNode = document.createElement("option"); 1939 var optionNode = root.createElement("option");
1896 optionNode.id = option.id; 1940 optionNode.id = option.id;
1897 optionNode.textContent = option.text; 1941 optionNode.textContent = option.text;
1898 node.appendChild(option); 1942 node.appendChild(optionNode);
1899 } 1943 }
1900 break; 1944 break;
1901 case "radio": 1945 case "radio":
1902 node.id = this.id; 1946 node.id = this.id;
1903 var statement = document.createElement("statement"); 1947 var statement = root.createElement("statement");
1904 statement.textContent = this.statement; 1948 statement.textContent = this.statement;
1905 node.appendChild(statement); 1949 node.appendChild(statement);
1906 for (var i=0; i<this.options.length; i++) 1950 for (var i=0; i<this.options.length; i++)
1907 { 1951 {
1908 var option = this.option[i]; 1952 var option = this.options[i];
1909 var optionNode = document.createElement("option"); 1953 var optionNode = root.createElement("option");
1910 optionNode.setAttribute("name") = option.name; 1954 optionNode.setAttribute("name",option.name);
1911 optionNode.textContent = option.text; 1955 optionNode.textContent = option.text;
1912 node.appendChild(option); 1956 node.appendChild(optionNode);
1913 } 1957 }
1914 break; 1958 break;
1915 } 1959 }
1916 return node; 1960 return node;
1917 }; 1961 };
1918 }; 1962 };
1963 this.construct = function(Collection)
1964 {
1965 if (Collection.childElementCount != 0) {
1966 var child = Collection.firstElementChild;
1967 var node = new this.OptionNode();
1968 node.decode(child);
1969 this.options.push(node);
1970 while (child.nextElementSibling != null) {
1971 child = child.nextElementSibling;
1972 node = new this.OptionNode();
1973 node.decode(child);
1974 this.options.push(node);
1975 }
1976 }
1977 };
1919 }; 1978 };
1979 this.preTest = new this.prepostNode("pretest");
1980 this.postTest = new this.prepostNode("posttest");
1920 1981
1921 this.metricNode = function(name) { 1982 this.metricNode = function(name) {
1922 this.enabled = name; 1983 this.enabled = name;
1923 }; 1984 };
1924 1985
1929 this.hostURL = undefined; 1990 this.hostURL = undefined;
1930 this.sampleRate = undefined; 1991 this.sampleRate = undefined;
1931 this.randomiseOrder = undefined; 1992 this.randomiseOrder = undefined;
1932 this.loop = undefined; 1993 this.loop = undefined;
1933 this.elementComments = undefined; 1994 this.elementComments = undefined;
1934 this.preTest = new parent.prepostNode('pretest'); 1995 this.outsideReference = null;
1935 this.postTest = new parent.prepostNode('posttest'); 1996 this.preTest = new parent.prepostNode("pretest");
1997 this.postTest = new parent.prepostNode("pretest");
1936 this.interfaces = []; 1998 this.interfaces = [];
1937 this.commentBoxPrefix = "Comment on track"; 1999 this.commentBoxPrefix = "Comment on track";
1938 this.audioElements = []; 2000 this.audioElements = [];
1939 this.commentQuestions = []; 2001 this.commentQuestions = [];
1940 2002
1941 this.interfaceNode = function(DOM) { 2003 this.decode = function(parent,xml)
1942 var title = DOM.getElementsByTagName('title'); 2004 {
1943 if (title.length == 0) {this.title = null;} 2005 this.presentedId = parent.audioHolders.length;
1944 else {this.title = title[0].textContent;} 2006 this.id = xml.id;
1945 this.options = parent.commonInterface.options; 2007 this.hostURL = xml.getAttribute('hostURL');
1946 var scale = DOM.getElementsByTagName('scale'); 2008 this.sampleRate = xml.getAttribute('sampleRate');
1947 this.scale = []; 2009 if (xml.getAttribute('randomiseOrder') == "true") {this.randomiseOrder = true;}
1948 for (var i=0; i<scale.length; i++) { 2010 else {this.randomiseOrder = false;}
1949 var arr = [null, null]; 2011 this.repeatCount = xml.getAttribute('repeatCount');
1950 arr[0] = scale[i].getAttribute('position'); 2012 if (xml.getAttribute('loop') == 'true') {this.loop = true;}
1951 arr[1] = scale[i].textContent; 2013 else {this.loop == false;}
1952 this.scale.push(arr); 2014 if (xml.getAttribute('elementComments') == "true") {this.elementComments = true;}
2015 else {this.elementComments = false;}
2016
2017 var setupPreTestNode = xml.getElementsByTagName('PreTest');
2018 if (setupPreTestNode.length != 0)
2019 {
2020 setupPreTestNode = setupPreTestNode[0];
2021 this.preTest.construct(setupPreTestNode);
2022 }
2023
2024 var setupPostTestNode = xml.getElementsByTagName('PostTest');
2025 if (setupPostTestNode.length != 0)
2026 {
2027 setupPostTestNode = setupPostTestNode[0];
2028 this.postTest.construct(setupPostTestNode);
2029 }
2030
2031 var interfaceDOM = xml.getElementsByTagName('interface');
2032 for (var i=0; i<interfaceDOM.length; i++) {
2033 var node = new this.interfaceNode();
2034 node.decode(interfaceDOM[i]);
2035 this.interfaces.push(node);
2036 }
2037 this.commentBoxPrefix = xml.getElementsByTagName('commentBoxPrefix');
2038 if (this.commentBoxPrefix.length != 0) {
2039 this.commentBoxPrefix = this.commentBoxPrefix[0].textContent;
2040 } else {
2041 this.commentBoxPrefix = "Comment on track";
2042 }
2043 var audioElementsDOM = xml.getElementsByTagName('audioElements');
2044 for (var i=0; i<audioElementsDOM.length; i++) {
2045 var node = new this.audioElementNode();
2046 node.decode(this,audioElementsDOM[i]);
2047 if (audioElementsDOM[i].getAttribute('type') == 'outsidereference') {
2048 if (this.outsideReference == null) {
2049 this.outsideReference = node;
2050 } else {
2051 console.log('Error only one audioelement can be of type outsidereference per audioholder');
2052 this.audioElements.push(node);
2053 console.log('Element id '+audioElementsDOM[i].id+' made into normal node');
2054 }
2055 } else {
2056 this.audioElements.push(node);
2057 }
2058 }
2059
2060 if (this.randomiseOrder == true && typeof randomiseOrder === "function")
2061 {
2062 this.audioElements = randomiseOrder(this.audioElements);
2063 }
2064
2065 var commentQuestionsDOM = xml.getElementsByTagName('CommentQuestion');
2066 for (var i=0; i<commentQuestionsDOM.length; i++) {
2067 var node = new this.commentQuestionNode();
2068 node.decode(commentQuestionsDOM[i]);
2069 this.commentQuestions.push(node);
1953 } 2070 }
1954 }; 2071 };
1955 2072
1956 this.audioElementNode = function(parent,audioObject) { 2073 this.encode = function(root)
1957 this.url = audioObject.file.name; 2074 {
1958 this.id = audioObject.id; 2075 var AHNode = root.createElement("audioHolder");
1959 this.parent = parent; 2076 AHNode.id = this.id;
2077 AHNode.setAttribute("hostURL",this.hostURL);
2078 AHNode.setAttribute("sampleRate",this.sampleRate);
2079 AHNode.setAttribute("randomiseOrder",this.randomiseOrder);
2080 AHNode.setAttribute("repeatCount",this.repeatCount);
2081 AHNode.setAttribute("loop",this.loop);
2082 AHNode.setAttribute("elementComments",this.elementComments);
2083
2084 for (var i=0; i<this.interfaces.length; i++)
2085 {
2086 AHNode.appendChild(this.interfaces[i].encode(root));
2087 }
2088
2089 for (var i=0; i<this.audioElements.length; i++) {
2090 AHNode.appendChild(this.audioElements[i].encode(root));
2091 }
2092 // Create <CommentQuestion>
2093 for (var i=0; i<this.commentQuestions.length; i++)
2094 {
2095 AHNode.appendChild(this.commentQuestions[i].exportXML(root));
2096 }
2097
2098 // Create <PreTest>
2099 var AHPreTest = root.createElement("PreTest");
2100 for (var i=0; i<this.preTest.options.length; i++)
2101 {
2102 AHPreTest.appendChild(this.preTest.options[i].exportXML(root));
2103 }
2104
2105 var AHPostTest = root.createElement("PostTest");
2106 for (var i=0; i<this.postTest.options.length; i++)
2107 {
2108 AHPostTest.appendChild(this.postTest.options[i].exportXML(root));
2109 }
2110 AHNode.appendChild(AHPreTest);
2111 AHNode.appendChild(AHPostTest);
2112 return AHNode;
2113 };
2114
2115 this.interfaceNode = function() {
2116 this.title = undefined;
2117 this.options = [];
2118 this.scale = [];
2119 this.name = undefined;
2120 this.decode = function(DOM)
2121 {
2122 var title = DOM.getElementsByTagName('title');
2123 if (title.length == 0) {this.title = null;}
2124 else {this.title = title[0].textContent;}
2125 var name = DOM.getAttribute("name");
2126 if (name != undefined) {this.name = name;}
2127 this.options = parent.commonInterface.options;
2128 var scale = DOM.getElementsByTagName('scale');
2129 this.scale = [];
2130 for (var i=0; i<scale.length; i++) {
2131 var arr = [null, null];
2132 arr[0] = scale[i].getAttribute('position');
2133 arr[1] = scale[i].textContent;
2134 this.scale.push(arr);
2135 }
2136 };
2137 this.encode = function(root)
2138 {
2139 var node = root.createElement("interface");
2140 if (this.title != undefined)
2141 {
2142 var title = root.createElement("title");
2143 title.textContent = this.title;
2144 node.appendChild(title);
2145 }
2146 for (var i=0; i<this.options.length; i++)
2147 {
2148 var optionNode = root.createElement(this.options[i].type);
2149 if (this.options[i].type == "option")
2150 {
2151 optionNode.setAttribute("name",this.options[i].name);
2152 } else if (this.options[i].type == "check") {
2153 optionNode.setAttribute("check",this.options[i].check);
2154 } else if (this.options[i].type == "scalerange") {
2155 optionNode.setAttribute("min",this.options[i].min*100);
2156 optionNode.setAttribute("max",this.options[i].max*100);
2157 }
2158 node.appendChild(optionNode);
2159 }
2160 for (var i=0; i<this.scale.length; i++) {
2161 var scale = root.createElement("scale");
2162 scale.setAttribute("position",this.scale[i][0]);
2163 scale.textContent = this.scale[i][1];
2164 node.appendChild(scale);
2165 }
2166 return node;
2167 };
2168 };
2169
2170 this.audioElementNode = function() {
2171 this.url = null;
2172 this.id = null;
2173 this.parent = null;
1960 this.type = "normal"; 2174 this.type = "normal";
1961 2175 this.marker = false;
1962 this.marker = undefined; 2176 this.enforce = false;
2177 this.gain = 1.0;
2178 this.decode = function(parent,xml)
2179 {
2180 this.url = xml.getAttribute('url');
2181 this.id = xml.id;
2182 this.parent = parent;
2183 this.type = xml.getAttribute('type');
2184 var gain = xml.getAttribute('gain');
2185 if (isNaN(gain) == false && gain != null)
2186 {
2187 this.gain = decibelToLinear(Number(gain));
2188 }
2189 if (this.type == null) {this.type = "normal";}
2190 if (this.type == 'anchor') {this.anchor = true;}
2191 else {this.anchor = false;}
2192 if (this.type == 'reference') {this.reference = true;}
2193 else {this.reference = false;}
2194 if (this.anchor == true || this.reference == true)
2195 {
2196 this.marker = xml.getAttribute('marker');
2197 if (this.marker != undefined)
2198 {
2199 this.marker = Number(this.marker);
2200 if (isNaN(this.marker) == false)
2201 {
2202 if (this.marker > 1)
2203 { this.marker /= 100.0;}
2204 if (this.marker >= 0 && this.marker <= 1)
2205 {
2206 this.enforce = true;
2207 return;
2208 } else {
2209 console.log("ERROR - Marker of audioElement "+this.id+" is not between 0 and 1 (float) or 0 and 100 (integer)!");
2210 console.log("ERROR - Marker not enforced!");
2211 }
2212 } else {
2213 console.log("ERROR - Marker of audioElement "+this.id+" is not a number!");
2214 console.log("ERROR - Marker not enforced!");
2215 }
2216 }
2217 }
2218 };
2219 this.encode = function(root)
2220 {
2221 var AENode = root.createElement("audioElements");
2222 AENode.id = this.id;
2223 AENode.setAttribute("url",this.url);
2224 AENode.setAttribute("type",this.type);
2225 AENode.setAttribute("gain",linearToDecibel(this.gain));
2226 if (this.marker != false)
2227 {
2228 AENode.setAttribute("marker",this.marker*100);
2229 }
2230 return AENode;
2231 };
1963 }; 2232 };
1964 2233
1965 this.commentQuestionNode = function(xml) { 2234 this.commentQuestionNode = function(xml) {
2235 this.id = null;
2236 this.type = undefined;
2237 this.question = undefined;
2238 this.options = [];
2239 this.statement = undefined;
2240
2241 this.childOption = function() {
2242 this.type = 'option';
2243 this.name = null;
2244 this.text = null;
2245 };
1966 this.exportXML = function(root) 2246 this.exportXML = function(root)
1967 { 2247 {
1968 var CQNode = root.createElement("CommentQuestion"); 2248 var CQNode = root.createElement("CommentQuestion");
1969 CQNode.id = this.id; 2249 CQNode.id = this.id;
1970 CQNode.setAttribute("type",this.type); 2250 CQNode.setAttribute("type",this.type);
1971 switch(this.type) 2251 switch(this.type)
1972 { 2252 {
1973 case "text": 2253 case "text":
1974 CQNode.textContent = this.question; 2254 CQNode.textContent = this.question;
1975 break; 2255 break;
1976 case "radio" || "checkbox": 2256 case "radio":
1977 var statement = document.createElement("statement"); 2257 var statement = root.createElement("statement");
1978 statement.textContent = this.statement; 2258 statement.textContent = this.statement;
1979 CQNode.appendChild(statement); 2259 CQNode.appendChild(statement);
1980 for (var i=0; i<this.options.length; i++) 2260 for (var i=0; i<this.options.length; i++)
1981 { 2261 {
1982 var optionNode = document.createElement("option"); 2262 var optionNode = root.createElement("option");
1983 optionNode.setAttribute("name",this.options[i].name); 2263 optionNode.setAttribute("name",this.options[i].name);
1984 optionNode.textContent = this.options[i].text; 2264 optionNode.textContent = this.options[i].text;
1985 CQNode.appendChild(optionNode); 2265 CQNode.appendChild(optionNode);
1986 } 2266 }
1987 break; 2267 break;
2268 case "checkbox":
2269 var statement = root.createElement("statement");
2270 statement.textContent = this.statement;
2271 CQNode.appendChild(statement);
2272 for (var i=0; i<this.options.length; i++)
2273 {
2274 var optionNode = root.createElement("option");
2275 optionNode.setAttribute("name",this.options[i].name);
2276 optionNode.textContent = this.options[i].text;
2277 CQNode.appendChild(optionNode);
2278 }
2279 break;
1988 } 2280 }
1989 return CQNode; 2281 return CQNode;
1990 }; 2282 };
1991 this.childOption = function(element) { 2283 this.decode = function(xml) {
1992 this.type = 'option'; 2284 this.id = xml.id;
1993 this.name = element.getAttribute('name'); 2285 if (xml.getAttribute('mandatory') == 'true') {this.mandatory = true;}
1994 this.text = element.textContent; 2286 else {this.mandatory = false;}
1995 }; 2287 this.type = xml.getAttribute('type');
1996 this.id = xml.id; 2288 if (this.type == undefined) {this.type = 'text';}
1997 if (xml.getAttribute('mandatory') == 'true') {this.mandatory = true;} 2289 switch (this.type) {
1998 else {this.mandatory = false;} 2290 case 'text':
1999 this.type = xml.getAttribute('type'); 2291 this.question = xml.textContent;
2000 if (this.type == undefined) {this.type = 'text';} 2292 break;
2001 switch (this.type) { 2293 case 'radio':
2002 case 'text': 2294 var child = xml.firstElementChild;
2003 this.question = xml.textContent; 2295 this.options = [];
2004 break; 2296 while (child != undefined) {
2005 case 'radio': 2297 if (child.nodeName == 'statement' && this.statement == undefined) {
2006 var child = xml.firstElementChild; 2298 this.statement = child.textContent;
2007 this.options = []; 2299 } else if (child.nodeName == 'option') {
2008 while (child != undefined) { 2300 var node = new this.childOption();
2009 if (child.nodeName == 'statement' && this.statement == undefined) { 2301 node.name = child.getAttribute('name');
2010 this.statement = child.textContent; 2302 node.text = child.textContent;
2011 } else if (child.nodeName == 'option') { 2303 this.options.push(node);
2012 this.options.push(new this.childOption(child)); 2304 }
2305 child = child.nextElementSibling;
2013 } 2306 }
2014 child = child.nextElementSibling; 2307 break;
2015 } 2308 case 'checkbox':
2016 break; 2309 var child = xml.firstElementChild;
2017 case 'checkbox': 2310 this.options = [];
2018 var child = xml.firstElementChild; 2311 while (child != undefined) {
2019 this.options = []; 2312 if (child.nodeName == 'statement' && this.statement == undefined) {
2020 while (child != undefined) { 2313 this.statement = child.textContent;
2021 if (child.nodeName == 'statement' && this.statement == undefined) { 2314 } else if (child.nodeName == 'option') {
2022 this.statement = child.textContent; 2315 var node = new this.childOption();
2023 } else if (child.nodeName == 'option') { 2316 node.name = child.getAttribute('name');
2024 this.options.push(new this.childOption(child)); 2317 node.text = child.textContent;
2318 this.options.push(node);
2319 }
2320 child = child.nextElementSibling;
2025 } 2321 }
2026 child = child.nextElementSibling; 2322 break;
2027 } 2323 }
2028 break; 2324 };
2029 }
2030 }; 2325 };
2031 }; 2326 };
2032
2033 this.preTest = new this.prepostNode("pretest");
2034 this.postTest = new this.prepostNode("posttest");
2035 } 2327 }
2036 2328
2329 function linearToDecibel(gain)
2330 {
2331 return 20.0*Math.log10(gain);
2332 }
2333
2334 function decibelToLinear(gain)
2335 {
2336 return Math.pow(10,gain/20.0);
2337 }
2338
2037 function createDeleteNodeButton(node) 2339 function createDeleteNodeButton(node)
2038 { 2340 {
2039 var button = document.createElement("button"); 2341 var button = document.createElement("button");
2040 button.textContent = "Delete"; 2342 button.textContent = "Delete";
2041 button.onclick = function(event) 2343 button.onclick = function(event)
2044 node.parentElement.removeChild(node); 2346 node.parentElement.removeChild(node);
2045 }; 2347 };
2046 return button; 2348 return button;
2047 } 2349 }
2048 2350
2049 function SpecficationToHTML() 2351 function SpecificationToHTML()
2050 { 2352 {
2051 // Take information from Specification Node and format it into an HTML layout 2353 // Take information from Specification Node and format it into an HTML layout
2052 var destination = document.getElementById("content"); 2354 var destination = document.getElementById("content");
2053 // Setup Header Node 2355 // Setup Header Node
2054 var setupNode = document.createElement("div"); 2356 var setupNode = document.createElement("div");
2477 audioElems.id = aHTML.id+"-audioElements"; 2779 audioElems.id = aHTML.id+"-audioElements";
2478 audioElems.className = "SecondLevel"; 2780 audioElems.className = "SecondLevel";
2479 var title = document.createElement("h3"); 2781 var title = document.createElement("h3");
2480 title.textContent = "Audio Elements"; 2782 title.textContent = "Audio Elements";
2481 audioElems.appendChild(title); 2783 audioElems.appendChild(title);
2482 for (var i=0; i<aH.audioElements.length; i++) 2784 for (var j=0; j<aH.audioElements.length; j++)
2483 { 2785 {
2484 var entry = document.createElement("div"); 2786 var entry = document.createElement("div");
2485 entry.className = "SecondLevel"; 2787 entry.className = "SecondLevel";
2486 entry.id = audioElems.id+"-"+aH.audioElements[i].id; 2788 entry.id = audioElems.id+"-"+aH.audioElements[j].id;
2487 var text = document.createElement("span"); 2789 var text = document.createElement("span");
2488 text.textContent = "ID:"; 2790 text.textContent = "ID:";
2489 var input = document.createElement("input"); 2791 var input = document.createElement("input");
2490 input.id = entry.id+"-id"; 2792 input.id = entry.id+"-id";
2491 input.value = aH.audioElements[i].id; 2793 input.value = aH.audioElements[j].id;
2492 input.onchange = function() { 2794 input.onchange = function() {
2493 var IDSplit = event.currentTarget.id.split("-"); 2795 var IDSplit = event.currentTarget.id.split("-");
2494 var ahNode = specificationNode.audioHolders[IDSplit[1]]; 2796 var ahNode = specificationNode.audioHolders[IDSplit[1]];
2495 ahNode.audioElements[IDSplit[3]].id = event.currentTarget.value; 2797 ahNode.audioElements[IDSplit[3]].id = event.currentTarget.value;
2496 }; 2798 };
2500 entry.appendChild(input); 2802 entry.appendChild(input);
2501 text = document.createElement("span"); 2803 text = document.createElement("span");
2502 text.textContent = "URL:"; 2804 text.textContent = "URL:";
2503 input = document.createElement("input"); 2805 input = document.createElement("input");
2504 input.id = entry.id+"-URL"; 2806 input.id = entry.id+"-URL";
2505 input.value = aH.audioElements[i].url; 2807 input.value = aH.audioElements[j].url;
2506 input.onchange = function() { 2808 input.onchange = function() {
2507 var IDSplit = event.currentTarget.id.split("-"); 2809 var IDSplit = event.currentTarget.id.split("-");
2508 var ahNode = specificationNode.audioHolders[IDSplit[1]]; 2810 var ahNode = specificationNode.audioHolders[IDSplit[1]];
2509 ahNode.audioElements[IDSplit[3]].url = event.currentTarget.value; 2811 ahNode.audioElements[IDSplit[3]].url = event.currentTarget.value;
2510 }; 2812 };
2511 text.style.margin = "5px"; 2813 text.style.margin = "5px";
2512 input.style.margin = "5px"; 2814 input.style.margin = "5px";
2513 entry.appendChild(text); 2815 entry.appendChild(text);
2514 entry.appendChild(input); 2816 entry.appendChild(input);
2817 text = document.createElement("span");
2818 text.textContent = "Gain:";
2819 input = document.createElement("input");
2820 input.type = "range";
2821 input.id = entry.id+"-gain";
2822 input.value = aH.audioElements[j].gain;
2823 input.min = -25;
2824 input.max = 6;
2825 input.step = 1;
2826 input.onchange = function() {
2827 var IDSplit = event.currentTarget.id.split("-");
2828 var ahNode = specificationNode.audioHolders[IDSplit[1]];
2829 ahNode.audioElements[IDSplit[3]].gain = decibelToLinear(Number(event.currentTarget.value));
2830 var textRet = document.getElementById(event.currentTarget.id+"-ret");
2831 textRet.textContent = String(event.currentTarget.value)+"dB";
2832 };
2833 var textRet = document.createElement("span");
2834 textRet.textContent = String(linearToDecibel(aH.audioElements[j].gain))+"dB";
2835 textRet.id = entry.id+"-gain-ret";
2836 text.style.margin = "5px";
2837 input.style.margin = "5px";
2838 entry.appendChild(text);
2839 entry.appendChild(input);
2840 entry.appendChild(textRet);
2515 var button_delete = document.createElement("button"); 2841 var button_delete = document.createElement("button");
2516 button_delete.textContent = "Delete"; 2842 button_delete.textContent = "Delete";
2517 button_delete.onclick = function() { 2843 button_delete.onclick = function() {
2518 var node = event.currentTarget.parentElement; 2844 var node = event.currentTarget.parentElement;
2519 var IDSplit = node.id.split("-"); 2845 var IDSplit = node.id.split("-");