mirror of
https://github.com/nathanp/crypto-price-widget.git
synced 2025-11-06 03:08:55 -05:00
v1.4.0 - updating packages, coin list, etc.
This commit is contained in:
parent
4b795fb375
commit
073a483bf2
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
node_modules
|
||||
release-builds
|
||||
out/
|
||||
*.code-workspace
|
||||
File diff suppressed because one or more lines are too long
10
index.html
10
index.html
@ -77,6 +77,11 @@
|
||||
<li>DOGE: DFHBdwUbcvGezfgHHbWmH8eLWjAjUhFSZ2</li>
|
||||
</ul>
|
||||
|
||||
<h4>Build Info</h4>
|
||||
node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
|
||||
</div><!-- #settings -->
|
||||
|
||||
<div id="portfolio" class="panel">
|
||||
@ -92,10 +97,6 @@
|
||||
|
||||
<div id="portfolio-total-value">Total Value: <span class="value"></span></div>
|
||||
|
||||
<div class="chart-container" style="position: relative; height:40vh; width:94vw">
|
||||
<canvas id="portfolioChart" width="360" height="360"></canvas>
|
||||
</div>
|
||||
|
||||
<!-- show what % each coin is of portfolio -->
|
||||
|
||||
<!-- Enter avg. purchase price for each coin -->
|
||||
@ -110,5 +111,4 @@
|
||||
</script>
|
||||
<script src="js/app_common.js"></script>
|
||||
<script src="js/html.sortable.min.js"></script>
|
||||
<script src="js/Chart.min.js"></script>
|
||||
</html>
|
||||
603
js/app_common.js
603
js/app_common.js
@ -1,91 +1,98 @@
|
||||
/******************
|
||||
* APP FUNCTIONALITY
|
||||
******************/
|
||||
* APP FUNCTIONALITY
|
||||
******************/
|
||||
//access electron from here
|
||||
const remote = require('electron').remote;
|
||||
const remote = require("electron").remote;
|
||||
//user settings
|
||||
const settings = require('electron-settings');
|
||||
const settings = require("electron-settings");
|
||||
|
||||
//default coins
|
||||
if(settings.has('user.coins')) {
|
||||
if (settings.has("user.coins")) {
|
||||
//do nothing because coins already set
|
||||
}
|
||||
else {
|
||||
settings.set('user', {
|
||||
coins: 'BTC,ETH,LTC'
|
||||
} else {
|
||||
settings.set("user", {
|
||||
coins: ["BTC", "ETH", "LTC"],
|
||||
});
|
||||
}
|
||||
//default base currency
|
||||
if(settings.has('user.currency')) {
|
||||
if (settings.has("user.currency")) {
|
||||
//do nothing because currency already set
|
||||
}
|
||||
else {
|
||||
settings.set('user.currency', 'USD');
|
||||
} else {
|
||||
settings.set("user.currency", "USD");
|
||||
}
|
||||
|
||||
/* Base Currency */
|
||||
base = settings.get('user.currency'); // get the user's base currency
|
||||
var currSel = document.getElementById('base'); //select the currency select box
|
||||
currSel.value = settings.get('user.currency'); //select the option that corresponds to the user's currency
|
||||
setBase = function() {
|
||||
base = settings.get("user.currency"); // get the user's base currency
|
||||
var currSel = document.getElementById("base"); //select the currency select box
|
||||
currSel.value = settings.get("user.currency"); //select the option that corresponds to the user's currency
|
||||
setBase = function () {
|
||||
//selected base currency
|
||||
var sel = document.getElementById('base');
|
||||
var x = sel.selectedIndex;
|
||||
var y = sel.options;
|
||||
base = y[x].text;
|
||||
settings.set('user.currency', base); //save the user's selection
|
||||
var sel = document.getElementById("base");
|
||||
var x = sel.selectedIndex;
|
||||
var y = sel.options;
|
||||
base = y[x].text;
|
||||
settings.set("user.currency", base); //save the user's selection
|
||||
updateData(); //immediately reflect the changed currency
|
||||
};
|
||||
|
||||
//Functions for creating/appending elements
|
||||
function createNode(element) {
|
||||
return document.createElement(element);
|
||||
return document.createElement(element);
|
||||
}
|
||||
function append(parent, el) {
|
||||
return parent.appendChild(el);
|
||||
}
|
||||
|
||||
const ul = document.getElementById('prices'); // Get the list where we will place coins
|
||||
const portfolio_ul = document.getElementById('portfolio-list');;
|
||||
var url = 'https://min-api.cryptocompare.com/data/pricemultifull?fsyms='+settings.get('user.coins') +'&tsyms='+base +'&extraParams=crypto-price-widget';
|
||||
const ul = document.getElementById("prices"); // Get the list where we will place coins
|
||||
const portfolio_ul = document.getElementById("portfolio-list");
|
||||
var url =
|
||||
"https://min-api.cryptocompare.com/data/pricemultifull?fsyms=" +
|
||||
settings.get("user.coins") +
|
||||
"&tsyms=" +
|
||||
base +
|
||||
"&extraParams=crypto-price-widget";
|
||||
var pinCheck = document.getElementById("pin-to-top");
|
||||
|
||||
function clearData() {
|
||||
ul.innerHTML = '';
|
||||
ul.innerHTML = "";
|
||||
clearTimeout(appRefresh);
|
||||
}
|
||||
|
||||
function initData() {
|
||||
//need to redeclare the url variable here to grab the latest user coins, etc.
|
||||
var url = 'https://min-api.cryptocompare.com/data/pricemultifull?fsyms='+settings.get('user.coins') +'&tsyms='+base +'&extraParams=crypto-price-widget';
|
||||
var url =
|
||||
"https://min-api.cryptocompare.com/data/pricemultifull?fsyms=" +
|
||||
settings.get("user.coins") +
|
||||
"&tsyms=" +
|
||||
base +
|
||||
"&extraParams=crypto-price-widget";
|
||||
fetch(url)
|
||||
.then(
|
||||
function(response) {
|
||||
function (response) {
|
||||
// Examine the response
|
||||
response.json().then(function(data) {
|
||||
response.json().then(function (data) {
|
||||
//console.log(url);
|
||||
let pricesDISPLAY = data.DISPLAY; // display for everything except coin symbol
|
||||
let pricesRAW = data.RAW; // raw to get "BTC" instead of bitcoin symbol
|
||||
let pricesRAW = data.RAW; // raw to get "BTC" instead of bitcoin symbol
|
||||
|
||||
var i = 0;
|
||||
for (let key of Object.keys(pricesDISPLAY)) {
|
||||
let coin = pricesDISPLAY[key];
|
||||
//console.log(coin);
|
||||
let li = createNode('li'),
|
||||
span = createNode('span');
|
||||
sym = createNode('span');
|
||||
let li = createNode("li"),
|
||||
span = createNode("span");
|
||||
sym = createNode("span");
|
||||
li.setAttribute("class", "price");
|
||||
li.setAttribute("id", "coin-"+[key]);
|
||||
li.setAttribute("id", "coin-" + [key]);
|
||||
|
||||
span.setAttribute("class", "draggable");
|
||||
|
||||
//when adding a new coin, default sortorder to 999
|
||||
if( settings.get(li.id+'.order') == null) {
|
||||
settings.set(li.id+'.order', 999);
|
||||
if (settings.get(li.id + ".order") == null) {
|
||||
settings.set(li.id + ".order", 999);
|
||||
li.setAttribute("sortorder", 999);
|
||||
}
|
||||
else {
|
||||
li.setAttribute("sortorder", settings.get(li.id+'.order'));
|
||||
} else {
|
||||
li.setAttribute("sortorder", settings.get(li.id + ".order"));
|
||||
}
|
||||
|
||||
append(li, span);
|
||||
@ -94,23 +101,24 @@ function initData() {
|
||||
} //for
|
||||
|
||||
//sort your coins
|
||||
sortable('#prices', {
|
||||
handle: 'span'
|
||||
})[0].addEventListener('sortstop', function(e) {
|
||||
sortable("#prices", {
|
||||
handle: "span",
|
||||
})[0].addEventListener("sortstop", function (e) {
|
||||
// Declare variables
|
||||
var ul, ulPortfolio, li, liPortfolio, i;
|
||||
ul = document.getElementById("prices");
|
||||
ulPortfolio = document.getElementById("portfolio-list");
|
||||
li = ul.getElementsByTagName('li');
|
||||
liPortfolio = ulPortfolio.getElementsByTagName('li');
|
||||
li = ul.getElementsByTagName("li");
|
||||
liPortfolio = ulPortfolio.getElementsByTagName("li");
|
||||
// Loop through all list items
|
||||
for (i = 0; i < li.length; i++) {
|
||||
li[i].setAttribute("sortorder", i);
|
||||
li[i].setAttribute("sortorder", i);
|
||||
|
||||
var elementID = li[i].id;
|
||||
//alert(elementID);
|
||||
settings.set(elementID, { // coin-BTC
|
||||
order: li[i].getAttribute('sortorder')
|
||||
var elementID = li[i].id;
|
||||
//alert(elementID);
|
||||
settings.set(elementID, {
|
||||
// coin-BTC
|
||||
order: li[i].getAttribute("sortorder"),
|
||||
});
|
||||
//alert(settings.get(elementID + '.order'));
|
||||
} //for
|
||||
@ -118,7 +126,7 @@ function initData() {
|
||||
}); //sortable
|
||||
|
||||
//Pin to Top - settings check - immediately set checkbox and window to saved state
|
||||
if(settings.get('user.pinToTop') == 'yes') {
|
||||
if (settings.get("user.pinToTop") == "yes") {
|
||||
pinCheck.checked = true;
|
||||
remote.getCurrentWindow().setAlwaysOnTop(true);
|
||||
} else {
|
||||
@ -126,119 +134,122 @@ function initData() {
|
||||
remote.getCurrentWindow().setAlwaysOnTop(false);
|
||||
}
|
||||
|
||||
sortChildren(
|
||||
document.getElementById('prices'),
|
||||
function(li) { return +li.getAttribute('sortorder') }
|
||||
);
|
||||
sortChildren(
|
||||
document.getElementById('portfolio-list'),
|
||||
function(li) { return +li.getAttribute('sortorder') }
|
||||
);
|
||||
|
||||
sortChildren(document.getElementById("prices"), function (li) {
|
||||
return +li.getAttribute("sortorder");
|
||||
});
|
||||
sortChildren(document.getElementById("portfolio-list"), function (
|
||||
li
|
||||
) {
|
||||
return +li.getAttribute("sortorder");
|
||||
});
|
||||
}); //response.json
|
||||
updateData();
|
||||
} //function(response)
|
||||
) //.then
|
||||
.catch(function(err) {
|
||||
console.log('Unable to connect!');
|
||||
.catch(function (err) {
|
||||
console.log("Unable to connect!");
|
||||
var mainDiv = document.getElementById("main");
|
||||
var errorDiv = document.createElement('div');
|
||||
errorDiv.className = 'error';
|
||||
errorDiv.innerHTML = '<h2>Uh-oh! Looks like you're offline.</h2>\
|
||||
var errorDiv = document.createElement("div");
|
||||
errorDiv.className = "error";
|
||||
errorDiv.innerHTML =
|
||||
'<h2>Uh-oh! Looks like you're offline.</h2>\
|
||||
<img src="images/offline_doge.jpg" />\
|
||||
<h4>Reconnect, then reload the app.</h4>\
|
||||
<button type="button" class="refresh" onClick="location.reload(false);" >Reload</button>';
|
||||
document.getElementById('main').appendChild(errorDiv);
|
||||
});//catch
|
||||
}//initData
|
||||
document.getElementById("main").appendChild(errorDiv);
|
||||
}); //catch
|
||||
} //initData
|
||||
|
||||
function updateData() {
|
||||
//need to redeclare the url variable here to grab the latest user coins, etc.
|
||||
var url = 'https://min-api.cryptocompare.com/data/pricemultifull?fsyms='+settings.get('user.coins') +'&tsyms='+base +'&extraParams=crypto-price-widget';
|
||||
/*
|
||||
** What data needs to be grabbed/changed?
|
||||
** Base currency
|
||||
** Coin price
|
||||
** % change
|
||||
** Portfolio - Coin price affects current value / total
|
||||
*/
|
||||
//console.log(settings.get('user.coins'));
|
||||
fetch(url)
|
||||
.then(
|
||||
function(response) {
|
||||
// Examine the text in the response
|
||||
response.json().then(function(data) {
|
||||
let pricesDISPLAY = data.DISPLAY; // display for everything except coin symbol
|
||||
let pricesRAW = data.RAW; // raw to get "BTC" instead of bitcoin symbol
|
||||
let portfolioSum = 0;
|
||||
var url =
|
||||
"https://min-api.cryptocompare.com/data/pricemultifull?fsyms=" +
|
||||
settings.get("user.coins") +
|
||||
"&tsyms=" +
|
||||
base +
|
||||
"&extraParams=crypto-price-widget";
|
||||
/*
|
||||
** What data needs to be grabbed/changed?
|
||||
** Base currency
|
||||
** Coin price
|
||||
** % change
|
||||
** Portfolio - Coin price affects current value / total
|
||||
*/
|
||||
//console.log(settings.get('user.coins'));
|
||||
fetch(url).then(
|
||||
function (response) {
|
||||
// Examine the text in the response
|
||||
response.json().then(function (data) {
|
||||
let pricesDISPLAY = data.DISPLAY; // display for everything except coin symbol
|
||||
let pricesRAW = data.RAW; // raw to get "BTC" instead of bitcoin symbol
|
||||
let portfolioSum = 0;
|
||||
|
||||
// Chart labels
|
||||
var chartLabels = [];
|
||||
// Chart data
|
||||
var chartData = [];
|
||||
// Chart colors - need to match these colors to the coin in a future release
|
||||
var chartColors = [
|
||||
'#FF9F1C',
|
||||
'#2EC4B6',
|
||||
'#E71D36',
|
||||
'#011627',
|
||||
'#FDFFFC',
|
||||
'#D31EE8',
|
||||
'#0288D1',
|
||||
'#5FC42D',
|
||||
'#E64A19',
|
||||
'#0097A7',
|
||||
'#FBC02D',
|
||||
'#00796B',
|
||||
'#388E3C',
|
||||
'#689F38',
|
||||
'#303F9F',
|
||||
'#C2185B',
|
||||
'#FFA000',
|
||||
'#D32F2F',
|
||||
'#C2185B',
|
||||
'#fff'
|
||||
];
|
||||
for (let key of Object.keys(pricesRAW)) {
|
||||
let coinDISPLAY = pricesDISPLAY[key];
|
||||
let coinDISPLAYchange = coinDISPLAY[base].CHANGEPCT24HOUR;
|
||||
let coinRAW = pricesRAW[key];
|
||||
//console.log(coinDISPLAY);
|
||||
let li = document.getElementById("coin-" + [key]),
|
||||
span = document.querySelector("#coin-" + [key] + " span");
|
||||
|
||||
for (let key of Object.keys(pricesRAW)) {
|
||||
let coinDISPLAY = pricesDISPLAY[key];
|
||||
let coinDISPLAYchange = coinDISPLAY[base].CHANGEPCT24HOUR;
|
||||
let coinRAW = pricesRAW[key];
|
||||
//console.log(coinDISPLAY);
|
||||
let li = document.getElementById("coin-"+[key]),
|
||||
span = document.querySelector("#coin-"+[key]+" span");
|
||||
let coinSymbol = coinRAW[base].FROMSYMBOL;
|
||||
let coinRate = coinDISPLAY[base].PRICE.replace(/ /g, ""); //.replace(/ /g,'') removes space after $
|
||||
|
||||
let coinSymbol = coinRAW[base].FROMSYMBOL;
|
||||
let coinRate = coinDISPLAY[base].PRICE.replace(/ /g,''); //.replace(/ /g,'') removes space after $
|
||||
//replace currencies that have no symbols with easier to read formats
|
||||
if (coinRate.includes("AUD")) {
|
||||
coinRate = coinRate.replace("AUD", "A$");
|
||||
}
|
||||
if (coinRate.includes("CAD")) {
|
||||
coinRate = coinRate.replace("CAD", "C$");
|
||||
}
|
||||
if (coinRate.includes("HKD")) {
|
||||
coinRate = coinRate.replace("HKD", "HK$");
|
||||
}
|
||||
if (coinRate.includes("MXN")) {
|
||||
coinRate = coinRate.replace("MXN", "$");
|
||||
}
|
||||
if (coinRate.includes("NOK")) {
|
||||
coinRate = coinRate.replace("NOK", "kr");
|
||||
}
|
||||
if (coinRate.includes("NZD")) {
|
||||
coinRate = coinRate.replace("NZD", "NZ$");
|
||||
}
|
||||
if (coinRate.includes("SEK")) {
|
||||
coinRate = coinRate.replace("SEK", "kr");
|
||||
}
|
||||
if (coinRate.includes("SGD")) {
|
||||
coinRate = coinRate.replace("SGD", "S$");
|
||||
}
|
||||
if (coinRate.includes("TRY")) {
|
||||
coinRate = coinRate.replace("TRY", "₺");
|
||||
}
|
||||
if (coinRate.includes("ZAR")) {
|
||||
coinRate = coinRate.replace("ZAR", "R");
|
||||
}
|
||||
|
||||
//replace currencies that have no symbols with easier to read formats
|
||||
if(coinRate.includes("AUD")) { coinRate = coinRate.replace("AUD", "A$"); }
|
||||
if(coinRate.includes("CAD")) { coinRate = coinRate.replace("CAD", "C$"); }
|
||||
if(coinRate.includes("HKD")) { coinRate = coinRate.replace("HKD", "HK$"); }
|
||||
if(coinRate.includes("MXN")) { coinRate = coinRate.replace("MXN", "$"); }
|
||||
if(coinRate.includes("NOK")) { coinRate = coinRate.replace("NOK", "kr"); }
|
||||
if(coinRate.includes("NZD")) { coinRate = coinRate.replace("NZD", "NZ$"); }
|
||||
if(coinRate.includes("SEK")) { coinRate = coinRate.replace("SEK", "kr"); }
|
||||
if(coinRate.includes("SGD")) { coinRate = coinRate.replace("SGD", "S$"); }
|
||||
if(coinRate.includes("TRY")) { coinRate = coinRate.replace("TRY", "₺"); }
|
||||
if(coinRate.includes("ZAR")) { coinRate = coinRate.replace("ZAR", "R"); }
|
||||
//console.log(span);
|
||||
span.innerHTML =
|
||||
'<span class="sym">' +
|
||||
coinSymbol +
|
||||
"</span> " +
|
||||
coinRate +
|
||||
'<span class="change">' +
|
||||
coinDISPLAYchange +
|
||||
"%</span>";
|
||||
|
||||
//console.log(span);
|
||||
span.innerHTML = '<span class="sym">' + coinSymbol + '</span> ' + coinRate + '<span class="change">' + coinDISPLAYchange + '%</span>';
|
||||
//Price Alert Test - PRO Feature
|
||||
/*
|
||||
* Choose crypto
|
||||
* Choose price
|
||||
* Choose equals, greater than, or less than price
|
||||
* Alert set to "on"
|
||||
* Alert when matches conditions
|
||||
* When click on notification, alert set to "off"
|
||||
* Use electron settings, localStorage, or sessionStorage?
|
||||
* Should this be included in the updateData or separate?
|
||||
*/
|
||||
|
||||
//Price Alert Test - PRO Feature
|
||||
/*
|
||||
* Choose crypto
|
||||
* Choose price
|
||||
* Choose equals, greater than, or less than price
|
||||
* Alert set to "on"
|
||||
* Alert when matches conditions
|
||||
* When click on notification, alert set to "off"
|
||||
* Use electron settings, localStorage, or sessionStorage?
|
||||
* Should this be included in the updateData or separate?
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
var alerted = localStorage.getItem('alerted') || '';
|
||||
if(coinSymbol.includes("BTC") && coinRAW[base].PRICE >= "5723" && alerted != 'yes') {
|
||||
let notif = new window.Notification('Price Alert', {
|
||||
@ -251,167 +262,149 @@ function updateData() {
|
||||
}
|
||||
*/
|
||||
|
||||
// % Change
|
||||
let change = document.querySelector("#coin-"+[key]+" .change");
|
||||
if(coinDISPLAYchange > 0) {
|
||||
change.className += " positive";
|
||||
change.classList.remove("negative");
|
||||
}
|
||||
else if(coinDISPLAYchange < 0) {
|
||||
change.className += " negative";
|
||||
change.classList.remove("postive");
|
||||
}
|
||||
else {
|
||||
change.classList.remove("postive");
|
||||
change.classList.remove("negative");
|
||||
}
|
||||
// % Change
|
||||
let change = document.querySelector("#coin-" + [key] + " .change");
|
||||
if (coinDISPLAYchange > 0) {
|
||||
change.className += " positive";
|
||||
change.classList.remove("negative");
|
||||
} else if (coinDISPLAYchange < 0) {
|
||||
change.className += " negative";
|
||||
change.classList.remove("postive");
|
||||
} else {
|
||||
change.classList.remove("postive");
|
||||
change.classList.remove("negative");
|
||||
}
|
||||
|
||||
// Portfolio
|
||||
let quantityValue = document.querySelector("#coin-"+[key]+" .quantity-value");
|
||||
let quantityNumber = settings.get('quantity.'+[key]);
|
||||
let regp = /[^0-9.-]+/g;
|
||||
if(quantityNumber != null) {
|
||||
quantityTotal = parseFloat(coinRate.replace(regp, '')) * parseFloat(quantityNumber.replace(regp, ''));
|
||||
}
|
||||
// sum of all total coin values
|
||||
portfolioSum += quantityTotal;
|
||||
// put sum into the markup
|
||||
let portfolioTotalValue = document.querySelector("#portfolio-total-value .value");
|
||||
// Portfolio
|
||||
let quantityValue = document.querySelector(
|
||||
"#coin-" + [key] + " .quantity-value"
|
||||
);
|
||||
let quantityNumber = settings.get("quantity." + [key]);
|
||||
let regp = /[^0-9.-]+/g;
|
||||
if (quantityNumber != null) {
|
||||
quantityTotal =
|
||||
parseFloat(coinRate.replace(regp, "")) *
|
||||
parseFloat(quantityNumber.replace(regp, ""));
|
||||
}
|
||||
// sum of all total coin values
|
||||
portfolioSum += quantityTotal;
|
||||
// put sum into the markup
|
||||
let portfolioTotalValue = document.querySelector(
|
||||
"#portfolio-total-value .value"
|
||||
);
|
||||
|
||||
// total value for each coin
|
||||
if(coinRate.includes("Ƀ")) {
|
||||
//because BTC has 8 decimal places
|
||||
quantityValue.innerHTML = quantityTotal.toFixed(8);
|
||||
portfolioTotalValue.innerHTML = portfolioSum.toFixed(8);
|
||||
}
|
||||
else if(quantityValue != null) {
|
||||
//standard currency format
|
||||
quantityValue.innerHTML = quantityTotal.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
|
||||
portfolioTotalValue.innerHTML = portfolioSum.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
|
||||
}
|
||||
|
||||
// Chart labels
|
||||
chartLabels.push(key);
|
||||
// Chart data
|
||||
chartData.push(quantityTotal);
|
||||
|
||||
} //for
|
||||
|
||||
var newChartLabels = chartLabels;
|
||||
|
||||
// Chart
|
||||
var ctx = document.getElementById("portfolioChart");
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: chartData,
|
||||
backgroundColor: chartColors,
|
||||
borderColor: '#000',
|
||||
borderWidth: 0
|
||||
}],
|
||||
|
||||
labels: newChartLabels
|
||||
},
|
||||
options: {
|
||||
animation : false,
|
||||
responsive: false,
|
||||
maintainAspectRatio: true,
|
||||
legend : {
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
}); //myChart
|
||||
|
||||
}); //response.json().then
|
||||
} //function(response)
|
||||
) //then
|
||||
appRefresh = setTimeout(function(){updateData()}, 5000); // run this once every 5 seconds
|
||||
// total value for each coin
|
||||
if (coinRate.includes("Ƀ")) {
|
||||
//because BTC has 8 decimal places
|
||||
quantityValue.innerHTML = quantityTotal.toFixed(8);
|
||||
portfolioTotalValue.innerHTML = portfolioSum.toFixed(8);
|
||||
} else if (quantityValue != null) {
|
||||
//standard currency format
|
||||
quantityValue.innerHTML = quantityTotal
|
||||
.toFixed(2)
|
||||
.replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
|
||||
portfolioTotalValue.innerHTML = portfolioSum
|
||||
.toFixed(2)
|
||||
.replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
|
||||
}
|
||||
} //for
|
||||
}); //response.json().then
|
||||
} //function(response)
|
||||
); //then
|
||||
appRefresh = setTimeout(function () {
|
||||
updateData();
|
||||
}, 5000); // run this once every 5 seconds
|
||||
} //updateData()
|
||||
|
||||
// Let's do this thing!
|
||||
initData();
|
||||
|
||||
// Click on #saveCoins, save the coin selection to the user
|
||||
document.getElementById('saveCoins').onclick = function(){
|
||||
var coinForm = document.getElementById('coinlist');
|
||||
document.getElementById("saveCoins").onclick = function () {
|
||||
var coinForm = document.getElementById("coinlist");
|
||||
var selchb = getSelectedChbox(coinForm); // gets the array returned by getSelectedChbox()
|
||||
settings.set('user.coins', selchb);
|
||||
settings.set("user.coins", selchb);
|
||||
//clear and reload
|
||||
clearData();
|
||||
initData();
|
||||
}
|
||||
};
|
||||
|
||||
/***********
|
||||
* PORTFOLIO
|
||||
***********/
|
||||
var portfolio_list_container = document.querySelector('#portfolio-list');
|
||||
var portfolio_list = settings.get('user.coins');
|
||||
* PORTFOLIO
|
||||
***********/
|
||||
var portfolio_list_container = document.querySelector("#portfolio-list");
|
||||
var portfolio_list = settings.get("user.coins");
|
||||
|
||||
//generate html from list of coins
|
||||
for (let key of Object.keys(portfolio_list)) {
|
||||
let coin = portfolio_list[key];
|
||||
//console.log(coin);
|
||||
let li = createNode('li'),
|
||||
span = createNode('span');
|
||||
sym = createNode('span');
|
||||
li.setAttribute("id", "coin-"+[coin]);
|
||||
li.setAttribute("sortorder", settings.get(li.id+'.order'));
|
||||
let li = createNode("li"),
|
||||
span = createNode("span");
|
||||
sym = createNode("span");
|
||||
li.setAttribute("id", "coin-" + [coin]);
|
||||
li.setAttribute("sortorder", settings.get(li.id + ".order"));
|
||||
|
||||
append(li, span);
|
||||
append(portfolio_ul, li);
|
||||
|
||||
if (settings.has('quantity.'+[coin])) {
|
||||
inputValue = settings.get('quantity.'+[coin]);
|
||||
}
|
||||
else {
|
||||
inputValue = '0';
|
||||
settings.set('quantity.'+[coin], '0');
|
||||
if (settings.has("quantity." + [coin])) {
|
||||
inputValue = settings.get("quantity." + [coin]);
|
||||
} else {
|
||||
inputValue = "0";
|
||||
settings.set("quantity." + [coin], "0");
|
||||
}
|
||||
|
||||
span.innerHTML = '<span class="sym">' + coin + '</span> <span class="block quantity"><label for="quantity.' + coin +'">Quantity</label> <input type="number" name="quantity.' + coin +'" min="0" value="'+inputValue+'" step=".01"></span> <span class="block value"><label>Current Value</label><span class="quantity-value"></span></span>';
|
||||
span.innerHTML =
|
||||
'<span class="sym">' +
|
||||
coin +
|
||||
'</span> <span class="block quantity"><label for="quantity.' +
|
||||
coin +
|
||||
'">Quantity</label> <input type="number" name="quantity.' +
|
||||
coin +
|
||||
'" min="0" value="' +
|
||||
inputValue +
|
||||
'" step=".01"></span> <span class="block value"><label>Current Value</label><span class="quantity-value"></span></span>';
|
||||
|
||||
i++;
|
||||
} //for
|
||||
|
||||
// save quantities
|
||||
document.getElementById('saveQuantities').onclick = function(){
|
||||
document.getElementById("saveQuantities").onclick = function () {
|
||||
var items = portfolio_ul.getElementsByTagName("input");
|
||||
for (var i = 0; i < items.length; ++i) {
|
||||
// do something with items[i], which is a <li> element
|
||||
inputName = items[i].getAttribute("name");
|
||||
inputValue = items[i].value;
|
||||
inputName = items[i].getAttribute("name");
|
||||
inputValue = items[i].value;
|
||||
//console.log(inputValue);
|
||||
settings.set(inputName, inputValue);
|
||||
}
|
||||
|
||||
|
||||
// just reloading the entire app because I have yet to figure out how to add/remove a coin from the primary list without a page reload
|
||||
//location.reload(false);
|
||||
}
|
||||
};
|
||||
|
||||
/***********
|
||||
* SETTINGS
|
||||
***********/
|
||||
* SETTINGS
|
||||
***********/
|
||||
// Settings - list of coins
|
||||
function loadJSON(callback) {
|
||||
//Stored local version of https://www.cryptocompare.com/api/data/coinlist/ for performance
|
||||
var file = './coinlist.json';
|
||||
var file = "./coinlist.json";
|
||||
var xobj = new XMLHttpRequest();
|
||||
xobj.overrideMimeType("application/json");
|
||||
xobj.open('GET', file, true);
|
||||
xobj.onreadystatechange = function () {
|
||||
if (xobj.readyState == 4 && xobj.status == "200") {
|
||||
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
|
||||
callback(xobj.responseText);
|
||||
}
|
||||
};
|
||||
xobj.send(null);
|
||||
|
||||
xobj.overrideMimeType("application/json");
|
||||
xobj.open("GET", file, true);
|
||||
xobj.onreadystatechange = function () {
|
||||
if (xobj.readyState == 4 && xobj.status == "200") {
|
||||
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
|
||||
callback(xobj.responseText);
|
||||
}
|
||||
};
|
||||
xobj.send(null);
|
||||
} //loadJSON
|
||||
|
||||
// Generate the list of all coins
|
||||
loadJSON(function(response) {
|
||||
loadJSON(function (response) {
|
||||
// Parse JSON string into object
|
||||
var myDiv = document.getElementById("coinlist");
|
||||
var actual_JSON = JSON.parse(response);
|
||||
@ -419,14 +412,14 @@ loadJSON(function(response) {
|
||||
//console.log(actual_JSON.Data);
|
||||
|
||||
//loop through data, get coin info, generate checkbox for each coin
|
||||
Object.keys(actual_JSON.Data).forEach(function(key) {
|
||||
Object.keys(actual_JSON.Data).forEach(function (key) {
|
||||
//console.log(actual_JSON.Data[key].Name);
|
||||
//console.log(actual_JSON.Data[key].CoinName);
|
||||
var li = document.createElement("li");
|
||||
var checkBox = document.createElement("input");
|
||||
checkBox.className = "coinCode";
|
||||
checkBox.className = "coinCode";
|
||||
var label = document.createElement("label");
|
||||
label.className = "coinName";
|
||||
label.className = "coinName";
|
||||
var div = document.createElement("div");
|
||||
checkBox.type = "checkbox";
|
||||
checkBox.value = actual_JSON.Data[key].Name;
|
||||
@ -434,54 +427,56 @@ loadJSON(function(response) {
|
||||
label.htmlFor = actual_JSON.Data[key].Name;
|
||||
checkBox.name = "cl[]";
|
||||
//check the coins the user has already set
|
||||
var str = String(settings.get('user.coins'));
|
||||
var str = String(settings.get("user.coins"));
|
||||
var split_str = str.split(",");
|
||||
if (split_str.indexOf(actual_JSON.Data[key].Name) !== -1) {
|
||||
checkBox.checked = true;
|
||||
checkBox.checked = true;
|
||||
}
|
||||
myDiv.appendChild(li);
|
||||
li.appendChild(checkBox);
|
||||
li.appendChild(label);
|
||||
label.appendChild(document.createTextNode(actual_JSON.Data[key].CoinName));
|
||||
label.appendChild(document.createTextNode(' ('+actual_JSON.Data[key].Name+')'));
|
||||
label.appendChild(
|
||||
document.createTextNode(" (" + actual_JSON.Data[key].Name + ")")
|
||||
);
|
||||
label.appendChild(div);
|
||||
}); //forEach
|
||||
|
||||
}); //loadJSON
|
||||
|
||||
// Returns an array with values of the selected (checked) checkboxes in "frm"
|
||||
function getSelectedChbox(frm) {
|
||||
var selchbox = []; // array that will store the value of selected checkboxes
|
||||
// gets all the input tags in frm, and their number
|
||||
var inpfields = frm.getElementsByTagName('input');
|
||||
var inpfields = frm.getElementsByTagName("input");
|
||||
var nr_inpfields = inpfields.length;
|
||||
// traverse the inpfields elements, and adds the value of selected (checked) checkbox in selchbox
|
||||
for(var i=0; i<nr_inpfields; i++) {
|
||||
if(inpfields[i].type == 'checkbox' && inpfields[i].checked == true) selchbox.push(inpfields[i].value);
|
||||
for (var i = 0; i < nr_inpfields; i++) {
|
||||
if (inpfields[i].type == "checkbox" && inpfields[i].checked == true)
|
||||
selchbox.push(inpfields[i].value);
|
||||
}
|
||||
return selchbox;
|
||||
}
|
||||
|
||||
/***********
|
||||
* PIN TO TOP
|
||||
*************/
|
||||
pinCheck.onclick = function(event) {
|
||||
* PIN TO TOP
|
||||
*************/
|
||||
pinCheck.onclick = function (event) {
|
||||
var window = remote.getCurrentWindow();
|
||||
var checkbox = event.target;
|
||||
if(checkbox.checked) {
|
||||
if (checkbox.checked) {
|
||||
//Checkbox has been checked
|
||||
window.setAlwaysOnTop(true); //immediately make the change to the window
|
||||
settings.set('user.pinToTop', 'yes');
|
||||
settings.set("user.pinToTop", "yes");
|
||||
} else {
|
||||
//Checkbox has been unchecked
|
||||
window.setAlwaysOnTop(false);
|
||||
settings.set('user.pinToTop', 'no');
|
||||
settings.set("user.pinToTop", "no");
|
||||
}
|
||||
};
|
||||
|
||||
/*******
|
||||
* APP UI
|
||||
********/
|
||||
* APP UI
|
||||
********/
|
||||
|
||||
//Window controls
|
||||
document.getElementById("close-btn").addEventListener("click", function (e) {
|
||||
@ -494,40 +489,40 @@ document.getElementById("min-btn").addEventListener("click", function (e) {
|
||||
});
|
||||
|
||||
//Panel tabs
|
||||
var tabLinks = document.querySelectorAll('.tabs button');
|
||||
var tabLinks = document.querySelectorAll(".tabs button");
|
||||
for (var i = 0; i < tabLinks.length; i++) {
|
||||
tabLinks[i].onclick = function() {
|
||||
var target = this.getAttribute('href').replace('#', '');
|
||||
var sections = document.querySelectorAll('.panel');
|
||||
for(var j=0; j < sections.length; j++) {
|
||||
sections[j].style.display = 'none';
|
||||
tabLinks[i].onclick = function () {
|
||||
var target = this.getAttribute("href").replace("#", "");
|
||||
var sections = document.querySelectorAll(".panel");
|
||||
for (var j = 0; j < sections.length; j++) {
|
||||
sections[j].style.display = "none";
|
||||
}
|
||||
document.getElementById(target).style.display = 'block';
|
||||
for(var k=0; k < tabLinks.length; k++) {
|
||||
tabLinks[k].removeAttribute('class');
|
||||
document.getElementById(target).style.display = "block";
|
||||
for (var k = 0; k < tabLinks.length; k++) {
|
||||
tabLinks[k].removeAttribute("class");
|
||||
}
|
||||
this.setAttribute('class', 'active');
|
||||
this.setAttribute("class", "active");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
//Coin search filter
|
||||
function myFunction() {
|
||||
// Declare variables
|
||||
var input, filter, ul, li, a, i;
|
||||
input = document.getElementById('myInput');
|
||||
input = document.getElementById("myInput");
|
||||
filter = input.value.toUpperCase();
|
||||
ul = document.getElementById("coinlist");
|
||||
li = ul.getElementsByTagName('li');
|
||||
li = ul.getElementsByTagName("li");
|
||||
|
||||
// Loop through all list items, and hide those who don't match the search query
|
||||
for (i = 0; i < li.length; i++) {
|
||||
label = li[i].getElementsByTagName("label")[0];
|
||||
checkbox = li[i].getElementsByTagName("input")[0].value;
|
||||
if (label.innerHTML.toUpperCase().indexOf(filter) > -1) {
|
||||
li[i].style.display = "";
|
||||
li[i].style.display = "";
|
||||
} else {
|
||||
li[i].style.display = "none";
|
||||
li[i].style.display = "none";
|
||||
}
|
||||
} //for
|
||||
} //myFunction
|
||||
@ -535,16 +530,20 @@ function myFunction() {
|
||||
//sort by attribute
|
||||
function sortChildren(wrap, f, isNum) {
|
||||
var l = wrap.children.length,
|
||||
arr = new Array(l);
|
||||
for(var i=0; i<l; ++i)
|
||||
arr[i] = [f(wrap.children[i]), wrap.children[i]];
|
||||
arr.sort(isNum
|
||||
? function(a,b){ return a[0]-b[0]; }
|
||||
: function(a,b){ return a[0]<b[0] ? -1 : a[0]>b[0] ? 1 : 0; }
|
||||
arr = new Array(l);
|
||||
for (var i = 0; i < l; ++i) arr[i] = [f(wrap.children[i]), wrap.children[i]];
|
||||
arr.sort(
|
||||
isNum
|
||||
? function (a, b) {
|
||||
return a[0] - b[0];
|
||||
}
|
||||
: function (a, b) {
|
||||
return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0;
|
||||
}
|
||||
);
|
||||
var par = wrap.parentNode,
|
||||
ref = wrap.nextSibling;
|
||||
ref = wrap.nextSibling;
|
||||
par.removeChild(wrap);
|
||||
for(var i=0; i<l; ++i) wrap.appendChild(arr[i][1]);
|
||||
for (var i = 0; i < l; ++i) wrap.appendChild(arr[i][1]);
|
||||
par.insertBefore(wrap, ref);
|
||||
} //sortChildren
|
||||
62
main.js
62
main.js
@ -1,29 +1,31 @@
|
||||
const electron = require('electron')
|
||||
const electron = require("electron");
|
||||
// Module to control application life.
|
||||
const app = electron.app
|
||||
const app = electron.app;
|
||||
// Module to create native browser window.
|
||||
const BrowserWindow = electron.BrowserWindow
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
//Store Window size and position
|
||||
const windowStateKeeper = require('electron-window-state');
|
||||
const windowStateKeeper = require("electron-window-state");
|
||||
|
||||
const path = require("path");
|
||||
const url = require("url");
|
||||
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
|
||||
const settings = require('electron-settings');
|
||||
const settings = require("electron-settings");
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
let mainWindow;
|
||||
|
||||
function createWindow () {
|
||||
function createWindow() {
|
||||
// Load the previous state with fallback to defaults
|
||||
let mainWindowState = windowStateKeeper({
|
||||
defaultWidth: 320,
|
||||
defaultHeight: 240
|
||||
defaultHeight: 240,
|
||||
});
|
||||
// Create the browser window.
|
||||
mainWindow = new electron.BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
},
|
||||
title: app.getName(),
|
||||
alwaysOnTop: false,
|
||||
//show: false,
|
||||
@ -37,10 +39,10 @@ function createWindow () {
|
||||
maximizable: false,
|
||||
fullscreenable: false,
|
||||
frame: false,
|
||||
titleBarStyle: 'customButtonsOnHover',
|
||||
titleBarStyle: "customButtonsOnHover",
|
||||
autoHideMenuBar: true,
|
||||
transparent: true,
|
||||
icon: 'images/icon.png'
|
||||
icon: "images/icon.png",
|
||||
});
|
||||
|
||||
// Let us register listeners on the window, so we can update the state
|
||||
@ -49,45 +51,47 @@ function createWindow () {
|
||||
mainWindowState.manage(mainWindow);
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadURL(url.format({
|
||||
pathname: path.join(__dirname, 'index.html'),
|
||||
protocol: 'file:',
|
||||
slashes: true
|
||||
}))
|
||||
mainWindow.loadURL(
|
||||
url.format({
|
||||
pathname: path.join(__dirname, "index.html"),
|
||||
protocol: "file:",
|
||||
slashes: true,
|
||||
})
|
||||
);
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
mainWindow.on("closed", function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
mainWindow = null;
|
||||
});
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.on('ready', createWindow)
|
||||
app.on("ready", createWindow);
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function () {
|
||||
app.on("window-all-closed", function () {
|
||||
// On OS X it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
if (process.platform !== "darwin") {
|
||||
app.quit();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
app.on('activate', function () {
|
||||
app.on("activate", function () {
|
||||
// On OS X it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
createWindow();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
10677
package-lock.json
generated
10677
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
21
package.json
21
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "crypto-price-widget",
|
||||
"productName": "Crypto Price Widget",
|
||||
"version": "1.2.0",
|
||||
"version": "1.4.0",
|
||||
"description": "A cross-platform app for tracking Crypto prices",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
@ -22,18 +22,19 @@
|
||||
"author": "Nathan Parikh",
|
||||
"license": "CC0-1.0",
|
||||
"devDependencies": {
|
||||
"electron": "~1.6.2",
|
||||
"electron-packager": "^8.7.2"
|
||||
"electron": "^9.0.4",
|
||||
"electron-packager": "^14.2.1",
|
||||
"electron-winstaller": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ava": "^0.15.2",
|
||||
"cryptocurrencies": "^1.0.0",
|
||||
"electron-settings": "^3.1.1",
|
||||
"electron-window-state": "^4.1.1",
|
||||
"html5sortable": "^0.6.1",
|
||||
"ava": "^3.8.2",
|
||||
"cryptocurrencies": "^7.0.0",
|
||||
"electron-settings": "^3.2.0",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"html5sortable": "^0.9.17",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"sortablejs": "^1.6.0",
|
||||
"xo": "^0.16.0"
|
||||
"sortablejs": "^1.10.2",
|
||||
"xo": "^0.32.0"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user