comparison index.html @ 16:1f999668080f

Migrate to eu central bank data and use local jquery
author nanaya <me@nanaya.pro>
date Fri, 08 Jun 2018 22:11:01 +0900
parents 72ee98d173a4
children aef027838046
comparison
equal deleted inserted replaced
15:4391020b8ebd 16:1f999668080f
1 <!doctype html> 1 <!doctype html>
2 <head> 2 <head>
3 <title>Kalkulator</title> 3 <title>Kalkulator</title>
4 <meta name="viewport" content="width=device-width"> 4 <meta name="viewport" content="width=device-width">
5 <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 5 <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
6 <style type="text/css"> 6 <style type="text/css">
7 body { 7 * {
8 font-size: 12px; 8 box-sizing: border-box;
9 font-family: Helvetica Neue, Helvetica, Arial, sans-serif; 9 }
10 line-height: 1.5; 10 body {
11 margin: 0px; 11 font-size: 12px;
12 background-color: #eee; 12 font-family: Arial, sans-serif;
13 } 13 line-height: 1.5;
14 #content { 14 margin: 0;
15 width: 100%; 15 background-color: #eee;
16 min-height: 100vh; 16 }
17 padding: 10px; 17 .content {
18 margin: auto; 18 width: 100%;
19 background-color: #fff; 19 max-width: 500px;
20 } 20 min-height: 100vh;
21 @media (min-width: 600px) { 21 padding: 10px;
22 #content { 22 margin: auto;
23 width: 500px; 23 background-color: #fff;
24 } 24 }
25 } 25
26 * { box-sizing: border-box; } 26 input, button, select, option, .js { font-size: 150%; }
27 ul { padding-left: 20px; } 27 .input {
28 #n, .js { display: none; } 28 font-size: 16px;
29 input, button, select, option, .js { font-size: 150%; } 29 width: 100%;
30 </style> 30 }
31
32 .button {
33 font-size: 16px;
34 padding: 5px 10px;
35 }
36
37 .result {
38 font-size: 16px;
39 padding: 10px;
40 background-color: #eee;
41 }
42
43 .result__title {
44 padding: 0;
45 margin: 0 0 10px;
46 }
47
48 .result__list {
49 margin: 0;
50 }
51
52 .list {
53 padding-left: 20px;
54 }
55
56 .u-hidden {
57 display: none !important;
58 }
59 </style>
60 <script src="jquery-3.3.1.min.js"></script>
61
62 <script>
63 $(document).ready(function () {
64 var $loading = $(".js-x-loading");
65 var $ok = $(".js-x-ok");
66 var $error = $(".js-x-error");
67
68 var $form = $(".js-x-form");
69 var $submit = $(".js-x-submit");
70 var $reset = $(".js-x-reset");
71 var $input = $(".js-x-input");
72 var $rateEu = $(".js-x-rate-eu");
73 var $resultEu = $(".js-x-result-eu");
74 var $rateBni = $(".js-x-rate-bni");
75 var $resultBni = $(".js-x-result-bni");
76 var $resultPaypal = $(".js-x-result-paypal");
77
78 var locks = {};
79 var rates = {};
80
81 var val = function() {
82 return parseFloat($input.val());
83 }
84
85 var lock = function(isLoading) {
86 if (!isLoading && (locks.eu || locks.bni)) {
87 return;
88 }
89
90 show(isLoading ? $loading : null);
91 $submit.attr("disabled", isLoading);
92 };
93
94 var displayResult = function() {
95 if (rates.eu == null || rates.bni == null) {
96 return;
97 }
98
99 var x = val();
100
101 var resultEu = (Math.ceil(x * 1.07 * rates.eu / 1000) * 1000).toLocaleString();
102
103 $rateEu.text(rates.eu.toLocaleString());
104 $resultEu.text(resultEu);
105
106 var resultBni;
107 var rateBni;
108
109 if (rates.bni !== 0) {
110 rateBni = rates.bni.toLocaleString();
111 resultBni = (Math.ceil(x * 1.04 * rates.bni / 1000) * 1000 + (25000 * Math.ceil(x / 35000))).toLocaleString();
112 } else {
113 rateBni = "x";
114 resultBni = "x";
115 };
116
117 $rateBni.text(rateBni);
118 $resultBni.text(resultBni);
119
120 $resultPaypal.text((Math.round(x * 1.05)).toLocaleString());
121 lock(false);
122 show($ok);
123 };
124
125 var fetchEu = function() {
126 if (rates.fixer != null) {
127 return;
128 }
129
130 lock(true);
131 locks.fixer = true;
132
133 $.get("eu-daily.xml")
134 .always(function() {
135 locks.fixer = false;
136 lock(false);
137 }).done(function(data) {
138 var $data = $(data);
139 var idrEur = parseFloat($data.find("[currency=IDR]").attr("rate"));
140 var jpyEur = parseFloat($data.find("[currency=JPY]").attr("rate"));
141 rates.eu = idrEur / jpyEur;
142
143 displayResult();
144 }).fail(function() {
145 error("connection");
146 });
147 };
148
149 var fetchBni = function() {
150 if (rates.bni != null) {
151 return;
152 }
153
154 lock(true);
155 locks.bni = true;
156
157 $.get("bni-jpyidr.txt")
158 .always(function() {
159 locks.bni = false;
160 lock(false);
161 }).done(function(data) {
162 if (data === "") {
163 rates.bni = 0;
164 } else {
165 rates.bni = parseFloat(data);
166 }
167
168 displayResult();
169 }).fail(function() {
170 error("connection");
171 });
172 };
173
174 var error = function(err) {
175 var message;
176
177 if (err === "connection") {
178 message = "Koneksi ke server nilai tukar bermasalah.";
179 } else if (err === "missing") {
180 message = "Masukkan jumlah.";
181 }
182
183 $error.text(message);
184 show($error);
185 }
186
187 var show = function($el) {
188 $error.toggleClass("u-hidden", $el !== $error);
189 $ok.toggleClass("u-hidden", $el !== $ok);
190 $loading.toggleClass("u-hidden", $el !== $loading);
191 }
192
193 var action = function(e) {
194 e.preventDefault();
195
196 show();
197
198 if (!isFinite(val())) {
199 error("missing");
200 return;
201 };
202
203 fetchEu();
204 fetchBni();
205
206 displayResult();
207 };
208
209 $form.submit(action)
210
211 $reset.click(function() {
212 $input.focus();
213 });
214 });
215 </script>
31 </head> 216 </head>
32 <body> 217 <body>
33 <div id="content"> 218 <div class="content">
34 <h1>Konversi buat nitip</h1> 219 <h1>Konversi buat nitip</h1>
35 <form> 220 <form class="js-x-form">
36 <p> 221 <label>
37 <label for="x">Jumlah dalam yen:</label> 222 <p>
38 <br> 223 Jumlah dalam yen:
39 <input id="x" name="x" type="number" autofocus> 224 <br>
40 </p> 225 <input class="input js-x-input" type="number" autofocus>
41 <p> 226 </p>
42 <button type="submit">Hitung</button> 227 </label>
43 <button type="reset">Hapus</button> 228 <p>
44 </p> 229 <button type="submit" class="button js-x-submit">Hitung</button>
45 </form> 230 <button type="reset" class="button js-x-reset">Hapus</button>
46 <div class="js" id="loading"> 231 </p>
47 <p>Memuat data nilai tukar...</p> 232 </form>
233
234 <div class="result js-x-loading u-hidden">
235 Memuat data nilai tukar...
236 </div>
237
238 <div class="result js-x-ok u-hidden">
239 <p class="result__title">
240 Biaya:
241 </p>
242 <ul class="result__list">
243 <li>
244 Bank transfer:
245 <strong><span class="js-x-result-eu"></span> IDR</strong>
246 (<span class="js-x-rate-eu"></span> IDR/JPY)
247
248 <li>
249 Bank transfer (alt):
250 <strong><span class="js-x-result-bni"></span> IDR</strong>
251 (<span class="js-x-rate-bni"></span> IDR/JPY)
252
253 <li>
254 PayPal:
255 <strong><span class="js-x-result-paypal"></span> JPY</strong>
256 </ul>
257 </div>
258
259 <div class="result js-x-error u-hidden">
260 </div>
261
262 <hr>
263
264 <ul class="list">
265 <li>Ongkir, cukai, dll tidak termasuk.
266 <li>Berhubung sudah punya timbangan, ongkir (estimasi) bisa dihitung sebelum dikirim.
267 <li><a href="http://www.post.japanpost.jp/int/charge/list/ems1_en.html">Tabel ongkir EMS</a>.
268 <li>Perhitungan:
269 <ul class="list">
270 <li>Bank: <code>jumlah &times; 1.07 &times; nilai_tukar</code>, dibulatkan ke seribuan terdekat.
271 <li>Bank (alt): <code>jumlah &times; 1.04 &times; nilai_tukar + (25000 * ceil(jumlah / 35000))</code>, dibulatkan ke seribuan terdekat. Rekeningnya sama.
272 <li>PayPal: <code>jumlah &times; 1.05</code>, dibulatkan ke satuan terdekat.
273 </ul>
274 <li>Jangan lupa memastikan jumlah setelah pajak dan ongkir (lokal).
275 <li>Data nilai tukar didapat dari <a href="https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html">Bank Sentral Eropa</a>.
276 <li>Data nilai tukar "(alt)" didapat dari <a href="http://bni.co.id/informasivalas.aspx">BNI</a>.
277 </ul>
48 </div> 278 </div>
49 <div class="js" id="ok">
50 <p>
51 Biaya:
52 </p>
53 <ul>
54 <li>
55 Bank transfer:
56 <span id="result-bank"></span> IDR
57 (<span id="rate-text"></span> IDR/JPY)
58 </li>
59
60 <li>
61 Bank transfer (alt):
62 <span id="result-bank-bni"></span> IDR
63 (<span id="rate-text-bni"></span> IDR/JPY)
64 </li>
65
66 <li>
67 PayPal:
68 <span id="result-paypal"></span> JPY
69 </li>
70 </ul>
71 </div>
72 <div class="js" id="error">
73 <p>Koneksi ke server nilai tukar bermasalah.</p>
74 </div>
75
76 <hr>
77 <ul>
78 <li>Ongkir, cukai, dll tidak termasuk.</li>
79 <li>Berhubung sudah punya timbangan, ongkir (estimasi) bisa dihitung sebelum dikirim.</li>
80 <li><a href="http://www.post.japanpost.jp/int/charge/list/ems1_en.html">Tabel ongkir EMS</a>.</li>
81 <li>Perhitungan:
82 <ul>
83 <li>Bank: <code>jumlah &times; 1.07 &times; nilai_tukar</code>, dibulatkan ke seribuan terdekat.</li>
84 <li>Bank (alt): <code>jumlah &times; 1.04 &times; nilai_tukar + (25000 * ceil(jumlah / 35000))</code>, dibulatkan ke seribuan terdekat. Rekeningnya sama.</li>
85 <li>PayPal: <code>jumlah &times; 1.05</code>, dibulatkan ke satuan terdekat.</li>
86 </ul>
87 </li>
88 <li>Jangan lupa memastikan jumlah setelah pajak dan ongkir (lokal).</li>
89 <li>Data nilai tukar didapat dari layanan <a href="http://fixer.io/">Fixer.io</a>.</li>
90 <li>Data nilai tukar "(alt)" didapat dari <a href="http://bni.co.id/informasivalas.aspx">BNI</a>.</li>
91 </ul>
92 </div>
93
94 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
95 <script>
96 var input = function() { return parseFloat($xForm.val()); }
97
98 var $loading = $("#loading");
99 var $doButton = $("button[type=submit]");
100 var $xForm = $("#x");
101
102 var locks = {};
103 var lock = function(isLoading) {
104 if (!isLoading && (locks.fixer === true || locks.bni === true)) { return; }
105 $loading.toggle(isLoading);
106 $doButton.attr("disabled", isLoading);
107 };
108
109 var rates = {};
110
111 var displayResult = function() {
112 if (rates.fixer === undefined || rates.bni === undefined) { return; }
113 var x = input();
114
115 $("#rate-text").text(rates.fixer.toLocaleString());
116 $("#result-bank").text((Math.ceil(x * 1.07 * rates.fixer / 1000) * 1000).toLocaleString());
117
118 if (rates.bni !== 0) {
119 $("#rate-text-bni").text(rates.bni.toLocaleString());
120 $("#result-bank-bni").text((Math.ceil(x * 1.04 * rates.bni / 1000) * 1000 + (25000 * Math.ceil(x / 35000))).toLocaleString());
121 } else {
122 $("#rate-text-bni").text('x');
123 $("#result-bank-bni").text('x');
124 };
125
126 $("#result-paypal").text((Math.round(x * 1.05)).toLocaleString());
127 $("#ok").show();
128 lock(false);
129 };
130
131 var fetchFixer = function() {
132 if (rates.fixer !== undefined) { return; }
133
134 lock(true);
135 locks.fixer = true;
136
137 $.getJSON("https://api.fixer.io/latest", { base: "JPY", symbols: "IDR" })
138 .done(function(data) {
139 rates.fixer = parseFloat(data.rates["IDR"]);
140
141 displayResult();
142 })
143 .fail(function() {
144 $("#error").show();
145 })
146 .always(function() {
147 locks.fixer = false;
148 lock(false);
149 });
150 };
151
152 var fetchBni = function() {
153 if (rates.bni !== undefined) { return; }
154
155 lock(true);
156 locks.bni = true;
157
158 $.get("bni-jpyidr.txt")
159 .done(function(data) {
160 if (data === "") {
161 rates.bni = 0;
162 } else {
163 rates.bni = parseFloat(data);
164 }
165
166 displayResult();
167 })
168 .fail(function() {
169 $("#error").show();
170 })
171 .always(function() {
172 locks.bni = false;
173 lock(false);
174 });
175 };
176
177 var action = function(e) {
178 e.preventDefault()
179 $(".js").hide()
180
181 var x = input();
182
183 if (x === NaN || x === undefined) { return false; };
184
185 fetchFixer();
186 fetchBni();
187
188 displayResult();
189 };
190
191 $("form").submit(action)
192 $("button[type=reset]").click(function(e) { xForm.focus(); });
193 </script>
194 </body> 279 </body>