From 1aa67cd3ef08e4b98340c0f6ab4601ef9bae9094 Mon Sep 17 00:00:00 2001 From: ajandera Date: Thu, 11 May 2017 14:46:45 +0200 Subject: [PATCH 1/8] New design part I. --- .../public/css/assets/icon_back_copy.svg | 96 ++++++++-- resources/public/css/style.css | 180 +++++++++++++----- src/cljs/token/wallet/page.cljs | 30 ++- src/cljs/token/wallets/page.cljs | 50 +++-- 4 files changed, 263 insertions(+), 93 deletions(-) diff --git a/resources/public/css/assets/icon_back_copy.svg b/resources/public/css/assets/icon_back_copy.svg index dbd5a94..571c2ee 100755 --- a/resources/public/css/assets/icon_back_copy.svg +++ b/resources/public/css/assets/icon_back_copy.svg @@ -1,17 +1,85 @@ - - - 3112D594-155C-47E1-89DA-2B9A18928723 - Created with sketchtool. - - - - - - - - - + + + + + image/svg+xml + + + + + + + 3112D594-155C-47E1-89DA-2B9A18928723 + Created with sketchtool. + + + + + + + + - \ No newline at end of file + + diff --git a/resources/public/css/style.css b/resources/public/css/style.css index d501b41..eac2142 100644 --- a/resources/public/css/style.css +++ b/resources/public/css/style.css @@ -15,7 +15,7 @@ body { font-size: 14px; font-family: 'Roboto', sans-serif; line-height: 1.6; - background-color: #eef2f5; + background-color: #fff; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; @@ -37,42 +37,65 @@ h2 { font-weight: 400; font-size: 32px; } - - +.slick-slider{ + margin-bottom: 0 !important; +} .top-nav { display: flex; align-items: center; - background-color: #eef2f5; vertical-align: middle; } .top-nav h2 { padding: 32px; flex: 1; - text-align: center; + text-align: left; + padding-left: 120px; + text-transform: uppercase; + color: #628fe3; + font-weight: 800; + letter-spacing: 4px; } .top-nav .nav-left { position: absolute; left: 32px; } - .top-nav .nav-left .nav-back { display: inline-block; width: 32px; height: 32px; padding: 16px; background: url(assets/icon_back_copy.svg) center center no-repeat; + background-color: #628fe3; + border-radius: 40px; +} +.top-nav .nav-left .nav-back-hp { + display: inline-block; + width: 32px; + height: 32px; + padding: 16px; + background-color: #628fe3; + border-radius: 40px; + text-align: center; + font-size: 30px; + font-weight: 800; + color: #fff; +} +.top-nav .nav-left .nav-back-hp span { + position: absolute; + top: 10px; + left: 19px; } - .top-nav .nav-right { position: absolute; right: 32px; } .top-nav .nav-right .nav-update { - display: inline-block; + /*display: inline-block;*/ + display: none; width: 32px; height: 32px; padding: 16px; @@ -84,23 +107,28 @@ h2 { /* Wallets */ .wallets { - background-color: #eef2f5; - text-align: center; - padding-top: 15vh; + margin-left: 25px; + margin-right: 25px; + margin-bottom: 20px; + position: relative; + background: #628fe3; + border-radius: 10px; } .wallets h2 { padding: 16px; } +.wallets a { + color: #fff; + text-decoration: none; +} + .wallets .wallet { - margin-top: 32px; - margin-bottom: 32px; - margin-left: 16px; - margin-right: 16px; + border-bottom: 2px solid #4669ad; + padding-bottom: 25px; position: relative; - background-color: #fff; - box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); + margin-left: 20px; } @@ -113,14 +141,17 @@ h2 { } .wallet-container { - background-color: #eef2f5; - padding: 16px; + background-color: #fff; + padding: 25px; + padding-top: 0px; } .wallet-container .wallet { position: relative; - background-color: #fff; - box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); + background-color: #628fe3; + border-radius: 15px; + padding: 10px; + color: #fff; } .wallet-image { @@ -134,13 +165,35 @@ h2 { } .wallet-name { - margin-left: 80px; - padding-top: 32px; - padding-left: 32px; + padding-top: 25px; text-align: left; - font-size: 32px; + font-size: 26px; +} +.manage-wallet{ + border-bottom: none !important; +} +.wallet-points { + position: absolute; + right: 20px; + top: 45px; +} +.wallet-points .point{ + background: #4669ad; + display: block; + width: 5px; + height: 5px; + border-radius: 5px; + float: left; + margin-right: 3px; +} +.btn-wallet { + margin-left: 0 !important; + border-top: 2px solid #4669ad !important; +} +.wallet-name span.cur { + margin-left: 10px; + color: #c0d2f3 !important; } - .wallet-hash { margin-left: 80px; padding-left: 32px; @@ -163,7 +216,6 @@ h2 { .wallet-address-container { background-color: #eef2f5; padding-top: 2px; - padding-bottom: 12px; } .wallet-address { @@ -195,8 +247,7 @@ h2 { } .wallet-transactions-container { - background-color: #eef2f5; - padding-top: 2px; + } .wallet-transactions { @@ -209,8 +260,8 @@ h2 { .wallet-transactions > span { display: block; - padding: 32px 0 0 32px; - font-weight: 500; + padding: 10px 0 0 20px; + font-weight: 400; margin-bottom: 12px; } @@ -220,10 +271,7 @@ h2 { } .wallet-currencies { - display: block; - margin-top: 60px; - width: 100%; - text-align: center; + text-align: right; } .wallet-btn:hover { @@ -242,14 +290,45 @@ h2 { .slick-slider .slick-dots li.slick-active button:before { opacity: 1; } - +.wallet-btn-left .wallet, +.wallet-btn-right .wallet { + border: none; +} +.wallet-btn-left, +.wallet-btn-right { + text-center; + width: 50%; + font-size: 25px; + background: #517bc9; +} +.wallet.btn-wallet { + border-bottom-right-radius: 10px; + background: #517bc9; + border-bottom-left-radius: 10px; +} +.cur{ + margin-left: 10px; +} +.wallet-btn-left{ + float: left; + border-right: 2px solid #4669ad; + position: relative; + z-index: 1111111; + border-bottom-left-radius: 10px; +} .currency-usd, .currency-rub { - display: inline-block; - width: 32%; - vertical-align: top; - font-size: 32px; + font-size: 25px; + position: absolute; + top: 25px; + right: 20px; +} +.wallet-href-name { + padding-top: 10px; + text-align: center; +} +.clearfix { + clear: both; } - span.currency { display: block; color: #838c93; @@ -327,10 +406,23 @@ span.currency { } .wallet-amount span { - float: right; - color: #939ba1; + padding-left: 10px; + color: #c0d2f3; + font-size: 20px; +} +.wallet-amount p.left-block { + flot:left +} +.wallet-amount span.pull-right { + text-align: right; + float:right; +} +.wallet-amount span.pull-right span { + color: #fff; +} +.wallet-amount p.right-block { + width:50%; } - .wallet-send { text-align: left; padding: 16px 16px 16px 16px; diff --git a/src/cljs/token/wallet/page.cljs b/src/cljs/token/wallet/page.cljs index 44fa0a9..e8421b9 100644 --- a/src/cljs/token/wallet/page.cljs +++ b/src/cljs/token/wallet/page.cljs @@ -11,7 +11,7 @@ (defn nav [wallet-id] [:div.top-nav - [:h2 "Main wallet"] + [:h2 "Wallet"] [:div.nav-left [:a.nav-back {:on-click @@ -45,17 +45,18 @@ #_(println (str "callback " (.stringify js/JSON params)))))) (defn wallet-info [wallet-id] - (let [balance (subscribe [:get-in (db/wallet-balance-path wallet-id)]) - send-amount (subscribe [:get :send-amount]) + (let [balance (subscribe [:get-in (db/wallet-balance-path wallet-id)]) + send-amount (subscribe [:get :send-amount]) request-amount (subscribe [:get :request-amount]) - text (subscribe [:get :text])] + text (subscribe [:get :text])] (fn [wallet-id] (let [balance-fmt (format-wei (unit->wei @balance "ether"))] [:div.wallet-container [:div.wallet [:div.wallet-amount - [:p (to-fixed (:amount balance-fmt) 6)] - [:span (:unit balance-fmt)]] + [:p.left-block "Main wallet"] + [:span (:unit balance-fmt)] + [:span.pull-right (to-fixed (:amount balance-fmt) 4) (:unit balance-fmt)]] [:div.wallet-send.row [:p.title "Send ETH"] [:div.amount-controls @@ -77,12 +78,6 @@ [:span {:on-click #(request-money @request-amount)} "RECEIVE"]]]]]])))) -(defn address [wallet-id] - [:div.wallet-address-container - [:div.wallet-address - [:span "Address"] - [:p wallet-id]]]) - (defn format-date [date-format date] (.format (goog.i18n.DateTimeFormat. date-format) (js/Date. date))) @@ -94,11 +89,11 @@ (let [{:keys [from to value timeStamp hash timestamp confirmations]} (js->clj tx :keywordize-keys true) {:keys [amount unit]} (format-wei value) - timestamp' (or timestamp (* 1000 timeStamp)) - incoming? (= to wallet-id) + timestamp' (or timestamp (* 1000 timeStamp)) + incoming? (= to wallet-id) action-class {:class (if incoming? "action-add" "action-remove")} amount-class {:class (if incoming? "green" "red")} - sign (if incoming? "+" "-")] + sign (if incoming? "+" "-")] ^{:key hash} [:div.transaction [:div.transaction-action [:div action-class]] @@ -112,11 +107,11 @@ (str sign amount " " unit)]]]])) (defn transactions [wallet-id] - (let [transactions (subscribe [:get-in (db/wallet-transactions-path wallet-id)]) + (let [transactions (subscribe [:get-in (db/wallet-transactions-path wallet-id)]) pending-transactions (subscribe [:pending-transactions wallet-id])] [:div.wallet-transactions-container [:div.wallet-transactions - [:span "Transactions"] + [:span "Transaction history"] (if (and (empty @pending-transactions) (empty? @transactions)) [:div.no-transactions "No transactions found"] (concat @@ -129,5 +124,4 @@ [:div.wallet-screen [nav wallet-id] [wallet-info wallet-id] - [address wallet-id] [transactions wallet-id]]) diff --git a/src/cljs/token/wallets/page.cljs b/src/cljs/token/wallets/page.cljs index 11ec6d1..06654ae 100644 --- a/src/cljs/token/wallets/page.cljs +++ b/src/cljs/token/wallets/page.cljs @@ -6,27 +6,30 @@ [re-frame.core :as re-frame] [token.db :as db])) -(defn wallet-uri [wallet-id] - [:a.wallet-btn {:href (str "#/wallet/" wallet-id)} "Open wallet"]) +(defn allTransactions [] + [:div.wallet-transactions-container + [:div.wallet-transactions + [:span "Transaction history"]]]) (defn wallet [wallet-id] - (let [balance (subscribe [:get-in (db/wallet-balance-path wallet-id)])] + (let [balance (subscribe [:get-in (db/wallet-balance-path wallet-id)])] (fn [wallet-id] (let [balance-fmt (format-wei (unit->wei @balance "ether"))] - [:div.wallet - [:div.wallet-image] - [:div.wallet-name "Main wallet"] - [:div.wallet-hash wallet-id] - [:div.wallet-currencies - [:div.currency-usd [:span.currency (:unit balance-fmt)] - (to-fixed (:amount balance-fmt) 6)]] - (wallet-uri wallet-id)])))) + [:a.wallet-btn {:href (str "#/wallet/" wallet-id)} + [:div.wallet + [:div.wallet-name "Main wallet" [:span.cur (:unit balance-fmt)]] + [:span.wallet-currencies + [:div.currency-usd + (to-fixed (:amount balance-fmt) 4) [:span.cur (:unit balance-fmt)]]] + ] [:div.clearfix]])))) (defn wallets [] (let [accounts (subscribe [:get-in db/wallet-accounts-path])] [:div [:div.top-nav - [:h2 {} "Wallets"] + [:h2 {} "Wallet"] + [:div.nav-left + [:a.nav-back-hp [:span "W"]]] [:div.nav-right [:a.nav-update {:on-click @@ -43,8 +46,21 @@ (doall (map (fn [id] ^{:key id} [:div [wallet id]]) - @accounts))]] - [:div.wallet-actions - [:a.trade-eth {:href "#"} "Trade ETH"] - [:a.create-wallet {:href "#"} - [:span.add-wallet] "Create a wallet"]]])) + @accounts))] + [:a.wallet-btn {:href (str "#/")} + [:div.wallet.manage-wallet + [:div.wallet-name "Manage wallets"] + [:span.wallet-points + [:div.point] [:div.point] [:div.point]] + ] [:div.clearfix]] + [:a.wallet-btn-left {:href (str "#/")} + [:div.wallet.btn-wallet + [:div.wallet-href-name "Recieve"] + ] [:div.clearfix]] + [:a.wallet-btn-right {:href (str "#/")} + [:div.wallet.btn-wallet + [:div.wallet-href-name "Send"] + ] [:div.clearfix]]] + [:div.wallet-transactions-container + [:div.wallet-transactions + [:span "Transaction History"]]]])) From 69b53f303e58f5b7aa8b88747bdedad7523f5d1e Mon Sep 17 00:00:00 2001 From: ajandera Date: Mon, 5 Jun 2017 19:54:37 +0200 Subject: [PATCH 2/8] Update New design part I after PR comments. --- resources/public/css/style.css | 65 ++++++++++++++++++--------------- src/cljs/token/wallet/page.cljs | 10 +++-- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/resources/public/css/style.css b/resources/public/css/style.css index eac2142..70365c0 100644 --- a/resources/public/css/style.css +++ b/resources/public/css/style.css @@ -45,8 +45,8 @@ h2 { display: flex; align-items: center; vertical-align: middle; + margin-left: 25px; } - .top-nav h2 { padding: 32px; flex: 1; @@ -60,33 +60,33 @@ h2 { .top-nav .nav-left { position: absolute; - left: 32px; + left: 25px; } .top-nav .nav-left .nav-back { display: inline-block; width: 32px; height: 32px; - padding: 16px; + padding: 12px; background: url(assets/icon_back_copy.svg) center center no-repeat; background-color: #628fe3; border-radius: 40px; } .top-nav .nav-left .nav-back-hp { display: inline-block; - width: 32px; - height: 32px; - padding: 16px; + width: 12px; + height: 12px; + padding: 12px; background-color: #628fe3; - border-radius: 40px; + border-radius: 45px; text-align: center; - font-size: 30px; + font-size: 19px; font-weight: 800; color: #fff; } .top-nav .nav-left .nav-back-hp span { position: absolute; - top: 10px; - left: 19px; + top: 5px; + left: 10px; } .top-nav .nav-right { position: absolute; @@ -126,9 +126,9 @@ h2 { .wallets .wallet { border-bottom: 2px solid #4669ad; - padding-bottom: 25px; + padding-bottom: 20px; position: relative; - margin-left: 20px; + margin-left: 15px; } @@ -149,7 +149,7 @@ h2 { .wallet-container .wallet { position: relative; background-color: #628fe3; - border-radius: 15px; + border-radius: 10px; padding: 10px; color: #fff; } @@ -165,9 +165,8 @@ h2 { } .wallet-name { - padding-top: 25px; + padding-top: 20px; text-align: left; - font-size: 26px; } .manage-wallet{ border-bottom: none !important; @@ -175,7 +174,7 @@ h2 { .wallet-points { position: absolute; right: 20px; - top: 45px; + top: 31px; } .wallet-points .point{ background: #4669ad; @@ -305,6 +304,7 @@ h2 { border-bottom-right-radius: 10px; background: #517bc9; border-bottom-left-radius: 10px; + padding-bottom: 10px; } .cur{ margin-left: 10px; @@ -319,7 +319,7 @@ h2 { .currency-usd, .currency-rub { font-size: 25px; position: absolute; - top: 25px; + top: 20px; right: 20px; } .wallet-href-name { @@ -399,24 +399,31 @@ span.currency { .wallet-amount p { padding: 0px; margin: 0px; - display: inline-block; - font-size: 21px; + display: block; + font-size: 15px; -webkit-touch-callout: none; -webkit-user-select: auto; } .wallet-amount span { - padding-left: 10px; - color: #c0d2f3; + color: #fff; font-size: 20px; } -.wallet-amount p.left-block { - flot:left +.unitDetail { + margin-left: 5px; } .wallet-amount span.pull-right { text-align: right; float:right; } +.left-block span { + font-size: 12px; +} +.address-detail { + margin-top: 20px; + font-size: 12px; + color: #c0d2f3; +} .wallet-amount span.pull-right span { color: #fff; } @@ -813,7 +820,6 @@ input:focus{ .wallet-name { font-size: 16px; - margin-left: 20px; } .wallet-hash { @@ -874,8 +880,8 @@ input:focus{ } .wallet-amount { - font-size: 24px; - padding: 16px; + font-size: 12px; + padding: 10px; } .wallet-controls .button { @@ -944,13 +950,12 @@ input:focus{ .top-nav h2 { padding: 16px; + margin-left: 35px; } - .top-nav .nav-left { - left: 6px; - top: 6px; + .top-nav .nav-left{ + height: 40px; } - .top-nav .nav-left .nav-back { width: 12px; height: 12px; diff --git a/src/cljs/token/wallet/page.cljs b/src/cljs/token/wallet/page.cljs index e8421b9..e9bd295 100644 --- a/src/cljs/token/wallet/page.cljs +++ b/src/cljs/token/wallet/page.cljs @@ -54,9 +54,13 @@ [:div.wallet-container [:div.wallet [:div.wallet-amount - [:p.left-block "Main wallet"] - [:span (:unit balance-fmt)] - [:span.pull-right (to-fixed (:amount balance-fmt) 4) (:unit balance-fmt)]] + [:div.left-block "Main wallet" + [:span.wallet-points + [:span.point] [:span.point] [:span.point]] + ] + [:p (to-fixed (:amount balance-fmt) 2) [:span.unitDetail (:unit balance-fmt)]] + [:p.address-detail "Address"] + ] [:div.wallet-send.row [:p.title "Send ETH"] [:div.amount-controls From 6e1b035db123ee5b1107c7ef773f749f5b25626b Mon Sep 17 00:00:00 2001 From: ajandera Date: Mon, 5 Jun 2017 21:06:38 +0200 Subject: [PATCH 3/8] Update wallet detail page for PR. --- resources/public/css/style.css | 52 +++++++++++++++++++++++++------- src/cljs/token/wallet/page.cljs | 41 ++++++++++--------------- src/cljs/token/wallets/page.cljs | 5 ++- 3 files changed, 59 insertions(+), 39 deletions(-) diff --git a/resources/public/css/style.css b/resources/public/css/style.css index 70365c0..57647b4 100644 --- a/resources/public/css/style.css +++ b/resources/public/css/style.css @@ -38,7 +38,7 @@ h2 { font-size: 32px; } .slick-slider{ - margin-bottom: 0 !important; + margin-bottom: 0; } .top-nav { @@ -150,7 +150,7 @@ h2 { position: relative; background-color: #628fe3; border-radius: 10px; - padding: 10px; + padding: 0; color: #fff; } @@ -171,20 +171,21 @@ h2 { .manage-wallet{ border-bottom: none !important; } + .wallet-points { position: absolute; right: 20px; - top: 31px; + top: -16px; + color: #4669ad; + font-size: 3em; } -.wallet-points .point{ - background: #4669ad; - display: block; - width: 5px; - height: 5px; - border-radius: 5px; - float: left; - margin-right: 3px; + +.wallet-points.detail{ + top: -25px; + color: #4669ad; + font-size: 3em; } + .btn-wallet { margin-left: 0 !important; border-top: 2px solid #4669ad !important; @@ -409,27 +410,56 @@ span.currency { color: #fff; font-size: 20px; } + .unitDetail { margin-left: 5px; } + .wallet-amount span.pull-right { text-align: right; float:right; } + .left-block span { font-size: 12px; } + .address-detail { margin-top: 20px; font-size: 12px; color: #c0d2f3; } + +.wallets-detail a { + margin: 0; +} +.wallets-detail .wallet-btn-right { + position: absolute; + right: 0; + padding: 0; + border-bottom-right-radius: 10px; +} +.wallets-detail .wallet-btn-left { + padding: 0; +} +.wallets-detail .wallet.btn-wallet { + border: none; +} +.wallets-detail .wallet-href-name { + padding-bottom: 10px; + color: #fff; +} +.wallet-amount.detail { + border-bottom: none; +} .wallet-amount span.pull-right span { color: #fff; } + .wallet-amount p.right-block { width:50%; } + .wallet-send { text-align: left; padding: 16px 16px 16px 16px; diff --git a/src/cljs/token/wallet/page.cljs b/src/cljs/token/wallet/page.cljs index e9bd295..a1675f0 100644 --- a/src/cljs/token/wallet/page.cljs +++ b/src/cljs/token/wallet/page.cljs @@ -48,39 +48,30 @@ (let [balance (subscribe [:get-in (db/wallet-balance-path wallet-id)]) send-amount (subscribe [:get :send-amount]) request-amount (subscribe [:get :request-amount]) - text (subscribe [:get :text])] + text (subscribe [:get :text])] (fn [wallet-id] (let [balance-fmt (format-wei (unit->wei @balance "ether"))] [:div.wallet-container [:div.wallet - [:div.wallet-amount + [:div.wallet-amount.detail [:div.left-block "Main wallet" - [:span.wallet-points - [:span.point] [:span.point] [:span.point]] + [:span.wallet-points.detail "..."] ] [:p (to-fixed (:amount balance-fmt) 2) [:span.unitDetail (:unit balance-fmt)]] - [:p.address-detail "Address"] + [:div.address-detail "Address"] + [:p wallet-id] ] - [:div.wallet-send.row - [:p.title "Send ETH"] - [:div.amount-controls - [:input.amount {:placeholder "Enter amount" - :value @send-amount - :on-change #(dispatch [:set :send-amount (u/value %)]) - :type :number}] - [:div.column - [:span {:on-click (when (pos? (js/parseFloat @balance)) - #(send-money @send-amount))} "SEND"]]]] - [:div.wallet-request.row - [:p.title "Request ETH"] - [:div.amount-controls - [:input.amount {:placeholder "Enter amount" - :value @request-amount - :on-change #(dispatch [:set :request-amount (u/value %)]) - :type :number}] - [:div.column - [:span {:on-click #(request-money @request-amount)} - "RECEIVE"]]]]]])))) + [:div.wallets-detail + [:a.wallet-btn-left {:href (str "#/")} + [:div.btn-wallet + [:div.wallet-href-name "Copy Address"] + ] [:div.clearfix]] + [:a.wallet-btn-right {:href (str "#/")} + [:div.btn-wallet + [:div.wallet-href-name "Show CR"] + ] [:div.clearfix]] + [:div.clearfix] + ]]])))) (defn format-date [date-format date] (.format (goog.i18n.DateTimeFormat. date-format) diff --git a/src/cljs/token/wallets/page.cljs b/src/cljs/token/wallets/page.cljs index 06654ae..976421f 100644 --- a/src/cljs/token/wallets/page.cljs +++ b/src/cljs/token/wallets/page.cljs @@ -6,7 +6,7 @@ [re-frame.core :as re-frame] [token.db :as db])) -(defn allTransactions [] +(defn all-transactions [] [:div.wallet-transactions-container [:div.wallet-transactions [:span "Transaction history"]]]) @@ -50,8 +50,7 @@ [:a.wallet-btn {:href (str "#/")} [:div.wallet.manage-wallet [:div.wallet-name "Manage wallets"] - [:span.wallet-points - [:div.point] [:div.point] [:div.point]] + [:span.wallet-points "..."] ] [:div.clearfix]] [:a.wallet-btn-left {:href (str "#/")} [:div.wallet.btn-wallet From 57e078c1f664671a525bbfcedabfa3f2bdf2b8eb Mon Sep 17 00:00:00 2001 From: ajandera Date: Tue, 13 Jun 2017 16:05:42 +0200 Subject: [PATCH 4/8] Add to clipboard button. --- resources/public/css/style.css | 34 +++++++++++++++++++----- src/cljs/token/components/clipboard.cljs | 3 +-- src/cljs/token/wallet/page.cljs | 4 +-- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/resources/public/css/style.css b/resources/public/css/style.css index 57647b4..b3bfba2 100644 --- a/resources/public/css/style.css +++ b/resources/public/css/style.css @@ -37,6 +37,7 @@ h2 { font-weight: 400; font-size: 32px; } + .slick-slider{ margin-bottom: 0; } @@ -47,6 +48,7 @@ h2 { vertical-align: middle; margin-left: 25px; } + .top-nav h2 { padding: 32px; flex: 1; @@ -62,6 +64,7 @@ h2 { position: absolute; left: 25px; } + .top-nav .nav-left .nav-back { display: inline-block; width: 32px; @@ -71,6 +74,7 @@ h2 { background-color: #628fe3; border-radius: 40px; } + .top-nav .nav-left .nav-back-hp { display: inline-block; width: 12px; @@ -83,11 +87,13 @@ h2 { font-weight: 800; color: #fff; } + .top-nav .nav-left .nav-back-hp span { position: absolute; top: 5px; left: 10px; } + .top-nav .nav-right { position: absolute; right: 32px; @@ -103,7 +109,6 @@ h2 { background: url(assets/icon_update.svg) center center no-repeat; } - /* Wallets */ .wallets { @@ -131,7 +136,6 @@ h2 { margin-left: 15px; } - /* Wallet screen */ .wallet-screen { @@ -168,6 +172,7 @@ h2 { padding-top: 20px; text-align: left; } + .manage-wallet{ border-bottom: none !important; } @@ -190,10 +195,12 @@ h2 { margin-left: 0 !important; border-top: 2px solid #4669ad !important; } + .wallet-name span.cur { margin-left: 10px; color: #c0d2f3 !important; } + .wallet-hash { margin-left: 80px; padding-left: 32px; @@ -290,10 +297,12 @@ h2 { .slick-slider .slick-dots li.slick-active button:before { opacity: 1; } + .wallet-btn-left .wallet, .wallet-btn-right .wallet { border: none; } + .wallet-btn-left, .wallet-btn-right { text-center; @@ -301,15 +310,18 @@ h2 { font-size: 25px; background: #517bc9; } + .wallet.btn-wallet { border-bottom-right-radius: 10px; background: #517bc9; border-bottom-left-radius: 10px; padding-bottom: 10px; } + .cur{ margin-left: 10px; } + .wallet-btn-left{ float: left; border-right: 2px solid #4669ad; @@ -317,19 +329,22 @@ h2 { z-index: 1111111; border-bottom-left-radius: 10px; } + .currency-usd, .currency-rub { font-size: 25px; position: absolute; top: 20px; right: 20px; } -.wallet-href-name { - padding-top: 10px; - text-align: center; + +.button-clipboard { + padding-bottom: 1px; } + .clearfix { clear: both; } + span.currency { display: block; color: #838c93; @@ -433,25 +448,32 @@ span.currency { .wallets-detail a { margin: 0; } + .wallets-detail .wallet-btn-right { position: absolute; right: 0; padding: 0; border-bottom-right-radius: 10px; } + .wallets-detail .wallet-btn-left { padding: 0; } + .wallets-detail .wallet.btn-wallet { border: none; } + .wallets-detail .wallet-href-name { padding-bottom: 10px; color: #fff; + padding-top: 10px; } + .wallet-amount.detail { border-bottom: none; } + .wallet-amount span.pull-right span { color: #fff; } @@ -513,8 +535,6 @@ input.amount { border: 0px; } - - .button-copy { display: inline-block; margin-right: 10px; diff --git a/src/cljs/token/components/clipboard.cljs b/src/cljs/token/components/clipboard.cljs index 6bfe093..0f6cd8d 100644 --- a/src/cljs/token/components/clipboard.cljs +++ b/src/cljs/token/components/clipboard.cljs @@ -16,5 +16,4 @@ (reset! clipboard-atom nil)) :reagent-render (fn [] - [:div.button {:data-clipboard-text text} - [:span.button-copy] label])}))) + [:div.button.button-clipboard {:data-clipboard-text text} label])}))) \ No newline at end of file diff --git a/src/cljs/token/wallet/page.cljs b/src/cljs/token/wallet/page.cljs index a1675f0..c401255 100644 --- a/src/cljs/token/wallet/page.cljs +++ b/src/cljs/token/wallet/page.cljs @@ -62,9 +62,9 @@ [:p wallet-id] ] [:div.wallets-detail - [:a.wallet-btn-left {:href (str "#/")} + [:div.wallet-btn-left [:div.btn-wallet - [:div.wallet-href-name "Copy Address"] + [:div.wallet-href-name [clipboard-button "Copy Address" wallet-id]] ] [:div.clearfix]] [:a.wallet-btn-right {:href (str "#/")} [:div.btn-wallet From a45a553f02a80ccc3442e28203f57eada5757b46 Mon Sep 17 00:00:00 2001 From: ajandera Date: Tue, 13 Jun 2017 17:33:17 +0200 Subject: [PATCH 5/8] Fix buttons align. --- resources/public/css/style.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/public/css/style.css b/resources/public/css/style.css index b3bfba2..493e11b 100644 --- a/resources/public/css/style.css +++ b/resources/public/css/style.css @@ -315,7 +315,7 @@ h2 { border-bottom-right-radius: 10px; background: #517bc9; border-bottom-left-radius: 10px; - padding-bottom: 10px; + padding-bottom: 0px; } .cur{ @@ -464,10 +464,11 @@ span.currency { border: none; } -.wallets-detail .wallet-href-name { +.wallet-href-name { padding-bottom: 10px; color: #fff; padding-top: 10px; + text-align: center; } .wallet-amount.detail { From 9d7e822580ddc63444bbace4dac5ee4ee103ccfd Mon Sep 17 00:00:00 2001 From: Tomas tomby Bily Date: Fri, 16 Jun 2017 16:11:17 +0200 Subject: [PATCH 6/8] show qr code of wallet address --- project.clj | 12 +- resources/js/qrcode.js | 614 ++++++++++++++++++++++++++++++ resources/js/qrcode.min.js | 1 + resources/public/css/style.css | 10 + src/cljs/token/components/qr.cljs | 28 ++ src/cljs/token/wallet/page.cljs | 21 +- 6 files changed, 673 insertions(+), 13 deletions(-) create mode 100644 resources/js/qrcode.js create mode 100644 resources/js/qrcode.min.js create mode 100644 src/cljs/token/components/qr.cljs diff --git a/project.clj b/project.clj index ccd297c..a2f42d0 100644 --- a/project.clj +++ b/project.clj @@ -41,7 +41,9 @@ :output-dir "resources/public/js/compiled/out" :asset-path "js/compiled/out" :foreign-libs [{:file "resources/js/react-slick.js" - :provides ["react-slick"]}] + :provides ["react-slick"]} + {:file "resources/js/qrcode.js" + :provides ["qrcode"]}] :source-map-timestamp true}} {:id "min" @@ -51,13 +53,17 @@ :optimizations :advanced :closure-defines {goog.DEBUG false} :foreign-libs [{:file "resources/js/react-slick.min.js" - :provides ["react-slick"]}] + :provides ["react-slick"]} + {:file "resources/js/qrcode.min.js" + :provides ["qrcode"]}] :pretty-print false :externs ["resources/externals/status.ext.js"]}} {:id "test" :source-paths ["src/cljs" "test/cljs"] :compiler {:output-to "resources/public/js/compiled/test.js" :foreign-libs [{:file "resources/js/react-slick.js" - :provides ["react-slick"]}] + :provides ["react-slick"]} + {:file "resources/js/qrcode.js" + :provides ["qrcode"]}] :main token.runner :optimizations :none}}]}) diff --git a/resources/js/qrcode.js b/resources/js/qrcode.js new file mode 100644 index 0000000..5507c15 --- /dev/null +++ b/resources/js/qrcode.js @@ -0,0 +1,614 @@ +/** + * @fileoverview + * - Using the 'QRCode for Javascript library' + * - Fixed dataset of 'QRCode for Javascript library' for support full-spec. + * - this library has no dependencies. + * + * @author davidshimjs + * @see http://www.d-project.com/ + * @see http://jeromeetienne.github.com/jquery-qrcode/ + */ +var QRCode; + +(function () { + //--------------------------------------------------------------------- + // QRCode for JavaScript + // + // Copyright (c) 2009 Kazuhiko Arase + // + // URL: http://www.d-project.com/ + // + // Licensed under the MIT license: + // http://www.opensource.org/licenses/mit-license.php + // + // The word "QR Code" is registered trademark of + // DENSO WAVE INCORPORATED + // http://www.denso-wave.com/qrcode/faqpatent-e.html + // + //--------------------------------------------------------------------- + function QR8bitByte(data) { + this.mode = QRMode.MODE_8BIT_BYTE; + this.data = data; + this.parsedData = []; + + // Added to support UTF-8 Characters + for (var i = 0, l = this.data.length; i < l; i++) { + var byteArray = []; + var code = this.data.charCodeAt(i); + + if (code > 0x10000) { + byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18); + byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12); + byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6); + byteArray[3] = 0x80 | (code & 0x3F); + } else if (code > 0x800) { + byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12); + byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6); + byteArray[2] = 0x80 | (code & 0x3F); + } else if (code > 0x80) { + byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6); + byteArray[1] = 0x80 | (code & 0x3F); + } else { + byteArray[0] = code; + } + + this.parsedData.push(byteArray); + } + + this.parsedData = Array.prototype.concat.apply([], this.parsedData); + + if (this.parsedData.length != this.data.length) { + this.parsedData.unshift(191); + this.parsedData.unshift(187); + this.parsedData.unshift(239); + } + } + + QR8bitByte.prototype = { + getLength: function (buffer) { + return this.parsedData.length; + }, + write: function (buffer) { + for (var i = 0, l = this.parsedData.length; i < l; i++) { + buffer.put(this.parsedData[i], 8); + } + } + }; + + function QRCodeModel(typeNumber, errorCorrectLevel) { + this.typeNumber = typeNumber; + this.errorCorrectLevel = errorCorrectLevel; + this.modules = null; + this.moduleCount = 0; + this.dataCache = null; + this.dataList = []; + } + + QRCodeModel.prototype={addData:function(data){var newData=new QR8bitByte(data);this.dataList.push(newData);this.dataCache=null;},isDark:function(row,col){if(row<0||this.moduleCount<=row||col<0||this.moduleCount<=col){throw new Error(row+","+col);} + return this.modules[row][col];},getModuleCount:function(){return this.moduleCount;},make:function(){this.makeImpl(false,this.getBestMaskPattern());},makeImpl:function(test,maskPattern){this.moduleCount=this.typeNumber*4+17;this.modules=new Array(this.moduleCount);for(var row=0;row=7){this.setupTypeNumber(test);} + if(this.dataCache==null){this.dataCache=QRCodeModel.createData(this.typeNumber,this.errorCorrectLevel,this.dataList);} + this.mapData(this.dataCache,maskPattern);},setupPositionProbePattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.moduleCount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getBestMaskPattern:function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}} + return pattern;},createMovieClip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createEmptyMovieClip(instance_name,depth);var cs=1;this.make();for(var row=0;row>i)&1)==1);this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;} + for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;}},setupTypeInfo:function(test,maskPattern){var data=(this.errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.moduleCount-15+i][8]=mod;}} + for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.moduleCount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}} + this.modules[this.moduleCount-8][8]=(!test);},mapData:function(data,maskPattern){var inc=-1;var row=this.moduleCount-1;var bitIndex=7;var byteIndex=0;for(var col=this.moduleCount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteIndex>>bitIndex)&1)==1);} + var mask=QRUtil.getMask(maskPattern,row,col-c);if(mask){dark=!dark;} + this.modules[row][col-c]=dark;bitIndex--;if(bitIndex==-1){byteIndex++;bitIndex=7;}}} + row+=inc;if(row<0||this.moduleCount<=row){row-=inc;inc=-inc;break;}}}}};QRCodeModel.PAD0=0xEC;QRCodeModel.PAD1=0x11;QRCodeModel.createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=new QRBitBuffer();for(var i=0;itotalDataCount*8){throw new Error("code length overflow. (" + +buffer.getLengthInBits() + +">" + +totalDataCount*8 + +")");} + if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);} + while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);} + while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;} + buffer.put(QRCodeModel.PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;} + buffer.put(QRCodeModel.PAD1,8);} + return QRCodeModel.createBytes(buffer,rsBlocks);};QRCodeModel.createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r=0)?modPoly.get(modIndex):0;}} + var totalCodeCount=0;for(var i=0;i=0){d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));} + return((data<<10)|d)^QRUtil.G15_MASK;},getBCHTypeNumber:function(data){var d=data<<12;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));} + return(data<<12)|d;},getBCHDigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;} + return digit;},getPatternPosition:function(typeNumber){return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];},getMask:function(maskPattern,i,j){switch(maskPattern){case QRMaskPattern.PATTERN000:return(i+j)%2==0;case QRMaskPattern.PATTERN001:return i%2==0;case QRMaskPattern.PATTERN010:return j%3==0;case QRMaskPattern.PATTERN011:return(i+j)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(i/2)+Math.floor(j/3))%2==0;case QRMaskPattern.PATTERN101:return(i*j)%2+(i*j)%3==0;case QRMaskPattern.PATTERN110:return((i*j)%2+(i*j)%3)%2==0;case QRMaskPattern.PATTERN111:return((i*j)%3+(i+j)%2)%2==0;default:throw new Error("bad maskPattern:"+maskPattern);}},getErrorCorrectPolynomial:function(errorCorrectLength){var a=new QRPolynomial([1],0);for(var i=0;i5){lostPoint+=(3+sameCount-5);}}} + for(var row=0;row=256){n-=255;} + return QRMath.EXP_TABLE[n];},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)};for(var i=0;i<8;i++){QRMath.EXP_TABLE[i]=1<>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i>>(length-i-1))&1)==1);}},getLengthInBits:function(){return this.length;},putBit:function(bit){var bufIndex=Math.floor(this.length/8);if(this.buffer.length<=bufIndex){this.buffer.push(0);} + if(bit){this.buffer[bufIndex]|=(0x80>>>(this.length%8));} + this.length++;}};var QRCodeLimitLength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]]; + + function _isSupportCanvas() { + return typeof CanvasRenderingContext2D != "undefined"; + } + + // android 2.x doesn't support Data-URI spec + function _getAndroid() { + var android = false; + var sAgent = navigator.userAgent; + + if (/android/i.test(sAgent)) { // android + android = true; + var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i); + + if (aMat && aMat[1]) { + android = parseFloat(aMat[1]); + } + } + + return android; + } + + var svgDrawer = (function() { + + var Drawing = function (el, htOption) { + this._el = el; + this._htOption = htOption; + }; + + Drawing.prototype.draw = function (oQRCode) { + var _htOption = this._htOption; + var _el = this._el; + var nCount = oQRCode.getModuleCount(); + var nWidth = Math.floor(_htOption.width / nCount); + var nHeight = Math.floor(_htOption.height / nCount); + + this.clear(); + + function makeSVG(tag, attrs) { + var el = document.createElementNS('http://www.w3.org/2000/svg', tag); + for (var k in attrs) + if (attrs.hasOwnProperty(k)) el.setAttribute(k, attrs[k]); + return el; + } + + var svg = makeSVG("svg" , {'viewBox': '0 0 ' + String(nCount) + " " + String(nCount), 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight}); + svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); + _el.appendChild(svg); + + svg.appendChild(makeSVG("rect", {"fill": _htOption.colorLight, "width": "100%", "height": "100%"})); + svg.appendChild(makeSVG("rect", {"fill": _htOption.colorDark, "width": "1", "height": "1", "id": "template"})); + + for (var row = 0; row < nCount; row++) { + for (var col = 0; col < nCount; col++) { + if (oQRCode.isDark(row, col)) { + var child = makeSVG("use", {"x": String(col), "y": String(row)}); + child.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template") + svg.appendChild(child); + } + } + } + }; + Drawing.prototype.clear = function () { + while (this._el.hasChildNodes()) + this._el.removeChild(this._el.lastChild); + }; + return Drawing; + })(); + + var useSVG = document.documentElement.tagName.toLowerCase() === "svg"; + + // Drawing in DOM by using Table tag + var Drawing = useSVG ? svgDrawer : !_isSupportCanvas() ? (function () { + var Drawing = function (el, htOption) { + this._el = el; + this._htOption = htOption; + }; + + /** + * Draw the QRCode + * + * @param {QRCode} oQRCode + */ + Drawing.prototype.draw = function (oQRCode) { + var _htOption = this._htOption; + var _el = this._el; + var nCount = oQRCode.getModuleCount(); + var nWidth = Math.floor(_htOption.width / nCount); + var nHeight = Math.floor(_htOption.height / nCount); + var aHTML = ['']; + + for (var row = 0; row < nCount; row++) { + aHTML.push(''); + + for (var col = 0; col < nCount; col++) { + aHTML.push(''); + } + + aHTML.push(''); + } + + aHTML.push('
'); + _el.innerHTML = aHTML.join(''); + + // Fix the margin values as real size. + var elTable = _el.childNodes[0]; + var nLeftMarginTable = (_htOption.width - elTable.offsetWidth) / 2; + var nTopMarginTable = (_htOption.height - elTable.offsetHeight) / 2; + + if (nLeftMarginTable > 0 && nTopMarginTable > 0) { + elTable.style.margin = nTopMarginTable + "px " + nLeftMarginTable + "px"; + } + }; + + /** + * Clear the QRCode + */ + Drawing.prototype.clear = function () { + this._el.innerHTML = ''; + }; + + return Drawing; + })() : (function () { // Drawing in Canvas + function _onMakeImage() { + this._elImage.src = this._elCanvas.toDataURL("image/png"); + this._elImage.style.display = "block"; + this._elCanvas.style.display = "none"; + } + + // Android 2.1 bug workaround + // http://code.google.com/p/android/issues/detail?id=5141 + if (this._android && this._android <= 2.1) { + var factor = 1 / window.devicePixelRatio; + var drawImage = CanvasRenderingContext2D.prototype.drawImage; + CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) { + if (("nodeName" in image) && /img/i.test(image.nodeName)) { + for (var i = arguments.length - 1; i >= 1; i--) { + arguments[i] = arguments[i] * factor; + } + } else if (typeof dw == "undefined") { + arguments[1] *= factor; + arguments[2] *= factor; + arguments[3] *= factor; + arguments[4] *= factor; + } + + drawImage.apply(this, arguments); + }; + } + + /** + * Check whether the user's browser supports Data URI or not + * + * @private + * @param {Function} fSuccess Occurs if it supports Data URI + * @param {Function} fFail Occurs if it doesn't support Data URI + */ + function _safeSetDataURI(fSuccess, fFail) { + var self = this; + self._fFail = fFail; + self._fSuccess = fSuccess; + + // Check it just once + if (self._bSupportDataURI === null) { + var el = document.createElement("img"); + var fOnError = function() { + self._bSupportDataURI = false; + + if (self._fFail) { + self._fFail.call(self); + } + }; + var fOnSuccess = function() { + self._bSupportDataURI = true; + + if (self._fSuccess) { + self._fSuccess.call(self); + } + }; + + el.onabort = fOnError; + el.onerror = fOnError; + el.onload = fOnSuccess; + el.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; // the Image contains 1px data. + return; + } else if (self._bSupportDataURI === true && self._fSuccess) { + self._fSuccess.call(self); + } else if (self._bSupportDataURI === false && self._fFail) { + self._fFail.call(self); + } + }; + + /** + * Drawing QRCode by using canvas + * + * @constructor + * @param {HTMLElement} el + * @param {Object} htOption QRCode Options + */ + var Drawing = function (el, htOption) { + this._bIsPainted = false; + this._android = _getAndroid(); + + this._htOption = htOption; + this._elCanvas = document.createElement("canvas"); + this._elCanvas.width = htOption.width; + this._elCanvas.height = htOption.height; + el.appendChild(this._elCanvas); + this._el = el; + this._oContext = this._elCanvas.getContext("2d"); + this._bIsPainted = false; + this._elImage = document.createElement("img"); + this._elImage.alt = "Scan me!"; + this._elImage.style.display = "none"; + this._el.appendChild(this._elImage); + this._bSupportDataURI = null; + }; + + /** + * Draw the QRCode + * + * @param {QRCode} oQRCode + */ + Drawing.prototype.draw = function (oQRCode) { + var _elImage = this._elImage; + var _oContext = this._oContext; + var _htOption = this._htOption; + + var nCount = oQRCode.getModuleCount(); + var nWidth = _htOption.width / nCount; + var nHeight = _htOption.height / nCount; + var nRoundedWidth = Math.round(nWidth); + var nRoundedHeight = Math.round(nHeight); + + _elImage.style.display = "none"; + this.clear(); + + for (var row = 0; row < nCount; row++) { + for (var col = 0; col < nCount; col++) { + var bIsDark = oQRCode.isDark(row, col); + var nLeft = col * nWidth; + var nTop = row * nHeight; + _oContext.strokeStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight; + _oContext.lineWidth = 1; + _oContext.fillStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight; + _oContext.fillRect(nLeft, nTop, nWidth, nHeight); + + // 안티 앨리어싱 방지 처리 + _oContext.strokeRect( + Math.floor(nLeft) + 0.5, + Math.floor(nTop) + 0.5, + nRoundedWidth, + nRoundedHeight + ); + + _oContext.strokeRect( + Math.ceil(nLeft) - 0.5, + Math.ceil(nTop) - 0.5, + nRoundedWidth, + nRoundedHeight + ); + } + } + + this._bIsPainted = true; + }; + + /** + * Make the image from Canvas if the browser supports Data URI. + */ + Drawing.prototype.makeImage = function () { + if (this._bIsPainted) { + _safeSetDataURI.call(this, _onMakeImage); + } + }; + + /** + * Return whether the QRCode is painted or not + * + * @return {Boolean} + */ + Drawing.prototype.isPainted = function () { + return this._bIsPainted; + }; + + /** + * Clear the QRCode + */ + Drawing.prototype.clear = function () { + this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height); + this._bIsPainted = false; + }; + + /** + * @private + * @param {Number} nNumber + */ + Drawing.prototype.round = function (nNumber) { + if (!nNumber) { + return nNumber; + } + + return Math.floor(nNumber * 1000) / 1000; + }; + + return Drawing; + })(); + + /** + * Get the type by string length + * + * @private + * @param {String} sText + * @param {Number} nCorrectLevel + * @return {Number} type + */ + function _getTypeNumber(sText, nCorrectLevel) { + var nType = 1; + var length = _getUTF8Length(sText); + + for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) { + var nLimit = 0; + + switch (nCorrectLevel) { + case QRErrorCorrectLevel.L : + nLimit = QRCodeLimitLength[i][0]; + break; + case QRErrorCorrectLevel.M : + nLimit = QRCodeLimitLength[i][1]; + break; + case QRErrorCorrectLevel.Q : + nLimit = QRCodeLimitLength[i][2]; + break; + case QRErrorCorrectLevel.H : + nLimit = QRCodeLimitLength[i][3]; + break; + } + + if (length <= nLimit) { + break; + } else { + nType++; + } + } + + if (nType > QRCodeLimitLength.length) { + throw new Error("Too long data"); + } + + return nType; + } + + function _getUTF8Length(sText) { + var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a'); + return replacedText.length + (replacedText.length != sText ? 3 : 0); + } + + /** + * @class QRCode + * @constructor + * @example + * new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie"); + * + * @example + * var oQRCode = new QRCode("test", { + * text : "http://naver.com", + * width : 128, + * height : 128 + * }); + * + * oQRCode.clear(); // Clear the QRCode. + * oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode. + * + * @param {HTMLElement|String} el target element or 'id' attribute of element. + * @param {Object|String} vOption + * @param {String} vOption.text QRCode link data + * @param {Number} [vOption.width=256] + * @param {Number} [vOption.height=256] + * @param {String} [vOption.colorDark="#000000"] + * @param {String} [vOption.colorLight="#ffffff"] + * @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H] + */ + QRCode = function (el, vOption) { + this._htOption = { + width : 256, + height : 256, + typeNumber : 4, + colorDark : "#000000", + colorLight : "#ffffff", + correctLevel : QRErrorCorrectLevel.H + }; + + if (typeof vOption === 'string') { + vOption = { + text : vOption + }; + } + + // Overwrites options + if (vOption) { + for (var i in vOption) { + this._htOption[i] = vOption[i]; + } + } + + if (typeof el == "string") { + el = document.getElementById(el); + } + + if (this._htOption.useSVG) { + Drawing = svgDrawer; + } + + this._android = _getAndroid(); + this._el = el; + this._oQRCode = null; + this._oDrawing = new Drawing(this._el, this._htOption); + + if (this._htOption.text) { + this.makeCode(this._htOption.text); + } + }; + + /** + * Make the QRCode + * + * @param {String} sText link data + */ + QRCode.prototype.makeCode = function (sText) { + this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel); + this._oQRCode.addData(sText); + this._oQRCode.make(); + this._el.title = sText; + this._oDrawing.draw(this._oQRCode); + this.makeImage(); + }; + + /** + * Make the Image from Canvas element + * - It occurs automatically + * - Android below 3 doesn't support Data-URI spec. + * + * @private + */ + QRCode.prototype.makeImage = function () { + if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) { + this._oDrawing.makeImage(); + } + }; + + /** + * Clear the QRCode + */ + QRCode.prototype.clear = function () { + this._oDrawing.clear(); + }; + + /** + * @name QRCode.CorrectLevel + */ + QRCode.CorrectLevel = QRErrorCorrectLevel; +})(); diff --git a/resources/js/qrcode.min.js b/resources/js/qrcode.min.js new file mode 100644 index 0000000..993e88f --- /dev/null +++ b/resources/js/qrcode.min.js @@ -0,0 +1 @@ +var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j=0?p.get(q):0}}for(var r=0,m=0;mm;m++)for(var j=0;jm;m++)for(var j=0;j=0;)b^=f.G15<=0;)b^=f.G18<>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;cf;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=[''],h=0;d>h;h++){g.push("");for(var i=0;d>i;i++)g.push('');g.push("")}g.push("
"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); \ No newline at end of file diff --git a/resources/public/css/style.css b/resources/public/css/style.css index 493e11b..bf73374 100644 --- a/resources/public/css/style.css +++ b/resources/public/css/style.css @@ -802,6 +802,16 @@ input:focus{ vertical-align: top; } +.qr-popup { + width: 100%; + height: 100%; + position: fixed; + top: 0px; + left: 0px; + z-index: 1; + background-color: rgba(112, 153, 230, 0.83); +} + @media only screen and (max-width: 650px) { h2 { diff --git a/src/cljs/token/components/qr.cljs b/src/cljs/token/components/qr.cljs new file mode 100644 index 0000000..3d4de61 --- /dev/null +++ b/src/cljs/token/components/qr.cljs @@ -0,0 +1,28 @@ +(ns token.components.qr + (:require [reagent.core :as reagent] + [qrcode])) + +(defn qr-popup + [label text] + (let [show? (reagent/atom false)] + (reagent/create-class + {:display-name "clipboard-button" + :component-did-mount + #(let [dom-node (aget (js/document.getElementsByClassName "qr-popup") 0) + qr (js/QRCode. dom-node + #js {:text text + :width 512 + :height 512 + :colorDark "#000000" + :colorLight "#ffffff", + :correctLevel js/QRCode.CorrectLevel.H})] + qr) + :reagent-render + (fn [] + [:div + [:div.button.button-clipboard + {:on-click #(swap! show? (fn [] true))} + label] + [:div.qr-popup {:style {:display (if @show? "block" "none")}} + [:span.qr-close {:on-click #(swap! show? (fn [] false))} "x"] + [:span {:style {:display "none"}} @show?]]])}))) diff --git a/src/cljs/token/wallet/page.cljs b/src/cljs/token/wallet/page.cljs index c401255..cb47961 100644 --- a/src/cljs/token/wallet/page.cljs +++ b/src/cljs/token/wallet/page.cljs @@ -7,7 +7,8 @@ [re-frame.core :as re-frame] [token.status :as status] [token.db :as db] - [token.utils :as u])) + [token.utils :as u] + [token.components.qr :as qr])) (defn nav [wallet-id] [:div.top-nav @@ -62,15 +63,15 @@ [:p wallet-id] ] [:div.wallets-detail - [:div.wallet-btn-left - [:div.btn-wallet - [:div.wallet-href-name [clipboard-button "Copy Address" wallet-id]] - ] [:div.clearfix]] - [:a.wallet-btn-right {:href (str "#/")} - [:div.btn-wallet - [:div.wallet-href-name "Show CR"] - ] [:div.clearfix]] - [:div.clearfix] + [:div.wallet-btn-left + [:div.btn-wallet + [:div.wallet-href-name [clipboard-button "Copy Address" wallet-id]] + ] [:div.clearfix]] + [:div.wallet-btn-right + [:div.btn-wallet + [:div.wallet-href-name [qr/qr-popup "Show QR" wallet-id]] + ] [:div.clearfix]] + [:div.clearfix] ]]])))) (defn format-date [date-format date] From 9bd47377e3ed9c6c262ba403e2419e2a7dd4be58 Mon Sep 17 00:00:00 2001 From: Tomas tomby Bily Date: Mon, 19 Jun 2017 16:40:34 +0200 Subject: [PATCH 7/8] fix css for qr popup --- resources/public/css/style.css | 28 +++++++++++++++++++++++----- src/cljs/token/components/qr.cljs | 8 +++++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/resources/public/css/style.css b/resources/public/css/style.css index bf73374..2556060 100644 --- a/resources/public/css/style.css +++ b/resources/public/css/style.css @@ -326,7 +326,7 @@ h2 { float: left; border-right: 2px solid #4669ad; position: relative; - z-index: 1111111; + z-index: 1; border-bottom-left-radius: 10px; } @@ -803,15 +803,33 @@ input:focus{ } .qr-popup { - width: 100%; - height: 100%; position: fixed; - top: 0px; + z-index: 100; left: 0px; - z-index: 1; + top: 0px; + width: 100%; + height: 100%; + + overflow: auto; + background-color: rgb(112, 153, 230); background-color: rgba(112, 153, 230, 0.83); } +.qr-popup-content { + background-color: #fff; + margin: 8% auto; + padding: 20px; + width: 68%; /* content width */ + text-align: center; + max-width: 512px; + min-width: 512px; +} + +.qr-popup-close { + color: grey; + float: right; +} + @media only screen and (max-width: 650px) { h2 { diff --git a/src/cljs/token/components/qr.cljs b/src/cljs/token/components/qr.cljs index 3d4de61..97829a1 100644 --- a/src/cljs/token/components/qr.cljs +++ b/src/cljs/token/components/qr.cljs @@ -8,7 +8,7 @@ (reagent/create-class {:display-name "clipboard-button" :component-did-mount - #(let [dom-node (aget (js/document.getElementsByClassName "qr-popup") 0) + #(let [dom-node (aget (js/document.getElementsByClassName "qr-popup-content-qr") 0) qr (js/QRCode. dom-node #js {:text text :width 512 @@ -24,5 +24,7 @@ {:on-click #(swap! show? (fn [] true))} label] [:div.qr-popup {:style {:display (if @show? "block" "none")}} - [:span.qr-close {:on-click #(swap! show? (fn [] false))} "x"] - [:span {:style {:display "none"}} @show?]]])}))) + [:div.qr-popup-content + [:span.qr-popup-close {:on-click #(swap! show? (fn [] false))} "×"] + [:div.qr-popup-content-qr] + [:span {:style {:display "none"}} @show?]]]])}))) From a3709192678997f91b7c6768440fe68225172318 Mon Sep 17 00:00:00 2001 From: Tomas tomby Bily Date: Sat, 24 Jun 2017 17:40:04 +0200 Subject: [PATCH 8/8] fix responsiveness of qr code --- resources/public/css/style.css | 12 ++++++++++++ src/cljs/token/components/qr.cljs | 12 ++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/resources/public/css/style.css b/resources/public/css/style.css index 2556060..a83254e 100644 --- a/resources/public/css/style.css +++ b/resources/public/css/style.css @@ -1092,4 +1092,16 @@ input:focus{ .fee-amount { margin-right: 16px; } + + .qr-popup-content { + max-width: 256px; + min-width: 256px; + } } + +@media only screen and (max-width: 256px) { + .qr-popup-content { + max-width: 128px; + min-width: 128px; + } +} \ No newline at end of file diff --git a/src/cljs/token/components/qr.cljs b/src/cljs/token/components/qr.cljs index 97829a1..184e35e 100644 --- a/src/cljs/token/components/qr.cljs +++ b/src/cljs/token/components/qr.cljs @@ -2,6 +2,13 @@ (:require [reagent.core :as reagent] [qrcode])) +(defn get-qr-size + [w] + (cond + (< w 256) 128 + (< w 650) 256 + :else 512)) + (defn qr-popup [label text] (let [show? (reagent/atom false)] @@ -9,10 +16,11 @@ {:display-name "clipboard-button" :component-did-mount #(let [dom-node (aget (js/document.getElementsByClassName "qr-popup-content-qr") 0) + w (get-qr-size js/window.innerWidth) qr (js/QRCode. dom-node #js {:text text - :width 512 - :height 512 + :width w + :height w :colorDark "#000000" :colorLight "#ffffff", :correctLevel js/QRCode.CorrectLevel.H})]