You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1 line
39 KiB
1 line
39 KiB
/*jshint sub:true*/(function () {'use strict';function $(selector) {return document.querySelector(selector);}function $$(selector, callback) {var elems = document.querySelectorAll(selector);for (var i = 0; i < elems.length; ++i) {if (callback && typeof callback == 'function')callback.call(this, elems[i]);}}var debounce = function (func, wait, now) {var timeout;return function debounced () {var that = this, args = arguments;function delayed() {if (!now)func.apply(that, args);timeout = null;}if (timeout) {clearTimeout(timeout);} else if (now) {func.apply(obj, args);}timeout = setTimeout(delayed, wait || 250);};};window.GoAccess = window.GoAccess || {initialize: function (options) {this.opts = options;this.AppState = {};this.AppTpls = {};this.AppCharts = {};this.AppUIData = (this.opts || {}).uiData || {};this.AppData = (this.opts || {}).panelData || {};this.AppWSConn = (this.opts || {}).wsConnection || {};this.i18n = (this.opts || {}).i18n || {};this.AppPrefs = {'autoHideTables': true,'layout': 'horizontal','perPage': 7,'theme': 'darkPurple',};this.AppPrefs = GoAccess.Util.merge(this.AppPrefs, this.opts.prefs);if (GoAccess.Util.hasLocalStorage()) {var ls = JSON.parse(localStorage.getItem('AppPrefs'));this.AppPrefs = GoAccess.Util.merge(this.AppPrefs, ls);}if (Object.keys(this.AppWSConn).length)this.setWebSocket(this.AppWSConn);},getPanelUI: function (panel) {return panel ? this.AppUIData[panel] : this.AppUIData;},getPrefs: function (panel) {return panel ? this.AppPrefs[panel] : this.AppPrefs;},setPrefs: function () {if (GoAccess.Util.hasLocalStorage()) {localStorage.setItem('AppPrefs', JSON.stringify(GoAccess.getPrefs()));}},getPanelData: function (panel) {return panel ? this.AppData[panel] : this.AppData;},setWebSocket: function (wsConn) {var host = null;host = wsConn.url ? wsConn.url : window.location.hostname ? window.location.hostname : "localhost";var str = /^(wss?:\/\/)?[^\/]+:[0-9]{1,5}\//.test(host + "/") ? host : String(host + ':' + wsConn.port);str = !/^wss?:\/\//i.test(str) ? (window.location.protocol === "https:" ? 'wss://' : 'ws://') + str : str;var socket = new WebSocket(str);socket.onopen = function (event) {GoAccess.Nav.WSOpen();}.bind(this);socket.onmessage = function (event) {this.AppState['updated'] = true;this.AppData = JSON.parse(event.data);this.App.renderData();}.bind(this);socket.onclose = function (event) {GoAccess.Nav.WSClose();}.bind(this);},};GoAccess.Util = {months: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul","Aug", "Sep", "Oct", "Nov", "Dec"],merge: function (o, n) {var obj = {}, i = 0, il = arguments.length, key;for (; i < il; i++) {for (key in arguments[i]) {if (arguments[i].hasOwnProperty(key)) {obj[key] = arguments[i][key];}}}return obj;},hashCode: function (s) {return (s.split('').reduce(function (a, b) {a = ((a << 5) - a) + b.charCodeAt(0);return a&a;}, 0) >>> 0).toString(16);},formatBytes: function (bytes, decimals, numOnly) {if (bytes == 0)return numOnly ? 0 : '0 Byte';var k = 1024;var dm = decimals + 1 || 2;var sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'];var i = Math.floor(Math.log(bytes) / Math.log(k));return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + (numOnly ? '' : (' ' + sizes[i]));},isNumeric: function (n) {return !isNaN(parseFloat(n)) && isFinite(n);},utime2str: function (usec) {if (usec >= 864E8)return ((usec) / 864E8).toFixed(2) + ' d';else if (usec >= 36E8)return ((usec) / 36E8).toFixed(2) + ' h';else if (usec >= 6E7)return ((usec) / 6E7).toFixed(2) + ' m';else if (usec >= 1E6)return ((usec) / 1E6).toFixed(2) + ' s';else if (usec >= 1E3)return ((usec) / 1E3).toFixed(2) + ' ms';return (usec).toFixed(2) + ' us';},formatDate: function (str) {var y = str.substr(0,4), m = str.substr(4,2) - 1, d = str.substr(6,2),h = str.substr(8,2) || 0, i = str.substr(10, 2) || 0, s = str.substr(12, 2) || 0;var date = new Date(y,m,d,h,i,s);var out = ('0' + date.getDate()).slice(-2) + '/' + this.months[date.getMonth()] + '/' + date.getFullYear();10 <= str.length && (out += ":" + h);12 <= str.length && (out += ":" + i);14 <= str.length && (out += ":" + s);return out;},fmtValue: function (value, dataType, decimals) {var val = 0;if (!dataType)val = value;switch (dataType) {case 'utime':val = this.utime2str(value);break;case 'date':val = this.formatDate(value);break;case 'numeric':if (this.isNumeric(value))val = value.toLocaleString();break;case 'bytes':val = this.formatBytes(value, decimals);break;case 'percent':val = parseFloat(value.replace(',', '.')).toFixed(2) + '%';break;case 'time':if (this.isNumeric(value))val = value.toLocaleString();break;case 'secs':val = value + ' secs';break;default:val = value;}return value == 0 ? String(val) : val;},isPanelValid: function (panel) {var data = GoAccess.getPanelData(), ui = GoAccess.getPanelUI();return (!ui.hasOwnProperty(panel) || !data.hasOwnProperty(panel) || !ui[panel].id);},getCount: function (item) {if (this.isObject(item) && 'count' in item)return item.count;return item;},getPercent: function (item) {if (this.isObject(item) && 'percent' in item)return this.fmtValue(item.percent, 'percent');return null;},isObject: function (o) {return o === Object(o);},setProp: function (o, s, v) {var schema = o;var a = s.split('.');for (var i = 0, n = a.length; i < n-1; ++i) {var k = a[i];if (!schema[k])schema[k] = {};schema = schema[k];}schema[a[n-1]] = v;},getProp: function (o, s) {s = s.replace(/\[(\w+)\]/g, '.$1');s = s.replace(/^\./, '');var a = s.split('.');for (var i = 0, n = a.length; i < n; ++i) {var k = a[i];if (this.isObject(o) && k in o) {o = o[k];} else {return;}}return o;},hasLocalStorage: function () {try {localStorage.setItem('test', 'test');localStorage.removeItem('test');return true;} catch(e) {return false;}},isWithinViewPort: function (el) {var elemTop = el.getBoundingClientRect().top;var elemBottom = el.getBoundingClientRect().bottom;return elemTop < window.innerHeight && elemBottom >= 0;},};GoAccess.OverallStats = {renderBox: function (data, ui, row, x, idx) {var wrap = $('.wrap-general-items');if (idx % 6 == 0) {row = document.createElement('div');row.setAttribute('class', 'row');wrap.appendChild(row);}var box = document.createElement('div');box.innerHTML = GoAccess.AppTpls.General.items.render({'id': x,'className': ui.items[x].className,'label': ui.items[x].label,'value': GoAccess.Util.fmtValue(data[x], ui.items[x].dataType),});row.appendChild(box);return row;},renderData: function (data, ui) {var idx = 0, row = null;$('.wrap-general').innerHTML = GoAccess.AppTpls.General.wrap.render(GoAccess.Util.merge(ui, {'lastUpdated': data.date_time,'from': data.start_date,'to': data.end_date,}));for (var x in data) {if (!data.hasOwnProperty(x) || !ui.items.hasOwnProperty(x))continue;row = this.renderBox(data, ui, row, x, idx);idx++;}},initialize: function () {var ui = GoAccess.getPanelUI('general');var data = GoAccess.getPanelData('general'), i = 0;this.renderData(data, ui);}};GoAccess.Nav = {events: function () {$('.nav-bars').onclick = function (e) {e.stopPropagation();this.renderMenu(e);}.bind(this);$('.nav-gears').onclick = function (e) {e.stopPropagation();this.renderOpts(e);}.bind(this);$('.nav-minibars').onclick = function (e) {e.stopPropagation();this.renderOpts(e);}.bind(this);$('body').onclick = function (e) {$('nav').classList.remove('active');}.bind(this);$$('.export-json', function (item) {item.onclick = function (e) {this.downloadJSON(e);}.bind(this);}.bind(this));$$('.theme-bright', function (item) {item.onclick = function (e) {this.setTheme('bright');}.bind(this);}.bind(this));$$('.theme-dark-blue', function (item) {item.onclick = function (e) {this.setTheme('darkBlue');}.bind(this);}.bind(this));$$('.theme-dark-gray', function (item) {item.onclick = function (e) {this.setTheme('darkGray');}.bind(this);}.bind(this));$$('.theme-dark-purple', function (item) {item.onclick = function (e) {this.setTheme('darkPurple');}.bind(this);}.bind(this));$$('.layout-horizontal', function (item) {item.onclick = function (e) {this.setLayout('horizontal');}.bind(this);}.bind(this));$$('.layout-vertical', function (item) {item.onclick = function (e) {this.setLayout('vertical');}.bind(this);}.bind(this));$$('[data-perpage]', function (item) {item.onclick = function (e) {this.setPerPage(e);}.bind(this);}.bind(this));$$('[data-show-tables]', function (item) {item.onclick = function (e) {this.toggleTables();}.bind(this);}.bind(this));$$('[data-autohide-tables]', function (item) {item.onclick = function (e) {this.toggleAutoHideTables();}.bind(this);}.bind(this));},downloadJSON: function (e) {var targ = e.currentTarget;var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(GoAccess.getPanelData()));targ.href = 'data:' + data;targ.download = 'goaccess-' + (+new Date()) + '.json';},setLayout: function (layout) {if ('horizontal' == layout) {$('.container').classList.add('container-fluid');$('.container').classList.remove('container');} else if ('vertical' == layout) {$('.container-fluid').classList.add('container');$('.container').classList.remove('container-fluid');}GoAccess.AppPrefs['layout'] = layout;GoAccess.setPrefs();GoAccess.Panels.initialize();GoAccess.Charts.initialize();GoAccess.Tables.initialize();},toggleAutoHideTables: function (e) {var autoHideTables = GoAccess.Tables.autoHideTables();$$('.table-wrapper', function (item) {if (autoHideTables) {item.classList.remove('hidden-xs');} else {item.classList.add('hidden-xs');}}.bind(this));GoAccess.AppPrefs['autoHideTables'] = !autoHideTables;GoAccess.setPrefs();},toggleTables: function () {var ui = GoAccess.getPanelUI();var showTables = GoAccess.Tables.showTables();Object.keys(ui).forEach(function (panel, idx) {if (!GoAccess.Util.isPanelValid(panel))ui[panel]['table'] = !showTables;}.bind(this));GoAccess.AppPrefs['showTables'] = !showTables;GoAccess.setPrefs();GoAccess.Panels.initialize();GoAccess.Charts.initialize();GoAccess.Tables.initialize();},setTheme: function (theme) {if (!theme)return;$('html').className = '';switch(theme) {case 'darkGray':$('html').classList.add('dark');$('html').classList.add('gray');break;case 'darkBlue':$('html').classList.add('dark');$('html').classList.add('blue');break;case 'darkPurple':$('html').classList.add('dark');$('html').classList.add('purple');break;}GoAccess.AppPrefs['theme'] = theme;GoAccess.setPrefs();},getIcon: function (key) {switch(key) {case 'visitors' : return 'users';case 'requests' : return 'file';case 'static_requests' : return 'file-text';case 'not_found' : return 'file-o';case 'hosts' : return 'user';case 'os' : return 'desktop';case 'browsers' : return 'chrome';case 'visit_time' : return 'clock-o';case 'vhosts' : return 'th-list';case 'referrers' : return 'external-link';case 'referring_sites' : return 'external-link';case 'keyphrases' : return 'google';case 'status_codes' : return 'warning';case 'remote_user' : return 'users';case 'geolocation' : return 'map-marker';default : return 'pie-chart';}},getItems: function () {var ui = GoAccess.getPanelUI(), menu = [];for (var panel in ui) {if (GoAccess.Util.isPanelValid(panel))continue;menu.push({'current': window.location.hash.substr(1) == panel,'head': ui[panel].head,'key': panel,'icon': this.getIcon(panel),});}return menu;},setPerPage: function (e) {GoAccess.AppPrefs['perPage'] = +e.currentTarget.getAttribute('data-perpage');GoAccess.App.renderData();GoAccess.setPrefs();},getTheme: function () {return GoAccess.AppPrefs.theme || 'darkGray';},getLayout: function () {return GoAccess.AppPrefs.layout || 'horizontal';},getPerPage: function () {return GoAccess.AppPrefs.perPage || 7;},renderOpts: function () {var o = {};o[this.getLayout()] = true;o[this.getTheme()] = true;o['perPage' + this.getPerPage()] = true;o['autoHideTables'] = GoAccess.Tables.autoHideTables();o['showTables'] = GoAccess.Tables.showTables();o['labels'] = GoAccess.i18n;$('.nav-list').innerHTML = GoAccess.AppTpls.Nav.opts.render(o);$('nav').classList.toggle('active');this.events();},renderMenu: function (e) {$('.nav-list').innerHTML = GoAccess.AppTpls.Nav.menu.render({'nav': this.getItems(),'overall': window.location.hash.substr(1) == '','labels': GoAccess.i18n,});$('nav').classList.toggle('active');this.events();},WSStatus: function () {if (Object.keys(GoAccess.AppWSConn).length)$$('.nav-ws-status', function (item) { item.style.display = 'block'; });},WSClose: function () {$$('.nav-ws-status', function (item) {item.classList.remove('connected');item.setAttribute('title', 'Disconnected');});},WSOpen: function () {$$('.nav-ws-status', function (item) {item.classList.add('connected');item.setAttribute('title', 'Connected to ' + GoAccess.AppWSConn.url);});},renderWrap: function (nav) {$('nav').innerHTML = GoAccess.AppTpls.Nav.wrap.render(GoAccess.i18n);},initialize: function () {this.setTheme(GoAccess.AppPrefs.theme);this.renderWrap();this.WSStatus();this.events();}};GoAccess.Panels = {events: function () {$$('[data-toggle=dropdown]', function (item) {item.onclick = function (e) {this.openOpts(e.currentTarget);}.bind(this);item.onblur = function (e) {this.closeOpts(e);}.bind(this);}.bind(this));$$('[data-plot]', function (item) {item.onclick = function (e) {GoAccess.Charts.redrawChart(e.currentTarget);}.bind(this);}.bind(this));$$('[data-chart]', function (item) {item.onclick = function (e) {GoAccess.Charts.toggleChart(e.currentTarget);}.bind(this);}.bind(this));$$('[data-chart-type]', function (item) {item.onclick = function (e) {GoAccess.Charts.setChartType(e.currentTarget);}.bind(this);}.bind(this));$$('[data-metric]', function (item) {item.onclick = function (e) {GoAccess.Tables.toggleColumn(e.currentTarget);}.bind(this);}.bind(this));},openOpts: function (targ) {var panel = targ.getAttribute('data-panel');targ.parentElement.classList.toggle('open');this.renderOpts(panel);},closeOpts: function (e) {e.currentTarget.parentElement.classList.remove('open');if (e.relatedTarget && e.relatedTarget.getAttribute('data-toggle') !== 'dropdown')e.relatedTarget.click();},setPlotSelection: function (ui, prefs) {var chartType = ((prefs || {}).plot || {}).chartType || ui.plot[0].chartType;var metric = ((prefs || {}).plot || {}).metric || ui.plot[0].className;ui[chartType] = true;for (var i = 0, len = ui.plot.length; i < len; ++i)if (ui.plot[i].className == metric)ui.plot[i]['selected'] = true;},setColSelection: function (items, prefs) {var columns = (prefs || {}).columns || {};for (var i = 0, len = items.length; i < len; ++i)if ((items[i].key in columns) && columns[items[i].key]['hide'])items[i]['hide'] = true;},setChartSelection: function (ui, prefs) {ui['showChart'] = prefs && ('chart' in prefs) ? prefs.chart : true;},setOpts: function (panel) {var ui = JSON.parse(JSON.stringify(GoAccess.getPanelUI(panel))), prefs = GoAccess.getPrefs(panel);this.setChartSelection(ui, prefs);this.setPlotSelection(ui, prefs);this.setColSelection(ui.items, prefs);return GoAccess.Util.merge(ui, {'labels': GoAccess.i18n});},renderOpts: function (panel) {$('.panel-opts-' + panel).innerHTML = GoAccess.AppTpls.Panels.opts.render(this.setOpts(panel));this.events();},enablePrev: function (panel) {var $pagination = $('#panel-' + panel + ' .pagination a.panel-prev');if ($pagination)$pagination.parentNode.classList.remove('disabled');},disablePrev: function (panel) {var $pagination = $('#panel-' + panel + ' .pagination a.panel-prev');if ($pagination)$pagination.parentNode.classList.add('disabled');},enableNext: function (panel) {var $pagination = $('#panel-' + panel + ' .pagination a.panel-next');if ($pagination)$pagination.parentNode.classList.remove('disabled');},disableNext: function (panel) {var $pagination = $('#panel-' + panel + ' .pagination a.panel-next');if ($pagination)$pagination.parentNode.classList.add('disabled');},enableFirst: function (panel) {var $pagination = $('#panel-' + panel + ' .pagination a.panel-first');if ($pagination)$pagination.parentNode.classList.remove('disabled');},disableFirst: function (panel) {var $pagination = $('#panel-' + panel + ' .pagination a.panel-first');if ($pagination)$pagination.parentNode.classList.add('disabled');},enableLast: function (panel) {var $pagination = $('#panel-' + panel + ' .pagination a.panel-last');if ($pagination)$pagination.parentNode.classList.remove('disabled');},disableLast: function (panel) {var $pagination = $('#panel-' + panel + ' .pagination a.panel-last');if ($pagination)$pagination.parentNode.classList.add('disabled');},enablePagination: function (panel) {this.enablePrev(panel);this.enableNext(panel);this.enableFirst(panel);this.enableLast(panel);},disablePagination: function (panel) {this.disablePrev(panel);this.disableNext(panel);this.disableFirst(panel);this.disableLast(panel);},hasSubItems: function (ui, data) {for (var i = 0, len = data.length; i < len; ++i) {if (!data[i].items)return (ui['hasSubItems'] = false);if (data[i].items.length) {return (ui['hasSubItems'] = true);}}return false;},setComputedData: function (panel, ui, data) {this.hasSubItems(ui, data.data);GoAccess.Charts.hasChart(panel, ui);GoAccess.Tables.hasTable(ui);},renderPanel: function (panel, ui, col) {var data = GoAccess.getPanelData(panel);this.setComputedData(panel, ui, data);var box = document.createElement('div');box.id = 'panel-' + panel;box.innerHTML = GoAccess.AppTpls.Panels.wrap.render(GoAccess.Util.merge(ui, {'labels': GoAccess.i18n}));col.appendChild(box);if (data.data.length <= GoAccess.getPrefs().perPage)this.disablePagination(panel);GoAccess.Tables.renderThead(panel, ui);return col;},createCol: function (row) {var perRow = GoAccess.AppPrefs['layout'] == 'horizontal' ? 6 : 12;var col = document.createElement('div');col.setAttribute('class', 'col-md-' + perRow + ' wrap-panel');row.appendChild(col);return col;},createRow: function (row, idx) {var wrap = $('.wrap-panels');var every = GoAccess.AppPrefs['layout'] == 'horizontal' ? 2 : 1;if (idx % every == 0) {row = document.createElement('div');row.setAttribute('class', 'row' + (every == 2 ? ' equal' : ''));wrap.appendChild(row);}return row;},resetPanel: function (panel) {var ui = GoAccess.getPanelUI(), idx = 0, row = null;var ele = $('#panel-' + panel);if (GoAccess.Util.isPanelValid(panel))return false;var col = ele.parentNode;col.removeChild(ele);this.renderPanel(panel, ui[panel], col);this.events();},renderPanels: function () {var ui = GoAccess.getPanelUI(), idx = 0, row = null, col = null;$('.wrap-panels').innerHTML = '';for (var panel in ui) {if (GoAccess.Util.isPanelValid(panel))continue;row = this.createRow(row, idx++);col = this.createCol(row);col = this.renderPanel(panel, ui[panel], col);}},initialize: function () {this.renderPanels();this.events();}};GoAccess.Charts = {iter: function (callback) {Object.keys(GoAccess.AppCharts).forEach(function (panel) {if (!GoAccess.Util.isWithinViewPort($('#panel-' + panel)))return;if (callback && typeof callback === 'function')callback.call(this, GoAccess.AppCharts[panel], panel);});},getMetricKeys: function (panel, key) {return GoAccess.getPanelUI(panel)['items'].map(function (a) { return a[key]; });},getPanelData: function (panel, data) {var plot = GoAccess.Util.getProp(GoAccess.AppState, panel + '.plot');data = data || this.processChartData(GoAccess.getPanelData(panel).data);return plot.chartReverse ? data.reverse() : data;},drawPlot: function (panel, plotUI, data) {var chart = this.getChart(panel, plotUI, data);if (!chart)return;this.renderChart(panel, chart, data);GoAccess.AppCharts[panel] = null;GoAccess.AppCharts[panel] = chart;},setChartType: function (targ) {var panel = targ.getAttribute('data-panel');var type = targ.getAttribute('data-chart-type');GoAccess.Util.setProp(GoAccess.AppPrefs, panel + '.plot.chartType', type);GoAccess.setPrefs();var plotUI = GoAccess.Util.getProp(GoAccess.AppState, panel + '.plot');this.drawPlot(panel, plotUI, this.getPanelData(panel));},toggleChart: function (targ) {var panel = targ.getAttribute('data-panel');var prefs = GoAccess.getPrefs(panel),chart = prefs && ('chart' in prefs) ? prefs.chart : true;GoAccess.Util.setProp(GoAccess.AppPrefs, panel + '.chart', !chart);GoAccess.setPrefs();GoAccess.Panels.resetPanel(panel);GoAccess.Charts.resetChart(panel);GoAccess.Tables.renderFullTable(panel);},hasChart: function (panel, ui) {var prefs = GoAccess.getPrefs(panel),chart = prefs && ('chart' in prefs) ? prefs.chart : true;ui['chart'] = ui.plot.length && chart && chart;},redrawChart: function (targ) {var plot = targ.getAttribute('data-plot');var panel = targ.getAttribute('data-panel');var ui = GoAccess.getPanelUI(panel);var plotUI = ui.plot;GoAccess.Util.setProp(GoAccess.AppPrefs, panel + '.plot.metric', plot);GoAccess.setPrefs();for (var x in plotUI) {if (!plotUI.hasOwnProperty(x) || plotUI[x].className != plot)continue;GoAccess.Util.setProp(GoAccess.AppState, panel + '.plot', plotUI[x]);this.drawPlot(panel, plotUI[x], this.getPanelData(panel));break;}},extractCount: function (item) {var o = {};for (var prop in item)o[prop] = GoAccess.Util.getCount(item[prop]);return o;},processChartData: function (data) {var out = [];for (var i = 0; i < data.length; ++i)out.push(this.extractCount(data[i]));return out;},findUIItem: function (panel, key) {var items = GoAccess.getPanelUI(panel).items, o = {};for (var i = 0; i < items.length; ++i) {if (items[i].key == key)return items[i];}return null;},getXKey: function (datum, key) {var arr = [];if (typeof key === 'string')return datum[key];for (var prop in key)arr.push(datum[key[prop]]);return arr.join(' ');},getAreaSpline: function (panel, plotUI, data) {var dualYaxis = plotUI['d3']['y1'];var chart = AreaChart(dualYaxis).labels({y0: plotUI['d3']['y0'].label,y1: dualYaxis ? plotUI['d3']['y1'].label : ''}).x(function (d) {if ((((plotUI || {}).d3 || {}).x || {}).key)return this.getXKey(d, plotUI['d3']['x']['key']);return d.data;}.bind(this)).y0(function (d) {return +d[plotUI['d3']['y0']['key']];}).width($("#chart-" + panel).getBoundingClientRect().width).height(175).format({x: (this.findUIItem(panel, 'data') || {}).dataType || null,y0: ((plotUI.d3 || {}).y0 || {}).format,y1: ((plotUI.d3 || {}).y1 || {}).format,}).opts(plotUI);dualYaxis && chart.y1(function (d) {return +d[plotUI['d3']['y1']['key']];});return chart;},getVBar: function (panel, plotUI, data) {var dualYaxis = plotUI['d3']['y1'];var chart = BarChart(dualYaxis).labels({y0: plotUI['d3']['y0'].label,y1: dualYaxis ? plotUI['d3']['y1'].label : ''}).x(function (d) {if ((((plotUI || {}).d3 || {}).x || {}).key)return this.getXKey(d, plotUI['d3']['x']['key']);return d.data;}.bind(this)).y0(function (d) {return +d[plotUI['d3']['y0']['key']];}).width($("#chart-" + panel).getBoundingClientRect().width).height(175).format({x: (this.findUIItem(panel, 'data') || {}).dataType || null,y0: ((plotUI.d3 || {}).y0 || {}).format,y1: ((plotUI.d3 || {}).y1 || {}).format,}).opts(plotUI);dualYaxis && chart.y1(function (d) {return +d[plotUI['d3']['y1']['key']];});return chart;},getChartType: function (panel) {var ui = GoAccess.getPanelUI(panel);if (!ui.chart)return '';return GoAccess.Util.getProp(GoAccess.getPrefs(), panel + '.plot.chartType') || ui.plot[0].chartType;},getPlotUI: function (panel, ui) {var metric = GoAccess.Util.getProp(GoAccess.getPrefs(), panel + '.plot.metric');if (!metric)return ui.plot[0];return ui.plot.filter(function (v) {return v.className == metric;})[0];},getChart: function (panel, plotUI, data) {var chart = null;switch (this.getChartType(panel)) {case 'area-spline':chart = this.getAreaSpline(panel, plotUI, data);break;case 'bar':chart = this.getVBar(panel, plotUI, data);break;}return chart;},renderChart: function (panel, chart, data) {d3.select('#chart-' + panel + '>.chart-tooltip-wrap').remove();d3.select('#chart-' + panel).select('svg').remove();d3.select("#chart-" + panel).datum(data).call(chart).append("div").attr("class", "chart-tooltip-wrap");},addChart: function (panel, ui) {var plotUI = null, chart = null;if (!ui.plot || !ui.plot.length)return;plotUI = this.getPlotUI(panel, ui);GoAccess.Util.setProp(GoAccess.AppState, panel + '.plot', plotUI);var data = this.getPanelData(panel);if (!(chart = this.getChart(panel, plotUI, data)))return;this.renderChart(panel, chart, data);GoAccess.AppCharts[panel] = chart;},renderCharts: function (ui) {for (var panel in ui) {if (!ui.hasOwnProperty(panel))continue;this.addChart(panel, ui[panel]);}},resetChart: function (panel) {var ui = {};if (GoAccess.Util.isPanelValid(panel))return false;ui = GoAccess.getPanelUI(panel);this.addChart(panel, ui);},reloadChart: function (chart, panel) {var subItems = GoAccess.Tables.getSubItemsData(panel);var data = (subItems.length ? subItems : GoAccess.getPanelData(panel).data).slice(0);d3.select("#chart-" + panel).datum(this.processChartData(this.getPanelData(panel, data))).call(chart.width($("#chart-" + panel).offsetWidth));},reloadCharts: function () {this.iter(function (chart, panel) {this.reloadChart(chart, panel);}.bind(this));GoAccess.AppState.updated = false;},redrawCharts: function () {this.iter(function (chart, panel) {d3.select("#chart-" + panel).call(chart.width($("#chart-" + panel).offsetWidth));});},initialize: function () {this.renderCharts(GoAccess.getPanelUI());d3.select(window).on('scroll.charts', debounce(function () {this.reloadCharts();}, 250, false).bind(this)).on('resize.charts', function () {this.redrawCharts();}.bind(this));}};GoAccess.Tables = {chartData: {},events: function () {$$('.panel-next', function (item) {item.onclick = function (e) {var panel = e.currentTarget.getAttribute('data-panel');this.renderTable(panel, this.nextPage(panel));}.bind(this);}.bind(this));$$('.panel-prev', function (item) {item.onclick = function (e) {var panel = e.currentTarget.getAttribute('data-panel');this.renderTable(panel, this.prevPage(panel));}.bind(this);}.bind(this));$$('.panel-first', function (item) {item.onclick = function (e) {var panel = e.currentTarget.getAttribute('data-panel');this.renderTable(panel, "FIRST_PAGE");}.bind(this);}.bind(this));$$('.panel-last', function (item) {item.onclick = function (e) {var panel = e.currentTarget.getAttribute('data-panel');this.renderTable(panel, "LAST_PAGE");}.bind(this);}.bind(this));$$('.expandable>td', function (item) {item.onclick = function (e) {if (!window.getSelection().toString())this.toggleRow(e.currentTarget);}.bind(this);}.bind(this));$$('.row-expandable.clickable', function (item) {item.onclick = function (e) {this.toggleRow(e.currentTarget);}.bind(this);}.bind(this));$$('.sortable', function (item) {item.onclick = function (e) {this.sortColumn(e.currentTarget);}.bind(this);}.bind(this));},toggleColumn: function (targ) {var panel = targ.getAttribute('data-panel');var metric = targ.getAttribute('data-metric');var columns = (GoAccess.getPrefs(panel) || {}).columns || {};if (metric in columns) {delete columns[metric];} else {GoAccess.Util.setProp(columns, metric + '.hide', true);}GoAccess.Util.setProp(GoAccess.AppPrefs, panel + '.columns', columns);GoAccess.setPrefs();GoAccess.Tables.renderThead(panel, GoAccess.getPanelUI(panel));GoAccess.Tables.renderFullTable(panel);},sortColumn: function (ele) {var field = ele.getAttribute('data-key');var order = ele.getAttribute('data-order');var panel = ele.parentElement.parentElement.parentElement.getAttribute('data-panel');order = order ? 'asc' == order ? 'desc' : 'asc' : 'asc';GoAccess.App.sortData(panel, field, order);GoAccess.Util.setProp(GoAccess.AppState, panel + '.sort', {'field': field,'order': order,});this.renderThead(panel, GoAccess.getPanelUI(panel));this.renderTable(panel, this.getCurPage(panel));GoAccess.Charts.reloadChart(GoAccess.AppCharts[panel], panel);},getDataByKey: function (panel, key) {var data = GoAccess.getPanelData(panel).data;for (var i = 0, n = data.length; i < n; ++i) {if (GoAccess.Util.hashCode(data[i].data) == key)return data[i];}return null;},getSubItemsData: function (panel) {var out = [], items = this.chartData[panel];for (var x in items) {if (!items.hasOwnProperty(x))continue;out = out.concat(items[x]);}return out;},addChartData: function (panel, key) {var data = this.getDataByKey(panel, key);var path = panel + '.' + key;if (!data || !data.items)return [];GoAccess.Util.setProp(this.chartData, path, data.items);return this.getSubItemsData(panel);},removeChartData: function (panel, key) {if (GoAccess.Util.getProp(this.chartData, panel + '.' + key))delete this.chartData[panel][key];if (!this.chartData[panel] || Object.keys(this.chartData[panel]).length == 0)return GoAccess.getPanelData(panel).data;return this.getSubItemsData(panel);},isExpanded: function (panel, key) {var path = panel + '.expanded.' + key;return GoAccess.Util.getProp(GoAccess.AppState, path);},toggleExpanded: function (panel, key) {var path = panel + '.expanded.' + key, ret = true;if (this.isExpanded(panel, key)) {delete GoAccess.AppState[panel]['expanded'][key];} else {GoAccess.Util.setProp(GoAccess.AppState, path, true), ret = false;}return ret;},toggleRow: function (ele) {var hide = false, data = [];var row = ele.parentNode;var panel = row.getAttribute('data-panel'), key = row.getAttribute('data-key');var plotUI = GoAccess.AppCharts[panel].opts();hide = this.toggleExpanded(panel, key);this.renderTable(panel, this.getCurPage(panel));if (!plotUI.redrawOnExpand)return;if (!hide) {data = GoAccess.Charts.processChartData(this.addChartData(panel, key));} else {data = GoAccess.Charts.processChartData(this.removeChartData(panel, key));}GoAccess.Charts.drawPlot(panel, plotUI, data);},getCurPage: function (panel) {return GoAccess.Util.getProp(GoAccess.AppState, panel + '.curPage') || 0;},pageOffSet: function (panel) {return ((this.getCurPage(panel) - 1) * GoAccess.getPrefs().perPage);},getTotalPages: function (dataItems) {return Math.ceil(dataItems.length / GoAccess.getPrefs().perPage);},getPage: function (panel, dataItems, page) {var totalPages = this.getTotalPages(dataItems);if (page < 1)page = 1;if (page > totalPages)page = totalPages;GoAccess.Util.setProp(GoAccess.AppState, panel + '.curPage', page);var start = this.pageOffSet(panel);var end = start + GoAccess.getPrefs().perPage;return dataItems.slice(start, end);},prevPage: function (panel) {return this.getCurPage(panel) - 1;},nextPage: function (panel) {return this.getCurPage(panel) + 1;},getMetaValue: function (ui, value) {if ('meta' in ui)return value[ui.meta];return null;},getMetaCell: function (ui, value) {var val = this.getMetaValue(ui, value);var max = (value || {}).max;var min = (value || {}).min;var vtype = ui.metaType || ui.dataType;var className = ui.className || '';className += ui.dataType != 'string' ? 'text-right' : '';return {'className': className,'max' : max != undefined ? GoAccess.Util.fmtValue(max, vtype) : null,'min' : min != undefined ? GoAccess.Util.fmtValue(min, vtype) : null,'value' : val != undefined ? GoAccess.Util.fmtValue(val, vtype) : null,'title' : ui.meta,'label' : ui.metaLabel || null,};},hideColumn: function (panel, col) {var columns = (GoAccess.getPrefs(panel) || {}).columns || {};return ((col in columns) && columns[col]['hide']);},showTables: function () {return ('showTables' in GoAccess.getPrefs()) ? GoAccess.getPrefs().showTables : true;},autoHideTables: function () {return ('autoHideTables' in GoAccess.getPrefs()) ? GoAccess.getPrefs().autoHideTables : true;},hasTable: function (ui) {ui['table'] = this.showTables();ui['autoHideTables'] = this.autoHideTables();},renderMetaRow: function (panel, ui) {var table = $('.table-' + panel + ' tbody.tbody-meta');if (!table)return;var cells = [], uiItems = ui.items;var data = GoAccess.getPanelData(panel).metadata;for (var i = 0; i < uiItems.length; ++i) {var item = uiItems[i];if (this.hideColumn(panel, item.key))continue;var value = data[item.key];cells.push(this.getMetaCell(item, value));}table.innerHTML = GoAccess.AppTpls.Tables.meta.render({row: [{'hasSubItems': ui.hasSubItems,'cells': cells}]});},iterUIItems: function (panel, uiItems, dataItems, callback) {var out = [];for (var i = 0; i < uiItems.length; ++i) {var uiItem = uiItems[i];if (this.hideColumn(panel, uiItem.key))continue;var dataItem = dataItems[uiItem.key];if (callback && typeof callback == 'function') {var ret = callback.call(this, panel, uiItem, dataItem);if (ret) out.push(ret);}}return out;},getObjectCell: function (panel, ui, value) {var className = ui.className || '';className += ui.dataType != 'string' ? 'text-right' : '';return {'className': className,'percent': GoAccess.Util.getPercent(value),'value': GoAccess.Util.fmtValue(GoAccess.Util.getCount(value), ui.dataType)};},renderRow: function (panel, callback, ui, dataItem, idx, subItem, parentId, expanded) {var shadeParent = ((!subItem && idx % 2 != 0) ? 'shaded' : '');var shadeChild = ((parentId % 2 != 0) ? 'shaded' : '');return {'panel' : panel,'idx' : !subItem && (String((idx + 1) + this.pageOffSet(panel))),'key' : !subItem ? GoAccess.Util.hashCode(dataItem.data) : '','expanded' : !subItem && expanded,'parentId' : subItem ? String(parentId) : '','className' : subItem ? 'child ' + shadeChild : 'parent ' + shadeParent,'hasSubItems' : ui.hasSubItems,'items' : dataItem.items ? dataItem.items.length : 0,'cells' : callback.call(this),};},renderRows: function (rows, panel, ui, dataItems, subItem, parentId) {subItem = subItem || false;if (dataItems.length == 0 && ui.items.length) {rows.push({cells: [{className: 'text-center',colspan: ui.items.length + 1,value: 'No data on this panel.'}]});}var cellcb = null;for (var i = 0; i < dataItems.length; ++i) {var dataItem = dataItems[i], data = null, expanded = false;switch(typeof dataItem) {case 'string':data = dataItem;cellcb = function () {return {'colspan': ui.items.length,'value': data};};break;default:data = dataItem.data;cellcb = this.iterUIItems.bind(this, panel, ui.items, dataItem, this.getObjectCell.bind(this));}expanded = this.isExpanded(panel, GoAccess.Util.hashCode(data));rows.push(this.renderRow(panel, cellcb, ui, dataItem, i, subItem, parentId, expanded));if (dataItem.items && dataItem.items.length && expanded) {this.renderRows(rows, panel, ui, dataItem.items, true, i, expanded);}}},renderDataRows: function (panel, ui, dataItems, page) {var table = $('.table-' + panel + ' tbody.tbody-data');if (!table)return;dataItems = this.getPage(panel, dataItems, page);var rows = [];this.renderRows(rows, panel, ui, dataItems);if (rows.length == 0)return;table.innerHTML = GoAccess.AppTpls.Tables.data.render({rows: rows});},togglePagination: function (panel, page, dataItems) {GoAccess.Panels.enablePagination(panel);if (page >= this.getTotalPages(dataItems)) {GoAccess.Panels.disableNext(panel);GoAccess.Panels.disableLast(panel);}if (page <= 1) {GoAccess.Panels.disablePrev(panel);GoAccess.Panels.disableFirst(panel);}},renderTable: function (panel, page) {var dataItems = GoAccess.getPanelData(panel).data;var ui = GoAccess.getPanelUI(panel);if (page === "LAST_PAGE") {page = this.getTotalPages(dataItems);} else if (page === "FIRST_PAGE") {page = 1;}this.togglePagination(panel, page, dataItems);this.renderDataRows(panel, ui, dataItems, page);this.events();},renderFullTable: function (panel) {var ui = GoAccess.getPanelUI(panel), page = 0;var data = GoAccess.getPanelData(panel);if (data.hasOwnProperty('metadata'))this.renderMetaRow(panel, ui);if (data.hasOwnProperty('data')) {page = this.getCurPage(panel);this.togglePagination(panel, page, data.data);this.renderDataRows(panel, ui, data.data, page);}},renderTables: function (force) {var ui = GoAccess.getPanelUI();for (var panel in ui) {if (GoAccess.Util.isPanelValid(panel) || !this.showTables())continue;if (force || GoAccess.Util.isWithinViewPort($('#panel-' + panel)))this.renderFullTable(panel);}},sort2Tpl: function (panel, ui) {var uiClone = JSON.parse(JSON.stringify(ui)), out = [];var sort = GoAccess.Util.getProp(GoAccess.AppState, panel + '.sort');for (var i = 0, len = uiClone.items.length; i < len; ++i) {var item = uiClone.items[i];if (this.hideColumn(panel, item.key))continue;item['sort'] = false;if (item.key == sort.field && sort.order) {item['sort'] = true;item[sort.order.toLowerCase()] = true;}out.push(item);}uiClone.items = out;return uiClone;},renderThead: function (panel, ui) {var $thead = $('.table-' + panel + '>thead'), $colgroup = $('.table-' + panel + '>colgroup');if ($thead && $colgroup && this.showTables()) {ui = this.sort2Tpl(panel, ui);$thead.innerHTML = GoAccess.AppTpls.Tables.head.render(ui);$colgroup.innerHTML = GoAccess.AppTpls.Tables.colgroup.render(ui);}},reloadTables: function () {this.renderTables(false);this.events();},initialize: function () {this.renderTables(true);this.events();d3.select(window).on('scroll.tables', debounce(function () {this.reloadTables();}, 250, false).bind(this));},};GoAccess.App = {hasFocus: true,tpl: function (tpl) {return Hogan.compile(tpl);},setTpls: function () {GoAccess.AppTpls = {'Nav': {'wrap': this.tpl($('#tpl-nav-wrap').innerHTML),'menu': this.tpl($('#tpl-nav-menu').innerHTML),'opts': this.tpl($('#tpl-nav-opts').innerHTML),},'Panels': {'wrap': this.tpl($('#tpl-panel').innerHTML),'opts': this.tpl($('#tpl-panel-opts').innerHTML),},'General': {'wrap': this.tpl($('#tpl-general').innerHTML),'items': this.tpl($('#tpl-general-items').innerHTML),},'Tables': {'colgroup': this.tpl($('#tpl-table-colgroup').innerHTML),'head': this.tpl($('#tpl-table-thead').innerHTML),'meta': this.tpl($('#tpl-table-row-meta').innerHTML),'data': this.tpl($('#tpl-table-row').innerHTML),},};},sortField: function (o, field) {var f = o[field];if (GoAccess.Util.isObject(f) && (f !== null))f = o[field].count;return f;},sortData: function (panel, field, order) {var panelData = GoAccess.getPanelData(panel).data;panelData.sort(function (a, b) {a = this.sortField(a, field);b = this.sortField(b, field);if (typeof a === 'string' && typeof b === 'string')return 'asc' == order ? a.localeCompare(b) : b.localeCompare(a);return 'asc' == order ? a - b : b - a;}.bind(this));},setInitSort: function () {var ui = GoAccess.getPanelUI();for (var panel in ui) {if (GoAccess.Util.isPanelValid(panel))continue;GoAccess.Util.setProp(GoAccess.AppState, panel + '.sort', ui[panel].sort);}},verifySort: function () {var ui = GoAccess.getPanelUI();for (var panel in ui) {if (GoAccess.Util.isPanelValid(panel))continue;var sort = GoAccess.Util.getProp(GoAccess.AppState, panel + '.sort');if (JSON.stringify(sort) === JSON.stringify(ui[panel].sort))continue;this.sortData(panel, sort.field, sort.order);}},initDom: function () {$('nav').classList.remove('hide');$('.container').classList.remove('hide');$('.spinner').classList.add('hide');if (GoAccess.AppPrefs['layout'] == 'horizontal') {$('.container').classList.add('container-fluid');$('.container-fluid').classList.remove('container');}},renderData: function () {if (!this.hasFocus)return;this.verifySort();GoAccess.OverallStats.initialize();if (!GoAccess.AppState.updated)return;GoAccess.Charts.reloadCharts();GoAccess.Tables.reloadTables();},initialize: function () {this.setInitSort();this.setTpls();GoAccess.Nav.initialize();this.initDom();GoAccess.OverallStats.initialize();GoAccess.Panels.initialize();GoAccess.Charts.initialize();GoAccess.Tables.initialize();},};document.addEventListener('visibilitychange', function () {if (document.visibilityState === 'hidden')GoAccess.App.hasFocus = false;if (document.visibilityState === 'visible') {var hasFocus = GoAccess.App.hasFocus;GoAccess.App.hasFocus = true;hasFocus || GoAccess.App.renderData();}});window.onload = function () {GoAccess.initialize({'i18n': window.json_i18n,'uiData': window.user_interface,'panelData': window.json_data,'wsConnection': window.connection || null,'prefs': window.html_prefs || {},});GoAccess.App.initialize();};}()); |