diff 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
line wrap: on
line diff
--- a/index.html	Fri Jun 08 22:08:31 2018 +0900
+++ b/index.html	Fri Jun 08 22:11:01 2018 +0900
@@ -1,194 +1,279 @@
 <!doctype html>
 <head>
-  <title>Kalkulator</title>
-  <meta name="viewport" content="width=device-width">
-  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-  <style type="text/css">
-    body {
-      font-size: 12px;
-      font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
-      line-height: 1.5;
-      margin: 0px;
-      background-color: #eee;
-    }
-    #content {
-      width: 100%;
-      min-height: 100vh;
-      padding: 10px;
-      margin: auto;
-      background-color: #fff;
-    }
-    @media (min-width: 600px) {
-      #content {
-        width: 500px;
-      }
-    }
-    * { box-sizing: border-box; }
-    ul { padding-left: 20px; }
-    #n, .js { display: none; }
-    input, button, select, option, .js { font-size: 150%; }
-  </style>
+    <title>Kalkulator</title>
+    <meta name="viewport" content="width=device-width">
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+    <style type="text/css">
+        * {
+            box-sizing: border-box;
+        }
+        body {
+            font-size: 12px;
+            font-family: Arial, sans-serif;
+            line-height: 1.5;
+            margin: 0;
+            background-color: #eee;
+        }
+        .content {
+            width: 100%;
+            max-width: 500px;
+            min-height: 100vh;
+            padding: 10px;
+            margin: auto;
+            background-color: #fff;
+        }
+
+        input, button, select, option, .js { font-size: 150%; }
+        .input {
+            font-size: 16px;
+            width: 100%;
+        }
+
+        .button {
+            font-size: 16px;
+            padding: 5px 10px;
+        }
+
+        .result {
+            font-size: 16px;
+            padding: 10px;
+            background-color: #eee;
+        }
+
+        .result__title {
+            padding: 0;
+            margin: 0 0 10px;
+        }
+
+        .result__list {
+            margin: 0;
+        }
+
+        .list {
+            padding-left: 20px;
+        }
+
+        .u-hidden {
+            display: none !important;
+        }
+    </style>
+    <script src="jquery-3.3.1.min.js"></script>
+
+    <script>
+        $(document).ready(function () {
+            var $loading = $(".js-x-loading");
+            var $ok = $(".js-x-ok");
+            var $error = $(".js-x-error");
+
+            var $form = $(".js-x-form");
+            var $submit = $(".js-x-submit");
+            var $reset = $(".js-x-reset");
+            var $input = $(".js-x-input");
+            var $rateEu = $(".js-x-rate-eu");
+            var $resultEu = $(".js-x-result-eu");
+            var $rateBni = $(".js-x-rate-bni");
+            var $resultBni = $(".js-x-result-bni");
+            var $resultPaypal = $(".js-x-result-paypal");
+
+            var locks = {};
+            var rates = {};
+
+            var val = function() {
+                return parseFloat($input.val());
+            }
+
+            var lock = function(isLoading) {
+                if (!isLoading && (locks.eu || locks.bni)) {
+                    return;
+                }
+
+                show(isLoading ? $loading : null);
+                $submit.attr("disabled", isLoading);
+            };
+
+            var displayResult = function() {
+                if (rates.eu == null || rates.bni == null) {
+                    return;
+                }
+
+                var x = val();
+
+                var resultEu = (Math.ceil(x * 1.07 * rates.eu / 1000) * 1000).toLocaleString();
+
+                $rateEu.text(rates.eu.toLocaleString());
+                $resultEu.text(resultEu);
+
+                var resultBni;
+                var rateBni;
+
+                if (rates.bni !== 0) {
+                    rateBni = rates.bni.toLocaleString();
+                    resultBni = (Math.ceil(x * 1.04 * rates.bni / 1000) * 1000 + (25000 * Math.ceil(x / 35000))).toLocaleString();
+                } else {
+                    rateBni = "x";
+                    resultBni = "x";
+                };
+
+                $rateBni.text(rateBni);
+                $resultBni.text(resultBni);
+
+                $resultPaypal.text((Math.round(x * 1.05)).toLocaleString());
+                lock(false);
+                show($ok);
+            };
+
+            var fetchEu = function() {
+                if (rates.fixer != null) {
+                    return;
+                }
+
+                lock(true);
+                locks.fixer = true;
+
+                $.get("eu-daily.xml")
+                .always(function() {
+                    locks.fixer = false;
+                    lock(false);
+                }).done(function(data) {
+                    var $data = $(data);
+                    var idrEur = parseFloat($data.find("[currency=IDR]").attr("rate"));
+                    var jpyEur = parseFloat($data.find("[currency=JPY]").attr("rate"));
+                    rates.eu = idrEur / jpyEur;
+
+                    displayResult();
+                }).fail(function() {
+                    error("connection");
+                });
+            };
+
+            var fetchBni = function() {
+                if (rates.bni != null) {
+                    return;
+                }
+
+                lock(true);
+                locks.bni = true;
+
+                $.get("bni-jpyidr.txt")
+                .always(function() {
+                    locks.bni = false;
+                    lock(false);
+                }).done(function(data) {
+                    if (data === "") {
+                        rates.bni = 0;
+                    } else {
+                        rates.bni = parseFloat(data);
+                    }
+
+                    displayResult();
+                }).fail(function() {
+                    error("connection");
+                });
+            };
+
+            var error = function(err) {
+                var message;
+
+                if (err === "connection") {
+                    message = "Koneksi ke server nilai tukar bermasalah.";
+                } else if (err === "missing") {
+                    message = "Masukkan jumlah.";
+                }
+
+                $error.text(message);
+                show($error);
+            }
+
+            var show = function($el) {
+                $error.toggleClass("u-hidden", $el !== $error);
+                $ok.toggleClass("u-hidden", $el !== $ok);
+                $loading.toggleClass("u-hidden", $el !== $loading);
+            }
+
+            var action = function(e) {
+                e.preventDefault();
+
+                show();
+
+                if (!isFinite(val())) {
+                    error("missing");
+                    return;
+                };
+
+                fetchEu();
+                fetchBni();
+
+                displayResult();
+            };
+
+            $form.submit(action)
+
+            $reset.click(function() {
+                $input.focus();
+            });
+        });
+    </script>
 </head>
 <body>
-  <div id="content">
-    <h1>Konversi buat nitip</h1>
-    <form>
-      <p>
-        <label for="x">Jumlah dalam yen:</label>
-        <br>
-        <input id="x" name="x" type="number" autofocus>
-      </p>
-      <p>
-        <button type="submit">Hitung</button>
-        <button type="reset">Hapus</button>
-      </p>
-    </form>
-    <div class="js" id="loading">
-      <p>Memuat data nilai tukar...</p>
-    </div>
-    <div class="js" id="ok">
-      <p>
-        Biaya:
-      </p>
-      <ul>
-        <li>
-          Bank transfer:
-          <span id="result-bank"></span> IDR
-          (<span id="rate-text"></span> IDR/JPY)
-        </li>
-
-        <li>
-          Bank transfer (alt):
-          <span id="result-bank-bni"></span> IDR
-          (<span id="rate-text-bni"></span> IDR/JPY)
-        </li>
+    <div class="content">
+        <h1>Konversi buat nitip</h1>
+        <form class="js-x-form">
+            <label>
+                <p>
+                    Jumlah dalam yen:
+                    <br>
+                    <input class="input js-x-input" type="number" autofocus>
+                </p>
+            </label>
+            <p>
+                <button type="submit" class="button js-x-submit">Hitung</button>
+                <button type="reset" class="button js-x-reset">Hapus</button>
+            </p>
+        </form>
 
-        <li>
-          PayPal:
-          <span id="result-paypal"></span> JPY
-        </li>
-      </ul>
-    </div>
-    <div class="js" id="error">
-      <p>Koneksi ke server nilai tukar bermasalah.</p>
-    </div>
+        <div class="result js-x-loading u-hidden">
+            Memuat data nilai tukar...
+        </div>
 
-    <hr>
-    <ul>
-      <li>Ongkir, cukai, dll tidak termasuk.</li>
-      <li>Berhubung sudah punya timbangan, ongkir (estimasi) bisa dihitung sebelum dikirim.</li>
-      <li><a href="http://www.post.japanpost.jp/int/charge/list/ems1_en.html">Tabel ongkir EMS</a>.</li>
-      <li>Perhitungan:
-        <ul>
-          <li>Bank: <code>jumlah &times; 1.07 &times; nilai_tukar</code>, dibulatkan ke seribuan terdekat.</li>
-          <li>Bank (alt): <code>jumlah &times; 1.04 &times; nilai_tukar + (25000 * ceil(jumlah / 35000))</code>, dibulatkan ke seribuan terdekat. Rekeningnya sama.</li>
-          <li>PayPal: <code>jumlah &times; 1.05</code>, dibulatkan ke satuan terdekat.</li>
-        </ul>
-      </li>
-      <li>Jangan lupa memastikan jumlah setelah pajak dan ongkir (lokal).</li>
-      <li>Data nilai tukar didapat dari layanan <a href="http://fixer.io/">Fixer.io</a>.</li>
-      <li>Data nilai tukar "(alt)" didapat dari <a href="http://bni.co.id/informasivalas.aspx">BNI</a>.</li>
-    </ul>
-  </div>
-
-  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
-  <script>
-    var input = function() { return parseFloat($xForm.val()); }
-
-    var $loading = $("#loading");
-    var $doButton = $("button[type=submit]");
-    var $xForm = $("#x");
-
-    var locks = {};
-    var lock = function(isLoading) {
-      if (!isLoading && (locks.fixer === true || locks.bni === true)) { return; }
-      $loading.toggle(isLoading);
-      $doButton.attr("disabled", isLoading);
-    };
-
-    var rates = {};
+        <div class="result js-x-ok u-hidden">
+            <p class="result__title">
+                Biaya:
+            </p>
+            <ul class="result__list">
+                <li>
+                Bank transfer:
+                <strong><span class="js-x-result-eu"></span> IDR</strong>
+                (<span class="js-x-rate-eu"></span> IDR/JPY)
 
-    var displayResult = function() {
-      if (rates.fixer === undefined || rates.bni === undefined) { return; }
-      var x = input();
-
-      $("#rate-text").text(rates.fixer.toLocaleString());
-      $("#result-bank").text((Math.ceil(x * 1.07 * rates.fixer / 1000) * 1000).toLocaleString());
-
-      if (rates.bni !== 0) {
-        $("#rate-text-bni").text(rates.bni.toLocaleString());
-        $("#result-bank-bni").text((Math.ceil(x * 1.04 * rates.bni / 1000) * 1000 + (25000 * Math.ceil(x / 35000))).toLocaleString());
-      } else {
-        $("#rate-text-bni").text('x');
-        $("#result-bank-bni").text('x');
-      };
-
-      $("#result-paypal").text((Math.round(x * 1.05)).toLocaleString());
-      $("#ok").show();
-      lock(false);
-    };
+                <li>
+                    Bank transfer (alt):
+                    <strong><span class="js-x-result-bni"></span> IDR</strong>
+                    (<span class="js-x-rate-bni"></span> IDR/JPY)
 
-    var fetchFixer = function() {
-      if (rates.fixer !== undefined) { return; }
-
-      lock(true);
-      locks.fixer = true;
-
-      $.getJSON("https://api.fixer.io/latest", { base: "JPY", symbols: "IDR" })
-      .done(function(data) {
-        rates.fixer = parseFloat(data.rates["IDR"]);
+                <li>
+                PayPal:
+                <strong><span class="js-x-result-paypal"></span> JPY</strong>
+            </ul>
+        </div>
 
-        displayResult();
-      })
-      .fail(function() {
-        $("#error").show();
-      })
-      .always(function() {
-        locks.fixer = false;
-        lock(false);
-      });
-    };
+        <div class="result js-x-error u-hidden">
+        </div>
+
+        <hr>
 
-    var fetchBni = function() {
-      if (rates.bni !== undefined) { return; }
-
-      lock(true);
-      locks.bni = true;
-
-      $.get("bni-jpyidr.txt")
-      .done(function(data) {
-        if (data === "") {
-          rates.bni = 0;
-        } else {
-          rates.bni = parseFloat(data);
-        }
-
-        displayResult();
-      })
-      .fail(function() {
-        $("#error").show();
-      })
-      .always(function() {
-        locks.bni = false;
-        lock(false);
-      });
-    };
-
-    var action = function(e) {
-      e.preventDefault()
-      $(".js").hide()
-
-      var x = input();
-
-      if (x === NaN || x === undefined) { return false; };
-
-      fetchFixer();
-      fetchBni();
-
-      displayResult();
-    };
-
-    $("form").submit(action)
-    $("button[type=reset]").click(function(e) { xForm.focus(); });
-  </script>
+        <ul class="list">
+            <li>Ongkir, cukai, dll tidak termasuk.
+            <li>Berhubung sudah punya timbangan, ongkir (estimasi) bisa dihitung sebelum dikirim.
+            <li><a href="http://www.post.japanpost.jp/int/charge/list/ems1_en.html">Tabel ongkir EMS</a>.
+            <li>Perhitungan:
+                <ul class="list">
+                    <li>Bank: <code>jumlah &times; 1.07 &times; nilai_tukar</code>, dibulatkan ke seribuan terdekat.
+                    <li>Bank (alt): <code>jumlah &times; 1.04 &times; nilai_tukar + (25000 * ceil(jumlah / 35000))</code>, dibulatkan ke seribuan terdekat. Rekeningnya sama.
+                    <li>PayPal: <code>jumlah &times; 1.05</code>, dibulatkan ke satuan terdekat.
+                </ul>
+            <li>Jangan lupa memastikan jumlah setelah pajak dan ongkir (lokal).
+            <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>.
+            <li>Data nilai tukar "(alt)" didapat dari <a href="http://bni.co.id/informasivalas.aspx">BNI</a>.
+        </ul>
+    </div>
 </body>