核心提示:investor_main.js(function(investor) {use strict;var controller = investor.controller;controller.disp...
investor_main.js
(function(investor) { "use strict"; var controller = investor.controller; controller.displayTable(); controller.displayWords(); }(window._investor = window._investor || {}));investor_controller.js
(function(investor) { "use strict"; investor.controller = investor.controller || (function(){ var headerProperties; var model = investor.model; function _displayTable(){ var tableElement = document.querySelector('#table'); var header = model.header; headerProperties = _getHeaderProperties(header); tableElement.appendChild(_createRow(header)); var market = investor.market; market.retrieve().then(function(){}).catch(function(){}).then(function(){ var tableData = model.tableData; tableData.forEach( function(rowData){ var newRowElement = _createRow(rowData); _addOnClickEventTo(newRowElement); tableElement.appendChild(newRowElement); } ); _addFreezeClassToColumn(0); }); _addScrollEvent(); } function _createRow(rowData){ var newRowElement = document.createElement('p'); newRowElement.className = 'row'; headerProperties.forEach( function(headerProperty){ newRowElement.appendChild(_createCell(rowData[headerProperty])); } ); return newRowElement; } function _createCell(cellData){ var newCellElement = document.createElement('p'); newCellElement.innerHTML = cellData; newCellElement.className = typeof cellData; return newCellElement; } function _getHeaderProperties(header){ var properties = []; for(var property in header){ if(header.hasOwnProperty(property)){ properties.push(property); } } return properties; } function _displayWords(){ var words = model.words; var wordsElement = document.querySelector('#words'); words.forEach( function(word){ var wordElement = document.createElement('p'); wordElement.innerHTML = word; wordsElement.appendChild(wordElement); } ); } function _addFreezeClassToColumn(index){ var rowElements = document.querySelectorAll('#table .row'); Array.prototype.forEach.call(rowElements, function(rowElement){ var cellElements = rowElement.querySelectorAll('p'); cellElements[index].classList.add('freezeX'); } ); } function _addScrollEvent(){ var freezeXStyle = document.styleSheets[0].rules[0].style; window.addEventListener('scroll', function(e){ freezeXStyle.left = window.scrollX.toString() + 'px'; //console.log(window.scrollX); }); } function _addOnClickEventTo(currentRowElement){ currentRowElement.onclick = _rowOnClickHandler; } function _rowOnClickHandler(){ var selectedRowElements = document.querySelectorAll('#table .row.selected'); Array.prototype.forEach.call(selectedRowElements, function(selectedRowElement){ selectedRowElement.classList.remove('selected'); } ); this.classList.add('selected'); } return { displayTable: _displayTable, displayWords: _displayWords }; }()); }(window._investor = window._investor || {}));
investor_model.js
(function(investor) { "use strict"; investor.model = investor.model || (function(){ // EPS earning per share // PER price earning ratio // NAV net asset value var model = {}; var Stock = (function(){ var Stock = function(){}; Object.defineProperty(Stock.prototype, 'PER_avg_7', { get: function(){ return (this.latest_price/this.EPS_avg_7).toFixed(1); } }); Object.defineProperty(Stock.prototype, 'PER_2015', { get: function(){ return (this.latest_price/this.EPS_2015).toFixed(1); } }); Object.defineProperty(Stock.prototype, 'price_to_pidend_ratio_2015', { get: function(){ return (this.pident_per_share_2015/this.latest_price*100).toFixed(1); } }); Object.defineProperty(Stock.prototype, 'book_to_price_ratio', { get: function(){ return (this.NAV_per_share_2015/this.latest_price).toFixed(1); } }); Object.defineProperty(Stock.prototype, 'EPS25_avg_7_minus_price', { get: function(){ return (this.EPS_avg_7*25 - this.latest_price).toFixed(1); } }); Object.defineProperty(Stock.prototype, 'PER20_2015_minus_price', { get: function(){ return (this.EPS_2015*20 - this.latest_price).toFixed(1); } }); Object.defineProperty(Stock.prototype, 'safe_price', { get: function(){ return Math.min((this.EPS_avg_7*25).toFixed(1), (this.EPS_2015*20).toFixed(1)); } }); Object.defineProperty(Stock.prototype, 'price_diff', { get: function(){ return (this.safe_price - this.latest_price).toFixed(1); } }); Object.defineProperty(Stock.prototype, 'price_diff_ratio', { get: function(){ return (this.price_diff/this.safe_price*100).toFixed(1); } }); return Stock; }()); Object.defineProperty(model, 'stockCodes', { get: function(){ var rawData = investor.data.stocks; return rawData.map(function(data){ return data.code; }); } }); Object.defineProperty(model, 'header', { get: function(){ return { name: '名称', code: '代码', price_20151231: '价格 2015.12.31', price_change_percent_in_one_year: '价格变动自2014.12 (%)', latest_price: '最近价格', pay_margin_since: '每年股利支付自', EPS_avg_7: '每股市场收益 2009-2015 (7年平均收益)', EPS_2015: '每股收益 2015', pident_per_share_2015: '每股股利 2015', NAV_per_share_2015: '每股净资产价值 2015', PER_avg_7: '2009-2015市场与收益(7年平均)', PER_2015: '市场与收益 2015', price_to_pidend_ratio_2015: '股利率 2015', book_to_price_ratio: '净有形资产比市价比率', EPS25_avg_7_minus_price: '25倍(7年平均收益)-价格', PER20_2015_minus_price: '20倍(2015年收益)-价格', safe_price: '安全边际价格', price_diff: '价差', price_diff_ratio:'价差比率', }; } }); Object.defineProperty(model, 'words', { get: function(){ return [ '每一个公司应该是大的、突出的、谨慎投资的。', '每个公司应该具有一个长期的连续的红利支付记录。', '联系到过去7年的平均收益,投资者应表明他愿意为一个证券所支付的价格的界限。(平均收益的25倍,并且不多于最近12月的20倍)', '应该有适当的但不是长度的多样化,就也许意味着有最少10种和最多大约30种不同的证券。', '', '发现廉价的普通股有两种方法:', '1。', '2。把更多的注意力放在实际资产价值上,特别强调流动资产或流动资本。', '', '影响资本化率的因素', '管理:', '公平地说,一个杰出的公司会有显著的良好的管理,它显示在以往的记录中,还会显示在下一个5年的预测中,并更多的作为影响长期前景的因素出现。在另一个时间,它会带着乐观的考虑估计它的趋势,并易导致价值的高估。', '财力和资本结构', '大量公积金,银行贷款。债券 (偶尔地,资本过大的结构--普通股相对债券和优先股太少--也许在顺利的状态下给普通股造成巨大的“投机”利润,这就是所谓的“杠杆作用”因素)。', '', '股利记录', '', '当期股利率(p176)', '幸运的是,大部分公司有所谓的标准股利政策。它意味着它们平均收益约2/3用于分配,除非近期高利润和通货膨胀要求更多的资本,使这个比率相对趋于降低。', '', ]; } }); Object.defineProperty(model, 'tableData', { get: function(){ var stocks = investor.data.stocks; var tableData = []; stocks.forEach(function(item){ var stock = new Stock(); for(var attr in item){ if(item.hasOwnProperty(attr)){ stock[attr] = item[attr]; } } //Object.assign(stock, item); //too new var live_market_data = window['hq_str_'+stock.code]; if(live_market_data){ stock.latest_price = live_market_data.split(',')[3]; } tableData.push(stock); }); return tableData; } }); return model; }()); }(window._investor = window._investor || {}));
investor_market.js
(function(investor) { "use strict"; investor.market = investor.market || (function(){ function _retrieve(){ var model = investor.model; var promise = new Promise(function(resolve, reject){ var script = document.createElement("script"); script.onload = function() { script.onload = null; resolve(); } script.onerror = function() { script.onerror = null; reject(); } script.src = "https://hq.sinajs.cn/list=" + model.stockCodes.toString(); document.head.appendChild( script ); }); return promise; } return { retrieve: _retrieve } }()); }(window._investor = window._investor || {}));
investor_data.js
(function(investor) { "use strict"; investor.data = investor.data || (function(){ var data = {}; Object.defineProperty(data, 'stocks', { get: function(){ return [ { name: '中国建筑', code: 'sh601668', price_20151231: 6.34, price_change_percent_in_one_year: '', //latest_price: undefined, pay_margin_since: '2009', EPS_avg_7: .5, EPS_2015: .84, pident_per_share_2015: .2, NAV_per_share_2015: 5.3, }, { name: '中国神华', code: 'sh601088', price_20151231: 14.97, price_change_percent_in_one_year: '', pay_margin_since: '2007', EPS_avg_7: 1.8, EPS_2015: .81, pident_per_share_2015: .32, NAV_per_share_2015: 12.9, }, { name: '中国石化', code: 'sh600028', price_20151231: 4.96, price_change_percent_in_one_year: '', pay_margin_since: '2001', EPS_avg_7: .6, EPS_2015: .27, pident_per_share_2015: .15, NAV_per_share_2015: 4.9, }, { name: '中集集团', code: 'sz000039', price_20151231: 21, price_change_percent_in_one_year: '', pay_margin_since: '2007', EPS_avg_7: .8, EPS_2015: .72, pident_per_share_2015: .22, NAV_per_share_2015: 7.9, }, { name: '建设银行', code: 'sh601939', price_20151231: 4.78, price_change_percent_in_one_year: '', pay_margin_since: '2007', EPS_avg_7: .7, EPS_2015: .91, pident_per_share_2015: .274, NAV_per_share_2015: 5.6, }, { name: '中国人寿', code: 'sh601628', price_20151231: 28.31, price_change_percent_in_one_year: '', pay_margin_since: '2006', EPS_avg_7: .9, EPS_2015: 1.22, pident_per_share_2015: .42, NAV_per_share_2015: 11.1, }, { name: '中国平安', code: 'sh601318', price_20151231: 36, price_change_percent_in_one_year: '', pay_margin_since: '2006', EPS_avg_7: 2.9, EPS_2015: 2.98, pident_per_share_2015: .53, NAV_per_share_2015: 16.6, }, ]; } }); return data; }()); }(window._investor = window._investor || {}));
investor_view.html
<html> <head> <style> .freezeX{ left: 0; /* value changed when scrollX */ position: relative; } .row{ display: flex; } .row p{ border-right: 1px solid gray; border-bottom: 1px solid gray; flex: 0 0 100px; word-wrap: break-word; background-color: white; } .row:first-child p{ border-top: 1px solid gray; } .row p:first-child{ border-left: 1px solid gray; } .row:nth-child(even) p{ background-color: whitesmoke; } .row.selected p{ background-color: lightcyan; } </style> </head> <body> <p id="table"></p> <p id="words"></p> <script src="investor_model.js" charset="utf-8"></script> <script src="investor_data.js" charset="utf-8"></script> <script src="investor_market.js" charset="utf-8"></script> <script src="investor_controller.js" charset="utf-8"></script> <script src="investor_main.js" charset="utf-8"></script> </body> </html>