質問するログイン新規登録

回答編集履歴

1

追加

2020/07/26 05:21

投稿

退会済みユーザー
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
- <!-- Bootstrap CSS -->
32
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
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
- <title></title>
41
+ dispName: "select payment yeart",
35
- <style>
42
+ intValue: 0,
36
- #loading, #results {
43
+ interest: 0
44
+ },
45
+ aa1: {
46
+ value: "aa1",
47
+ dispName: "1 year payment",
37
- display:none;
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
- </style>
57
+ }
40
58
 
59
+ /**
60
+ * DOMLoaded
61
+ */
62
+ document.addEventListener("DOMContentLoaded", function(e) {
41
63
 
42
- </head>
64
+ // submit
43
- <body class="bg-dark">
44
- <div class="container">
65
+ document.loanform.addEventListener('submit', function(e) {
66
+ onSubmit(e);
67
+ });
45
- <div class="row">
68
+ // yearsコンボボックス要素設定
46
- <div class="col-md-6 mx-auto">
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
- <form name="loanform">
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
- </div>
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
- </div>
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
- </div>
108
+ loopCnt++;
66
- </div>
109
+ });
110
+ }
67
111
 
112
+ /**
113
+ * 計算前チェック処理
114
+ * @return チェックOK:true, チェックNG:false
115
+ */
116
+ function checkValue() {
68
- <div class="form-group">
117
+ let rtn = true; // 返却用
69
118
 
119
+ let downpayment = document.getElementById(elementId.downpayment).value; // 頭金
70
- <div class="input-group">
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
- </div>
126
+ // amountが未設定の場合エラー
127
+ showError("Please check amount");
75
- </div>
128
+ rtn = false;
76
129
 
77
- <div class="form-group">
78
- <select class="form-control" name="years" id="years">
79
- </select>
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
- </form>
132
+ // downpaymentが未設定の場合エラー
86
- <div id="loading">
87
- <img src="img/loading.gif" alt="Loading">
88
- </div>
89
- <div id="results" class="pt-4">
133
+ showError("Please check downpayment.");
90
- <h5>result</h5>
134
+ rtn = false;
91
135
 
92
- <div class="form-group">
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
- <div class="form-group">
138
+ // cb_amountが未設定の場合エラー
100
- <div class="input-group">
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
- </div>
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
- </div>
144
+ // yearsが未選択の場合エラー
112
- </div>
113
- <div class="form-group">
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
- </div>
146
+ rtn = false;
118
- </div>
119
147
 
148
+ }
120
149
 
121
- <div class="form-group">
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
- </div>
151
+ if (rtn) {
126
- </div>
127
152
 
128
- <div class="form-group">
129
- <div class="input-group">
130
- <span class="input-group-addon">Combined bonus paying times</span>
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
- <div class="form-group">
155
+ // ボーナス併用払い金額 >= 商品代金と頭金の差額 / 2の場合エラー
136
- <div class="input-group">
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
- </div>
157
+ rtn = false;
140
- </div>
158
+ }
159
+ }
141
160
 
161
+ // チェック通過
162
+ return rtn;
163
+ }
142
164
 
143
- <div class="form-group">
165
+ /**
166
+ * 金利の算出
167
+ */
144
- <div class="input-group">
168
+ function calculateResults(e) {
145
- <span class="input-group-addon">total - downpayment </span>
169
+ let downpayment = document.getElementById(elementId.downpayment).value; // 頭金
146
- <input class="form-control t_rlt" id="showdiffrence" disabled>
170
+ let amount = document.getElementById(elementId.amount).value; // 製品料金
171
+ let cb_amount = document.getElementById(elementId.cb_amount).value; // ボーナス支払い金額
147
- </div>
172
+ let years, interest;
148
- </div>
149
173
 
150
- <div class="form-group">
151
- <div class="input-group">
174
+ // yearsコンボボックス内選択値に応じて、years, interestをENUMから設定
152
- <span class="input-group-addon">total payment</span>
175
+ let selectedYears = document.getElementById(elementId.years).value; // yearsコンボボックス
176
+ years = yearsElement[selectedYears].intValue;
153
- <input class="form-control t_rlt" id="total-payment" disabled>
177
+ interest = yearsElement[selectedYears].interest;
154
- </div>
155
- </div>
156
178
 
157
- <div class="form-group">
179
+ // 算出
158
- <div class="input-group">
180
+ console.log('Calculating...');
159
- <span class="input-group-addon">total interest</span>
181
+ console.log('downpayment = ' + downpayment);
182
+ console.log('amount = ' + amount);
160
- <input class="form-control t_rlt" id="total_interest" disabled>
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
- </body>
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
- </html>
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
  一応動作環境が異なるので、不具合があればお伝えください。