﻿var lib = YAHOO, Dom = lib.util.Dom, Event = lib.util.Event; if (typeof (ETFTable) == "undefined") { var ETFTable = {}; } ETFTable.expandedAndFilteredData = {}; ETFTable.expandedData = {}; ETFTable.tempData = {}; ETFTable.initialData = {}; ETFTable.formulaTemplate = {}; ETFTable.expandComplete = new lib.util.CustomEvent("expandComplete"); ETFTable.formulaTemplate.EMACROSSOVER = "\n    if (!Item.EMA__slowPeriod__Series) {\n        Item.EMA__slowPeriod__Series = Item.CloseSeries.slice(0, (__slowPeriod__ + 30)).EMAverage(__slowPeriod__);\n    }\n    if (!Item.EMA__fastPeriod__Series) {\n        Item.EMA__fastPeriod__Series = Item.CloseSeries.slice(0, (__fastPeriod__ + 30)).EMAverage(__fastPeriod__);\n    }\n    Item.__propName___Hist = [];\n    var len = Item.EMA__slowPeriod__Series.length >= 2 ? 2 : Item.EMA__slowPeriod__Series.length;\n    for (var i = 0; i < len; i++) {\n        Item.__propName___Hist[i] = PercentDiff(Item.EMA__fastPeriod__Series[i], Item.EMA__slowPeriod__Series[i]).roundFloat();\n    }\n    return Item.__propName___Hist[0];"; ETFTable.formulaTemplate.PERFORMANCE = "\n    Item.__propName___Hist = [];\n    var len = Item.CloseSeries.length >= 2 ? 2 : Item.CloseSeries.length;\n    for (var i = 0; i < len; i++) {\n        Item.__propName___Hist[i] = PercentDiff(Item.CloseSeries[i], Item.CloseSeries[__daysBack__ + i]).roundFloat();\n    }\n    return Item.__propName___Hist[0];"; ETFTable.formulaTemplate.getFormula = function(b) { var d = ETFTable.formulaTemplate[b.name.toUpperCase()]; var a, c; for (c in b.params) { a = new RegExp("__" + c + "__", "gi"); d = d.replace(a, b.params[c]); } return d; }; function copy(a) { return lib.lang.JSON.parse(lib.lang.JSON.stringify(a)); } Array.prototype.Sum = function(a) { return TA.Sum(this, a); }; Array.prototype.SMAverage = function(a) { return TA.SMAverage(this, a); }; Array.prototype.EMAverage = function(a) { return TA.EMAverage(this, a); }; Array.prototype.LinearReg = function(a) { return TA.LinearReg(this, a); }; Array.prototype.Roc = function(a) { return TA.Roc(this, a); }; Array.prototype.contains = function(b) { for (var a = 0; a < this.length; a++) { if (this[a].toUpperCase() == b.toUpperCase()) { return true; } } return false; }; String.prototype.buildArray = function() { return this.replace(", ", " ").replace(",", " ").replace('"', "").replace("'", "").split(" "); }; Number.prototype.roundFloat = function(a) { return TA.Helpers.roundDecimal(this, a); }; PercentDiff = function(b, a) { return TA.Helpers.percentDiff(b, a); }; SignedNumberSort = function(d, c) { var f = parseFloat(d), e = parseFloat(c); if (!isFinite(f) || isNaN(f) || typeof (f) == "undefined" || f == null) { f = -9999999.999; } if (!isFinite(e) || isNaN(e) || typeof (e) == "undefined" || e == null) { e = -9999999.999; } if (f === e) { return 0; } else { if (f < e) { return -1; } } return 1; }; SimpleIntRank = function(d, c, e) { var f = e ? -1 : 1; if (d < c) { return -1 * f; } else { if (d === c) { return 0; } } return 1 * f; }; function setWaitStatus(d, c) { waiting(); var b = document.getElementById("progressbar").getElementsByTagName("div")[0]; var e = document.getElementById("percentComplete"); var a = document.getElementById("spnStatus"); b.style.width = d + "%"; e.innerHTML = d + "%"; if (c) { a.innerHTML = c; } if (d >= 100) { e.className = "complete"; a.className = "complete"; } } function waitComplete() { document.getElementById("pageContainer").style.display = "block"; ETFTable.ui.wait.hide(); } ETFTable.ui.RankToColorConverter = function(b, a, d, c) { this.numberMin = new Number(b); this.numberMax = new Number(a); this.colorMin = new String(d).replace("#", ""); this.colorMax = new String(c).replace("#", ""); this.colors = []; this.build(); }; ETFTable.ui.RankToColorConverter.prototype.build = function() { var o = this.numberMax - this.numberMin, k = parseInt(this.colorMin.substr(0, 2), 16), a = parseInt(this.colorMax.substr(0, 2), 16), h = parseInt(this.colorMin.substr(2, 2), 16), n = parseInt(this.colorMax.substr(2, 2), 16), m = parseInt(this.colorMin.substr(4, 2), 16), d = parseInt(this.colorMax.substr(4, 2), 16), c, f, l, j; for (var e = this.numberMin; e <= this.numberMax; e++) { j = ((e - this.numberMin) / o); this.colors[e] = { r: Math.round(((a - k) * j) + k), g: Math.round(((n - h) * j) + h), b: Math.round(((d - m) * j) + m) }; } }; ETFTable.ui.RankToColorConverter.prototype.getHexColor = function(a) { return "#" + this.colors[a].r.toString(16) + this.colors[a].g.toString(16) + this.colors[a].b.toString(16); }; ETFTable.ui.downRankToColorConverter = new ETFTable.ui.RankToColorConverter(1, 50, "#E76161", "#FFFFFF"); ETFTable.ui.upRankToColorConverter = new ETFTable.ui.RankToColorConverter(51, 100, "#FFFFFF", "#61E761"); function createFormatters() { ETFTable.formatters = {}; ETFTable.formatters.myFormatDetailLink = function(c, b, d, e) { var a = "ETFTable.ui.showDetailFrame('<<TICKER>>');"; c.innerHTML = '<a href="javascript:' + a.replace("<<TICKER>>", b.getData("Ticker")) + '" alt="Click for ETF Details">' + e + "</a>"; return true; }; ETFTable.formatters.myFormatDate = function(i, j, e, a) { var b = new Date(); var f = a.getMonth() + 1; var g = a.getFullYear(); var h = a.getDate(); var d = a.getHours(); var c = a.getMinutes(); if (g < 1000) { g += 1900; } if (h >= b.getDate() && f >= b.getMonth() + 1 && g >= b.getFullYear()) { i.innerHTML = d + ((c < 10) ? ":0" : ":") + c; } else { i.innerHTML = f + "/" + h + "/" + g; } }; ETFTable.formatters.myFormatCrossover = function(c, b, e, g) { if (b.getData(e.getField() + "_Hist") != null) { var d = b.getData(e.getField() + "_Hist"); var f = Math.ceil((b.getData(e.getField() + "_Rank") / ETFTable.initialData.Results.length) * 100), a; if (f <= 50) { a = ETFTable.ui.downRankToColorConverter.getHexColor(f); } else { a = ETFTable.ui.upRankToColorConverter.getHexColor(f); } if (!isFinite(d[0]) || isNaN(d[0]) || typeof (d[0]) == "undefined" || d[0] == null) { (new lib.util.Element(c)).setStyle("background-color", "#BBBBBB"); c.innerHTML = "n/a"; return; } (new lib.util.Element(c)).setStyle("background-color", a); if (d[0] > 0 && d[1] <= 0) { c.innerHTML = '<span style="color:Green;">' + g + "</span>"; } else { if (d[1] >= 0 && d[0] < 0) { c.innerHTML = '<span style="color:#CC0000;">' + g + "</span>"; } else { c.innerHTML = g; } } } }; ETFTable.formatters.myFormat1to100Rank = function(c, b, e, g) { if (b.getData(e.getField() + "_Hist") != null) { var d = b.getData(e.getField() + "_Hist"); var f = Math.ceil((b.getData(e.getField() + "_Rank") / ETFTable.initialData.Results.length) * 100), a; if (f <= 50) { a = ETFTable.ui.downRankToColorConverter.getHexColor(f); } else { a = ETFTable.ui.upRankToColorConverter.getHexColor(f); } if (!isFinite(d[0]) || isNaN(d[0]) || typeof (d[0]) == "undefined" || d[0] == null) { (new lib.util.Element(c)).setStyle("background-color", "#BBBBBB"); c.innerHTML = "n/a"; return; } (new lib.util.Element(c)).setStyle("background-color", a); c.innerHTML = f; } }; } ETFTable.doTransform = function(h, m, o) { ETFTable.expandedData = h; var k = ETFTable.expandedData.Results; var d = k.length; var a = ETFTable.dataConfig.properties.length, c; var l = 0; var j = 1000; var n = 0; var b = false; var g = []; var p, q, f; for (var e = 0; e < a; e++) { c = ETFTable.dataConfig.properties[e]; if (!c.value && typeof (c.template) == "object") { c.template.params.propName = c.name; f = ETFTable.formulaTemplate.getFormula(c.template); g.push(new Function(ETFTable.dataConfig.item, f)); } else { if (c.value) { f = c.value; g.push(new Function(ETFTable.dataConfig.item, f)); } else { g.push(null); } } } (function() { var r = new Date().getTime(); var i; for (; l < d; l++) { for (e = 0; e < a; e++) { c = ETFTable.dataConfig.properties[e]; i = g[e](k[l]); if (typeof (i) != "object" && (typeof (i) == "undefined" || i == null || (typeof (i) == "number" && !isFinite(i)))) { i = null; } k[l][c.name] = i; } if (new Date().getTime() - r > j) { l++; setTimeout(arguments.callee, n); break; } } m(l, d); if (l >= d && b == false) { o(ETFTable.expandedData); b = true; } })(); return true; }; ETFTable.doRankings = function(d, b) { var g = ETFTable.expandedData.Results; var f = g.length; var e = ETFTable.dataConfig.properties.length, h; for (var a = 0; a < e; a++) { h = ETFTable.dataConfig.properties[a]; if ((h.showCol && h.showCol == true) || typeof (h.showCol) == "undefined") { switch (h.dataType) { case "number": g.sort(function(j, i) { var k = SignedNumberSort(j[h.name], i[h.name]); if (k == 0) { k = SimpleIntRank(j.VolumeEMA10, i.VolumeEMA10, true); } return k; }); break; default: g.sort(function(j, i) { var k = lib.util.Sort.compare(j[h.name], i[h.name]); if (k == 0) { k = lib.util.Sort.compare(j.VolumeEMA10, i.VolumeEMA10); } return k; }); break; } for (var c = 0; c < f; c++) { g[c][h.name + "_Rank"] = c + 1; } } } b(ETFTable.expandedData); return true; }; ETFTable.doPostFilter = function(a) { ETFTable.expandedAndFilteredData.Results = a.slice(0); var h = ETFTable.expandedAndFilteredData.Results; var j = "", b, g, c = ""; for (var e = 0; e < ETFTable.dataConfig.filters.length; e++) { j += c; c = " && "; if (ETFTable.dataConfig.filters[e].operator == "is in list") { j += "new String('" + ETFTable.dataConfig.filters[e].compValue + "').buildArray().contains(" + ETFTable.dataConfig.filters[e].property + ")"; } else { j += ETFTable.dataConfig.filters[e].property + " "; j += ETFTable.dataConfig.filters[e].operator + " "; j += ETFTable.dataConfig.filters[e].compValue; if (!ETFTable.dataConfig.filters[e].showNulls) { j += " && " + ETFTable.dataConfig.filters[e].property + " != null"; } } } if (j.length > 0) { g = new Function("Item", "return " + j); for (var d = 0; d < h.length; d++) { if (!g(h[d])) { h.splice(d, 1); d = d - 1; } } } }; Event.onDOMReady(function() { waiting(); var c = { success: function(e) { ETFTable.initialData = YAHOO.lang.JSON.parse(e.responseText).ResultSet; var d; createFormatters(); setConfigs(); ETFTable.doTransform(ETFTable.initialData, function(g, f) { d = (100 * g / f).roundFloat(2); setWaitStatus(d, "Transforming Data..."); }, function(f) { setWaitStatus(99, "Ranking Data..."); ETFTable.doRankings(function(h, g) { d = (100 * h / g).roundFloat(2); setWaitStatus(d, "Ranking Data..."); }, function(g) { ETFTable.doPostFilter(g.Results); ETFTable.tempData.expandComplete = true; ETFTable.expandComplete.fire(ETFTable.expandedAndFilteredData); }); }); }, failure: function(d) { alert("Cannot Connect to Data Source. Please try again later."); }, argument: ["ARG_DATA"] }; setWaitStatus(90, "Downloading..."); var b = "js_handlers/DailyHandler.ashx"; var a = YAHOO.util.Connect.asyncRequest("GET", b, c, null); }); ETFTable.expandComplete.subscribe(function(l, c) { ETFTable.ui.dataTable = new lib.util.Element("dataTableContainer"); ETFTable.ui.layout = new lib.widget.Layout({ units: [{ position: "top", height: 67, body: "top1", gutter: "0px", collapse: false, resize: false }, { position: "center", body: "center1", gutter: "2px", scroll: false }, { position: "right", body: "rightTabsContainer", header: "", width: 320, gutter: "2px", scroll: true, collapse: true, animate: false, resize: true }, { position: "bottom", body: "footer1", height: 26, gutter: "0px", scroll: false, collapse: true}] }); ETFTable.ui.layout.on("resize", function() { ETFTable.ui.dataTable.set("height", (this.getSizes().center.h - 82) + "px"); }); ETFTable.ui.layout.on("render", function() { r(ETFTable.ui.layout.getSizes().center.h - 82); }); ETFTable.ui.tabView = new YAHOO.widget.TabView("rightTabs"); ETFTable.ui.showDetailFrame = function(w) { var i = "js/lib/yui/assets/skins/sam/wait.gif"; var j = "http://stockcharts.com/h-sc/ui?s=<<TICKER>>&p=D&yr=0&mn=6&dy=0&id=p28717686630&r=5030&cmd=sendchart"; var v = document.getElementById("detailFrame"); v.src = i; v.style.display = "block"; ETFTable.ui.layout.getUnitByPosition("right").set("width", 484); ETFTable.ui.layout.getUnitByPosition("right").expand(); v.src = j.replace("<<TICKER>>", w); ETFTable.ui.tabView.set("activeIndex", 1); }; var s = c[0].Results; s.sort(function(v, j) { var i = ETFTable.dataConfig.sort; return SimpleIntRank(v[i.by + "_Rank"], j[i.by + "_Rank"], (i.byDir == "desc")); }); ETFTable.ui.dataSource = new YAHOO.util.LocalDataSource(c[0]); ETFTable.ui.dataSource.responseType = lib.util.DataSource.TYPE_JSON; ETFTable.ui.dataSource.responseSchema = { resultsList: "Results", fields: [], metaFields: { totalRecords: "ResultSet.TotalRecords", sortDirection: "ResultSet.SortDirection", sortKey: "ResultSet.SortKey"} }; ETFTable.ui.dataSource.doBeforeCallback = function(v, j, w, i) { return w; }; var t = []; var n = ETFTable.dataConfig.properties.length, d, k = 0, o = 0, g, m, h; for (var q = 0; q < n; q++) { d = ETFTable.dataConfig.properties[q]; if ((d.showCol && d.showCol == true) || typeof (d.showCol) == "undefined") { if (typeof (d.colGroup) != "undefined") { g = k; for (var p = 0; p < t.length; p++) { if (typeof (t[p].label) != "undefined" && t[p].label == d.colGroup) { g = p; break; } } if (!t[g] || !t[g].children) { m = []; k++; } else { m = t[g].children; } m.push({ key: d.name, label: (typeof (d.label) == "undefined" ? d.name : d.label), sortable: true, resizeable: false, sortOptions: { field: d.name + "_Rank", defaultDir: YAHOO.widget.DataTable.CLASS_DESC }, formatter: d.formatter }); t[g] = { label: d.colGroup, sortable: false, resizeable: false, children: m }; } else { t[k] = { key: d.name, label: (typeof (d.label) == "undefined" ? d.name : d.label), sortable: true, resizeable: false, sortOptions: { field: d.name + "_Rank", defaultDir: lib.widget.DataTable.CLASS_DESC }, formatter: d.formatter }; k++; } h = { key: d.name }; if (d.dataType) { h.parser = d.dataType; } ETFTable.ui.dataSource.responseSchema.fields[o] = h; o++; h = { key: d.name + "_Rank", parser: "number" }; ETFTable.ui.dataSource.responseSchema.fields[o] = h; o++; if (d.hasHistory) { h = { key: d.name + "_Hist" }; ETFTable.ui.dataSource.responseSchema.fields[o] = h; o++; } } } var r = function(i) { ETFTable.ui.dataTable = new lib.widget.DataTable("dataTableContainer", t, ETFTable.ui.dataSource, { paginator: new lib.widget.Paginator({ rowsPerPage: 50, containers: "pagerContainer" }), sortedBy: { key: ETFTable.dataConfig.sort.by, dir: ETFTable.dataConfig.sort.byDir }, scrollable: true, height: i + "px", width: "99.9%", renderLoopSize: 25, draggableColumns: true, resizeable: false }); ETFTable.ui.dataTable.doBeforeSortColumn = function(v, j) { ETFTable.dataConfig.sort.thenBy = ETFTable.dataConfig.sort.by; ETFTable.dataConfig.sort.thenByDir = ETFTable.dataConfig.sort.byDir; ETFTable.dataConfig.sort.by = v.key; ETFTable.dataConfig.sort.byDir = (j == YAHOO.widget.DataTable.CLASS_DESC) ? "desc" : "asc"; lib.util.Cookie.set("relstr.dataConfig.sort", encodeURIComponent(lib.lang.JSON.stringify(ETFTable.dataConfig.sort)), { expires: new Date("1/1/2025") }); return true; }; ETFTable.ui.dataTable.subscribe("rowMouseoverEvent", ETFTable.ui.dataTable.onEventHighlightRow); ETFTable.ui.dataTable.subscribe("rowMouseoutEvent", ETFTable.ui.dataTable.onEventUnhighlightRow); waitComplete(); }; ETFTable.ui.layout.render(); var e = new YAHOO.util.LocalDataSource(ETFTable.dataConfig.filters); e.responseType = lib.util.DataSource.TYPE_JSARRAY; e.responseSchema.responseSchema = { fields: ["property", "operator", "compValue", "showNulls"] }; var b = ["-"], u; for (var q = 0; q < ETFTable.dataConfig.properties.length; q++) { if (ETFTable.dataConfig.properties[q].showCol == undefined || ETFTable.dataConfig.properties[q].showCol == true) { u = "Item." + ETFTable.dataConfig.properties[q].name; if (ETFTable.dataConfig.properties[q].label) { b.push({ label: ETFTable.dataConfig.properties[q].label, value: u }); } else { b.push({ label: u, value: u }); } } } var a = [{ key: "property", label: "Column", editor: new lib.widget.DropdownCellEditor({ dropdownOptions: b, disableBtns: true, asyncSubmitter: function(v, j) { var i = this.getDataTable().getRecordIndex(this.getRecord()); ETFTable.dataConfig.filters[i].property = j; v(true, j); } }) }, { key: "operator", label: "", editor: new lib.widget.DropdownCellEditor({ dropdownOptions: [">", ">=", "<=", "<", "is in list"], disableBtns: true, asyncSubmitter: function(v, j) { var i = this.getDataTable().getRecordIndex(this.getRecord()); ETFTable.dataConfig.filters[i].operator = j; v(true, j); } }) }, { key: "compValue", label: "Filter Value", editor: new lib.widget.TextareaCellEditor({ disableBtns: true, asyncSubmitter: function(v, j) { var i = this.getDataTable().getRecordIndex(this.getRecord()); ETFTable.dataConfig.filters[i].compValue = j; v(true, j); } }) }, { key: "delete", label: " ", className: "delete-button", action: "delete" }, { key: "insert", label: " ", className: "insert-button", action: "insert"}]; var f = new lib.widget.DataTable("filterTableContainer", a, e, { scrollable: true, height: "360px", width: "99.5%" }); f.subscribe("cellClickEvent", function(v) { var x = v.target; var j = this.getColumn(x); switch (j.action) { case "delete": if (confirm("Are you sure you want to delete this filter?")) { var i = this.getRecordIndex(x); ETFTable.dataConfig.filters.splice(i, 1); this.deleteRow(x); } break; case "insert": var i, w; i = this.getRecordIndex(x) + 1; ETFTable.dataConfig.filters.splice(i, 0, { property: "", operator: ">", compValue: "", showNulls: false }); this.addRow({}, i); w = this.getTrEl(i); Dom.addClass(w, "my-highlight-row"); setTimeout(function() { Dom.removeClass(w, "my-highlight-row"); }, 2000); break; default: this.onEventShowCellEditor(v); break; } }); f.subscribe("cellMouseoverEvent", f.onEventHighlightCell); f.subscribe("cellMouseoutEvent", f.onEventUnhighlightCell); lib.util.Event.addListener("btnAddFilter", "click", function(j) { var i = ETFTable.dataConfig.filters.length; ETFTable.dataConfig.filters.splice(i, 0, { property: "", operator: ">", compValue: "", showNulls: false }); f.addRow({}, i); }); lib.util.Event.addListener("btnApplyFilter", "click", function(i) { setWaitStatus(45, "Filtering..."); ETFTable.doPostFilter(ETFTable.expandedData.Results); setWaitStatus(90); ETFTable.expandComplete.fire(ETFTable.expandedAndFilteredData); lib.util.Cookie.set("relstr.dataConfig.filters", encodeURIComponent(lib.lang.JSON.stringify(ETFTable.dataConfig.filters)), { expires: new Date(2025, 1, 1) }); }); ETFTable.ui.layout.getUnitByPosition("right").expand(); });