/* [ 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); } }); }