From 1d5abf7c23abb21c21e11ea587c9c35353d3825b Mon Sep 17 00:00:00 2001 From: Yih Sun Khoo Date: Sat, 8 Mar 2014 23:42:34 -0800 Subject: [PATCH 1/6] Updated UI of new transaction form. --- public/css/styles.less | 44 ++++++++++++++------------------------ views/new_transaction.jade | 31 +++++++++++++++++---------- 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/public/css/styles.less b/public/css/styles.less index 6032964..77f626c 100644 --- a/public/css/styles.less +++ b/public/css/styles.less @@ -96,21 +96,26 @@ body { color: white; } +// New Transaction +// ------------------------- + +#amount { + margin-top: 15px; +} + // Typeahead +// ------------------------- -typeahead, +.tt-dropdown-menu, +.tt-hint, +.tt-input, .tt-query, +.twitter-typeahead { + width: 100%; +} + .tt-hint { - width: 396px; - height: 30px; - padding: 8px 12px; - font-size: 14px; - line-height: 30px; - border: 2px solid #ccc; - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - border-radius: 8px; - outline: none; + color: #999 } .typeahead { @@ -121,29 +126,12 @@ typeahead, border: 2px solid #0097cf; } -.tt-query { - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.tt-hint { - color: #999 -} - .tt-dropdown-menu { - width: 396px; margin-top: 12px; padding: 8px 0; background-color: #fff; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - border-radius: 8px; - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); - -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); - box-shadow: 0 5px 10px rgba(0,0,0,.2); } .tt-suggestion { diff --git a/views/new_transaction.jade b/views/new_transaction.jade index 88d34c3..61b9e16 100644 --- a/views/new_transaction.jade +++ b/views/new_transaction.jade @@ -7,24 +7,33 @@ block content form.form-horizontal(role='form', method='POST') input(type='hidden', name='_csrf', value=token) .form-group - label(class='col-sm-2 control-label', for='name') To - .col-sm-8 + label(class='col-xs-2 control-label', for='name') + i.fa.fa-user + .col-xs-8 .example-numbers - input.form-control(class='tt-query typeahead', type='text', autofocus=true, autocomplete='off', spellcheck='false', dir='auto', style='position: relative; vertical-align: top; background-color: transparent;') + input.form-control(class='typeahead', type='text', autofocus=true, autocomplete='off', spellcheck='false', dir='auto') .form-group - label(class='col-sm-2 control-label', for='amount') Amount - .col-sm-8 - input.form-control(class='tt-query', type='text', name='amount', id='amount') + label(class='col-xs-2 control-label', for='amount') Amount + .col-xs-8 + .btn-group.btn-group-justified + .btn-group + button.btn.btn-default(type='button') + i.fa.fa-usd + .btn-group + button.btn.btn-default(type='button') + i.fa.fa-btc + input.form-control(type='text', name='amount', id='amount') .form-group - label(class='col-sm-2 control-label', for='message') What's it for? - .col-sm-8 - textarea.form-control(class='tt-query', type='text', name='message', id='message', rows='7') + label(class='col-xs-2 control-label', for='message') + i.fa.fa-comment + .col-xs-8 + textarea.form-control(type='text', name='message', id='message', rows='7') .form-group - .col-sm-offset-2.col-sm-2 + .col-xs-offset-2.col-xs-2 button.btn.btn-pay(type='submit') i.fa.fa-btc | Pay - .col-sm-2 + .col-xs-2 button.btn.btn-charge(type='submit') i.fa.fa-btc | Charge From 7c8213ae99a60a29581addd0071dddc755f5070d Mon Sep 17 00:00:00 2001 From: Yih Sun Khoo Date: Sun, 9 Mar 2014 00:57:31 -0800 Subject: [PATCH 2/6] Implemented RJProto design pattern for executing JS functions selectively. --- .jshintrc | 3 ++- controllers/new_transaction.js | 1 + public/js/application.js | 1 + public/js/main.js | 24 ++++++------------------ public/js/new_transaction.js | 23 +++++++++++++++++++++++ views/layout.jade | 5 +++++ 6 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 public/js/new_transaction.js diff --git a/.jshintrc b/.jshintrc index 584ed78..30f558c 100644 --- a/.jshintrc +++ b/.jshintrc @@ -47,7 +47,8 @@ "$": true, "_": true, "Backbone": true, - "Bloodhound": true + "Bloodhound": true, + "cf": true }, "regexdash": false, "scripturl": false, diff --git a/controllers/new_transaction.js b/controllers/new_transaction.js index 3e27a50..0be96ac 100644 --- a/controllers/new_transaction.js +++ b/controllers/new_transaction.js @@ -33,6 +33,7 @@ exports.getNewTransaction = function(req, res, next) { res.render('new_transaction', { + controllerJs: 'new_transaction', title: 'New Transaction', dump: { friends: friendsJson, diff --git a/public/js/application.js b/public/js/application.js index 7c0d502..2ad3c64 100644 --- a/public/js/application.js +++ b/public/js/application.js @@ -13,3 +13,4 @@ //= require lib/bootstrap.min //= require lib/typeahead.bundle.min //= require main +//= require new_transaction diff --git a/public/js/main.js b/public/js/main.js index 7b3308e..ed465c3 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,19 +1,7 @@ -$(document).ready(function() { - var $transactionRecipient = $('#transactionRecipient'); - if ($transactionRecipient.length) { - var names = new Bloodhound({ - datumTokenizer: function(d) { - return Bloodhound.tokenizers.whitespace(d.name); - }, - queryTokenizer: Bloodhound.tokenizers.whitespace, - local: window.cf.dump.friends - }); +if (typeof window.cf === 'undefined') { + window.cf = { apps: {} }; +} - names.initialize(); - - $transactionRecipient.typeahead(null, { - displayKey: 'name', - source: names.ttAdapter() - }); - } -}); +if (typeof window.cf.apps === 'undefined') { + window.cf.apps = {}; +} diff --git a/public/js/new_transaction.js b/public/js/new_transaction.js new file mode 100644 index 0000000..082733d --- /dev/null +++ b/public/js/new_transaction.js @@ -0,0 +1,23 @@ +cf.apps.new_transaction = function() { + this.initializeForm(); +}; + +cf.apps.new_transaction.prototype.initializeForm = function() { + var $transactionRecipient = $('#transactionRecipient'); + if ($transactionRecipient.length) { + var names = new Bloodhound({ + datumTokenizer: function(d) { + return Bloodhound.tokenizers.whitespace(d.name); + }, + queryTokenizer: Bloodhound.tokenizers.whitespace, + local: window.cf.dump.friends + }); + + names.initialize(); + + $transactionRecipient.typeahead(null, { + displayKey: 'name', + source: names.ttAdapter() + }); + } +}; diff --git a/views/layout.jade b/views/layout.jade index f8fa779..5cccc59 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -17,3 +17,8 @@ html include partials/footer include partials/dump != js('application') + if controllerJs + script. + $(document).ready(function() { + cf.currentApp = new window.cf.apps.#{controllerJs}(); + }); From 3b2373c6f009107938071d63684e0308d14f163c Mon Sep 17 00:00:00 2001 From: Yih Sun Khoo Date: Sun, 9 Mar 2014 16:59:44 -0700 Subject: [PATCH 3/6] Dynamically change currency label. --- public/css/styles.less | 15 ++++++++------- public/js/new_transaction.js | 10 ++++++++++ views/new_transaction.jade | 17 +++++++++-------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/public/css/styles.less b/public/css/styles.less index 77f626c..07d34e1 100644 --- a/public/css/styles.less +++ b/public/css/styles.less @@ -85,7 +85,15 @@ body { bottom: 25px; } +// New Transaction +// ------------------------- + +#amount { + margin-top: 15px; +} + // Buttons + .btn.btn-pay { background-color: @brand-primary; color: white; @@ -96,13 +104,6 @@ body { color: white; } -// New Transaction -// ------------------------- - -#amount { - margin-top: 15px; -} - // Typeahead // ------------------------- diff --git a/public/js/new_transaction.js b/public/js/new_transaction.js index 082733d..d624bb2 100644 --- a/public/js/new_transaction.js +++ b/public/js/new_transaction.js @@ -20,4 +20,14 @@ cf.apps.new_transaction.prototype.initializeForm = function() { source: names.ttAdapter() }); } + + $(".currency-btns label").on('click', function(event) { + var $target = $(event.target); + + if ($target.is("#optionBTC")) { + $('#currencyLabel').html(''); + } else if ($target.is("#optionUSD")) { + $('#currencyLabel').html(''); + } + }); }; diff --git a/views/new_transaction.jade b/views/new_transaction.jade index d849465..6aeba93 100644 --- a/views/new_transaction.jade +++ b/views/new_transaction.jade @@ -13,15 +13,16 @@ block content .example-numbers input#transactionRecipient.form-control(class='typeahead', type='text', autofocus=true, autocomplete='off', spellcheck='false', dir='auto') .form-group - label(class='col-xs-2 control-label', for='amount') Amount + label#currencyLabel(class='col-xs-2 control-label', for='amount') + i.fa.fa-btc .col-xs-8 - .btn-group.btn-group-justified - .btn-group - button.btn.btn-default(type='button') - i.fa.fa-usd - .btn-group - button.btn.btn-default(type='button') - i.fa.fa-btc + .btn-group.btn-group-justified.currency-btns(data-toggle='buttons') + label.btn.btn-primary.active#optionBTC + input(type='radio') + i.fa.fa-btc + label.btn.btn-primary#optionUSD + input(type='radio') + i.fa.fa-usd input.form-control(type='text', name='amount', id='amount') .form-group label(class='col-xs-2 control-label', for='message') From 554bbdeefd9a473c5ab1e69898a1ca2cd9b12b85 Mon Sep 17 00:00:00 2001 From: Yih Sun Khoo Date: Sun, 9 Mar 2014 18:13:47 -0700 Subject: [PATCH 4/6] Convert between USD and BTC. --- controllers/coinbase_api.js | 3 ++- public/js/new_transaction.js | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/controllers/coinbase_api.js b/controllers/coinbase_api.js index 5aab505..49466f6 100644 --- a/controllers/coinbase_api.js +++ b/controllers/coinbase_api.js @@ -1,7 +1,8 @@ var request = require('request'); +var _ = require('underscore'); exports.getExchangeRates = function(params, cb) { - request.get({ url: "https://coinbase.com/api/v1/currencies/exchange_rates" }, function (error, response, rates) { + request.get({ url: "https://coinbase.com/api/v1/currencies/exchange_rates" }, function (error, response, rates) { cb(error, rates); }); }; diff --git a/public/js/new_transaction.js b/public/js/new_transaction.js index d624bb2..1edcd23 100644 --- a/public/js/new_transaction.js +++ b/public/js/new_transaction.js @@ -1,3 +1,11 @@ +function usdToBtc(usd) { + return (Number(usd) * Number(window.cf.dump.rates.usd_to_btc)); +} + +function btcToUsd(btc) { + return (Number(btc) / Number(window.cf.dump.rates.usd_to_btc)); +} + cf.apps.new_transaction = function() { this.initializeForm(); }; @@ -23,11 +31,16 @@ cf.apps.new_transaction.prototype.initializeForm = function() { $(".currency-btns label").on('click', function(event) { var $target = $(event.target); + var $amount = $('#amount'); + var $currencyLabel = $('#currencyLabel'); - if ($target.is("#optionBTC")) { - $('#currencyLabel').html(''); - } else if ($target.is("#optionUSD")) { - $('#currencyLabel').html(''); + // TODO: Check if valid currency format + if ($target.is("#optionBTC:not(.active)")) { + $currencyLabel.html(''); + $amount.val(usdToBtc($amount.val())); + } else if ($target.is("#optionUSD:not(.active)")) { + $currencyLabel.html(''); + $amount.val(btcToUsd($amount.val())); } }); }; From a26c6d1e69197b99cdf71a57e26c3a7b9319db12 Mon Sep 17 00:00:00 2001 From: Yih Sun Khoo Date: Tue, 11 Mar 2014 22:00:43 -0700 Subject: [PATCH 5/6] Added TODO for matching friends in DB --- controllers/new_transaction.js | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/new_transaction.js b/controllers/new_transaction.js index 0be96ac..3054a65 100644 --- a/controllers/new_transaction.js +++ b/controllers/new_transaction.js @@ -12,6 +12,7 @@ exports.getNewTransaction = function(req, res, next) { var token = _.findWhere(req.user.tokens, { kind: 'facebook' }); graph.setAccessToken(token.accessToken); async.parallel({ + // TODO: Filter out friends that do not match a user in DB getMyFriends: function(done) { graph.get(req.user.facebook + '/friends', function(err, friends) { done(err, friends.data); From 7973609e0af8b8cd0ac6bee2841a548f3ac439f7 Mon Sep 17 00:00:00 2001 From: Yih Sun Khoo Date: Wed, 12 Mar 2014 00:24:42 -0700 Subject: [PATCH 6/6] Select elements by class instead of id. --- controllers/coinbase_api.js | 5 ++--- controllers/new_transaction.js | 1 + public/css/styles.less | 2 +- public/js/new_transaction.js | 11 ++++++----- views/new_transaction.jade | 10 +++++----- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/controllers/coinbase_api.js b/controllers/coinbase_api.js index a96a9af..5133dc2 100644 --- a/controllers/coinbase_api.js +++ b/controllers/coinbase_api.js @@ -13,12 +13,11 @@ var getCoinbaseAccessToken = function (user) { exports.getExchangeRates = function(params, cb) { request.get({ url: BASE_URI + "/currencies/exchange_rates" }, function (error, response, rates) { ->>>>>>> a50f8f7059c6d347c99ffd27e33ac035d59b66d4 cb(error, rates); }); }; -// @Todo: Figure this out. +// TODO: Figure this out. exports.sendMoney = function(params, cb) { var accessToken = getCoinbaseAccessToken(params.user); if (!accessToken) { @@ -26,7 +25,7 @@ exports.sendMoney = function(params, cb) { } }; -// @Todo: Figure this out. +// TODO: Figure this out. exports.getBalance = function(params, cb) { var accessToken = getCoinbaseAccessToken(params.user); if (!accessToken) { diff --git a/controllers/new_transaction.js b/controllers/new_transaction.js index 5ae176b..0e35d1e 100644 --- a/controllers/new_transaction.js +++ b/controllers/new_transaction.js @@ -52,6 +52,7 @@ exports.getNewTransaction = function(req, res, next) { } res.render('new_transaction', { + controllerJs: 'new_transaction', title: 'New Transaction', balance_amount: balance_amount, balance_currency: balance_currency, diff --git a/public/css/styles.less b/public/css/styles.less index 07d34e1..6081921 100644 --- a/public/css/styles.less +++ b/public/css/styles.less @@ -88,7 +88,7 @@ body { // New Transaction // ------------------------- -#amount { +.form-control.amount { margin-top: 15px; } diff --git a/public/js/new_transaction.js b/public/js/new_transaction.js index 1edcd23..93b98a6 100644 --- a/public/js/new_transaction.js +++ b/public/js/new_transaction.js @@ -11,7 +11,7 @@ cf.apps.new_transaction = function() { }; cf.apps.new_transaction.prototype.initializeForm = function() { - var $transactionRecipient = $('#transactionRecipient'); + var $transactionRecipient = $('.transactionRecipient'); if ($transactionRecipient.length) { var names = new Bloodhound({ datumTokenizer: function(d) { @@ -31,14 +31,15 @@ cf.apps.new_transaction.prototype.initializeForm = function() { $(".currency-btns label").on('click', function(event) { var $target = $(event.target); - var $amount = $('#amount'); - var $currencyLabel = $('#currencyLabel'); + var $amount = $('.amount'); + var $currencyLabel = $('.currencyLabel'); // TODO: Check if valid currency format - if ($target.is("#optionBTC:not(.active)")) { + // TODO: If you click fast enough, the conversion will be incorrect + if ($target.is(".optionBTC:not(.active)")) { $currencyLabel.html(''); $amount.val(usdToBtc($amount.val())); - } else if ($target.is("#optionUSD:not(.active)")) { + } else if ($target.is(".optionUSD:not(.active)")) { $currencyLabel.html(''); $amount.val(btcToUsd($amount.val())); } diff --git a/views/new_transaction.jade b/views/new_transaction.jade index 83320e0..8155fbd 100644 --- a/views/new_transaction.jade +++ b/views/new_transaction.jade @@ -15,19 +15,19 @@ block content i.fa.fa-user .col-xs-8 .example-numbers - input#transactionRecipient.form-control(class='typeahead', type='text', autofocus=true, autocomplete='off', spellcheck='false', dir='auto') + input.form-control.transactionRecipient(class='typeahead', type='text', autofocus=true, autocomplete='off', spellcheck='false', dir='auto') .form-group - label#currencyLabel(class='col-xs-2 control-label', for='amount') + label.currencyLabel(class='col-xs-2 control-label', for='amount') i.fa.fa-btc .col-xs-8 .btn-group.btn-group-justified.currency-btns(data-toggle='buttons') - label.btn.btn-primary.active#optionBTC + label.btn.btn-primary.optionBTC.active input(type='radio') i.fa.fa-btc - label.btn.btn-primary#optionUSD + label.btn.btn-primary.optionUSD input(type='radio') i.fa.fa-usd - input.form-control(type='text', name='amount', id='amount') + input.form-control.amount(type='text', name='amount') .form-group label(class='col-xs-2 control-label', for='message') i.fa.fa-comment