回答編集履歴
1
追加
answer
CHANGED
@@ -20,165 +20,236 @@
|
|
20
20
|
結果が下のソースです。
|
21
21
|
HTMLはidの追加とコンボボックス要素の削除、jsは上記の説明の修正と、submitを設定している箇所を少し実践向きに修正してます。(本来はsubmitではなくonslickの方がいいと思われますが、もともとsubmitで製造していたようなのでsubmitのままです。)
|
22
22
|
|
23
|
-
```HTML
|
24
|
-
<!doctype html>
|
25
|
-
<html lang="ja">
|
26
|
-
<head>
|
27
|
-
<!-- Required meta tags -->
|
28
|
-
<meta charset="utf-8">
|
29
|
-
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
30
23
|
|
31
|
-
|
32
|
-
|
24
|
+
```JS
|
25
|
+
/**
|
26
|
+
* エレメントの属性値
|
27
|
+
*/
|
28
|
+
var elementId = {
|
29
|
+
downpayment: "downpayment", // 頭金
|
30
|
+
amount: "amount", // 製品料金
|
31
|
+
cb_amount: "cb_amount", // ボーナス併用払い
|
32
|
+
years: "years" // yearsコンボボックス
|
33
|
+
}
|
33
34
|
|
35
|
+
/**
|
36
|
+
* yearsコンボボックス要素
|
37
|
+
*/
|
38
|
+
var yearsElement = {
|
39
|
+
blank: {
|
40
|
+
value: "",
|
34
|
-
|
41
|
+
dispName: "select payment yeart",
|
35
|
-
|
42
|
+
intValue: 0,
|
36
|
-
|
43
|
+
interest: 0
|
44
|
+
},
|
45
|
+
aa1: {
|
46
|
+
value: "aa1",
|
47
|
+
dispName: "1 year payment",
|
37
|
-
|
48
|
+
intValue: 1,
|
49
|
+
interest: 1.5
|
50
|
+
},
|
51
|
+
bb2: {
|
52
|
+
value: "bb2",
|
53
|
+
dispName: "2 year payment",
|
54
|
+
intValue: 2,
|
55
|
+
interest: 2.5
|
38
|
-
|
56
|
+
}
|
39
|
-
|
57
|
+
}
|
40
58
|
|
59
|
+
/**
|
60
|
+
* DOMLoaded
|
61
|
+
*/
|
62
|
+
document.addEventListener("DOMContentLoaded", function(e) {
|
41
63
|
|
42
|
-
|
64
|
+
// submit
|
43
|
-
<body class="bg-dark">
|
44
|
-
|
65
|
+
document.loanform.addEventListener('submit', function(e) {
|
66
|
+
onSubmit(e);
|
67
|
+
});
|
45
|
-
|
68
|
+
// yearsコンボボックス要素設定
|
46
|
-
|
69
|
+
setSelectboxValue(elementId.years, yearsElement);
|
47
|
-
<div class="card card-body text-center mt-5">
|
48
|
-
<h6 class="heading display-5 pb-3">loan calc</h6>
|
49
|
-
|
70
|
+
}, false)
|
50
71
|
|
72
|
+
/**
|
73
|
+
* サブミットイベント
|
74
|
+
*/
|
75
|
+
function onSubmit(e) {
|
76
|
+
// 入力チェック通過後、calculateResultsを実行する
|
77
|
+
if (checkValue()) {
|
78
|
+
// 活性制御
|
79
|
+
document.getElementById('results').style.display = 'none';
|
80
|
+
document.getElementById('loading').style.display = 'block';
|
51
81
|
|
82
|
+
// calculateResults実行
|
83
|
+
setTimeout(calculateResults, 3500);
|
84
|
+
}
|
85
|
+
e.preventDefault();
|
86
|
+
}
|
52
87
|
|
88
|
+
/**
|
89
|
+
* セレクトボックス要素設定
|
90
|
+
* @param id セットするセレクトボックスのid
|
91
|
+
* @param object セットするオブジェクト
|
92
|
+
* セットするオブジェクトはkey.valueの形式であること
|
93
|
+
*/
|
94
|
+
function setSelectboxValue(id, object) {
|
95
|
+
let selectBox = document.getElementById(id);
|
96
|
+
let loopCnt = 1;
|
53
97
|
|
54
|
-
<div class="form-group">
|
55
|
-
<div class="input-group">
|
56
|
-
<span class="input-group-addon">amount</span>
|
57
|
-
<input class="form-control t_rlt" id="amount" name="amount" placeholder="amount">
|
58
|
-
|
98
|
+
// 要素数分ループ
|
99
|
+
Object.keys(object).forEach(function(key) {
|
100
|
+
let element = document.createElement("option");
|
101
|
+
element.value = object[key].value;
|
102
|
+
element.innerHTML = object[key].dispName;
|
103
|
+
if (loopCnt == 1) {
|
59
|
-
|
104
|
+
element.selected = true;
|
105
|
+
}
|
106
|
+
selectBox.appendChild(element);
|
60
107
|
|
61
|
-
<div class="form-group">
|
62
|
-
<div class="input-group">
|
63
|
-
<span class="input-group-addon">downpayment</span>
|
64
|
-
<input class="form-control t_rlt" id="downpayment" name="downpayment" placeholder="downpayment">
|
65
|
-
|
108
|
+
loopCnt++;
|
66
|
-
|
109
|
+
});
|
110
|
+
}
|
67
111
|
|
112
|
+
/**
|
113
|
+
* 計算前チェック処理
|
114
|
+
* @return チェックOK:true, チェックNG:false
|
115
|
+
*/
|
116
|
+
function checkValue() {
|
68
|
-
|
117
|
+
let rtn = true; // 返却用
|
69
118
|
|
119
|
+
let downpayment = document.getElementById(elementId.downpayment).value; // 頭金
|
70
|
-
|
120
|
+
let amount = document.getElementById(elementId.amount).value; // 製品料金
|
121
|
+
let cb_amount = document.getElementById(elementId.cb_amount).value; // ボーナス支払い金額
|
122
|
+
let selectedYears = document.getElementById(elementId.years).value; // yearsコンボボックス
|
123
|
+
// 必須チェック
|
124
|
+
if (!amount) {
|
71
125
|
|
72
|
-
<span class="input-group-addon">combind bonus</span>
|
73
|
-
<input class="form-control t_rlt" id="cb_amount" name="cb_amount" placeholder="combind bonus">
|
74
|
-
|
126
|
+
// amountが未設定の場合エラー
|
127
|
+
showError("Please check amount");
|
75
|
-
|
128
|
+
rtn = false;
|
76
129
|
|
77
|
-
<div class="form-group">
|
78
|
-
<select class="form-control" name="years" id="years">
|
79
|
-
|
130
|
+
} else if (!downpayment) {
|
80
|
-
</div>
|
81
131
|
|
82
|
-
<div class="form-group">
|
83
|
-
<input type="submit" value="submit" class="btn btn-dark btn-block">
|
84
|
-
</div>
|
85
|
-
|
132
|
+
// downpaymentが未設定の場合エラー
|
86
|
-
<div id="loading">
|
87
|
-
<img src="img/loading.gif" alt="Loading">
|
88
|
-
</div>
|
89
|
-
|
133
|
+
showError("Please check downpayment.");
|
90
|
-
|
134
|
+
rtn = false;
|
91
135
|
|
92
|
-
|
136
|
+
} else if (!cb_amount) {
|
93
|
-
<div class="input-group">
|
94
|
-
<span class="input-group-addon">Years </span>
|
95
|
-
<input class="form-control t_rlt" id="showyears" disabled>
|
96
|
-
</div>
|
97
|
-
</div>
|
98
137
|
|
99
|
-
|
138
|
+
// cb_amountが未設定の場合エラー
|
100
|
-
|
139
|
+
showError("Please check cb_amount.");
|
101
|
-
<span class="input-group-addon">Interest</span>
|
102
|
-
<input class="form-control t_rlt" id="showinterest" disabled>
|
103
|
-
|
140
|
+
rtn = false;
|
104
|
-
</div>
|
105
141
|
|
142
|
+
} else if (!selectedYears) {
|
106
143
|
|
107
|
-
<div class="form-group">
|
108
|
-
<div class="input-group">
|
109
|
-
<span class="input-group-addon">monthly payment</span>
|
110
|
-
<input class="form-control t_rlt" id="monthly-payment2" disabled>
|
111
|
-
|
144
|
+
// yearsが未選択の場合エラー
|
112
|
-
</div>
|
113
|
-
|
145
|
+
showError("Please check selectbox of years.");
|
114
|
-
<div class="input-group">
|
115
|
-
<span class="input-group-addon">Fist month payment</span>
|
116
|
-
<input class="form-control t_rlt" id="monthly-payment1" disabled>
|
117
|
-
|
146
|
+
rtn = false;
|
118
|
-
</div>
|
119
147
|
|
148
|
+
}
|
120
149
|
|
121
|
-
|
150
|
+
// 必須チェックがtrueの場合、相関チェックを行う
|
122
|
-
<div class="input-group">
|
123
|
-
<span class="input-group-addon">Combined bonus</span>
|
124
|
-
<input class="form-control t_rlt" id="cb_input" disabled>
|
125
|
-
|
151
|
+
if (rtn) {
|
126
|
-
</div>
|
127
152
|
|
128
|
-
<div class="form-group">
|
129
|
-
<div class="input-group">
|
130
|
-
|
153
|
+
if (cb_amount >= ( amount - downpayment ) / 2 ) {
|
131
|
-
<input class="form-control t_rlt" id="cb_num" disabled>
|
132
|
-
</div>
|
133
|
-
</div>
|
134
154
|
|
135
|
-
|
155
|
+
// ボーナス併用払い金額 >= 商品代金と頭金の差額 / 2の場合エラー
|
136
|
-
|
156
|
+
showError("正しい金額を入力してください");
|
137
|
-
<span class="input-group-addon">total bonus paying times</span>
|
138
|
-
<input class="form-control t_rlt" id="cb_everypayment" disabled>
|
139
|
-
|
157
|
+
rtn = false;
|
140
|
-
|
158
|
+
}
|
159
|
+
}
|
141
160
|
|
161
|
+
// チェック通過
|
162
|
+
return rtn;
|
163
|
+
}
|
142
164
|
|
143
|
-
|
165
|
+
/**
|
166
|
+
* 金利の算出
|
167
|
+
*/
|
144
|
-
|
168
|
+
function calculateResults(e) {
|
145
|
-
|
169
|
+
let downpayment = document.getElementById(elementId.downpayment).value; // 頭金
|
146
|
-
|
170
|
+
let amount = document.getElementById(elementId.amount).value; // 製品料金
|
171
|
+
let cb_amount = document.getElementById(elementId.cb_amount).value; // ボーナス支払い金額
|
147
|
-
|
172
|
+
let years, interest;
|
148
|
-
</div>
|
149
173
|
|
150
|
-
<div class="form-group">
|
151
|
-
|
174
|
+
// yearsコンボボックス内選択値に応じて、years, interestをENUMから設定
|
152
|
-
|
175
|
+
let selectedYears = document.getElementById(elementId.years).value; // yearsコンボボックス
|
176
|
+
years = yearsElement[selectedYears].intValue;
|
153
|
-
|
177
|
+
interest = yearsElement[selectedYears].interest;
|
154
|
-
</div>
|
155
|
-
</div>
|
156
178
|
|
157
|
-
|
179
|
+
// 算出
|
158
|
-
|
180
|
+
console.log('Calculating...');
|
159
|
-
|
181
|
+
console.log('downpayment = ' + downpayment);
|
182
|
+
console.log('amount = ' + amount);
|
160
|
-
|
183
|
+
console.log('cb_amount = ' + cb_amount);
|
161
184
|
|
162
|
-
</div>
|
163
|
-
</div>
|
164
|
-
</div>
|
165
|
-
</div>
|
166
|
-
</div>
|
167
|
-
</div>
|
168
|
-
</div>
|
169
185
|
|
186
|
+
const difference = amount - downpayment; // 商品代金と頭金の差額
|
187
|
+
const cbTimes = years * 2; // ボーナス支払いの回数
|
188
|
+
const cbEveryPayment = cb_amount / cbTimes; // ボーナス一回あたりに支払う金額
|
189
|
+
const paymentTimes = years * 12; // 支払い回数(ボーナス除く)
|
190
|
+
const interestMod = 1 + (interest / 100); // 手を加えた金利を算出
|
191
|
+
// const amountWithoutBns = difference * interestMod;
|
192
|
+
const totalPayment = (difference - cb_amount) * interestMod; // ボーナス支払い以外の支払金額を算出
|
193
|
+
const justDevideMonthlyPayment = totalPayment / paymentTimes; // ひと月辺りの支払額を一度算出
|
194
|
+
const secondToLastMonthlyPayment = (Math.floor(justDevideMonthlyPayment / 100) * 100); // 10円単位の切り捨て
|
195
|
+
const firstMonthlyPayment = totalPayment - (secondToLastMonthlyPayment * (paymentTimes - 1)); // 切り捨て額を1ヶ月目の支払額に集約
|
196
|
+
const totalInterest = (difference * interestMod) - difference; // 商品にかかる金利
|
170
197
|
|
171
|
-
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
172
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
|
173
|
-
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
|
174
|
-
<script src="eng.js"></script>
|
175
198
|
|
199
|
+
// 各項目にセット
|
200
|
+
document.getElementById('monthly-payment1').value = comma(parseInt(firstMonthlyPayment));
|
201
|
+
document.getElementById('monthly-payment2').value = comma(parseInt(secondToLastMonthlyPayment));
|
202
|
+
document.getElementById('total-payment').value = comma(parseInt(interestMod));
|
203
|
+
document.getElementById('total_interest').value = comma(parseInt(totalInterest));
|
204
|
+
document.getElementById('showyears').value = years;
|
205
|
+
document.getElementById('showinterest').value = interest / 100;
|
206
|
+
document.getElementById('showdiffrence').value = comma(parseInt(difference));
|
207
|
+
document.getElementById('cb_num').value = cbTimes;
|
208
|
+
document.getElementById('cb_input').value = comma(parseInt(cb_amount));
|
209
|
+
document.getElementById('cb_everypayment').value = comma(parseInt(cbEveryPayment));
|
210
|
+
}
|
176
211
|
|
212
|
+
/**
|
213
|
+
* 金額をカンマ編集する
|
214
|
+
* @param num 金額
|
215
|
+
* @return カンマ編集後の金額
|
216
|
+
*/
|
217
|
+
function comma(num) {
|
218
|
+
return String(num).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
|
219
|
+
}
|
177
220
|
|
221
|
+
/*
|
222
|
+
* エラーハンドラ
|
223
|
+
*/
|
178
224
|
|
179
|
-
|
225
|
+
// Error message
|
226
|
+
function showError(error){
|
227
|
+
console.log("Error ..." + error);
|
180
228
|
|
229
|
+
// create a div
|
230
|
+
const errorDiv = document.createElement("div");
|
231
|
+
|
181
|
-
|
232
|
+
// get element
|
233
|
+
const card = document.querySelector(".card");
|
234
|
+
const heading = document.querySelector(".heading");
|
235
|
+
|
236
|
+
// add class
|
237
|
+
errorDiv.className = "alert alert-danger";
|
238
|
+
|
239
|
+
// create text node and append div
|
240
|
+
errorDiv.appendChild(document.createTextNode(error));
|
241
|
+
|
242
|
+
// Insert error above heading
|
243
|
+
card.insertBefore(errorDiv, heading);
|
244
|
+
|
245
|
+
// clear error after 3 secs.
|
246
|
+
setTimeout(clearError, 3000);
|
247
|
+
}
|
248
|
+
|
249
|
+
// clear error function
|
250
|
+
function clearError() {
|
251
|
+
document.querySelector(".alert").remove();
|
252
|
+
}
|
182
253
|
```
|
183
254
|
|
184
255
|
一応動作環境が異なるので、不具合があればお伝えください。
|