LING 408/508: Programming for Linguists Lecture 13 October 14th Administrivia • • • • • Homework 5 graded Homework 5 review Javascript: Forms An SVG-based library: BMI revisited (Next time, Javascript regular expressions) Homework 4 Review Homework 5 Review <!DOCTYPE HTML> <html> <head> <title>15 Puzzle</title> <style> div { font-size: x-large } table { border: medium solid blue } td { border: 1px solid blue; font-size: xx-large; width: 45px; height: 45px; text-align: center; vertical-align: middle } td:hover { background: yellow } </style> CSS section Homework 5 Review <script> var empty_r = 3; var empty_c = 3; function f(e) { if (can_move(e)) { move(e); if (solved()) { msg("Solved!") } } } function msg(s) { document.getElementById("msgline").innerHTML = s } function can_move(e) { True var row = e.parentElement.rowIndex; var col = e.cellIndex; return ((row == empty_r && Math.abs(col - empty_c) == 1) || (col == empty_c && Math.abs(row - empty_r) == 1)); } The empty row and column When a cell is clicked, f(this) gets called used to display "Solved" if one off from the empty cell Homework 5 Review function set_empty(e) { Updates empty row and column var row = e.parentElement.rowIndex; to be this cell var col = e.cellIndex; var td = document.getElementById("puzzle").rows[row].cells[col]; td.innerHTML = ""; td.style.border = "initial"; empty_r = row; empty_c = col } function empty_td() { var t = document.getElementById("puzzle"); var tr = t.rows[empty_r]; Returns the cell for the current var td = tr.cells[empty_c]; empty cell return td } function move(e) { var empty = empty_td(); Updates empty cell to have the empty.innerHTML = e.innerHTML; empty.style.border = "1px solid blue"; value of this cell set_empty(e) Calls set_empty(this) } Homework 5 Review function random_td() { var row = Math.floor(Math.random() * 4); var col = Math.floor(Math.random() * 4); return document.getElementById("puzzle").rows[row].cells[col]; } function shuffle() { if (typeof shuffle.times == "undefined") { shuffle.times = 100 } for (var i = 0; i < shuffle.times; i++) { var e = random_td(); if (can_move(e)) { One possible way to shuffle: move(e) Pick a random cell to be the } } empty cell shuffle.times += 100; (if it can move, move it) msg(""); Repeat 100 times } new Next time we need to shuffle, shuffle 100 times more Homework 5 Review var answer = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; function solved () { for (var i=0; i < answer.length; i++) { if (cell_list[i].innerHTML != answer[i]) { return false } Return true or false depending } on whether the solved configuration return true is obtained } </script> </head> Homework 5 Review <body> <h1>15 Puzzle</h1> <p> <div>Tiles: <button type="button" onclick="shuffle()">Shuffle</button> <button type="button" onclick="window.location.reload()">Reset</button> </div> </p> <p> <table id="puzzle"> <tr> <td onclick="f(this)">1</td> <td onclick="f(this)">2</td> <td onclick="f(this)">3</td> <td onclick="f(this)">4</td> </tr> <tr> <td onclick="f(this)">5</td> <td onclick="f(this)">6</td> <td onclick="f(this)">7</td> <td onclick="f(this)">8</td> </tr> <tr> <td onclick="f(this)">9</td> <td onclick="f(this)">10</td> <td onclick="f(this)">11</td> <td onclick="f(this)">12</td> </tr> <tr> <td onclick="f(this)">13</td> <td onclick="f(this)">14</td> <td onclick="f(this)">15</td> <td onclick="f(this)"></td> </tr> </table> <span id="msgline" style="font-size:xx-large; font-family:sans-serif; font-weight:bold" ></span> </p> Homework 5 Review <script> document.getElementById("puzzle").rows[3].cells[3].style.border = "initial"; var cell_list = document.getElementById("puzzle").getElementsByTagName("td"); </script> </body> </html> Puts the list of table cells into the variable cell_list Javascript Forms • Dealing with user input … Javascript Forms • HTML Forms: – allow the user to input information – multiple named input fields for text, numbers, radio buttons, check boxes etc. can be defined within a form – values can be sent to a Web server (using GET or POST) by clicking on a button • web server implementation: later in this course – we'll use forms and call javascript functions (browser-side functionality only) <form action="" method="GET"> Weight (kg/lbs): <input type="text" name="weight" size=5> <br> Height (cm/ins): <input type="text" name="height" size=5> <br> <input type="radio" name="units" value="kg" checked>kg-cm <input type="radio" name="units" value="lbs">lbs-ins <br> <input type="button" name="button" Value="Click" onClick="computeBMI(this)"> </form> Javascript Forms • Example: – http://html5doctor.com/ demos/forms/formsexample.html Shell script BMI Recall… Javascript BMI Let's write the function computeBMI(e) • we'll need access to the following properties: e will be the input button element 1. 2. 3. e.form.weight.value e.form.height.value e.form.units[0].checked – 4. returns true|false document.getElementById("output") – returns the div with id="output" • We can place the computed value, e.g. bmi, in div (id="output") using: • document.getElementById("output").innerHT ML = bmi Javascript BMI Let's write the function computeBMI(e) • we'll need access to the following properties: 1. e.form.weight.value 2. e.form.height.value 3. e.form.units[0].checked – returns true|false 4. document.getElementById("output") – returns the div with id="output" • We can place the computed value, •e.g.BMI bmi,range: in div (id="output") using: • document.getElementById("output").innerHTML if (bmi < 18.5) { = bmi range = "underweight" } else if (bmi < 25) { range = "normal" } else if (bmi < 30) { range = "overweight" } else { range = "obese" } Javascript BMI Kinda boring … let's spiff it up a bit Javascript/SVG BMI Javascript/SVG BMI gaugeSVG.js • http://www.codeproject.com/Articles/604502/A-universal-gauge-for-your-web-dashboard Download gaugeSVG.js from the course webpage (I've modified his code a bit) gaugeSVG.js • Note: I've modified his code slightly to allow for different colors for lower and upper warning ranges gaugeSVG.js 25 (upperWarningLimit) (lowerWarningLimit) 30 (upperActionLimit) 18.5 "" To set the value: gauge.refresh(bmi, true); animation true|false Javascript/SVG BMI • Let's modify our plain Javascript BMI code to incorporate the SVG gauge … Javascript/SVG BMI Code: <script src="gaugeSVG.js"></script> <script> var gauge; window.onload = function() { gauge = new GaugeSVG({id: "gauge-div", value: 10, min: 10, max: 40, label: "BMI", lowerWarningLimit: 18.5, upperWarningLimit: 25, warningLowerRangeColor: "#eeee00", warningUpperRangeColor: "#ff8800", actionRangeColor: "#ff0000", upperActionLimit: 30, lowerActionLimit: -1}); gauge.gaugeVAL.childNodes[0].textContent = ""; }; function computeBMI(e) { var weight = e.form.weight.value; var height = e.form.height.value; var scalingfactor = e.form.units[0].checked ? 10000 : 703; var bmi = weight * scalingfactor / (height * height); var div = document.getElementById("output"); var range; if (bmi < 18.5) { range = "underweight" } else if (bmi < 25) { range = "normal" } else if (bmi < 30) { range = "overweight" } else { range = "obese" } gauge.refresh(bmi.toFixed(2),true); } </script> {property: value, … } Javascript/SVG BMI <body> <h1>Javascript BMI</h1> <form> Weight (kg/lbs): <input type="text" name="weight" size=5> Height (cm/ins): <input type="text" name="height" size=5> <br> <input type="radio" name="units" value="kg" checked> kg-cm <input type="radio" name="units" value="lbs"> lbs-ins <br> <input type="button" value="Click me!" onClick="computeBMI(this);"> </form> <div id="gauge-div" style="width: 250px; height: 200px"></div> </body> Data validation • Typically, form data is sent to a webserver. • For efficiency: validation can be done using Javascript on the browser side and data sent to the webserver only when validated. • Example (we'll use this in later lectures): – <form onSubmit="return validateForm(this)"> – … – </form> • BMI example: – make sure weight and height fields contain numeric data when the user clicks the button Data validation Several possible ways: • Use the string.match() method with a regular expression, e.g. /^[0-9\.]+$/, that permits only digits and decimal points – x.match(/^[0-9\.]+$/) • or the regular expression test method – /^[0-9\.]+$/.test(x); • or convert to 32-bit integer for bitwise or, > 0 and no fractional part after dividing by 1 – ((x | 0) > 0 && x % 1 == 0) Regular Expressions • Regular expressions (regex) are used in many natural language applications to search for and extract patterns. – LING 438/538: Perl regular expressions • Javascript has a (relatively simple) regex engine: – Introduction: – http://www.w3schools.com/js/js_regexp.asp