mirror of
https://github.com/Ekokumppanit/Lentolaskuri.git
synced 2026-02-09 00:44:57 +00:00
Initial commit
This commit is contained in:
40
app/scripts/app.js
Normal file
40
app/scripts/app.js
Normal file
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'collections/route',
|
||||
'collections/results',
|
||||
'views/route',
|
||||
'views/leginput',
|
||||
'views/roundtrip',
|
||||
'views/passengers',
|
||||
'views/map',
|
||||
'views/total',
|
||||
'views/operation'
|
||||
], function (Route, Results, RouteView, LegInput, RoundtripInput, PassengersInput, MapView, TotalView, OperationView) {
|
||||
|
||||
var App = function () {
|
||||
this.initialize = function () {
|
||||
this.route = new Route();
|
||||
|
||||
this.legInput = new LegInput({collection: this.route});
|
||||
this.roundtripInput = new RoundtripInput();
|
||||
this.passengersInput = new PassengersInput();
|
||||
|
||||
this.routeView = new RouteView({collection: this.route});
|
||||
this.mapView = new MapView({collection: this.route});
|
||||
|
||||
// Order is important. ResultsView requires that Route legs are
|
||||
// on dom as ResultView references from and to legs to calculate
|
||||
// position.
|
||||
this.results = new Results([], {route: this.route});
|
||||
this.totalView = new TotalView({model: this.results.total});
|
||||
|
||||
new OperationView();
|
||||
};
|
||||
|
||||
this.initialize();
|
||||
};
|
||||
|
||||
return App;
|
||||
|
||||
});
|
||||
53
app/scripts/collections/results.js
Normal file
53
app/scripts/collections/results.js
Normal file
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'models/result',
|
||||
'models/total'
|
||||
], function (Backbone, Result, Total) {
|
||||
var Results = Backbone.Collection.extend({
|
||||
model: Result,
|
||||
initialize: function (model, opts) {
|
||||
this.route = opts.route;
|
||||
|
||||
this.route.on('add', this.newLeg, this);
|
||||
this.route.on('remove', this.calculate, this);
|
||||
this.route.on('sort', this.calculate, this);
|
||||
|
||||
this.total = new Total();
|
||||
},
|
||||
newLeg: function (model, collection, options) {
|
||||
if (this.route.length < 2) {
|
||||
return;
|
||||
}
|
||||
var from;
|
||||
if (this.length > 0) {
|
||||
from = this.route.get(this.last().get('to'));
|
||||
} else {
|
||||
from = this.route.first();
|
||||
}
|
||||
|
||||
var result = new Result({from: from, to: model});
|
||||
this.push(result);
|
||||
this.total.add(result);
|
||||
},
|
||||
calculate: function (model, collection, options) {
|
||||
var models = [];
|
||||
this.total.reset();
|
||||
|
||||
var prev = null;
|
||||
this.route.forEach(function (leg) {
|
||||
if (prev) {
|
||||
var result = new Result({from: prev, to: leg});
|
||||
models.push(result);
|
||||
this.total.add(result);
|
||||
}
|
||||
prev = leg;
|
||||
}.bind(this));
|
||||
|
||||
this.reset(models);
|
||||
}
|
||||
});
|
||||
|
||||
return Results;
|
||||
});
|
||||
19
app/scripts/collections/route.js
Normal file
19
app/scripts/collections/route.js
Normal file
@@ -0,0 +1,19 @@
|
||||
define([
|
||||
'lodash',
|
||||
'backbone',
|
||||
'../models/leg'
|
||||
], function (_, Backbone, Leg) {
|
||||
|
||||
// var stages = [];
|
||||
// var data = {};
|
||||
var num = 1;
|
||||
|
||||
var Route = Backbone.Collection.extend({
|
||||
model: Leg,
|
||||
comparator: function (model) {
|
||||
return model.get('order');
|
||||
}
|
||||
});
|
||||
|
||||
return Route;
|
||||
});
|
||||
64
app/scripts/config.js
Normal file
64
app/scripts/config.js
Normal file
@@ -0,0 +1,64 @@
|
||||
'use strict';
|
||||
|
||||
define(function () {
|
||||
return {
|
||||
api: 'http://work.lentolaskuri.fi/api',
|
||||
R: 6371,
|
||||
radiativeForceFactor: function (dist) {
|
||||
return (dist >= 500) ? 2.0 : 1.0;
|
||||
},
|
||||
distanceRanges: [{
|
||||
name: '0',
|
||||
}, {
|
||||
name: '500',
|
||||
min: 500
|
||||
}, {
|
||||
name: '1400',
|
||||
min: 1400
|
||||
}, {
|
||||
name: '5500',
|
||||
min: 5500,
|
||||
}, {
|
||||
name: '9000',
|
||||
min: 9000
|
||||
}],
|
||||
parameters: [{
|
||||
name: 'Suomi',
|
||||
regex: /^EF/,
|
||||
// Parameters for different distances
|
||||
co2factor: [0.08, 0.07, 0.07, 0.07, 0.07],
|
||||
ltoCycle: [15, 15, 15, 15, 15],
|
||||
load: [0.6, 0.65, 0.65, 0.65, 0.65],
|
||||
freight: [0.05, 0.05, 0.05, 0.05, 0.05]
|
||||
}, {
|
||||
name: 'Pohjois-Eurooppa',
|
||||
regex: /^E/,
|
||||
co2factor: [0.07, 0.06, 0.06, 0.06, 0.06],
|
||||
ltoCycle: [22, 22, 22, 22, 22],
|
||||
load: [0.65, 0.7, 0.75, 0.75, 0.75],
|
||||
freight: [0.05, 0.1, 0.1, 0.1, 0.1]
|
||||
}, {
|
||||
name: 'Etelä-Eurooppa',
|
||||
regex: /^L/,
|
||||
co2factor: [0.07, 0.07, 0.07, 0.07, 0.07],
|
||||
ltoCycle: [22, 22, 22, 22, 22],
|
||||
load: [0.65, 0.7, 0.8, 0.8, 0.8],
|
||||
freight: [0.05, 0.1, 0.1, 0.1, 0.1],
|
||||
}, {
|
||||
name: 'Euroopasta/aan',
|
||||
co2factor: [0.07, 0.07, 0.08, 0.09, 0.09],
|
||||
ltoCycle: [21, 24, 22, 26, 26], // 3rd value?
|
||||
load: [0.7, 0.7, 0.8, 0.8, 0.8],
|
||||
freight: [0.05, 0.15, 0.15, 0.15, 0.15]
|
||||
}, {
|
||||
name: 'Euroopan ulkopuoliset',
|
||||
co2factor: [0.08, 0.07, 0.08, 0.08, 0.09], // 2th value?
|
||||
ltoCycle: [21, 22, 23, 26, 26],
|
||||
load: [0.7, 0.7, 0.8, 0.8, 0.8],
|
||||
freight: [0.05, 0.1, 0.15, 0.2, 0.2]
|
||||
}],
|
||||
indirectRouteMultiplier: 1.09,
|
||||
// http://co2-raportti.fi/?heading=EU:n-p%C3%A4%C3%A4st%C3%B6kaupan-arvo-laski-kolmanneksen-t%C3%A4n%C3%A4-vuonna&page=ilmastouutisia&news_id=3665
|
||||
priceCO2: 7.5, // euros per tonne of CO2
|
||||
};
|
||||
});
|
||||
75
app/scripts/libs/airports.js
Normal file
75
app/scripts/libs/airports.js
Normal file
@@ -0,0 +1,75 @@
|
||||
'use strict';
|
||||
define([
|
||||
'jquery',
|
||||
'lodash',
|
||||
'config'
|
||||
], function ($, _, config) {
|
||||
var airportById = function (element, callback) {
|
||||
$.get('http://localhost:8000/search.php?i=' + element.val(), null, function (data) {
|
||||
callback(data[0]);
|
||||
});
|
||||
};
|
||||
|
||||
var data = function (term, page) {
|
||||
return {
|
||||
s: term
|
||||
};
|
||||
};
|
||||
|
||||
var results = function (data, page) {
|
||||
return {results: data};
|
||||
};
|
||||
|
||||
var findArea = function (icao) {
|
||||
for (var i = 0; i < config.parameters.length; ++i) {
|
||||
var param = config.parameters[i];
|
||||
if (param.regex && icao.match(param.regex)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return config.parameters.length - 2;
|
||||
};
|
||||
|
||||
var selectArea = function (fromCode, toCode) {
|
||||
var outside = config.parameters.length - 2;
|
||||
if (fromCode === outside && toCode === outside) {
|
||||
return config.parameters.length - 1;
|
||||
}
|
||||
return Math.max(fromCode, toCode);
|
||||
};
|
||||
|
||||
var selectRange = function (dist) {
|
||||
for (var i = 0; i < config.distanceRanges.length; ++i) {
|
||||
if (config.distanceRanges[i].min && dist <= config.distanceRanges[i].min) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
// Should select "greater of two", finland to western europe -> west europe
|
||||
// west europe to south europe -> south europe
|
||||
var parameters = function (from, to, range) {
|
||||
var i = selectArea(findArea(from.icao), findArea(to.icao));
|
||||
var p = config.parameters[i];
|
||||
return {
|
||||
name: p.name,
|
||||
co2factor: p.co2factor[range],
|
||||
ltoCycle: p.ltoCycle[range],
|
||||
load: p.load[range],
|
||||
freight: p.freight[range]
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
ajax: {
|
||||
url: config.api + '/search.php',
|
||||
dataType: 'json',
|
||||
data: data,
|
||||
results: results
|
||||
},
|
||||
airportById: airportById,
|
||||
selectRange: selectRange,
|
||||
parameters: parameters
|
||||
};
|
||||
});
|
||||
9
app/scripts/libs/gmaps.js
Normal file
9
app/scripts/libs/gmaps.js
Normal file
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
// convert Google Maps into an AMD module
|
||||
define([
|
||||
'async!http://maps.google.com/maps/api/js?v=3&sensor=false'
|
||||
], function() {
|
||||
// return the gmaps namespace for brevity
|
||||
return window.google.maps;
|
||||
});
|
||||
10
app/scripts/libs/handlebar_helpers.js
Normal file
10
app/scripts/libs/handlebar_helpers.js
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'handlebars'
|
||||
], function (Handlebars) {
|
||||
Handlebars.registerHelper('displayFloat', function (num, precision) {
|
||||
precision = precision;
|
||||
return ''+(num.toFixed(precision)).replace('.', ',');
|
||||
});
|
||||
});
|
||||
120
app/scripts/libs/maps.js
Normal file
120
app/scripts/libs/maps.js
Normal file
@@ -0,0 +1,120 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'require',
|
||||
'jquery',
|
||||
'lodash',
|
||||
'backbone'
|
||||
], function (require, $, _, Backbone) {
|
||||
var gmaps;
|
||||
|
||||
function glatlng(latlng) {
|
||||
if (_.isArray(latlng)) {
|
||||
return new gmaps.LatLng(latlng[0], latlng[1]);
|
||||
} else if (latlng instanceof Backbone.Model) {
|
||||
return new gmaps.LatLng(latlng.get('lat'), latlng.get('long'));
|
||||
} else {
|
||||
return new gmaps.LatLng(latlng.lat, latlng.long);
|
||||
}
|
||||
}
|
||||
|
||||
var maps = {};
|
||||
|
||||
var deferred = $.Deferred();
|
||||
|
||||
var i = 0;
|
||||
var Map = function (el, opts) {
|
||||
var num = i;
|
||||
deferred.done(function () {
|
||||
maps[num] = new gmaps.Map(el, {
|
||||
center: glatlng([0, 0]),
|
||||
mapTypeId: gmaps.MapTypeId.ROADMAP,
|
||||
zoom: 0,
|
||||
streetViewControl: false,
|
||||
mapTypeControl: false,
|
||||
draggable: false,
|
||||
scrollwheel: false,
|
||||
zoomControl: false
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
id: i++
|
||||
}
|
||||
};
|
||||
|
||||
var Line = function (attr) {
|
||||
var data;
|
||||
deferred.done(function () {
|
||||
attr = attr || {};
|
||||
attr.map = maps[attr.map.id];
|
||||
|
||||
data = new gmaps.Polyline(attr);
|
||||
});
|
||||
|
||||
return {
|
||||
clear: function () {
|
||||
deferred.done(function () {
|
||||
data.setPath([]);
|
||||
});
|
||||
},
|
||||
add: function (latlng) {
|
||||
deferred.done(function () {
|
||||
data.getPath().push(glatlng(latlng));
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var Bounds = function (map) {
|
||||
var map;
|
||||
var i;
|
||||
var data;
|
||||
|
||||
var reset = function () {
|
||||
i = 0;
|
||||
map.setZoom(1);
|
||||
map.setCenter(glatlng([0, 0]));
|
||||
};
|
||||
|
||||
deferred.done(function () {
|
||||
data = new gmaps.LatLngBounds();
|
||||
map = maps[map.id];
|
||||
|
||||
reset();
|
||||
});
|
||||
|
||||
return {
|
||||
clear: function () {
|
||||
deferred.done(function () {
|
||||
reset();
|
||||
});
|
||||
},
|
||||
add: function (latlng) {
|
||||
deferred.done(function () {
|
||||
data.extend(glatlng(latlng));
|
||||
++i;
|
||||
});
|
||||
},
|
||||
use: function () {
|
||||
deferred.done(function () {
|
||||
if (i >= 2) {
|
||||
map.fitBounds(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
require(['libs/gmaps'], function (_gmaps) {
|
||||
gmaps = _gmaps;
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return {
|
||||
Map: Map,
|
||||
Line: Line,
|
||||
Bounds: Bounds
|
||||
};
|
||||
|
||||
});
|
||||
26
app/scripts/libs/math.js
Normal file
26
app/scripts/libs/math.js
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
define([
|
||||
'config',
|
||||
'libs/airports'
|
||||
], function (cfg, airports) {
|
||||
var toRad = function toRad(n) {
|
||||
return n * Math.PI / 180;
|
||||
};
|
||||
|
||||
var haversine = function haversine(from, to) {
|
||||
var dLat = toRad(to.get('lat') - from.get('lat'));
|
||||
var dLon = toRad(to.get('long') - from.get('long'));
|
||||
var lat1 = toRad(from.get('lat'));
|
||||
var lat2 = toRad(to.get('lat'));
|
||||
|
||||
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
|
||||
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
return cfg.R * c;
|
||||
};
|
||||
|
||||
return {
|
||||
toRad: toRad,
|
||||
haversine: haversine
|
||||
};
|
||||
});
|
||||
58
app/scripts/main.js
Normal file
58
app/scripts/main.js
Normal file
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
require.config({
|
||||
map: {
|
||||
'*': {
|
||||
'underscore': 'lodash'
|
||||
}
|
||||
},
|
||||
paths: {
|
||||
jquery: '../components/jquery/jquery',
|
||||
bootstrap: '../scripts/bootstrap',
|
||||
select2: '../components/select2/select2',
|
||||
lodash: '../components/lodash/lodash',
|
||||
handlebars: '../components/handlebars/handlebars.runtime',
|
||||
Template: '../scripts/templates',
|
||||
'jquery-ui-core': '../components/jquery-ui/ui/jquery.ui.core',
|
||||
'jquery-ui-mouse': '../components/jquery-ui/ui/jquery.ui.mouse',
|
||||
'jquery-ui-widget': '../components/jquery-ui/ui/jquery.ui.widget',
|
||||
'jquery-ui-sortable': '../components/jquery-ui/ui/jquery.ui.sortable',
|
||||
async: '../components/requirejs-plugins/src/async',
|
||||
backbone: '../components/backbone/backbone',
|
||||
'backbone-mediator': '../components/Backbone-Mediator/backbone-mediator'
|
||||
},
|
||||
shim: {
|
||||
backbone: {
|
||||
deps: ['lodash'],
|
||||
exports: 'Backbone'
|
||||
},
|
||||
bootstrap: {
|
||||
deps: ['jquery'],
|
||||
exports: 'jquery'
|
||||
},
|
||||
select2: {
|
||||
deps: ['jquery'],
|
||||
exports: 'jquery'
|
||||
},
|
||||
'jquery-ui-core': {
|
||||
deps: ['jquery'],
|
||||
exports: 'jquery'
|
||||
},
|
||||
'jquery-ui-sortable': {
|
||||
deps: ['jquery-ui-core', 'jquery-ui-widget', 'jquery-ui-mouse'],
|
||||
exports: 'jquery'
|
||||
},
|
||||
handlebars: {
|
||||
exports: 'Handlebars'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
require([
|
||||
'jquery',
|
||||
'app',
|
||||
'bootstrap',
|
||||
'libs/handlebar_helpers'
|
||||
], function ($, App) {
|
||||
var app = new App();
|
||||
});
|
||||
20
app/scripts/models/leg.js
Normal file
20
app/scripts/models/leg.js
Normal file
@@ -0,0 +1,20 @@
|
||||
define([
|
||||
'backbone'
|
||||
], function (Backbone) {
|
||||
|
||||
var num = 1;
|
||||
|
||||
var Leg = Backbone.Model.extend({
|
||||
initialize: function () {
|
||||
this.set('airportId', this.get('id'));
|
||||
this.set('id', num);
|
||||
++num;
|
||||
},
|
||||
destroy: function () {
|
||||
this.trigger('destroy', this, this.collection, {});
|
||||
}
|
||||
});
|
||||
|
||||
return Leg;
|
||||
|
||||
});
|
||||
45
app/scripts/models/result.js
Normal file
45
app/scripts/models/result.js
Normal file
@@ -0,0 +1,45 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'backbone-mediator',
|
||||
'libs/math',
|
||||
'libs/airports',
|
||||
'config'
|
||||
], function (Backbone, BackboneMediator, Math, airports, config) {
|
||||
var Result = Backbone.Model.extend({
|
||||
defaults: {
|
||||
dist: 0,
|
||||
total: 0,
|
||||
lto: 0,
|
||||
co2factor: 0,
|
||||
ltoCycle: 0,
|
||||
load: 0,
|
||||
freight: 0
|
||||
},
|
||||
initialize: function (attr, options) {
|
||||
if (this.get('from') && this.get('to')) {
|
||||
this.set('dist', Math.haversine(this.get('from'), this.get('to')));
|
||||
}
|
||||
|
||||
this.calculate.apply(this);
|
||||
},
|
||||
calculate: function () {
|
||||
var roundtrip = 0;
|
||||
if (this.get('from') && this.get('to')) {
|
||||
var roundtripFactor = (roundtrip) ? 2.0 : 1.0; // fuu
|
||||
|
||||
this.set('range', airports.selectRange(this.get('dist')));
|
||||
this.set(airports.parameters(this.get('from').toJSON(), this.get('to').toJSON(), this.get('range')));
|
||||
|
||||
var dist = this.get('dist') * config.indirectRouteMultiplier;
|
||||
|
||||
var m = config.radiativeForceFactor(dist) * (1 - this.get('freight')) * (1 / this.get('load'));
|
||||
this.set('lto', m * this.get('ltoCycle'));
|
||||
this.set('total', m * this.get('co2factor') * dist + this.get('lto'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Result;
|
||||
});
|
||||
54
app/scripts/models/total.js
Normal file
54
app/scripts/models/total.js
Normal file
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'backbone-mediator',
|
||||
'libs/math',
|
||||
'libs/airports',
|
||||
'config'
|
||||
], function (Backbone, BackboneMediator, Math, airports, config) {
|
||||
var Result = Backbone.Model.extend({
|
||||
defaults: {
|
||||
dist: 0,
|
||||
total: 0,
|
||||
rawTotal: 0,
|
||||
alone: true,
|
||||
roundtrip: false,
|
||||
passengers: 1,
|
||||
price: 0
|
||||
},
|
||||
initialize: function () {
|
||||
Backbone.Mediator.subscribe('roundtrip:change', this.set.bind(this, 'roundtrip'));
|
||||
Backbone.Mediator.subscribe('passengers:change', this.set.bind(this, 'passengers'));
|
||||
Backbone.Mediator.subscribe('passengers:change', function (num) {
|
||||
this.set('alone', num === 1);
|
||||
}.bind(this));
|
||||
|
||||
this.on('change:roundtrip change:passengers', this.calc, this);
|
||||
},
|
||||
reset: function () {
|
||||
this.set('dist', 0);
|
||||
this.set('total', 0);
|
||||
this.set('rawTotal', 0);
|
||||
this.set('price', 0);
|
||||
},
|
||||
calc: function () {
|
||||
var mult = this.get('roundtrip') ? 2 : 1;
|
||||
this.set('total', mult * this.get('passengers') * this.get('rawTotal'));
|
||||
this.set('price', this.get('total') / 1000 * config.priceCO2);
|
||||
},
|
||||
add: function (another) {
|
||||
var keys = {
|
||||
'dist': 'dist',
|
||||
'total': 'rawTotal'
|
||||
};
|
||||
for (var i in keys) {
|
||||
this.set(keys[i], this.get(keys[i]) + another.get(i));
|
||||
}
|
||||
|
||||
this.calc();
|
||||
}
|
||||
});
|
||||
|
||||
return Result;
|
||||
});
|
||||
22
app/scripts/views/dropdown.js
Normal file
22
app/scripts/views/dropdown.js
Normal file
@@ -0,0 +1,22 @@
|
||||
define([
|
||||
'backbone',
|
||||
'select2'
|
||||
], function (Backbone) {
|
||||
var Dropdown = Backbone.View.extend({
|
||||
events: {
|
||||
'change': 'change'
|
||||
},
|
||||
initialize: function (opts) {
|
||||
this.$el.select2(opts.select2);
|
||||
},
|
||||
open: function () {
|
||||
this.$el.select2('open');
|
||||
},
|
||||
change: function () {
|
||||
this.trigger('new-leg', this.$el.select2('data'));
|
||||
this.$el.select2('data', {});
|
||||
}
|
||||
});
|
||||
|
||||
return Dropdown;
|
||||
});
|
||||
29
app/scripts/views/leg.js
Normal file
29
app/scripts/views/leg.js
Normal file
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'Template'
|
||||
], function (Backbone, Template) {
|
||||
var LegView = Backbone.View.extend({
|
||||
tagName: 'div',
|
||||
className: 'leg',
|
||||
events: {
|
||||
'click a.delete': 'destroy'
|
||||
},
|
||||
initialize: function () {
|
||||
this.model.on('change', this.render, this);
|
||||
this.model.on('destroy', this.remove, this);
|
||||
},
|
||||
destroy: function () {
|
||||
this.model.destroy();
|
||||
},
|
||||
render: function () {
|
||||
this.$el.data('id', this.model.get('id'));
|
||||
this.$el.attr('id', 'leg-' + this.model.get('id')); // fuu
|
||||
this.$el.html(Template.leg(this.model.toJSON()));
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
return LegView;
|
||||
});
|
||||
39
app/scripts/views/leginput.js
Normal file
39
app/scripts/views/leginput.js
Normal file
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'models/leg',
|
||||
'views/dropdown',
|
||||
'libs/airports',
|
||||
'Template'
|
||||
], function (Backbone, Leg, Dropdown, airports, Template) {
|
||||
var LegInput = Backbone.View.extend({
|
||||
el: '.legInputWidget',
|
||||
events: {
|
||||
'click button': 'openDropdown'
|
||||
},
|
||||
initialize: function () {
|
||||
this.dropdown = new Dropdown({
|
||||
el: this.$el.find('input'),
|
||||
select2: {
|
||||
initSelection: airports.airportById,
|
||||
formatResult: Template.choice,
|
||||
formatSelection: Template.choice,
|
||||
minimumInputLength: 1,
|
||||
ajax: airports.ajax
|
||||
}
|
||||
});
|
||||
|
||||
this.dropdown.bind('new-leg', this.newLeg, this);
|
||||
},
|
||||
openDropdown: function () {
|
||||
this.dropdown.open();
|
||||
},
|
||||
newLeg: function (data) {
|
||||
this.collection.push(new Leg(data));
|
||||
}
|
||||
});
|
||||
|
||||
return LegInput;
|
||||
});
|
||||
|
||||
41
app/scripts/views/map.js
Normal file
41
app/scripts/views/map.js
Normal file
@@ -0,0 +1,41 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'libs/maps'
|
||||
], function (Backbone, Maps) {
|
||||
|
||||
var MapView = Backbone.View.extend({
|
||||
el: '#gmap',
|
||||
initialize: function () {
|
||||
this.collection.on('sort', this.render, this);
|
||||
this.collection.on('remove', this.render, this);
|
||||
this.collection.on('add', this.add, this);
|
||||
|
||||
this.map = new Maps.Map(this.el);
|
||||
|
||||
this.route = new Maps.Line({
|
||||
geodesic: true,
|
||||
map: this.map,
|
||||
strokeColor: '#000'
|
||||
});
|
||||
|
||||
this.bounds = new Maps.Bounds(this.map);
|
||||
},
|
||||
render: function () {
|
||||
this.route.clear();
|
||||
this.bounds.clear();
|
||||
this.collection.forEach(this.route.add);
|
||||
this.collection.forEach(this.bounds.add);
|
||||
this.bounds.use();
|
||||
},
|
||||
add: function (model, collection, options) {
|
||||
this.route.add(model);
|
||||
this.bounds.add(model);
|
||||
this.bounds.use();
|
||||
}
|
||||
});
|
||||
|
||||
return MapView;
|
||||
|
||||
});
|
||||
22
app/scripts/views/operation.js
Normal file
22
app/scripts/views/operation.js
Normal file
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'Template',
|
||||
'config',
|
||||
'bootstrap'
|
||||
], function (Backbone, Template, config) {
|
||||
var Operation = Backbone.View.extend({
|
||||
el: '#operation',
|
||||
initialize: function () {
|
||||
this.render.apply(this);
|
||||
},
|
||||
render: function () {
|
||||
this.$el.html(Template.operation(config));
|
||||
this.$el.find('abbr').tooltip();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
return Operation;
|
||||
});
|
||||
28
app/scripts/views/passengers.js
Normal file
28
app/scripts/views/passengers.js
Normal file
@@ -0,0 +1,28 @@
|
||||
define([
|
||||
'backbone',
|
||||
'backbone-mediator'
|
||||
], function (Backbone) {
|
||||
var PassengersInput = Backbone.View.extend({
|
||||
el: '.passengersWidget',
|
||||
events: {
|
||||
'change input': 'change',
|
||||
'keyup input': 'change'
|
||||
},
|
||||
initialize: function () {
|
||||
this.value = 1;
|
||||
},
|
||||
change: function (event) {
|
||||
var val = this.$el.find('input').val();
|
||||
if (!val) {
|
||||
val = 1;
|
||||
}
|
||||
val = Number(val);
|
||||
if (val !== this.value) {
|
||||
this.value = val;
|
||||
Backbone.Mediator.publish('passengers:change', this.value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return PassengersInput;
|
||||
});
|
||||
22
app/scripts/views/roundtrip.js
Normal file
22
app/scripts/views/roundtrip.js
Normal file
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'backbone-mediator'
|
||||
], function (Backbone) {
|
||||
var RoundtripInput = Backbone.View.extend({
|
||||
el: '.roundtripWidget',
|
||||
events: {
|
||||
'click button': 'click'
|
||||
},
|
||||
click: function (event, el) {
|
||||
this.$el.find('button').removeClass('active');
|
||||
var current = this.$el.find(event.currentTarget);
|
||||
current.addClass('active');
|
||||
|
||||
Backbone.Mediator.publish('roundtrip:change', current.hasClass('roundtrip'));
|
||||
}
|
||||
});
|
||||
|
||||
return RoundtripInput;
|
||||
});
|
||||
49
app/scripts/views/route.js
Normal file
49
app/scripts/views/route.js
Normal file
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'views/leg',
|
||||
'jquery-ui-sortable'
|
||||
], function (Backbone, LegView) {
|
||||
|
||||
var RouteView = Backbone.View.extend({
|
||||
el: '.route',
|
||||
events: {
|
||||
'sortstart': 'sortStart',
|
||||
'sortstop': 'sortStop'
|
||||
},
|
||||
initialize: function () {
|
||||
this.collection.bind('add', this.add, this);
|
||||
this.collection.bind('sort', this.render, this);
|
||||
|
||||
this.$el.sortable({
|
||||
handle: 'div > div',
|
||||
scroll: false,
|
||||
});
|
||||
},
|
||||
sortStart: function () {
|
||||
// fadeOut results
|
||||
},
|
||||
sortStop: function (event, ui) {
|
||||
this.updateSort();
|
||||
// fadeIn results
|
||||
},
|
||||
updateSort: function () {
|
||||
// jQuery UI already updates DOM order,
|
||||
// so we only have to update Backbone collection to match that
|
||||
var self = this;
|
||||
this.$el.find('.leg').each(function (index) {
|
||||
// Get id of model from element
|
||||
var id = $(this).data('id');
|
||||
self.collection.get(id).set('order', index);
|
||||
});
|
||||
this.collection.sort();
|
||||
},
|
||||
add: function (model, collection, options) {
|
||||
var item = new LegView({model: model});
|
||||
this.$el.append(item.render().el);
|
||||
}
|
||||
});
|
||||
|
||||
return RouteView;
|
||||
});
|
||||
19
app/scripts/views/total.js
Normal file
19
app/scripts/views/total.js
Normal file
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'Template'
|
||||
], function (Backbone, Template) {
|
||||
var TotalView = Backbone.View.extend({
|
||||
el: '.totalWidget',
|
||||
initialize: function () {
|
||||
this.render.apply(this);
|
||||
this.model.bind('change', this.render, this);
|
||||
},
|
||||
render: function () {
|
||||
this.$el.html(Template.total(this.model.toJSON()));
|
||||
}
|
||||
});
|
||||
|
||||
return TotalView;
|
||||
});
|
||||
Reference in New Issue
Block a user