JSFiddle - React, Tailwind, and code Playground
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src=" https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<div class="container main-container" id="mainContainer">
<div class="row">
<div class="col-xs-12"><h1>Калькулятор доставки</h1></div>
</div>
<div class="content-container row" id="contentContainer"></div>
</div>
<script type="text/template" id="calculatorSubmitButtonTemplate">
<div class="col-xs-12"><div class="btn btn-default pull-right" id="calculatorSubmitButton">Рассчитать</div></div>
</script>
<script type="text/template" id="paymentModalTemplate">
<!-- Modal payment -->
<div class="modal fade payment_modal" id="paymentModal" tabindex="-1" role="dialog" aria-labelledby="paymentLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form class="" id="paymentForm" method="get" action="#" onSubmit="return false;">
<fieldset>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="paymentLabel">Заказ составлен</h4>
</div>
<div class="modal-body" id="paymentModalFields">
<form>
<fieldset disabled>
<div class="form-group">
<label>Город отправления</label>
<input type="text" class="form-control" placeholder="<%= cityOfDepartureName %>">
</div>
<div class="form-group">
<label>Город отправления</label>
<input...
CSS
/****************************************************************************** COMMON_STYLES */
.hide{
display: none !important;
}
.show{
display: block !important;
}
.not_valid{
border: 1px solid red;
}
.valid{
border: 1px solid #ccc;
}
.form-group {
margin-bottom: 0px;
}
h2{
margin-top: 0;
}
/****************************************************************************** GLOBAL_layout */
/*.main-container{
width: 100%;
}
*/
/****************************************************************************** GLOBAL_blocks: payment_modal */
.payment_modal .shipping_options .input-group{
margin-bottom: 20px;
}
.payment_modal label:after{
content: ': ';
}
.payment_modal .form-group{
margin-bottom: 15px;
}
JavaScript
window.APP = window.APP || {};
APP.CityOfDepartureModel = Backbone.Model.extend({
defaults: {
cityName: undefined
},
validate: function(attrs) {
var errorsArr = [];
if($.trim(attrs.cityName).length == 0) {
errorsArr.push('Это поле не может быть пустым');
} else {
if(isNaN(attrs.cityName) == false) {
errorsArr.push('Это поле не может быть цифрой');
};
};
if(errorsArr.length != 0) { return errorsArr };
}
});
APP.CityOfDestinationModel = Backbone.Model.extend({
defaults: {
cityName: undefined
},
validate: function(attrs) {
var errorsArr = [];
if($.trim(attrs.cityName).length == 0) {
errorsArr.push('Это поле не может быть пустым');
} else {
if(isNaN(attrs.cityName) == false) {
errorsArr.push('Это поле не может быть цифрой');
};
};
if(errorsArr.length != 0) { return errorsArr };
}
});
APP.ShippingOptionsModel = Backbone.Model.extend({
defaults: {
weight: undefined,
volume: undefined
},
validate: function(attrs) {
var errorsArr = {
'weight': [],
'volume': []
};
if($.trim(attrs.weight).length == 0) {
errorsArr.weight.push('Это поле не может быть пустым');
} else {
if(isNaN(attrs.weight) == true) {
errorsArr.weight.push('Это значение должно быть цифрой');
};
if(attrs.weight <= 0) {
errorsArr.weight.push('Это значение не может быть меньше нуля');
};
};
if($.trim(attrs.volume).length == 0) {
errorsArr.volume.push('Это поле не может быть пустым');
} else {
if(isNaN(attrs.volume) == true) {
errorsArr.volume.push('Это значение должно быть цифрой');
};
if(attrs.volume <= 0) {
errorsArr.volume.push('Это значение не может быть меньше нуля');
};
};
if(errorsArr.weight.length != 0...