/*
[ jQuery ]
웹사이트에 자바스크립트를 쉽게 활용할 수 있도록 도와주는 오픈소스 기반의 자바스크립트 라이브러리
[ 최근 Trends + 비슷한 종류 ]
1. Lodash
2. Moment
3. jQuery
4. date-fns
5. RxJS
*/
/*
".ready()"는 DOM(Document Object Model)이 완전히 불러와지면 실행되는 Event 이다.
일반적으로 브라우저가 HTML을 보여주기 위해서는
먼저 문서 구조를 만들고 만들어진 문서 구조 위에 디자인을 입히는 형식을 취한다.
이 과정에서 디자인이 입혀지지 않은 상태로 문서 구조가 만들어진 시점에 시행되는 Event가 ".ready()" 이다.
jQuery 3.0 버전 이후부터는 "$(handler)" 구문만 권장
".read()" Event는 1.8 버전에서는 deprecated 되었으며 3.0에서는 지원하지 않기 때문
( 근데 여기서는 실행 문제 잘됨 )
*/
// $(document).ready(function() { });
$(function() {
var nasdaq_table_container_element = document.getElementById("nasdaq-table-container");
var chart_container_element = document.getElementById("chart-container");
var news_container_element = document.getElementById("news-container");
console.log(nasdaq_table_container_element, chart_container_element, news_container_element);
// nasdaq_table_container_element.style.display = "block";
// chart_container_element.style.display = "none";
// news_container_element.style.display = "none";
// $("#news-container").hide();
// $("#news-container").show();
nasdaq_table_init();
});
/**
*
*
*
*
*/
function nasdaq_table_init() {
// HTML 수정
$("#chart-container").hide();
$("#news-container").hide();
// Javascript -> Flask (Python) -> Javascript
output = sendAjax_sync("/stocks", {}, "json", handle_one_return);
// console.log("stocksInit() Output : ", output);
// console.log(typeof output);
// Ticker 길이 확인해보기
var object_length = Object.keys(output.ticker).length;
// console.log(object_length);
// 랜더링 HTML 요소 생성
stocks = document.querySelector('.stocks');
stocks.innerHTML = '';
// "HTML"에 요소 추가
for (var i = 0; i < object_length; i++) {
stocks.innerHTML = stocks.innerHTML + '
';
stocks.innerHTML = stocks.innerHTML + '' + output.name[i] + '
';
if (output.diff[i] > 0) {
stocks.innerHTML = stocks.innerHTML + '' + '+' + output.diff[i] + ' %' + '
';
}
else { stocks.innerHTML = stocks.innerHTML + '' + output.diff[i] + ' %' + '
'; }
stocks.innerHTML = stocks.innerHTML + '' + output.open[i] + '
';
stocks.innerHTML = stocks.innerHTML + '' + output.close[i] + '
';
stocks.innerHTML = stocks.innerHTML + '' + output.sector[i] + '
';
stocks.innerHTML = stocks.innerHTML + '' + output.industry[i] + '
';
// Add ticker's chart link
execution_function = `javascript:chartInit('${ output.ticker[i] }')`;
stock = document.querySelectorAll('.stock.ticker')[i];
stock.innerHTML = '';
stock.innerHTML = stock.innerHTML + `${ output.ticker[i] }`;
}
}
/**
*
*
*
*
*
*
*
*
*/
function chartInit(ticker, already=false) {
// HTML 수정
$("#nasdaq-table-container").hide();
$("#chart-container").show();
$("#news-container").hide();
// ticker 이름 설정 (부제목 설정)
$('#chart-container .goticker .tickerName').text(ticker.concat(' Chart'));
// Javascript -> Flask (Python) -> Javascript
let [chart_data, news_articles] = sendAjax_sync_about_chartData_and_newsArticles("/chart", {"ticker": ticker}, "json", handle_two_return);
if (!already) {
// x축과 data 설정
// data: [{'x': date, 'o': open, 'h': high, 'l': low, 'c': close}, { }, { }, ... ]
data = [];
key_list = Object.keys(chart_data.Close);
for (var i=key_list.length-15; i b) { return -1; }
else { return 0; }
}).reduce((sorted_news, key) => {
sorted_news[key] = news_articles[key];
return sorted_news;
}, {});
// console.log(sorted_news);
var key_list = Object.keys(chart_data.Open);
var open_list = Object.values(chart_data.Open);
var close_list = Object.values(chart_data.Close);
for (var i=0; i for item in list:
Object.keys(sorted_news).forEach(key => {
var date_idx_in_key_list = key_list.indexOf(String(key));
// console.log(key, key_list, date_idx_in_key_list);
if (date_idx_in_key_list != -1) {
var diff = ((open_list[date_idx_in_key_list]-close_list[date_idx_in_key_list-1])/(open_list[date_idx_in_key_list]) * 100.0).toFixed(2);
}
else { var diff = 0; }
if (diff == 0) {
var diff_html = '0.0 % | ';
}
else if (diff > 0) {
var diff_html = '+' + diff + ' % | ';
}
else {
var diff_html = '' + diff + ' % | ';
}
var html = `+ | ${ key } | ${ diff_html }`;
for (var i = 0; i < sorted_news[key].length; i++) {
var title = sorted_news[key][i].substring(0, sorted_news[key][i].length-4);
var sendTitle = title; // Javascript -> Python 보내기 위한 title
// title에서 & 표시가 있을 수 있음.
// Title 에서 '&'로 표시되어 있는데 따로 구별해야 된다.
// andSymbolInTitle 에서 가져온 '&' 위치 index를 title과 합쳐준다.
andSymbolInTitle = [];
let idx = 0;
// title = "asdf&asdf&AS&DF&&";
// sendTitle = title;
while (true) {
idx = sendTitle.indexOf('&', idx);
if (idx == -1) { break; }
sendTitle = sendTitle.substring(0, idx) + sendTitle.substring(idx+1, sendTitle.length);
// console.log(sendTitle);
andSymbolInTitle.push(idx + andSymbolInTitle.length);
}
var link = String(`/info_and_newsNER?ticker=${ ticker }&date=${ key }&title=${ sendTitle }&andSymbolInTitle=${ andSymbolInTitle }`);
linkList.push(link);
var execution_function = String(`javascript:getData(linkList[${ link_list_idx }], ${ diff });`);
html = html + `${ title } `;
link_list_idx = link_list_idx + 1;
}
html = html + ' | ';
news_table.innerHTML = news_table.innerHTML + html;
});
}
linkList = [];
async function getData(link, diff) {
try {
console.log("link : ", link);
await $.getJSON(link, function(data)
{
// console.log("ticker : ", data.ticker);
// console.log("date : ", data.date);
// console.log("title : ", data.title);
// console.log("url : ", data.url);
// console.log("ents : ", data.ents);
console.log("diff : ", diff);
newsInit(data.ticker, data.date, data.title, data.url, data.ents, diff);
});
} catch (error) {
console.log("Error : ", error);
}
}
/**
*
*
*
*
*
*
*
*
*
*
*/
function newsInit(ticker, date, title, url, ents, diff) {
// HTML 수정
$("#nasdaq-table-container").hide();
$("#chart-container").hide();
$("#news-container").show();
// console.log(ticker);
// console.log(date);
// console.log(title);
//////////////////////////////////////////////////////////////////////
// Javascript를 이용해 HTML에 동적으로 태그 추가
document.querySelector('#news-container .goticker .tickerName').textContent = ticker + " Chart";
document.querySelector('#news-container .titleDate').textContent = "Date : " + date;
document.querySelector('#news-container .titleName').textContent = "Article : " + title;
document.querySelector('#news-container .newsURL .input-News-URL').textContent = "URL : " + url;
// a 태그 onclick 적용
var execution_function = `javascript:chartInit('${ ticker }', true)`;
const goTicker = document.querySelector('#news-container .goticker');
goTicker.setAttribute('href', execution_function);
// a 태그에 URL 적용
const addURL = document.querySelector('.newsURL .input-News-URL');
addURL.setAttribute('href', url);
// 모델에서 질문 예시 Ticker에 알맞게 작성하기
const model_input_example = document.querySelector('#model .text-form #text-input');
if (diff == 0) { example = "What is your outlook for the future direction of this stock?" }
else if (diff > 0) { example = "Why did " + ticker + "'s stock go up?"; }
else if (diff < 0) { example = "Why did " + ticker + "'s stock go down?"; }
else { throw new Error('Error : diff Error '); }
model_input_example.setAttribute('value', example);
//////////////////////////////////////////////////////////////////////
// NER 관련
console.log(ents);
let news = ents['news'];
let numOfNER = ents['text'].length;
// console.log("total news : ", news);
// 랜더링 html 요소 생성
news_ner = document.querySelector('.entities');
news_ner.innerHTML = '';
for (i=0; i'
+ news.substring(end_idx, last_idx)
+ ''
+ label + '';
// console.log(add_html);
news_ner.innerHTML = news_ner.innerHTML + add_html;
}
// console.log("last html : ", news.substring(ents['end_char'][numOfNER-1]));
news_ner.innerHTML = news_ner.innerHTML + news.substring(ents['end_char'][numOfNER-1]);
//////////////////////////////////////////////////////////////////////
// 모델 적용 내용 ( Submit )
var sendTitle = title; // Javascript -> Python 보내기 위한 title
// title에서 & 표시가 있을 수 있음.
// Title 에서 '&'로 표시되어 있는데 따로 구별해야 된다.
// andSymbolInTitle 에서 가져온 '&' 위치 index를 title과 합쳐준다.
andSymbolInTitle = [];
let idx = 0;
// title = "asdf&asdf&AS&DF&&";
// sendTitle = title;
while (true) {
idx = sendTitle.indexOf('&', idx);
if (idx == -1) { break; }
sendTitle = sendTitle.substring(0, idx) + sendTitle.substring(idx+1, sendTitle.length);
// console.log(sendTitle);
andSymbolInTitle.push(idx + andSymbolInTitle.length);
}
// console.log(andSymbolInTitle);
// console.log("Last String", sendTitle);
// function 앞에 "async"를 붙이면 해당 함수는 항상 프라미스를 반환한다.
const translateText = async (text) => {
// 목적 : Flask에 input을 보내주고 output을 받아오는 과정
console.log("Start translateText async");
// "await"는 "async" 함수 안에서만 동작한다.
// "await" 키워드를 만나면 Promise가 처리될 때까지 기다린다.
// Promise가 처리되길 기다리는 동안엔 엔진이 다른일(다른 스크립트를 실행, 이벤트 처리 등)을 할 수 있기 때문에, CPU 리소스가 낭비되지 않는다.
const inferResponse = await fetch(`newsQuestions?ticker=${ ticker }&date=${ date }&title=${ sendTitle }&andSymbolInTitle=${ andSymbolInTitle }&questions=${ text }`); // Javascript -> Flask(python)
// console.log("inferResponse : ", inferResponse);
const inferJson = await inferResponse.json(); // Flask(python) -> Javascript
// console.log(inferJson);
return inferJson.result['answer'];
};
/* 모델 Submit button 관련 내용 */
// form 태그의 class 이름
const textForm = document.querySelector('.text-form');
// addEventListener(type, listener)
// addEventListener(type, listener, options)
// addEventListener(type, listener, useCapture)
textForm.addEventListener('submit', async (event) => {
event.preventDefault();
// console.log(event);
// html -> javascript : input 받아와서 output 보내기
const textInput = document.getElementById('text-input');
const textParagraph = document.querySelector('.text-output');
console.log("textInput : ", textInput, textInput.value);
try {
// sendAjax("/inference", {"input_text" : textInput.value}, handleOutput);
// "await"는 "async" 함수 안에서만 동작한다.
// "await" 키워드를 만나면 Promise가 처리될 때까지 기다린다.
// Promise가 처리되길 기다리는 동안엔 엔진이 다른일(다른 스크립트를 실행, 이벤트 처리 등)을 할 수 있기 때문에, CPU 리소스가 낭비되지 않는다.
const answer = await translateText(textInput.value); // Flask에 input을 보내주고 output을 받아오는 과정
console.log("Result : ", answer);
textParagraph.textContent = answer;
} catch (err) {
console.error(err);
}
});
}
---|