Some super-old changes I don't remember, along with a new search function which sorts by relevance and a few minor bugfixes

This commit is contained in:
Travis Burtrum 2014-01-25 22:53:39 -05:00
parent 87f5d3390c
commit cecf1c6b90
44 changed files with 232 additions and 196 deletions

View File

@ -18,7 +18,9 @@
under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="com.moparisthebest.pointswatcher" android:versionName="0.1" android:versionCode="1" android:hardwareAccelerated="true">
package="com.moparisthebest.pointswatcher" android:versionName="0.1" android:versionCode="1"
android:hardwareAccelerated="true">
<uses-sdk android:minSdkVersion="7"/>
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
@ -28,19 +30,19 @@
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:hardwareAccelerated="true"
android:debuggable="true">
<activity android:name="Points Watcher" android:label="@string/app_name"
<activity android:name="PointsWatcher" android:label="@string/app_name"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

19
android/android.iml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android" name="Android">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="cordova-2.5.0" level="project" />
</component>
</module>

BIN
android/assets/values.db Normal file

Binary file not shown.

View File

@ -1 +0,0 @@
../../www

View File

@ -1,10 +1,10 @@
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/gen/com/moparisthebest/pointswatcher/R.java \
: /home/mopar/devel/priv/pointsplus/PointsWatcher/android/res/drawable-mdpi/icon.png \
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/res/drawable-xhdpi/icon.png \
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/res/layout/main.xml \
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/res/drawable-hdpi/icon.png \
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/res/drawable/icon.png \
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/res/xml/config.xml \
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/res/values/strings.xml \
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/res/drawable-ldpi/icon.png \
/home/mopar/devel/priv/pointsplus/PointsWatcher/android/bin/AndroidManifest.xml \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/gen/com/moparisthebest/pointswatcher/R.java \
: /home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/res/drawable-mdpi/icon.png \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/res/drawable-xhdpi/icon.png \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/res/layout/main.xml \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/res/drawable-hdpi/icon.png \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/res/drawable/icon.png \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/res/xml/config.xml \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/res/values/strings.xml \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/res/drawable-ldpi/icon.png \
/home/mopar/IdeaProjects/pointsplus/PointsWatcher/android/bin/AndroidManifest.xml \

View File

@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package com.moparisthebest.pointswatcher;
/* This stub is for using by IDE only. It is NOT the Manifest class actually packed into APK */
public final class Manifest {
}

View File

@ -1,25 +1,7 @@
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
/*___Generated_by_IDEA___*/
package com.moparisthebest.pointswatcher;
/* This stub is for using by IDE only. It is NOT the R class actually packed into APK */
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int icon=0x7f020000;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f050000;
}
public static final class xml {
public static final int config=0x7f040000;
}
}

View File

@ -1 +0,0 @@
../../../www/res/icon/android/icon-72-hdpi.png

View File

@ -1 +0,0 @@
../../../www/res/icon/android/icon-36-ldpi.png

View File

@ -1 +0,0 @@
../../../www/res/icon/android/icon-48-mdpi.png

View File

@ -1 +0,0 @@
../../../www/res/icon/android/icon-96-xhdpi.png

View File

@ -1 +0,0 @@
../../../www/res/icon/android/icon-96-xhdpi.png

View File

@ -1 +0,0 @@
../../SQLitePlugin/Android/src/com/phonegap

View File

@ -1 +0,0 @@
../www

View File

@ -1 +0,0 @@
../android/SQLitePlugin/Android/assets/www/SQLitePlugin.js

View File

@ -1,58 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Font Face Demo</title>
<link rel="stylesheet" href="stylesheet.css" type="text/css" charset="utf-8">
<style type="text/css" media="screen">
h1.fontface {font: 60px/68px 'SansationRegular', Arial, sans-serif;letter-spacing: 0;}
p.style1 {font: 18px/27px 'SansationRegular', Arial, sans-serif;}
p.style2 {font: 18px/27px 'SansationLight', Arial, sans-serif;}
p.style3 {font: 18px/27px 'SansationBold', Arial, sans-serif;}
p.style4 {font: 18px/27px 'SansationLightLightItalic', Arial, sans-serif;}
p.style5 {font: 18px/27px 'SansationItalic', Arial, sans-serif;}
p.style6 {font: 18px/27px 'SansationBoldItalic', Arial, sans-serif;}
#container {
width: 800px;
margin-left: auto;
margin-right: auto;
}
</style>
</head>
<body>
<div id="container">
<h1 class="fontface">Font-face Demo for the Sansation Font</h1>
<p class="style1">Sansation Regular - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p class="style2">Sansation Light - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p class="style3">Sansation Bold - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p class="style4">Sansation Light Light Italic - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p class="style5">Sansation Italic - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p class="style6">Sansation Bold Italic - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 605 B

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 B

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -47,7 +47,6 @@
<preference name="permissions" value="none"/>
<!-- Customize your app and platform with the preference element. -->
<preference name="phonegap-version" value="2.3.0" /> <!-- all: current version of PhoneGap -->
<preference name="orientation" value="default" /> <!-- all: default means both landscape and portrait are enabled -->
<preference name="target-device" value="universal" /> <!-- all: possible values handset, tablet, or universal -->
<preference name="fullscreen" value="false" /> <!-- all: hides the status bar at the top of the screen -->

View File

@ -16,6 +16,10 @@
<link rel="stylesheet" href="js/libs/css/activityIndicator.css" type="text/css" />
<script src="js/fooddatabase/ArrayDatabase.js"></script>
<script type="text/javascript" charset="utf-8" src="SQLitePlugin.js"></script>
<script src="js/fooddatabase/SQLDatabase.js"></script>
<script src="cordova.js"></script>
<script src="js/viewAssembler.js"></script>
<script src="js/application.js"></script>

View File

@ -12,8 +12,10 @@ var maxSearchLength = 50;
var weeklyPointsAllowed = 49;
var valuesLoaded = false;
var values = [];
var foodSearchResults = undefined;
var runningCordova = false;
var foodDb = undefined;
var database;
var viewAssembler = new ViewAssembler();
var backButtonLabel = " ";
@ -43,7 +45,6 @@ function setupDefaultView() {
}
function onNearbyListItemClick(event) {
$("li").removeClass("listSelected");
var target = $(event.target)
if (target.get(0).nodeName.toUpperCase() != "LI") {
@ -54,19 +55,11 @@ function onNearbyListItemClick(event) {
var index = target.attr("index");
index = parseInt(index);
database.setItem("amount", values[index][3]);
database.setItem("amount", foodSearchResults[index].points);
showPointsPage(true);
}
function scriptSuccess(data, textStatus, jqXHR) {
//for (var i = 0; i < values.length; i++) {
// values[i].push(i.toString());
//}
//console.log( "scriptSuccess: " + values.length );
}
function pushPointsPage() {
showPointsPage(true);
}
@ -82,52 +75,36 @@ function showPointsPage(push) {
window.viewNavigator.pushView(view);
}
function prepareSearch() {
if(foodDb == undefined){
//if(window.sqlitePlugin == undefined)
//if(!runningCordova)
foodDb = new ArrayDatabase();
//else
// foodDb = new SQLDatabase();
}
}
function onSearchButtonClick(event) {
var $input = $("#search_searchPhrase");
var searchPhrase = $input.val();
if (searchPhrase != undefined && searchPhrase.length > 0) {
var values = filterValuesBySearchCriteria(searchPhrase);
foodSearchResults = foodDb.searchFood(searchPhrase);
var view = { title: "Search Results",
backLabel: backButtonLabel,
view: viewAssembler.searchResultsView(values, searchPhrase)
view: viewAssembler.searchResultsView(foodSearchResults, searchPhrase)
};
window.viewNavigator.pushView(view);
}
}
function filterValuesBySearchCriteria(searchPhrase) {
var result = [];
//var startTime = new Date().getTime();
var tokens = searchPhrase.toLowerCase().split(" ");
var regexps = new Array(tokens.length);
for (var x = 0; x < regexps.length; ++x)
regexps[x] = new RegExp(tokens[x]);
var numFound = 0;
for (var y = 0; y < values.length; ++y) {
var found = true;
for (var z = 0; z < regexps.length; ++z) {
if (!regexps[z].test(values[y][0])) {
found = false;
break;
}
}
if (found) {
result.push(y);
if (++numFound == maxSearchLength)
break;
}
}
//console.log( new Date().getTime() - startTime );
return result;
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function isPositiveNumber(n) {
return isNumber(n) && n > 0;
return isNumber(n) && n >= 0;
}
function roundPoints(points){
@ -241,20 +218,6 @@ function onResetPointsButtonClick(dailyNotWeekly) {
showPointsPage();
}
function arrayToFoodObject(index) {
var result = {};
var row = values[index];
result.name = row[1];
result.amount = row[2];
result.points = row[3];
result.index = index;
return result;
}
function openExternalURL(url) {
var result = confirm("You will leave the Points Watcher App. Continue?");
if (result == true) {
@ -262,10 +225,9 @@ function openExternalURL(url) {
}
}
function dbGetNum(key) {
var ret = dbGet(key, 0);
return ret < 1 ? undefined : ret;
var ret = dbGet(key, -1);
return ret < 0 ? undefined : ret;
}
function dbGet(key, defaultVal) {
@ -280,6 +242,7 @@ function dbGet(key, defaultVal) {
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
runningCordova = true;
document.addEventListener("backbutton", onBackKey, false);
}

View File

@ -0,0 +1,78 @@
function ArrayDatabase() {
this.type = 'array';
//$.getScript("values.js", scriptSuccess);
var thisClass = this;
$.ajax({
url: "values.js",
dataType: "text",
cache: true
}).done(function (data) {
thisClass.values = eval(data);
});
}
ArrayDatabase.prototype.searchFood = function (searchPhrase) {
//alert('type: ' + this.type + ' searchPhrase: ' + searchPhrase);
//searchPhrase = 'banana bread';
var result = [];
//var startTime = new Date().getTime();
var tokens = searchPhrase.toLowerCase().split(" ");
var num_tokens = tokens.length;
// partials
var regexps = new Array(num_tokens);
for (var x = 0; x < num_tokens; ++x)
regexps[x] = new RegExp(tokens[x]);
// whole words
var whole_regexps = new Array(num_tokens);
for (var x = 0; x < num_tokens; ++x)
whole_regexps[x] = new RegExp('\\b'+tokens[x]+'\\b');
var right_order = new RegExp(tokens.join('.*'));
var exact_order = new RegExp(tokens.join('\\s*'));
var numFound = -1;
valueLoop:
for (var y = 0; y < this.values.length; ++y) {
var relevance = 0;
for (var z = 0; z < num_tokens; ++z) {
if (regexps[z].test(this.values[y][0]))
++relevance; // add a point for each word found
else
continue valueLoop; // for now, only display a result if all tokens were found
}
// now add a point for each WHOLE word that was found
for (var z = 0; z < num_tokens; ++z)
if (whole_regexps[z].test(this.values[y][0]))
++relevance;
// add a point if it's in the right order
if(right_order.test(this.values[y][0])){
relevance *= 2;
// and another if it's in the exact right order
if(exact_order.test(this.values[y][0]))
relevance *= 2;
}
result.push({
relevance: relevance,
name: this.values[y][1],
amount: this.values[y][2],
points: this.values[y][3],
//points: relevance,
index: ++numFound
});
}
// sort preferring a higher relevance and a shorter name
result.sort(function(a, b) {
var ret = b.relevance - a.relevance;
if(ret == 0)
ret = a.name.length - b.name.length;
return ret;
});
//console.log( new Date().getTime() - startTime );
return result.slice(0,maxSearchLength);
};

View File

@ -0,0 +1,44 @@
function ArrayDatabase() {
this.type = 'array';
//$.getScript("values.js", scriptSuccess);
var thisClass = this;
$.ajax({
url: "values.js",
dataType: "text",
cache: true
}).done(function (data) {
thisClass.values = eval(data);
});
}
ArrayDatabase.prototype.searchFood = function (searchPhrase) {
//alert('type: ' + this.type + ' searchPhrase: ' + searchPhrase);
var result = [];
//var startTime = new Date().getTime();
var tokens = searchPhrase.toLowerCase().split(" ");
var regexps = new Array(tokens.length);
for (var x = 0; x < regexps.length; ++x)
regexps[x] = new RegExp(tokens[x]);
var numFound = 0;
for (var y = 0; y < this.values.length; ++y) {
var found = true;
for (var z = 0; z < regexps.length; ++z) {
if (!regexps[z].test(this.values[y][0])) {
found = false;
break;
}
}
if (found) {
result.push({
name: this.values[y][1],
amount: this.values[y][2],
points: this.values[y][3],
index: numFound
});
if (++numFound == maxSearchLength)
break;
}
}
//console.log( new Date().getTime() - startTime );
return result;
};

View File

@ -0,0 +1,11 @@
function SQLDatabase() {
this.type = 'sql';
//this.db = open(bla);
//this.db = window.sqlitePlugin.openDatabase("Database", "1.0", "Demo", -1);
this.db = window.sqlitePlugin.openDatabase({name: "values"});
}
SQLDatabase.prototype.searchFood = function(searchPhrase) {
alert('type: '+this.type+' searchPhrase: '+searchPhrase);
//return this.color + ' ' + this.type + ' apple';
};

View File

@ -108,19 +108,6 @@ ViewAssembler.prototype.aboutView = function() {
return el;
}
ViewAssembler.prototype.searchView = function () {
if(!valuesLoaded){
valuesLoaded = true;
$.getScript("values.js", scriptSuccess);
}
var el = $( templates.searchViewTemplate );
el.find( "#searchButton" ).on( this.CLICK_EVENT, onSearchButtonClick );
return el;
}
ViewAssembler.prototype.calcPointsView = function () {
var viewModel = {};
viewModel.amount = dbGetNum("calcPointsAmount");
@ -155,12 +142,19 @@ ViewAssembler.prototype.calcAllowanceView = function () {
return el;
}
ViewAssembler.prototype.searchResultsView = function( indices, searchPhrase ) {
var viewModel = {values:[]};
for (var i=0; i< indices.length; ++i) {
var food = arrayToFoodObject( indices[i] );
viewModel.values.push( food );
}
ViewAssembler.prototype.searchView = function () {
prepareSearch();
var el = $( templates.searchViewTemplate );
el.find( "#searchButton" ).on( this.CLICK_EVENT, onSearchButtonClick );
return el;
}
ViewAssembler.prototype.searchResultsView = function( foodSearchResults, searchPhrase ) {
var viewModel = {};
viewModel.values = foodSearchResults;
/*
viewModel.values.sort( function(a, b){
if ( a.foodName < b.foodName ) { return -1; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -1,4 +1,4 @@
var values = [
[
["0881 tea black tea 100 organic","0881 Tea Black Tea, 100% Organic","1 bag","0"],
["0881 tea green jasmine tea","0881 Tea Green Jasmine Tea","1 bag","0"],
["100 grand bars","100 Grand Bars","2 bars","5"],
@ -167703,4 +167703,4 @@ var values = [
["zwieback","Zwieback","1 oz","3"],
["zwieback","Zwieback","4 item(s)","3"],
["zydeco fruit nut bar","Zydeco Fruit Nut Bar","1 bar","5"],
];
]

View File

@ -8,7 +8,7 @@
<input type="number" step="1" id="calcAge" prompt="Age" value="{{age}}" /> (in years)<br/>
<strong>Weight:</strong><br/>
<input type="number" step="1" id="calcWeight" prompt="Weight" value="{{weight}}" />
<select id="calcWeightType"><option>pounds</option><option>inches</option></select><br/>
<select id="calcWeightType"><option>pounds</option><option>kilograms</option></select><br/>
<strong>Height:</strong><br/>
<input type="number" step="1" id="calcHeight" prompt="Height" value="{{height}}" />
<select id="calcHeightType"><option>inches</option><option>meters</option></select><br/>