mirror of
https://github.com/Ekokumppanit/CalCalc.git
synced 2026-01-26 03:04:04 +00:00
Init
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
*.sublime-workspace
|
||||||
|
*.css
|
||||||
|
temp
|
||||||
|
build
|
||||||
14
README.md
Normal file
14
README.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Calcalc
|
||||||
|
|
||||||
|
http://www.liikkumisenohjaus.fi/kalorilaskuri
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
npm install -g nodefront
|
||||||
|
|
||||||
|
## Development server
|
||||||
|
|
||||||
|
nodefront serve -cl
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
build.sh
|
||||||
16
build.sh
Executable file
16
build.sh
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
nodefront compile -r
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
mkdir -p temp
|
||||||
|
|
||||||
|
nodefront minify --out build/calcalc.min.css main.css
|
||||||
|
|
||||||
|
nodefront minify --out build/calcalc.min.js main.js
|
||||||
|
|
||||||
|
# cp main.js build/calcalc.min.js
|
||||||
|
|
||||||
|
cp index.html build/calcalc.html
|
||||||
|
|
||||||
|
|
||||||
8
calcalc.sublime-project
Normal file
8
calcalc.sublime-project
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"folders":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
dynamicgif.less
Normal file
16
dynamicgif.less
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
.gifhex(@hex) {
|
||||||
|
@s: ~`(function(s){s=s.substring(1,7); return (s.length<6)? s[0]+s[0]+s[1]+s[1]+s[2]+s[2] : s;})("@{hex}")`;
|
||||||
|
@func: ~`(function(s,i){return parseInt(s[0+2*i]+s[1+2*i],16);})`;
|
||||||
|
@r: ~`@{func}("@{s}", 0)`;
|
||||||
|
@g: ~`@{func}("@{s}", 1)`;
|
||||||
|
@b: ~`@{func}("@{s}", 2)`;
|
||||||
|
.gifrgb(@r, @g, @b);
|
||||||
|
|
||||||
|
}
|
||||||
|
.gifrgb(@r,@g,@b) {
|
||||||
|
@k: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||||
|
@g1: "url(data:image/gif;base64,R0lGODlhAQABAPAAA";
|
||||||
|
@g2: "///yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==)";
|
||||||
|
@b64img: ~`function(r,g,b){var k=@{k};return @{g1}+k.charAt(((0&3)<<4)|(r>>4))+k.charAt(((r&15)<<2)|(g>>6))+k.charAt(g&63)+k.charAt(b>>2)+k.charAt(((b&3)<<4)|(255>>4))+@{g2}}(@{r},@{g},@{b})`;
|
||||||
|
background-image: @b64img;
|
||||||
|
}
|
||||||
136
elements.less
Normal file
136
elements.less
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/*---------------------------------------------------
|
||||||
|
LESS Elements 0.6
|
||||||
|
---------------------------------------------------
|
||||||
|
A set of useful LESS mixins by Dmitry Fadeyev
|
||||||
|
Special thanks for mixin suggestions to:
|
||||||
|
Kris Van Herzeele,
|
||||||
|
Benoit Adam,
|
||||||
|
Portenart Emile-Victor,
|
||||||
|
Ryan Faerman
|
||||||
|
|
||||||
|
More info at: http://lesselements.com
|
||||||
|
-----------------------------------------------------*/
|
||||||
|
|
||||||
|
.gradient(@color: #F5F5F5, @start: #EEE, @stop: #FFF) {
|
||||||
|
background: @color;
|
||||||
|
background: -webkit-gradient(linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0, @start),
|
||||||
|
color-stop(1, @stop));
|
||||||
|
background: -ms-linear-gradient(bottom,
|
||||||
|
@start,
|
||||||
|
@stop);
|
||||||
|
background: -moz-linear-gradient(center bottom,
|
||||||
|
@start 0%,
|
||||||
|
@stop 100%);
|
||||||
|
}
|
||||||
|
.bw-gradient(@color: #F5F5F5, @start: 0, @stop: 255) {
|
||||||
|
background: @color;
|
||||||
|
background: -webkit-gradient(linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0, rgb(@start,@start,@start)),
|
||||||
|
color-stop(1, rgb(@stop,@stop,@stop)));
|
||||||
|
background: -ms-linear-gradient(bottom,
|
||||||
|
rgb(@start,@start,@start) 0%,
|
||||||
|
rgb(@start,@start,@start) 100%);
|
||||||
|
background: -moz-linear-gradient(center bottom,
|
||||||
|
rgb(@start,@start,@start) 0%,
|
||||||
|
rgb(@stop,@stop,@stop) 100%);
|
||||||
|
}
|
||||||
|
.bordered(@top-color: #EEE, @right-color: #EEE, @bottom-color: #EEE, @left-color: #EEE) {
|
||||||
|
border-top: solid 1px @top-color;
|
||||||
|
border-left: solid 1px @left-color;
|
||||||
|
border-right: solid 1px @right-color;
|
||||||
|
border-bottom: solid 1px @bottom-color;
|
||||||
|
}
|
||||||
|
.drop-shadow(@x-axis: 0, @y-axis: 1px, @blur: 2px, @alpha: 0.1) {
|
||||||
|
-webkit-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
|
||||||
|
-moz-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
|
||||||
|
box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
|
||||||
|
}
|
||||||
|
.rounded(@radius: 2px) {
|
||||||
|
-webkit-border-radius: @radius;
|
||||||
|
-moz-border-radius: @radius;
|
||||||
|
border-radius: @radius;
|
||||||
|
-moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
|
||||||
|
}
|
||||||
|
.border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) {
|
||||||
|
-webkit-border-top-right-radius: @topright;
|
||||||
|
-webkit-border-bottom-right-radius: @bottomright;
|
||||||
|
-webkit-border-bottom-left-radius: @bottomleft;
|
||||||
|
-webkit-border-top-left-radius: @topleft;
|
||||||
|
-moz-border-radius-topright: @topright;
|
||||||
|
-moz-border-radius-bottomright: @bottomright;
|
||||||
|
-moz-border-radius-bottomleft: @bottomleft;
|
||||||
|
-moz-border-radius-topleft: @topleft;
|
||||||
|
border-top-right-radius: @topright;
|
||||||
|
border-bottom-right-radius: @bottomright;
|
||||||
|
border-bottom-left-radius: @bottomleft;
|
||||||
|
border-top-left-radius: @topleft;
|
||||||
|
-moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
|
||||||
|
}
|
||||||
|
.opacity(@opacity: 0.5) {
|
||||||
|
-moz-opacity: @opacity;
|
||||||
|
-khtml-opacity: @opacity;
|
||||||
|
-webkit-opacity: @opacity;
|
||||||
|
opacity: @opacity;
|
||||||
|
}
|
||||||
|
.transition-duration(@duration: 0.2s) {
|
||||||
|
-moz-transition-duration: @duration;
|
||||||
|
-webkit-transition-duration: @duration;
|
||||||
|
transition-duration: @duration;
|
||||||
|
}
|
||||||
|
.rotation(@deg:5deg){
|
||||||
|
-webkit-transform: rotate(@deg);
|
||||||
|
-moz-transform: rotate(@deg);
|
||||||
|
transform: rotate(@deg);
|
||||||
|
}
|
||||||
|
.scale(@ratio:1.5){
|
||||||
|
-webkit-transform:scale(@ratio);
|
||||||
|
-moz-transform:scale(@ratio);
|
||||||
|
transform:scale(@ratio);
|
||||||
|
}
|
||||||
|
.transition(@duration:0.2s, @ease:ease-out) {
|
||||||
|
-webkit-transition: all @duration @ease;
|
||||||
|
-moz-transition: all @duration @ease;
|
||||||
|
transition: all @duration @ease;
|
||||||
|
}
|
||||||
|
.inner-shadow(@horizontal:0, @vertical:1px, @blur:2px, @alpha: 0.4) {
|
||||||
|
-webkit-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
|
||||||
|
-moz-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
|
||||||
|
box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
|
||||||
|
}
|
||||||
|
.box-shadow(@arguments) {
|
||||||
|
-webkit-box-shadow: @arguments;
|
||||||
|
-moz-box-shadow: @arguments;
|
||||||
|
box-shadow: @arguments;
|
||||||
|
}
|
||||||
|
.columns(@colwidth: 250px, @colcount: 0, @colgap: 50px, @columnRuleColor: #EEE, @columnRuleStyle: solid, @columnRuleWidth: 1px) {
|
||||||
|
-moz-column-width: @colwidth;
|
||||||
|
-moz-column-count: @colcount;
|
||||||
|
-moz-column-gap: @colgap;
|
||||||
|
-moz-column-rule-color: @columnRuleColor;
|
||||||
|
-moz-column-rule-style: @columnRuleStyle;
|
||||||
|
-moz-column-rule-width: @columnRuleWidth;
|
||||||
|
-webkit-column-width: @colwidth;
|
||||||
|
-webkit-column-count: @colcount;
|
||||||
|
-webkit-column-gap: @colgap;
|
||||||
|
-webkit-column-rule-color: @columnRuleColor;
|
||||||
|
-webkit-column-rule-style: @columnRuleStyle;
|
||||||
|
-webkit-column-rule-width: @columnRuleWidth;
|
||||||
|
column-width: @colwidth;
|
||||||
|
column-count: @colcount;
|
||||||
|
column-gap: @colgap;
|
||||||
|
column-rule-color: @columnRuleColor;
|
||||||
|
column-rule-style: @columnRuleStyle;
|
||||||
|
column-rule-width: @columnRuleWidth;
|
||||||
|
}
|
||||||
|
.translate(@x:0, @y:0) {
|
||||||
|
-moz-transform: translate(@x, @y);
|
||||||
|
-webkit-transform: translate(@x, @y);
|
||||||
|
-o-transform: translate(@x, @y);
|
||||||
|
-ms-transform: translate(@x, @y);
|
||||||
|
transform: translate(@x, @y);
|
||||||
|
}
|
||||||
128
index.html
Normal file
128
index.html
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<title>Calcalc proto</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
|
||||||
|
<!--<link href='http://fonts.googleapis.com/css?family=Cabin' rel='stylesheet' type='text/css'>-->
|
||||||
|
<link href="//netdna.bootstrapcdn.com/font-awesome/2.0/css/font-awesome.css" rel="stylesheet"/>
|
||||||
|
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/css/bootstrap.no-icons.min.css" rel="stylesheet">
|
||||||
|
<link href="main.css" rel="stylesheet"/>
|
||||||
|
<style>
|
||||||
|
* { font-family: Arial; }
|
||||||
|
.calculator { width: 60%; margin: 0 auto; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
|
||||||
|
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container calculator">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span12">
|
||||||
|
<h1>Polkupyöräily kalorilaskuri</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- copy+paste -->
|
||||||
|
|
||||||
|
<script src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"></script>
|
||||||
|
<script src="main.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<legend>
|
||||||
|
Sukupuoli
|
||||||
|
<span class="help"><i class="icon-question-sign" rel="tooltip" title="Ei vaikuta tulokseen. Käytetään tulosten tilastoinnissa."></i></span>
|
||||||
|
</legend>
|
||||||
|
<div class="btn-group row-fluid" data-toggle="buttons-radio" id="gender">
|
||||||
|
<button type="button" class="btn span6 btn-large" data-gender="1">M</button>
|
||||||
|
<button type="button" class="btn span6 btn-large" data-gender="2">N</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="span3 select-speed">
|
||||||
|
<legend>Nopeus</legend>
|
||||||
|
<div class="dropdown">
|
||||||
|
<a href="#" class="btn speed-btn dropdown-toggle" data-toggle="dropdown" id="selectedSpeed">
|
||||||
|
<span class="activity"> </span>
|
||||||
|
<span class="description"> </span>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu" id="speed">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="span6">
|
||||||
|
<legend>Paino</legend>
|
||||||
|
<div>
|
||||||
|
<div class="input-append large">
|
||||||
|
<input type="text" id="weight" size="1"/>
|
||||||
|
<span class="add-on">kg</span>
|
||||||
|
</div>
|
||||||
|
<div class="error-msg message hide">Kirjoita kenttään numero.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span6">
|
||||||
|
<legend>
|
||||||
|
Reitti
|
||||||
|
<span class="help"><i class="icon-question-sign" rel="tooltip" title="Käyttää Google Mapsia reittien laskemiseen. Reitit kulkevat pyöräilyyn sopivia teitä."></i></span>
|
||||||
|
</legend>
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span9">
|
||||||
|
<div class="input-prepend">
|
||||||
|
<span class="add-on">1.</span>
|
||||||
|
<input type="text" id="place1" data-var="place1" placeholder="Lähtöosoite"/>
|
||||||
|
</div>
|
||||||
|
<div class="input-prepend">
|
||||||
|
<span class="add-on">2.</span>
|
||||||
|
<input type="text" id="place2" data-var="place2" placeholder="Kohdeosoite"/>
|
||||||
|
</div>
|
||||||
|
<div class="zero-results-msg message hide">Ei reittiä osoitteiden välillä.</div>
|
||||||
|
<div class="not-found-msg message hide">Toista osoitteista ei löytynyt.</div>
|
||||||
|
<a href="#" target="new" class="google-maps-msg hide" tabindex="-1">Katso reitti Google Mapsissa <i class="icon-external-link"></i></a>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn find-route span3 btn-large" id="compute"><i class="icon-arrow-right"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="span6">
|
||||||
|
<legend>Matka</legend>
|
||||||
|
<div>
|
||||||
|
<div class="input-append large">
|
||||||
|
<input type="text" id="distance" size="1"/>
|
||||||
|
<span class="add-on">km</span>
|
||||||
|
</div>
|
||||||
|
<div class="error-msg message hide">Kirjoita kenttään numero.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span12">
|
||||||
|
<p class="result">Kulutit matkallasi <strong><span id="calories">0</span> kilokaloria</strong><span id="control"></span>.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<button type="button" class="btn facebook-btn" id="facebook-share"><i class="icon-facebook-sign"></i> Lähetä Facebookiin</button>
|
||||||
|
tai vaihtoehtoisesti voit kopioida sivun osoitteen ja jakaa sen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><strong>Kalorinkulutuksen laskeminen</strong> perustuu MET-arvoihin (<a href="http://fi.wikipedia.org/wiki/Metabolinen_ekvivalentti" target="new">Metabolinen ekvivalentti</a>). Yksi <italic>MET</italic> on 1<italic>kcal/kg/tunti</italic>, joten kertomalla MET arvo painolla ja ajalla saadaan kalorien kulutus.</p>
|
||||||
|
<ul class="sources">
|
||||||
|
<li>Lähde 1: <a href="https://sites.google.com/site/compendiumofphysicalactivities/" target="new">Compendium of Physical Activities</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p><strong>Vastaukset tilastoidaan</strong>, jotta voidaan seurata sukupuolijakaumaa, keskimääräistä matkaa ja kalorinkulutusta. Tietoja ei yksilöidä.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- / copy+paste -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
422
main.js
Normal file
422
main.js
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
$.fn.show_message = function (message) {
|
||||||
|
return this.each(function () {
|
||||||
|
$(this).parent('div').parent().children('.' + message + '-msg').removeClass('hide');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.hide_message = function (message) {
|
||||||
|
return this.each(function () {
|
||||||
|
$(this).parent('div').parent().children('.' + message + '-msg').addClass('hide');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.valueChanged = function (callback) {
|
||||||
|
return this.each(function () {
|
||||||
|
var el = $(this),
|
||||||
|
prev = null,
|
||||||
|
focus = function () {
|
||||||
|
prev = el.attr('value');
|
||||||
|
},
|
||||||
|
change = function () {
|
||||||
|
var val = el.attr('value');
|
||||||
|
if (val !== prev) {
|
||||||
|
prev = val;
|
||||||
|
callback.apply(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
el.bind('focus', focus).bind('blur', change).bind('keyup', change);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var toFloat = function (str) {
|
||||||
|
return Number(str.replace(/,/g, '.'));
|
||||||
|
};
|
||||||
|
var displayFloat = function (num) {
|
||||||
|
return num.toString().replace(/\./g, ',');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Okay, this should have been done using eq. JQuery-BBQ
|
||||||
|
// But changing it now would require some hacks as we don't want to break
|
||||||
|
// existing urls.
|
||||||
|
// (places=place+1;place+2 vs. places[]=place+1&places[]=place+2)
|
||||||
|
var HashSave = {
|
||||||
|
settings: {
|
||||||
|
filter: null,
|
||||||
|
types: {},
|
||||||
|
display: {}
|
||||||
|
},
|
||||||
|
init: function (settings) {
|
||||||
|
$.extend(true, HashSave.settings, settings);
|
||||||
|
},
|
||||||
|
save: function (dict) {
|
||||||
|
var hash = [],
|
||||||
|
encode = function (value) {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return value.replace(/\ /g, '+');
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var key in dict) {
|
||||||
|
if ((1 + $.inArray(key, HashSave.settings.ignored)) ||
|
||||||
|
HashSave.settings.filter === null ||
|
||||||
|
HashSave.settings.filter(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var val;
|
||||||
|
if ($.isArray(dict[key])) {
|
||||||
|
var r = [];
|
||||||
|
for (var i in dict[key]) {
|
||||||
|
r.push(encode(dict[key][i]));
|
||||||
|
}
|
||||||
|
val = r.join(';');
|
||||||
|
} else {
|
||||||
|
val = encode(dict[key]);
|
||||||
|
}
|
||||||
|
hash.push(key + '=' + val);
|
||||||
|
}
|
||||||
|
|
||||||
|
location.hash = '!' + hash.join('&');
|
||||||
|
},
|
||||||
|
load: function (dict) {
|
||||||
|
var hash = location.hash,
|
||||||
|
display = HashSave.settings.display,
|
||||||
|
decode = function (type, value) {
|
||||||
|
if (type === 'string') {
|
||||||
|
return value.replace(/\+/g, ' ');
|
||||||
|
} else if (type === 'Number') {
|
||||||
|
return toFloat(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
types = HashSave.settings.types;
|
||||||
|
|
||||||
|
if (!hash || hash[1] !== '!') return false;
|
||||||
|
|
||||||
|
hash = hash.slice(2).split('&');
|
||||||
|
for (var i in hash) {
|
||||||
|
var a = hash[i].split('='),
|
||||||
|
key = a[0], value = a[1];
|
||||||
|
|
||||||
|
if ($.isArray(types[key])) {
|
||||||
|
value = value.split(';');
|
||||||
|
for (var b in value) {
|
||||||
|
value[b] = decode(types[key][b], value[b]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = decode(types[key], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(value);
|
||||||
|
dict[key] = value;
|
||||||
|
if (key in display) {
|
||||||
|
display[key]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var CalCalc = {
|
||||||
|
mets: {
|
||||||
|
bike: {
|
||||||
|
text: 'Pyöräillen',
|
||||||
|
text2: 'pyöräilen',
|
||||||
|
travelMode: google.maps.TravelMode.BICYCLING,
|
||||||
|
googleLink: '&mra=ltm&lci=bike&z=14&oq=mann&t=h&dirflg=b',
|
||||||
|
data: {
|
||||||
|
18: {activity: 'Hidas', met: 6.8, description: '16-19 km/h'},
|
||||||
|
21: {activity: 'Normaali', met: 8.0, description: '19-23 km/h'},
|
||||||
|
24: {activity: 'Nopea', met: 10.0, description: '23-26 km/h'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
foot: {
|
||||||
|
text: 'Jalan',
|
||||||
|
text2: 'kuljen jalan',
|
||||||
|
travelMode: google.maps.TravelMode.WALKING,
|
||||||
|
googleLink: '&t=h&dirflg=w&mra=ltm&z=14',
|
||||||
|
data: {
|
||||||
|
5: {activity: 'Kävely', met: 3.0, description: '70 m/min'},
|
||||||
|
12: {activity: 'Juoksu', met: 11.8, description: '200 m/min'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
genders: {
|
||||||
|
0: 'Puuttuu',
|
||||||
|
1: 'Mies',
|
||||||
|
2: 'Nainen'
|
||||||
|
},
|
||||||
|
calories: [
|
||||||
|
{name: 'omenaa', kcal: 46},
|
||||||
|
{name: 'maitolasillista', kcal: 100},
|
||||||
|
{name: 'jäätelötuuttia', kcal: 200},
|
||||||
|
{name: 'korvapuustia', kcal: 380},
|
||||||
|
{name: 'hampurilaista', kcal: 500},
|
||||||
|
{name: 'pakastepizzaa', kcal: 900},
|
||||||
|
{name: 'sipsipussia', kcal: 1800}
|
||||||
|
],
|
||||||
|
vars: {
|
||||||
|
places: [null, null],
|
||||||
|
calories: 0,
|
||||||
|
weight: 70, // default weight
|
||||||
|
distance: 0,
|
||||||
|
method: ['bike', 21],
|
||||||
|
gender: 0
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
reporting: false
|
||||||
|
},
|
||||||
|
display: {
|
||||||
|
places: function () {
|
||||||
|
$("#place1").attr('value', CalCalc.vars.places[0]);
|
||||||
|
$("#place2").attr('value', CalCalc.vars.places[1]);
|
||||||
|
},
|
||||||
|
calories: function () {
|
||||||
|
$('#calories').html(CalCalc.vars.calories);
|
||||||
|
},
|
||||||
|
distance: function () {
|
||||||
|
$('#distance').attr('value', displayFloat(CalCalc.vars.distance));
|
||||||
|
},
|
||||||
|
weight: function () {
|
||||||
|
$('#weight').attr('value', displayFloat(CalCalc.vars.weight));
|
||||||
|
},
|
||||||
|
method: function () {
|
||||||
|
var el = $('#selectedSpeed');
|
||||||
|
el.find('.activity').html(CalCalc.mets[CalCalc.vars.method[0]].text + ', ' + CalCalc.mets[CalCalc.vars.method[0]].data[CalCalc.vars.method[1]].activity);
|
||||||
|
el.find('.description').html(CalCalc.mets[CalCalc.vars.method[0]].data[CalCalc.vars.method[1]].description);
|
||||||
|
|
||||||
|
$('#speed li').removeClass('active');
|
||||||
|
$('#speed a[data-method=' + CalCalc.vars.method[0] + '][data-speed=' + CalCalc.vars.method[1] + ']').parent().addClass('active');
|
||||||
|
},
|
||||||
|
url: function (value) {
|
||||||
|
return value.replace(/\ /g, '+');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReady: function () {
|
||||||
|
// Google Places Autocomplete
|
||||||
|
var autocompleteOptions = {componentRestrictions: {country: 'fi'}, types: ['geocode']},
|
||||||
|
place1complete = new google.maps.places.Autocomplete($('#place1').get(0), autocompleteOptions),
|
||||||
|
place2complete = new google.maps.places.Autocomplete($('#place2').get(0), autocompleteOptions);
|
||||||
|
|
||||||
|
// Activate inputs with prefilled data
|
||||||
|
$('#weight').attr('placeholder', CalCalc.vars.weight);
|
||||||
|
$('#distance').attr('placeholder', CalCalc.vars.distance);
|
||||||
|
var speedList = '';
|
||||||
|
for (var method in CalCalc.mets) {
|
||||||
|
speedList += '<li class="nav-header">' + CalCalc.mets[method].text + '</li>';
|
||||||
|
for (var speed in CalCalc.mets[method].data) {
|
||||||
|
speedList += '<li><a href="#" data-method="' + method + '" data-speed="' + speed + '">' + CalCalc.mets[method].data[speed].activity + '</a></li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$('#speed').html(speedList);
|
||||||
|
CalCalc.display.method();
|
||||||
|
|
||||||
|
// Update variables if input value changes
|
||||||
|
$('#place1, #place2').bind('keyup', function (event) {
|
||||||
|
if (event.keyCode === 13) {
|
||||||
|
if (CalCalc.addressChange()) {
|
||||||
|
$(this).blur();
|
||||||
|
$(this).addClass('focus');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#compute').click(CalCalc.addressChange);
|
||||||
|
$('#weight').valueChanged(CalCalc.weightChange);
|
||||||
|
$('#distance').valueChanged(CalCalc.distanceChange);
|
||||||
|
$('#speed').find('a').click(CalCalc.speedChange);
|
||||||
|
$('#gender').find('button').click(CalCalc.genderChange);
|
||||||
|
|
||||||
|
HashSave.init({
|
||||||
|
ignored: ['gender', 'calories'],
|
||||||
|
filter: function (key) {
|
||||||
|
// Skip distance if both places are set
|
||||||
|
// Skip places if either of places is null
|
||||||
|
return ((CalCalc.vars.places[0] !== null && CalCalc.vars.places[1] !== null) && key === 'distance') ||
|
||||||
|
((CalCalc.vars.places[0] === null || CalCalc.vars.places[1] === null) && key === 'places');
|
||||||
|
},
|
||||||
|
types: {
|
||||||
|
calories: 'Number',
|
||||||
|
weight: 'Number',
|
||||||
|
distance: 'Number',
|
||||||
|
method: ['string', 'Number'],
|
||||||
|
places: ['string', 'string']
|
||||||
|
},
|
||||||
|
display: CalCalc.display
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Read hashbang
|
||||||
|
if (HashSave.load(CalCalc.vars)) {
|
||||||
|
if (CalCalc.vars.places[0] !== null && CalCalc.vars.places[1] !== null) {
|
||||||
|
CalCalc.updateRoute();
|
||||||
|
} else {
|
||||||
|
CalCalc.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Android - Dropdown fix - Bootstrap 2.1.1
|
||||||
|
// https://github.com/twitter/bootstrap/issues/4550
|
||||||
|
$('body').on('touchstart.dropdown', '.dropdown-menu', function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
$('a.dropdown-toggle').on('touchstart', function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
update: function () {
|
||||||
|
var reportTimeout = null;
|
||||||
|
return function () {
|
||||||
|
if (CalCalc.vars.distance !== null &&
|
||||||
|
CalCalc.vars.method[0] !== null && CalCalc.vars.method[1] !== null &&
|
||||||
|
CalCalc.vars.weight !== null) {
|
||||||
|
|
||||||
|
var duration = CalCalc.vars.distance / CalCalc.vars.method[1], // -> hours
|
||||||
|
met = CalCalc.mets[CalCalc.vars.method[0]].data[CalCalc.vars.method[1]].met;
|
||||||
|
|
||||||
|
CalCalc.vars.calories = (met * CalCalc.vars.weight * duration).toFixed(0);
|
||||||
|
|
||||||
|
CalCalc.display.calories();
|
||||||
|
|
||||||
|
var multi,
|
||||||
|
food,
|
||||||
|
fuu = 0;
|
||||||
|
|
||||||
|
for (var i in CalCalc.calories) {
|
||||||
|
if (CalCalc.vars.calories > CalCalc.calories[i].kcal) {
|
||||||
|
fuu = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
food = CalCalc.calories[fuu].name;
|
||||||
|
multi = (CalCalc.vars.calories / CalCalc.calories[fuu].kcal).toFixed(2);
|
||||||
|
if (multi > 0) {
|
||||||
|
$('#control').html(', tämä vastaa ' + displayFloat(multi) + ' ' + food);
|
||||||
|
} else {
|
||||||
|
$('#control').html('');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 5 sec after latest update, report values
|
||||||
|
clearTimeout(reportTimeout);
|
||||||
|
reportTimeout = setTimeout(CalCalc.report, 5000);
|
||||||
|
|
||||||
|
HashSave.save(CalCalc.vars);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}(),
|
||||||
|
distanceChange: function () {
|
||||||
|
var el = $('#distance').removeClass('from-route'),
|
||||||
|
distance = toFloat(el.attr('value'));
|
||||||
|
|
||||||
|
if (!isNaN(distance)) {
|
||||||
|
CalCalc.vars.places[0] = null;
|
||||||
|
CalCalc.vars.places[1] = null;
|
||||||
|
$('#place1').attr('value', '').hide_message('error');
|
||||||
|
$('#place2').attr('value', '').hide_message('error').hide_message('zero-results').hide_message('google-maps');
|
||||||
|
|
||||||
|
CalCalc.vars.distance = distance || 0;
|
||||||
|
el.hide_message('error');
|
||||||
|
CalCalc.update();
|
||||||
|
} else {
|
||||||
|
CalCalc.vars.distance = null;
|
||||||
|
el.show_message('error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
weightChange: function () {
|
||||||
|
var el = $(this),
|
||||||
|
weight = toFloat(el.attr('value'));
|
||||||
|
|
||||||
|
if (!isNaN(weight)) {
|
||||||
|
CalCalc.vars.weight = weight || toFloat(el.attr('placeholder'));
|
||||||
|
el.hide_message('error');
|
||||||
|
CalCalc.update();
|
||||||
|
} else {
|
||||||
|
// Parse error - weight not number
|
||||||
|
CalCalc.vars.weight = null;
|
||||||
|
el.show_message('error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
speedChange: function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var data = $(this).data('speed');
|
||||||
|
var data2 = $(this).data('method');
|
||||||
|
if (data2 in CalCalc.mets && data in CalCalc.mets[data2].data) {
|
||||||
|
CalCalc.vars.method = [data2, data];
|
||||||
|
CalCalc.display.method();
|
||||||
|
if (!CalCalc.updateRoute()) {
|
||||||
|
CalCalc.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
genderChange: function () {
|
||||||
|
var data = $(this).data('gender');
|
||||||
|
if (data in CalCalc.genders) {
|
||||||
|
CalCalc.vars.gender = data;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addressChange: function () {
|
||||||
|
CalCalc.vars.places[0] = $("#place1").attr('value');
|
||||||
|
CalCalc.vars.places[1] = $("#place2").attr('value');
|
||||||
|
CalCalc.updateRoute();
|
||||||
|
|
||||||
|
return CalCalc.vars.places[0] !== '' && CalCalc.vars.places[1] !== '';
|
||||||
|
},
|
||||||
|
updateRoute: function () {
|
||||||
|
var service = new google.maps.DirectionsService();
|
||||||
|
return function () {
|
||||||
|
$("#place2").hide_message('zero-results').hide_message('not-found');
|
||||||
|
if (!CalCalc.vars.places[0] || !CalCalc.vars.places[1]) return false;
|
||||||
|
|
||||||
|
var request = {
|
||||||
|
destination: CalCalc.vars.places[1],
|
||||||
|
origin: CalCalc.vars.places[0],
|
||||||
|
travelMode: CalCalc.mets[CalCalc.vars.method[0]].travelMode,
|
||||||
|
region: 'fi'
|
||||||
|
};
|
||||||
|
|
||||||
|
service.route(request, function (result, status) {
|
||||||
|
// console.log(status);
|
||||||
|
if (status === google.maps.DirectionsStatus.ZERO_RESULTS) {
|
||||||
|
$("#place2").show_message('zero-results').hide_message('google-maps');
|
||||||
|
} else if (status === google.maps.DirectionsStatus.NOT_FOUND) {
|
||||||
|
$("#place2").show_message('not-found').hide_message('google-maps');
|
||||||
|
} else if (status === google.maps.DirectionsStatus.OK && result.routes.length !== 0 || result.routes[0].legs.length !== 0) {
|
||||||
|
$("#place2").show_message('google-maps');
|
||||||
|
$(".google-maps-msg").attr('href', 'https://maps.google.com/maps?saddr=' + CalCalc.display.url(CalCalc.vars.places[0]) + '&daddr=' + CalCalc.display.url(CalCalc.vars.places[1]) + CalCalc.mets[CalCalc.vars.method[0]].googleLink);
|
||||||
|
|
||||||
|
// console.log(result.routes[0].legs[0]);
|
||||||
|
CalCalc.vars.places[0] = result.routes[0].legs[0].start_address;
|
||||||
|
CalCalc.vars.places[1] = result.routes[0].legs[0].end_address;
|
||||||
|
CalCalc.display.places();
|
||||||
|
|
||||||
|
CalCalc.vars.distance = result.routes[0].legs[0].distance.value / 1000; // m -> km
|
||||||
|
$('#distance').addClass('from-route').hide_message('error');//.attr('value', displayFloat(CalCalc.vars.distance.toFixed(2)));
|
||||||
|
CalCalc.display.distance();
|
||||||
|
CalCalc.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that input value has been changed, focus can be returned to it.
|
||||||
|
$("#place1, #place2").filter(".focus").focus().removeClass('focus');
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}(),
|
||||||
|
report: function () {
|
||||||
|
if (CalCalc.vars.distance > 100 || !CalCalc.settings.reporting) return;
|
||||||
|
|
||||||
|
_gaq.push(['_trackEvent', 'CalCalc', 'Weight', 'Weight', Number(CalCalc.vars.weight.toFixed(0)), true]);
|
||||||
|
_gaq.push(['_trackEvent', 'CalCalc', 'Distance', 'Distance', Number(CalCalc.vars.distance.toFixed(0)), true]);
|
||||||
|
_gaq.push(['_trackEvent', 'CalCalc', 'Kilocalories', 'Kilocalories', Number(CalCalc.vars.calories), true]);
|
||||||
|
_gaq.push(['_trackEvent', 'CalCalc', 'Gender', CalCalc.genders[CalCalc.vars.gender], undefined, true]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('[rel=tooltip]').tooltip({
|
||||||
|
container: 'body'
|
||||||
|
});
|
||||||
|
CalCalc.onReady();
|
||||||
|
});
|
||||||
144
main.less
Normal file
144
main.less
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
@import "dynamicgif.less";
|
||||||
|
@import "elements.less";
|
||||||
|
|
||||||
|
.gradient (@origin: left, @start: #ffffff, @stop: #000000) {
|
||||||
|
background-color: @start;
|
||||||
|
background-image: -webkit-linear-gradient(@origin, @start, @stop);
|
||||||
|
background-image: -moz-linear-gradient(@origin, @start, @stop);
|
||||||
|
background-image: -o-linear-gradient(@origin, @start, @stop);
|
||||||
|
background-image: -ms-linear-gradient(@origin, @start, @stop);
|
||||||
|
background-image: linear-gradient(@origin, @start, @stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@input_padding: 2%;
|
||||||
|
@input_width: 85.85%;
|
||||||
|
@addon_width: 9.85%;
|
||||||
|
|
||||||
|
@large_input_width: 60.85%;
|
||||||
|
@large_addon_width: 34.85%;
|
||||||
|
|
||||||
|
@result_input_width: 35%;
|
||||||
|
@result_addon_width: 20%;
|
||||||
|
|
||||||
|
.calculator {
|
||||||
|
input {
|
||||||
|
width: @input_width;
|
||||||
|
padding-left: @input_padding;
|
||||||
|
padding-right: @input_padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-on {
|
||||||
|
width: @addon_width;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-append.large {
|
||||||
|
input {
|
||||||
|
font-size: 48px;
|
||||||
|
line-height: 55px;
|
||||||
|
height: 55px;
|
||||||
|
text-align: right;
|
||||||
|
width: @large_input_width;
|
||||||
|
}
|
||||||
|
.add-on {
|
||||||
|
height: 55px;
|
||||||
|
font-size: 48px;
|
||||||
|
line-height: 55px;
|
||||||
|
width: @large_addon_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 48px;
|
||||||
|
line-height: 64px;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.sources {
|
||||||
|
margin-top: -0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
span {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span.help {
|
||||||
|
color: #3D5DA8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.from-route {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-large {
|
||||||
|
padding: 4px 19px;
|
||||||
|
line-height: 55px;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group {
|
||||||
|
& > .btn + .btn {
|
||||||
|
margin-left: 0;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
[class*="span"] { float: left; }
|
||||||
|
.span6 { width: 49.9998%; }
|
||||||
|
.span4 { width: 33.332%; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.speed-btn {
|
||||||
|
height: 55px;
|
||||||
|
line-height: 27px;
|
||||||
|
text-align: left;
|
||||||
|
display: block;
|
||||||
|
span.activity {
|
||||||
|
display: block;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
span.description {
|
||||||
|
display: block;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
.caret {
|
||||||
|
margin-top: -27px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
li.active a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
background: #DD4F4F;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 1px 12px;
|
||||||
|
position: absolute;
|
||||||
|
.rounded(3px);
|
||||||
|
&::after {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
left: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid #DD4F4F;
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
&.hide { display: none; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user