diff --git a/panoramix/assets/.eslintignore b/panoramix/assets/.eslintignore new file mode 100644 index 0000000000..926b5a451b --- /dev/null +++ b/panoramix/assets/.eslintignore @@ -0,0 +1,3 @@ +node_modules/* +vendor/* +javascripts/dist/* diff --git a/panoramix/assets/.eslintrc b/panoramix/assets/.eslintrc new file mode 100644 index 0000000000..66a04af5c4 --- /dev/null +++ b/panoramix/assets/.eslintrc @@ -0,0 +1,234 @@ +{ + "root": true, + + "globals": { + "Symbol": false, + "Map": false, + "Set": false, + "Reflect": false, + }, + + "env": { + "es6": false, + "browser": true, + "node": true, + }, + + "parserOptions": { + "ecmaVersion": 5, + "sourceType": "module" + }, + + "rules": { + "array-bracket-spacing": [2, "never", { + "singleValue": false, + "objectsInArrays": false, + "arraysInArrays": false + }], + "array-callback-return": [2], + "block-spacing": [2, "always"], + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "callback-return": [2, ["callback"]], + "camelcase": [0], + "comma-dangle": [2, "never"], + "comma-spacing": [2], + "comma-style": [2, "last"], + "curly": [2, "all"], + "eqeqeq": 2, + "func-names": [0], + "id-length": [2, { "min": 1, "max": 25, "properties": "never" }], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "keyword-spacing": [2, { + "before": true, + "after": true, + "overrides": { + "return": { "after": true }, + "throw": { "after": true }, + "case": { "after": true } + } + }], + "linebreak-style": [2, "unix"], + "lines-around-comment": [2, { + "beforeBlockComment": false, + "afterBlockComment": false, + "beforeLineComment": false, + "allowBlockStart": true, + "allowBlockEnd": true + }], + "max-depth": [2, 5], + "max-len": [0, 80, 4], + "max-nested-callbacks": [1, 2], + "max-params": [1, 3], + "new-parens": [2], + "newline-after-var": [0], + "no-bitwise": [0], + "no-cond-assign": [2], + "no-console": [2], + "no-const-assign": [2], + "no-constant-condition": [2], + "no-control-regex": [2], + "no-debugger": [2], + "no-delete-var": [2], + "no-dupe-args": [2], + "no-dupe-class-members": [2], + "no-dupe-keys": [2], + "no-duplicate-case": [2], + "no-else-return": [0], + "no-empty": [2], + "no-eq-null": [0], + "no-eval": [2], + "no-ex-assign": [2], + "no-extend-native": [2], + "no-extra-bind": [2], + "no-extra-boolean-cast": [2], + "no-extra-label": [2], + "no-extra-parens": [0], // needed for clearer #math eg (a - b) / c + "no-extra-semi": [2], + "no-fallthrough": [2], + "no-floating-decimal": [2], + "no-func-assign": [2], + "no-implied-eval": [2], + "no-implicit-coercion": [2, { + "boolean": false, + "number": true, + "string": true + }], + "no-implicit-globals": [2], + "no-inline-comments": [0], + "no-invalid-regexp": [2], + "no-irregular-whitespace": [2], + "no-iterator": [2], + "no-label-var": [2], + "no-labels": [2, { "allowLoop": false, "allowSwitch": false }], + "no-lone-blocks": [2], + "no-lonely-if": [2], + "no-loop-func": [2], + "no-magic-numbers": [0], // doesn't work well with vis cosmetic constant + "no-mixed-requires": [1, false], + "no-mixed-spaces-and-tabs": [2, false], + "no-multi-spaces": [2, { + "exceptions": { + "ImportDeclaration": true, + "Property": true, + "VariableDeclarator": true + } + }], + "no-multi-str": [2], + "no-multiple-empty-lines": [2, { "max": 1, "maxEOF": 1 }], + "no-native-reassign": [2], + "no-negated-condition": [2], + "no-negated-in-lhs": [2], + "no-nested-ternary": [0], + "no-new": [2], + "no-new-func": [2], + "no-new-object": [2], + "no-new-require": [0], + "no-new-symbol": [2], + "no-new-wrappers": [2], + "no-obj-calls": [2], + "no-octal": [2], + "no-octal-escape": [2], + "no-path-concat": [0], + "no-process-env": [0], + "no-process-exit": [2], + "no-proto": [2], + "no-redeclare": [2], + "no-regex-spaces": [2], + "no-restricted-modules": [0], + "no-restricted-imports": [0], + "no-restricted-syntax": [2, + "DebuggerStatement", + "LabeledStatement", + "WithStatement" + ], + "no-return-assign": [2, "always"], + "no-script-url": [2], + "no-self-assign": [2], + "no-self-compare": [0], + "no-sequences": [2], + "no-shadow-restricted-names": [2], + "no-spaced-func": [2], + "no-sparse-arrays": [2], + "no-sync": [0], + "no-ternary": [0], + "no-this-before-super": [2], + "no-throw-literal": [2], + "no-trailing-spaces": [2, { "skipBlankLines": false }], + "no-undef": [2, { "typeof": true }], + "no-undef-init": [2], + "no-undefined": [0], + "no-underscore-dangle": [0], // __data__ sometimes + "no-unexpected-multiline": [2], + "no-unmodified-loop-condition": [2], + "no-unneeded-ternary": [2], + "no-unreachable": [2], + "no-unused-expressions": [2], + "no-unused-labels": [2], + "no-unused-vars": [2, { + "vars": "all", + "args": "none", // (d, i) pattern d3 func makes difficult to enforce + "varsIgnorePattern": "jQuery" + }], + "no-use-before-define": [0], + "no-useless-call": [2], + "no-useless-concat": [2], + "no-useless-constructor": [2], + "no-void": [0], + "no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }], + "no-with": [2], + "no-whitespace-before-property": [2], + "object-curly-spacing": [2, "always"], + "object-shorthand": [2, "never"], + "one-var": [0], + "one-var-declaration-per-line": [2, "initializations"], + "operator-assignment": [0, "always"], + "padded-blocks": [0], + "prefer-arrow-callback": [0], + "prefer-const": [0], + "prefer-reflect": [0], + "prefer-rest-params": [0], + "prefer-spread": [0], + "prefer-template": [0], + "quote-props": [2, "as-needed", { "keywords": true }], + "radix": [2], + "require-yield": [2], + "semi": [2], + "semi-spacing": [2, { "before": false, "after": true }], + "sort-vars": [0], + "sort-imports": [0], + "space-before-function-paren": [2, { "anonymous": "always", "named": "never" }], + "space-before-blocks": [2, { "functions": "always", "keywords": "always" }], + "space-in-brackets": [0, "never", { + "singleValue": true, + "arraysInArrays": false, + "arraysInObjects": false, + "objectsInArrays": true, + "objectsInObjects": true, + "propertyName": false + }], + }, + // Temporarily not enforced + "new-cap": [2], // @TODO more tricky for the moment + "newline-per-chained-call": [2, { "ignoreChainWithDepth": 6 }], + "no-param-reassign": [0], // turn on once default args supported + "no-shadow": [2, { // @TODO more tricky for the moment with eg 'data' + "builtinGlobals": false, + "hoist": "functions", + "allow": ["i", "d"] + }], + "space-in-parens": [2, "never"], + "space-infix-ops": [2], + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-comment": [2, "always", { "markers": ["!"] }], + "spaced-line-comment": [0, "always"], + "strict": [2, "global"], + "template-curly-spacing": [2, "never"], + "use-isnan": [2], + "valid-jsdoc": [0], + "valid-typeof": [2], + "vars-on-top": [0], + "wrap-iife": [2], + "wrap-regex": [2], + "yield-star-spacing": [2, { "before": false, "after": true }], + "yoda": [2, "never", { "exceptRange": true, "onlyEquality": false }] +} diff --git a/panoramix/assets/javascripts/dashboard.js b/panoramix/assets/javascripts/dashboard.js index 18ce5818e1..950ed206ac 100644 --- a/panoramix/assets/javascripts/dashboard.js +++ b/panoramix/assets/javascripts/dashboard.js @@ -11,17 +11,16 @@ require('brace/theme/crimson_editor'); require('select2'); require('../node_modules/gridster/dist/jquery.gridster.min.js'); - -var Dashboard = function(dashboardData) { +var Dashboard = function (dashboardData) { var dashboard = $.extend(dashboardData, { filters: {}, - init: function() { + init: function () { this.initDashboardView(); var sliceObjects = [], dash = this; - dashboard.slices.forEach(function(data) { + dashboard.slices.forEach(function (data) { var slice = px.Slice(data, dash); - $("#slice_" + data.slice_id).find('a.refresh').click(function() { + $("#slice_" + data.slice_id).find('a.refresh').click(function () { slice.render(); }); sliceObjects.push(slice); @@ -29,11 +28,10 @@ var Dashboard = function(dashboardData) { }); this.slices = sliceObjects; }, - setFilter: function(slice_id, col, vals) { - console.log([slice_id, col, vals]); + setFilter: function (slice_id, col, vals) { this.addFilter(slice_id, col, vals, false); }, - addFilter: function(slice_id, col, vals, merge) { + addFilter: function (slice_id, col, vals, merge) { if (merge === undefined) { merge = true; } @@ -47,27 +45,27 @@ var Dashboard = function(dashboardData) { } this.refreshExcept(slice_id); }, - readFilters: function() { + readFilters: function () { // Returns a list of human readable active filters return JSON.stringify(this.filters, null, 4); }, - refreshExcept: function(slice_id) { + refreshExcept: function (slice_id) { var immune = this.metadata.filter_immune_slices; - this.slices.forEach(function(slice) { + this.slices.forEach(function (slice) { if (slice.data.slice_id !== slice_id && immune.indexOf(slice.data.slice_id) === -1) { slice.render(); } }); }, - clearFilters: function(slice_id) { + clearFilters: function (slice_id) { delete this.filters[slice_id]; this.refreshExcept(slice_id); }, - removeFilter: function(slice_id, col, vals) { + removeFilter: function (slice_id, col, vals) { if (slice_id in this.filters) { if (col in this.filters[slice_id]) { var a = []; - this.filters[slice_id][col].forEach(function(v) { + this.filters[slice_id][col].forEach(function (v) { if (vals.indexOf(v) < 0) { a.push(v); } @@ -77,29 +75,29 @@ var Dashboard = function(dashboardData) { } this.refreshExcept(slice_id); }, - getSlice: function(slice_id) { - this.slices.forEach(function(slice, i) { + getSlice: function (slice_id) { + this.slices.forEach(function (slice, i) { if (slice.slice_id === slice_id) { return slice; } }); }, - initDashboardView: function() { + initDashboardView: function () { dashboard = this; var gridster = $(".gridster ul").gridster({ widget_margins: [5, 5], widget_base_dimensions: [100, 100], draggable: { - handle: '.drag', + handle: '.drag' }, resize: { enabled: true, - stop: function(e, ui, element) { + stop: function (e, ui, element) { var slice_data = $(element).data('slice'); dashboard.getSlice(slice_data.slice_id).resize(); } }, - serialize_params: function(_w, wgd) { + serialize_params: function (_w, wgd) { return { slice_id: $(_w).attr('slice_id'), col: wgd.col, @@ -107,34 +105,35 @@ var Dashboard = function(dashboardData) { size_x: wgd.size_x, size_y: wgd.size_y }; - }, + } }).data('gridster'); $("div.gridster").css('visibility', 'visible'); - $("#savedash").click(function() { + $("#savedash").click(function () { var expanded_slices = {}; - $.each($(".slice_info"), function(i, d) { + $.each($(".slice_info"), function (i, d) { var widget = $(this).parents('.widget'); var slice_description = widget.find('.slice_description'); - if (slice_description.is(":visible")) + if (slice_description.is(":visible")) { expanded_slices[$(d).attr('slice_id')] = true; + } }); var data = { positions: gridster.serialize(), css: editor.getValue(), - expanded_slices: expanded_slices, + expanded_slices: expanded_slices }; $.ajax({ type: "POST", url: '/panoramix/save_dash/' + dashboard.id + '/', data: { - 'data': JSON.stringify(data) + data: JSON.stringify(data) }, - success: function() { + success: function () { alert("Saved!"); }, - error: function() { + error: function () { alert("Error :("); - }, + } }); }); @@ -144,40 +143,40 @@ var Dashboard = function(dashboardData) { editor.setTheme("ace/theme/crimson_editor"); editor.setOptions({ minLines: 16, - maxLines: Infinity, + maxLines: Infinity }); editor.getSession().setMode("ace/mode/css"); $(".select2").select2({ dropdownAutoWidth: true }); - $("#css_template").on("change", function() { + $("#css_template").on("change", function () { var css = $(this).find('option:selected').data('css'); editor.setValue(css); $('#dash_css').val(css); $("#user_style").html(css); }); - $('#filters').click(function() { + $('#filters').click(function () { alert(dashboard.readFilters()); }); - $("a.closeslice").click(function() { + $("a.closeslice").click(function () { var li = $(this).parents("li"); gridster.remove_widget(li); }); - $(".slice_info").click(function() { + $(".slice_info").click(function () { var widget = $(this).parents('.widget'); var slice_description = widget.find('.slice_description'); - slice_description.slideToggle(500, function() { + slice_description.slideToggle(500, function () { widget.find('.refresh').click(); }); }); - $("table.slice_header").mouseover(function() { + $("table.slice_header").mouseover(function () { $(this).find("td.icons nobr").show(); }); - $("table.slice_header").mouseout(function() { + $("table.slice_header").mouseout(function () { $(this).find("td.icons nobr").hide(); }); - editor.on("change", function() { + editor.on("change", function () { var css = editor.getValue(); $('#dash_css').val(css); $("#user_style").html(css); @@ -188,6 +187,6 @@ var Dashboard = function(dashboardData) { return dashboard; }; -$(document).ready(function() { - var dashboard = Dashboard($('.dashboard').data('dashboard')); +$(document).ready(function () { + Dashboard($('.dashboard').data('dashboard')); }); diff --git a/panoramix/assets/javascripts/explore.js b/panoramix/assets/javascripts/explore.js index 60c7f9be4d..ee5362257f 100644 --- a/panoramix/assets/javascripts/explore.js +++ b/panoramix/assets/javascripts/explore.js @@ -6,7 +6,6 @@ var $ = window.$ = require('jquery'); var jQuery = window.jQuery = $; var px = require('./modules/panoramix.js'); -var d3 = require('d3'); require('jquery-ui'); $.widget.bridge('uitooltip', $.ui.tooltip); // Shutting down jq-ui tooltips @@ -25,29 +24,29 @@ var slice; function prepForm() { var i = 1; // Assigning the right id to form elements in filters - $("#filters > div").each(function() { - $(this).attr("id", function() { - return "flt_" + i; - }) + $("#filters > div").each(function () { + $(this).attr("id", function () { + return "flt_" + i; + }); $(this).find("#flt_col_0") - .attr("id", function() { + .attr("id", function () { return "flt_col_" + i; }) - .attr("name", function() { + .attr("name", function () { return "flt_col_" + i; }); $(this).find("#flt_op_0") - .attr("id", function() { + .attr("id", function () { return "flt_op_" + i; }) - .attr("name", function() { + .attr("name", function () { return "flt_op_" + i; }); $(this).find("#flt_eq_0") - .attr("id", function() { + .attr("id", function () { return "flt_eq_" + i; }) - .attr("name", function() { + .attr("name", function () { return "flt_eq_" + i; }); i++; @@ -83,20 +82,8 @@ function initExploreView() { var fieldset = parent.find(".legend_label").text(); var collapsed_fieldsets = get_collapsed_fieldsets(); var index; - if (!parent.hasClass("collapsed")) { - if (animation) { - parent.find(".fieldset_content").slideUp(); - } else { - parent.find(".fieldset_content").hide(); - } - parent.addClass("collapsed"); - parent.find("span.collapser").text("[+]"); - index = collapsed_fieldsets.indexOf(fieldset); - if (index === -1 && fieldset !== "" && fieldset !== undefined) { - collapsed_fieldsets.push(fieldset); - } - } else { + if (parent.hasClass("collapsed")) { if (animation) { parent.find(".fieldset_content").slideDown(); } else { @@ -110,11 +97,25 @@ function initExploreView() { if (index !== -1) { collapsed_fieldsets.splice(index, 1); } + } else { // not collapsed + if (animation) { + parent.find(".fieldset_content").slideUp(); + } else { + parent.find(".fieldset_content").hide(); + } + + parent.addClass("collapsed"); + parent.find("span.collapser").text("[+]"); + index = collapsed_fieldsets.indexOf(fieldset); + if (index === -1 && fieldset !== "" && fieldset !== undefined) { + collapsed_fieldsets.push(fieldset); + } } + $("#collapsed_fieldsets").val(collapsed_fieldsets.join("||")); } - $('legend').click(function() { + $('legend').click(function () { toggle_fieldset($(this), true); }); @@ -130,7 +131,7 @@ function initExploreView() { try { var successful = document.execCommand('copy'); if (!successful) { - throw "Not successful"; + throw new Error("Not successful"); } } catch (err) { window.alert("Sorry, your browser does not support copying. Use Ctrl / Cmd + C!"); @@ -139,17 +140,17 @@ function initExploreView() { return successful; } - $('#shortner').click(function() { + $('#shortner').click(function () { $.ajax({ type: "POST", url: '/r/shortner/', data: { - 'data': '/' + window.location.pathname + slice.querystring() + data: '/' + window.location.pathname + slice.querystring() }, - success: function(data) { + success: function (data) { var close = ''; var copy = ''; - var spaces = '   ' + var spaces = '   '; var popover = data + spaces + copy + spaces + close; var $shortner = $('#shortner') @@ -161,26 +162,25 @@ function initExploreView() { }) .popover('show'); - $('#copy_url').tooltip().click(function() { + $('#copy_url').tooltip().click(function () { var success = copyURLToClipboard(data); - if (success) { $(this).attr("data-original-title", "Copied!").tooltip('fixTitle').tooltip('show'); - window.setTimeout(function() { - $shortner.popover('destroy'); - }, 1200); + window.setTimeout(destroyPopover, 1200); } }); - $('#close_shortner').click(function() { + $('#close_shortner').click(destroyPopover); + + function destroyPopover() { $shortner.popover('destroy'); - }); + } }, - error: function() { + error: function () { alert("Error :("); - }, + } }); }); - $("#viz_type").change(function() { + $("#viz_type").change(function () { $("#query").submit(); }); @@ -224,12 +224,12 @@ function initExploreView() { $(cp).find("#flt_col_0").val(px.getParam("flt_col_" + i)); } $(cp).find('select').select2(); - $(cp).find('.remove').click(function() { + $(cp).find('.remove').click(function () { $(this).parent().parent().remove(); }); } - $(window).bind("popstate", function(event) { + $(window).bind("popstate", function (event) { // Browser back button var returnLocation = history.location || document.location; // Could do something more lightweight here, but we're not optimizing @@ -237,9 +237,8 @@ function initExploreView() { returnLocation.reload(); }); - $("#plus").click(add_filter); - $("#btn_save").click(function() { + $("#btn_save").click(function () { var slice_name = prompt("Name your slice!"); if (slice_name !== "" && slice_name !== null) { $("#slice_name").val(slice_name); @@ -248,7 +247,7 @@ function initExploreView() { $("#query").submit(); } }); - $("#btn_overwrite").click(function() { + $("#btn_overwrite").click(function () { var flag = confirm("Overwrite slice [" + $("#slice_name").val() + "] !?"); if (flag) { $("#action").val("overwrite"); @@ -260,7 +259,7 @@ function initExploreView() { $(".druidify").click(druidify); function create_choices(term, data) { - var filtered = $(data).filter(function() { + var filtered = $(data).filter(function () { return this.text.localeCompare(term) === 0; }); if (filtered.length === 0) { @@ -278,17 +277,7 @@ function initExploreView() { }); } - function list_data(arr) { - var obj = []; - for (var i = 0; i < arr.length; i++) { - obj.push({ - id: arr[i], - text: arr[i] - }); - } - return obj; - } - $(".select2_freeform").each(function() { + $(".select2_freeform").each(function () { var parent = $(this).parent(); var name = $(this).attr('name'); var l = []; @@ -302,7 +291,7 @@ function initExploreView() { selected = this.options[i].value; } } - var obj = parent.append( + parent.append( '' ); $("input[name='" + name + "']").select2({ @@ -310,20 +299,19 @@ function initExploreView() { initSelection: initSelectionToValue, dropdownAutoWidth: true, multiple: false, - data: l, + data: l }); $(this).remove(); }); } -$(document).ready(function() { +$(document).ready(function () { initExploreView(); // Dynamically register this visualization var visType = window.viz_type.value; px.registerViz(visType); - var data = $('.slice').data('slice'); slice = px.Slice(data); diff --git a/panoramix/assets/javascripts/featured.js b/panoramix/assets/javascripts/featured.js index dc54d4e116..8f7b1414e4 100644 --- a/panoramix/assets/javascripts/featured.js +++ b/panoramix/assets/javascripts/featured.js @@ -4,10 +4,10 @@ require('datatables'); require('datatables-bootstrap3-plugin'); require('bootstrap'); -$(document).ready(function() { +$(document).ready(function () { $('#dataset-table').DataTable({ - "bPaginate": false, - "order": [ + bPaginate: false, + order: [ [1, "asc"] ] }); diff --git a/panoramix/assets/javascripts/modules/panoramix.js b/panoramix/assets/javascripts/modules/panoramix.js index 8500f337df..4696412836 100644 --- a/panoramix/assets/javascripts/modules/panoramix.js +++ b/panoramix/assets/javascripts/modules/panoramix.js @@ -1,5 +1,5 @@ -var $ = require('jquery'), - jQuery = $; +var $ = require('jquery'); +var jQuery = $; var d3 = require('d3'); // vis sources @@ -23,35 +23,36 @@ var sourceMap = { sunburst: 'sunburst.js', table: 'table.js', word_cloud: 'word_cloud.js', - world_map: 'world_map.js', + world_map: 'world_map.js' }; -var color = function() { +var color = function () { // Color related utility functions go in this object var bnbColors = [ //rausch hackb kazan babu lima beach barol '#ff5a5f', '#7b0051', '#007A87', '#00d1c1', '#8ce071', '#ffb400', '#b4a76c', '#ff8083', '#cc0086', '#00a1b3', '#00ffeb', '#bbedab', '#ffd266', '#cbc29a', - '#ff3339', '#ff1ab1', '#005c66', '#00b3a5', '#55d12e', '#b37e00', '#988b4e', + '#ff3339', '#ff1ab1', '#005c66', '#00b3a5', '#55d12e', '#b37e00', '#988b4e' ]; var spectrums = { - 'blue_white_yellow': ['#00d1c1', 'white', '#ffb400'], - 'fire': ['white', 'yellow', 'red', 'black'], - 'white_black': ['white', 'black'], - 'black_white': ['black', 'white'], + blue_white_yellow: ['#00d1c1', 'white', '#ffb400'], + fire: ['white', 'yellow', 'red', 'black'], + white_black: ['white', 'black'], + black_white: ['black', 'white'] }; - var colorBnb = function() { + var colorBnb = function () { // Color factory var seen = {}; - return function(s) { + return function (s) { // next line is for dashed series that should have the same color s = s.replace('---', ''); - if (seen[s] === undefined) + if (seen[s] === undefined) { seen[s] = Object.keys(seen).length; + } return this.bnbColors[seen[s] % this.bnbColors.length]; }; }; - var colorScalerFactory = function(colors, data, accessor) { + var colorScalerFactory = function (colors, data, accessor) { // Returns a linear scaler our of an array of color if (!Array.isArray(colors)) { colors = spectrums[colors]; @@ -64,7 +65,7 @@ var color = function() { var points = []; var chunkSize = (ext[1] - ext[0]) / colors.length; - $.each(colors, function(i, c) { + $.each(colors, function (i, c) { points.push(i * chunkSize); }); return d3.scale.linear().domain(points).range(colors); @@ -72,14 +73,13 @@ var color = function() { return { bnbColors: bnbColors, category21: colorBnb(), - colorScalerFactory: colorScalerFactory, + colorScalerFactory: colorScalerFactory }; }; -var px = (function() { +var px = (function () { var visualizations = {}; - var dashboard; var slice; function getParam(name) { @@ -93,25 +93,25 @@ var px = (function() { return new Date(dttm.getUTCFullYear(), dttm.getUTCMonth(), dttm.getUTCDate(), dttm.getUTCHours(), dttm.getUTCMinutes(), dttm.getUTCSeconds()); } var tickMultiFormat = d3.time.format.multi([ - [".%L", function(d) { + [".%L", function (d) { return d.getMilliseconds(); }], // If there are millisections, show only them - [":%S", function(d) { + [":%S", function (d) { return d.getSeconds(); }], // If there are seconds, show only them - ["%a %b %d, %I:%M %p", function(d) { + ["%a %b %d, %I:%M %p", function (d) { return d.getMinutes() !== 0; }], // If there are non-zero minutes, show Date, Hour:Minute [AM/PM] - ["%a %b %d, %I %p", function(d) { + ["%a %b %d, %I %p", function (d) { return d.getHours() !== 0; }], // If there are hours that are multiples of 3, show date and AM/PM - ["%a %b %d, %Y", function(d) { + ["%a %b %d, %Y", function (d) { return d.getDate() !== 1; }], // If not the first of the month, do "month day, year." - ["%B %Y", function(d) { + ["%B %Y", function (d) { return d.getMonth() !== 0 && d.getDate() === 1; }], // If the first of the month, do "month day, year." - ["%Y", function(d) { + ["%Y", function (d) { return true; }] // fall back on month, year ]); @@ -124,28 +124,27 @@ var px = (function() { function timeFormatFactory(d3timeFormat) { var f = d3.time.format(d3timeFormat); - return function(dttm) { + return function (dttm) { var d = UTC(new Date(dttm)); return f(d); }; } - var Slice = function(data, dashboard) { + var Slice = function (data, dashboard) { var timer; var token = $('#' + data.token); var container_id = data.token + '_con'; var selector = '#' + container_id; var container = $(selector); var slice_id = data.slice_id; - var name = data.viz_name; var dttm = 0; - var stopwatch = function() { + var stopwatch = function () { dttm += 10; var num = dttm / 1000; $('#timer').text(num.toFixed(2) + " sec"); }; var qrystr = ''; - var always = function(data) { + var always = function (data) { //Private f, runs after done and error clearInterval(timer); $('#timer').removeClass('btn-warning'); @@ -155,7 +154,7 @@ var px = (function() { container: container, container_id: container_id, selector: selector, - querystring: function() { + querystring: function () { var parser = document.createElement('a'); parser.href = data.json_endpoint; if (dashboard !== undefined) { @@ -168,13 +167,13 @@ var px = (function() { } return qrystr; }, - jsonEndpoint: function() { + jsonEndpoint: function () { var parser = document.createElement('a'); parser.href = data.json_endpoint; var endpoint = parser.pathname + this.querystring() + "&json=true"; return endpoint; }, - done: function(data) { + done: function (data) { clearInterval(timer); token.find("img.loading").hide(); container.show(); @@ -184,19 +183,19 @@ var px = (function() { $('#timer').removeClass('btn-warning'); $('#timer').addClass('btn-success'); $('span.query').removeClass('disabled'); - $('#json').click(function() { + $('#json').click(function () { window.location = data.json_endpoint; }); - $('#standalone').click(function() { + $('#standalone').click(function () { window.location = data.standalone_endpoint; }); - $('#csv').click(function() { + $('#csv').click(function () { window.location = data.csv_endpoint; }); $('.btn-group.results span').removeAttr('disabled'); always(data); }, - error: function(msg) { + error: function (msg) { token.find("img.loading").hide(); var err = '
' + msg + '
'; container.html(err); @@ -205,19 +204,20 @@ var px = (function() { $('#timer').addClass('btn-danger'); always(data); }, - width: function() { + width: function () { return token.width(); }, - height: function() { + height: function () { var others = 0; var widget = container.parents('.widget'); var slice_description = widget.find('.slice_description'); - if (slice_description.is(":visible")) + if (slice_description.is(":visible")) { others += widget.find('.slice_description').height() + 25; + } others += widget.find('.slice_header').height(); return widget.height() - others; }, - render: function() { + render: function () { $('.btn-group.results span').attr('disabled', 'disabled'); token.find("img.loading").show(); container.hide(); @@ -228,29 +228,33 @@ var px = (function() { $('#timer').addClass('btn-warning'); this.viz.render(); }, - resize: function() { + resize: function () { token.find("img.loading").show(); container.hide(); container.html(''); this.viz.render(); this.viz.resize(); }, - addFilter: function(col, vals) { - if (dashboard !== undefined) + addFilter: function (col, vals) { + if (dashboard !== undefined) { dashboard.addFilter(slice_id, col, vals); + } }, - setFilter: function(col, vals) { - if (dashboard !== undefined) + setFilter: function (col, vals) { + if (dashboard !== undefined) { dashboard.setFilter(slice_id, col, vals); + } }, - clearFilter: function() { - if (dashboard !== undefined) + clearFilter: function () { + if (dashboard !== undefined) { delete dashboard.clearFilter(slice_id); + } }, - removeFilter: function(col, vals) { - if (dashboard !== undefined) + removeFilter: function (col, vals) { + if (dashboard !== undefined) { delete dashboard.removeFilter(slice_id, col, vals); - }, + } + } }; var visType = data.form_data.viz_type; px.registerViz(visType); @@ -267,47 +271,10 @@ var px = (function() { visualizations[name] = visFactory; } } else { - console.error("require(", visType, ") failed."); + throw new Error("require(" + name + ") failed."); } } - function prepForm() { - var i = 1; - // Assigning the right id to form elements in filters - $("#filters > div").each(function() { - $(this).attr("id", function() { - return "flt_" + i; - }); - $(this).find("#flt_col_0") - .attr("id", function() { - return "flt_col_" + i; - }) - .attr("name", function() { - return "flt_col_" + i; - }); - $(this).find("#flt_op_0") - .attr("id", function() { - return "flt_op_" + i; - }) - .attr("name", function() { - return "flt_op_" + i; - }); - $(this).find("#flt_eq_0") - .attr("id", function() { - return "flt_eq_" + i; - }) - .attr("name", function() { - return "flt_eq_" + i; - }); - i++; - }); - } - - function renderSlice() { - prepForm(); - slice.render(); - } - // Export public functions return { registerViz: registerViz, @@ -315,7 +282,7 @@ var px = (function() { formatDate: formatDate, timeFormatFactory: timeFormatFactory, color: color(), - getParam: getParam, + getParam: getParam }; })(); diff --git a/panoramix/assets/javascripts/sql.js b/panoramix/assets/javascripts/sql.js index 57f2f79065..daa33740e9 100644 --- a/panoramix/assets/javascripts/sql.js +++ b/panoramix/assets/javascripts/sql.js @@ -8,7 +8,7 @@ var ace = require('brace'); require('brace/mode/sql'); require('brace/theme/crimson_editor'); -$(document).ready(function() { +$(document).ready(function () { function getParam(name) { name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), @@ -22,11 +22,11 @@ $(document).ready(function() { editor.$blockScrolling = Infinity; editor.getSession().setUseWrapMode(true); - var textarea = $('#sql').hide(); + $('#sql').hide(); editor.setTheme("ace/theme/crimson_editor"); editor.setOptions({ minLines: 16, - maxLines: Infinity, + maxLines: Infinity }); editor.getSession().setMode("ace/mode/sql"); editor.focus(); @@ -40,26 +40,28 @@ $(document).ready(function() { } $("#dbtable").on("change", showTableMetadata); showTableMetadata(); - $("#create_view").click(function() { + $("#create_view").click(function () { alert("Not implemented"); }); $(".sqlcontent").show(); - $("#select_star").click(function() { + + function selectStarOnClick() { $.ajax('/panoramix/select_star/' + database_id + '/' + $("#dbtable").val() + '/') - .done(function(msg) { + .done(function (msg) { editor.setValue(msg); }); - }); + } + + $("#select_star").click(selectStarOnClick); + editor.setValue(getParam('sql')); - $(window).bind("popstate", function(event) { - // Browser back button - var returnLocation = history.location || document.location; + $(window).bind("popstate", function (event) { // Could do something more lightweight here, but we're not optimizing // for the use of the back button anyways editor.setValue(getParam('sql')); $("#run").click(); }); - $("#run").click(function() { + $("#run").click(function () { $('#results').hide(0); $('#loading').show(0); history.pushState({}, document.title, '?sql=' + encodeURIComponent(editor.getValue())); @@ -67,27 +69,27 @@ $(document).ready(function() { type: "POST", url: '/panoramix/runsql/', data: { - 'data': JSON.stringify({ - 'database_id': $('#database_id').val(), - 'sql': editor.getSession().getValue(), + data: JSON.stringify({ + database_id: $('#database_id').val(), + sql: editor.getSession().getValue() }) }, - success: function(data) { + success: function (data) { $('#loading').hide(0); $('#results').show(0); $('#results').html(data); - var datatable = $('table.sql_results').DataTable({ + $('table.sql_results').DataTable({ paging: false, searching: true, - aaSorting: [], + aaSorting: [] }); }, - error: function(err, err2) { + error: function (err, err2) { $('#loading').hide(0); $('#results').show(0); $('#results').html(err.responseText); - }, + } }); }); } diff --git a/panoramix/assets/javascripts/standalone.js b/panoramix/assets/javascripts/standalone.js index 31ba1eabe6..333fdd43c6 100644 --- a/panoramix/assets/javascripts/standalone.js +++ b/panoramix/assets/javascripts/standalone.js @@ -2,9 +2,9 @@ var $ = window.$ = require('jquery'); var jQuery = window.jQuery = $; var px = require('./modules/panoramix.js'); -require('bootstrap') +require('bootstrap'); -$(document).ready(function() { +$(document).ready(function () { var slice; var data = $('.slice').data('slice'); slice = px.Slice(data); diff --git a/panoramix/assets/package.json b/panoramix/assets/package.json index fd97477b36..7884ace77a 100644 --- a/panoramix/assets/package.json +++ b/panoramix/assets/package.json @@ -9,7 +9,9 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack -d --watch --colors", - "prod": "webpack -p --colors" + "prod": "webpack -p --colors", + "lint": "npm run --silent lint:js", + "lint:js": "eslint --ignore-path=.eslintignore --ext .js .; exit 0;" }, "repository": { "type": "git", @@ -65,6 +67,7 @@ }, "devDependencies": { "css-loader": "^0.23.1", + "eslint": "^2.2.0", "style-loader": "^0.13.0" } } diff --git a/panoramix/assets/visualizations/big_number.js b/panoramix/assets/visualizations/big_number.js index db46745e1a..f1b0461ec6 100644 --- a/panoramix/assets/visualizations/big_number.js +++ b/panoramix/assets/visualizations/big_number.js @@ -7,11 +7,10 @@ require('./big_number.css'); var px = require('../javascripts/modules/panoramix.js'); function bigNumberVis(slice) { - var data_attribute = slice.data; var div = d3.select(slice.selector); function render() { - d3.json(slice.jsonEndpoint(), function(error, payload) { + d3.json(slice.jsonEndpoint(), function (error, payload) { //Define the percentage bounds that define color from red to green if (error !== null) { slice.error(error.responseText); @@ -20,8 +19,6 @@ function bigNumberVis(slice) { var fd = payload.form_data; var json = payload.data; var color_range = [-1, 1]; - var compare_pos = -23; - var target_url = 'd3js.org'; var f = d3.format(fd.y_axis_format); var fp = d3.format('+.1%'); @@ -40,10 +37,10 @@ function bigNumberVis(slice) { v_compare = (v / data[pos][1]) - 1; } } - var date_ext = d3.extent(data, function(d) { + var date_ext = d3.extent(data, function (d) { return d[0]; }); - var value_ext = d3.extent(data, function(d) { + var value_ext = d3.extent(data, function (d) { return d[1]; }); @@ -56,18 +53,19 @@ function bigNumberVis(slice) { .interpolate(d3.interpolateHsl) .range(colorRange).clamp(true); var line = d3.svg.line() - .x(function(d) { + .x(function (d) { return scale_x(d[0]); }) - .y(function(d) { + .y(function (d) { return scale_y(d[1]); }) .interpolate("basis"); //Drawing trend line var g = svg.append('g'); - var path = g.append('path') - .attr('d', function(d) { + + g.append('path') + .attr('d', function (d) { return line(data); }) .attr('stroke-width', 5) @@ -137,14 +135,14 @@ function bigNumberVis(slice) { g.selectAll("text") .style('font-size', '10px'); - div.on('mouseover', function(d) { + div.on('mouseover', function (d) { var div = d3.select(this); div.select('path').transition().duration(500).attr('opacity', 1) .style('stroke-width', '2px'); div.select('g.digits').transition().duration(500).attr('opacity', 0.1); div.select('g.axis').transition().duration(500).attr('opacity', 1); }) - .on('mouseout', function(d) { + .on('mouseout', function (d) { var div = d3.select(this); div.select('path').transition().duration(500).attr('opacity', 0.5) .style('stroke-width', '5px'); @@ -157,7 +155,7 @@ function bigNumberVis(slice) { return { render: render, - resize: render, + resize: render }; } diff --git a/panoramix/assets/visualizations/directed_force.js b/panoramix/assets/visualizations/directed_force.js index 28fe1834c3..a0252067e6 100644 --- a/panoramix/assets/visualizations/directed_force.js +++ b/panoramix/assets/visualizations/directed_force.js @@ -10,10 +10,10 @@ function directedForceVis(slice) { var link_length = slice.data.form_data.link_length || 200; var charge = slice.data.form_data.charge || -500; - var render = function() { + var render = function () { var width = slice.width(); var height = slice.height() - 25; - d3.json(slice.jsonEndpoint(), function(error, json) { + d3.json(slice.jsonEndpoint(), function (error, json) { if (error !== null) { slice.error(error.responseText); @@ -22,14 +22,14 @@ function directedForceVis(slice) { var links = json.data; var nodes = {}; // Compute the distinct nodes from the links. - links.forEach(function(link) { + links.forEach(function (link) { link.source = nodes[link.source] || (nodes[link.source] = { name: link.source }); link.target = nodes[link.target] || (nodes[link.target] = { name: link.target }); - link.value = +link.value; + link.value = Number(link.value); var target_name = link.target.name; var source_name = link.source.name; @@ -90,7 +90,7 @@ function directedForceVis(slice) { .data(force.links()) .enter().append("svg:path") .attr("class", "link") - .style("opacity", function(d) { + .style("opacity", function (d) { return edgeScale(d.value / d.target.max); }) .attr("marker-end", "url(#end)"); @@ -100,7 +100,7 @@ function directedForceVis(slice) { .data(force.nodes()) .enter().append("g") .attr("class", "node") - .on("mouseenter", function(d) { + .on("mouseenter", function (d) { d3.select(this) .select("circle") .transition() @@ -111,7 +111,7 @@ function directedForceVis(slice) { .transition() .style('font-size', 25); }) - .on("mouseleave", function(d) { + .on("mouseleave", function (d) { d3.select(this) .select("circle") .transition() @@ -124,7 +124,7 @@ function directedForceVis(slice) { .call(force.drag); // add the nodes - var ext = d3.extent(d3.values(nodes), function(d) { + var ext = d3.extent(d3.values(nodes), function (d) { return Math.sqrt(d.total); }); var circleScale = d3.scale.linear() @@ -132,7 +132,7 @@ function directedForceVis(slice) { .range([3, 30]); node.append("circle") - .attr("r", function(d) { + .attr("r", function (d) { return circleScale(Math.sqrt(d.total)); }); @@ -140,13 +140,13 @@ function directedForceVis(slice) { node.append("text") .attr("x", 6) .attr("dy", ".35em") - .text(function(d) { + .text(function (d) { return d.name; }); // add the curvy lines function tick() { - path.attr("d", function(d) { + path.attr("d", function (d) { var dx = d.target.x - d.source.x, dy = d.target.y - d.source.y, dr = Math.sqrt(dx * dx + dy * dy); @@ -158,7 +158,7 @@ function directedForceVis(slice) { d.target.y; }); - node.attr("transform", function(d) { + node.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; }); } @@ -168,7 +168,7 @@ function directedForceVis(slice) { }; return { render: render, - resize: render, + resize: render }; } diff --git a/panoramix/assets/visualizations/filter_box.js b/panoramix/assets/visualizations/filter_box.js index 2b43d6531e..249e8efa57 100644 --- a/panoramix/assets/visualizations/filter_box.js +++ b/panoramix/assets/visualizations/filter_box.js @@ -1,4 +1,6 @@ // JS +var $ = window.$ = require('jquery'); +var jQuery = window.jQuery = $; var d3 = window.d3 || require('d3'); // CSS @@ -8,7 +10,7 @@ function filterBox(slice) { var filtersObj = {}; var d3token = d3.select(slice.selector); - var fltChanged = function() { + var fltChanged = function () { for (var filter in filtersObj) { var obj = filtersObj[filter]; var val = obj.val(); @@ -20,25 +22,27 @@ function filterBox(slice) { } }; - var refresh = function() { + var refresh = function () { d3token.selectAll("*").remove(); var container = d3token .append('div') .classed('padded', true); - $.getJSON(slice.jsonEndpoint(), function(payload) { + $.getJSON(slice.jsonEndpoint(), function (payload) { var maxes = {}; + for (var filter in payload.data) { var data = payload.data[filter]; - maxes[filter] = d3.max(data, function(d) { + maxes[filter] = d3.max(data, function (d) { return d.metric; }); var id = 'fltbox__' + filter; var div = container.append('div'); + div.append("label").text(filter); - var sel = div - .append('div') + + div.append('div') .attr('name', filter) .classed('form-control', true) .attr('multiple', '') @@ -50,28 +54,30 @@ function filterBox(slice) { dropdownAutoWidth: true, data: data, multiple: true, - formatResult: function(result, container, query, escapeMarkup) { - var perc = Math.round((result.metric / maxes[result.filter]) * 100); - var style = 'padding: 2px 5px;'; - style += "background-image: "; - style += "linear-gradient(to right, lightgrey, lightgrey " + perc + "%, rgba(0,0,0,0) " + perc + "%"; - - $(container).attr('style', 'padding: 0px; background: white;'); - $(container).addClass('filter_box'); - return '
' + result.text + '
'; - }, + formatResult: select2Formatter }) .on('change', fltChanged); } slice.done(); + + function select2Formatter(result, container /*, query, escapeMarkup*/) { + var perc = Math.round((result.metric / maxes[result.filter]) * 100); + var style = 'padding: 2px 5px;'; + style += "background-image: "; + style += "linear-gradient(to right, lightgrey, lightgrey " + perc + "%, rgba(0,0,0,0) " + perc + "%"; + + $(container).attr('style', 'padding: 0px; background: white;'); + $(container).addClass('filter_box'); + return '
' + result.text + '
'; + } }) - .fail(function(xhr) { + .fail(function (xhr) { slice.error(xhr.responseText); }); }; return { render: refresh, - resize: refresh, + resize: refresh }; } diff --git a/panoramix/assets/visualizations/heatmap.js b/panoramix/assets/visualizations/heatmap.js index 895cae8922..1112ae3807 100644 --- a/panoramix/assets/visualizations/heatmap.js +++ b/panoramix/assets/visualizations/heatmap.js @@ -24,7 +24,7 @@ function heatmapVis(slice) { var hmWidth = width - (margins.l + margins.r); var hmHeight = height - (margins.b + margins.t); var fp = d3.format('.3p'); - d3.json(slice.jsonEndpoint(), function(error, payload) { + d3.json(slice.jsonEndpoint(), function (error, payload) { var matrix = {}; if (error) { slice.error(error.responseText); @@ -38,10 +38,10 @@ function heatmapVis(slice) { reverse = false; } var domain = {}; - $.each(data, function(i, d) { + $.each(data, function (i, d) { domain[d[k]] = true; }); - domain = Object.keys(domain).sort(function(a, b) { + domain = Object.keys(domain).sort(function (a, b) { return b - a; }); if (reverse) { @@ -104,12 +104,12 @@ function heatmapVis(slice) { var tip = d3.tip() .attr('class', 'd3-tip') - .offset(function() { + .offset(function () { var k = d3.mouse(this); var x = k[0] - (hmWidth / 2); return [k[1] - 20, x]; }) - .html(function(d) { + .html(function (d) { var k = d3.mouse(this); var m = Math.floor(scale[0].invert(k[0])); var n = Math.floor(scale[1].invert(k[1])); @@ -126,21 +126,18 @@ function heatmapVis(slice) { rect.call(tip); - var xscale_skip = 2; - var yscale_skip = 2; - var xAxis = d3.svg.axis() .scale(xRbScale) .tickValues(xRbScale.domain().filter( - function(d, i) { - return !(i % (parseInt(fd.xscale_interval))); + function (d, i) { + return !(i % (parseInt(fd.xscale_interval, 10))); })) .orient("bottom"); var yAxis = d3.svg.axis() .scale(yRbScale) .tickValues(yRbScale.domain().filter( - function(d, i) { - return !(i % (parseInt(fd.yscale_interval))); + function (d, i) { + return !(i % (parseInt(fd.yscale_interval, 10))); })) .orient("left"); @@ -163,9 +160,6 @@ function heatmapVis(slice) { var context = canvas.node().getContext("2d"); context.imageSmoothingEnabled = false; - var imageObj; - var imageDim; - var imageScale; createImageObj(); // Compute the pixel colors; scaled by CSS. @@ -173,15 +167,17 @@ function heatmapVis(slice) { var imageObj = new Image(); var image = context.createImageData(heatmapDim[0], heatmapDim[1]); var pixs = {}; - $.each(data, function(i, d) { + $.each(data, function (i, d) { var c = d3.rgb(color(d.perc)); var x = xScale(d.x); var y = yScale(d.y); pixs[x + (y * xScale.domain().length)] = c; - if (matrix[x] === undefined) + if (matrix[x] === undefined) { matrix[x] = {}; - if (matrix[x][y] === undefined) + } + if (matrix[x][y] === undefined) { matrix[x][y] = d; + } }); var p = -1; @@ -206,7 +202,7 @@ function heatmapVis(slice) { } return { render: refresh, - resize: refresh, + resize: refresh }; } diff --git a/panoramix/assets/visualizations/iframe.js b/panoramix/assets/visualizations/iframe.js index f2faae8f69..0f9fddc8ba 100644 --- a/panoramix/assets/visualizations/iframe.js +++ b/panoramix/assets/visualizations/iframe.js @@ -4,21 +4,21 @@ function iframeWidget(slice) { function refresh() { $('#code').attr('rows', '15'); - $.getJSON(slice.jsonEndpoint(), function(payload) { + $.getJSON(slice.jsonEndpoint(), function (payload) { slice.container.html(''); var iframe = slice.container.find('iframe'); iframe.css('height', slice.height()); iframe.attr('src', payload.form_data.url); slice.done(); }) - .fail(function(xhr) { + .fail(function (xhr) { slice.error(xhr.responseText); }); } return { render: refresh, - resize: refresh, + resize: refresh }; } diff --git a/panoramix/assets/visualizations/markup.js b/panoramix/assets/visualizations/markup.js index 3c31ce5a14..f202c92dd9 100644 --- a/panoramix/assets/visualizations/markup.js +++ b/panoramix/assets/visualizations/markup.js @@ -5,18 +5,18 @@ function markupWidget(slice) { function refresh() { $('#code').attr('rows', '15'); - $.getJSON(slice.jsonEndpoint(), function(payload) { + $.getJSON(slice.jsonEndpoint(), function (payload) { slice.container.html(payload.data.html); slice.done(); }) - .fail(function(xhr) { + .fail(function (xhr) { slice.error(xhr.responseText); }); } return { render: refresh, - resize: refresh, + resize: refresh }; } diff --git a/panoramix/assets/visualizations/nvd3_vis.js b/panoramix/assets/visualizations/nvd3_vis.js index e949687d7e..b9a15fa317 100644 --- a/panoramix/assets/visualizations/nvd3_vis.js +++ b/panoramix/assets/visualizations/nvd3_vis.js @@ -1,7 +1,8 @@ // JS -var $ = window.$ || require('jquery'); +var $ = window.$ || require('jquery'); +var d3 = window.d3 || require('d3'); var px = window.px || require('../javascripts/modules/panoramix.js'); -require('nvd3'); +var nv = require('nvd3'); // CSS require('../node_modules/nvd3/build/nv.d3.min.css'); @@ -9,19 +10,17 @@ require('./nvd3_vis.css'); function nvd3Vis(slice) { var chart; - var data = {}; - var render = function() { - $.getJSON(slice.jsonEndpoint(), function(payload) { + var render = function () { + $.getJSON(slice.jsonEndpoint(), function (payload) { var fd = payload.form_data; var viz_type = fd.viz_type; var f = d3.format('.3s'); var colorKey = 'key'; - nv.addGraph(function() { + nv.addGraph(function () { switch (viz_type) { - case 'line': if (fd.show_brush) { chart = nv.models.lineWithFocusChart(); @@ -93,13 +92,13 @@ function nvd3Vis(slice) { break; case 'bubble': - var row = function(col1, col2) { + var row = function (col1, col2) { return "" + col1 + "" + col2 + ""; }; chart = nv.models.scatterChart(); chart.showDistX(true); chart.showDistY(true); - chart.tooltip.contentGenerator(function(obj) { + chart.tooltip.contentGenerator(function (obj) { var p = obj.point; var s = ""; s += ''; @@ -122,7 +121,7 @@ function nvd3Vis(slice) { break; default: - console.error("unrecognized visualization for nvd3", viz_type); + throw new Error("Unrecognized visualization for nvd3" + viz_type); } if ("showLegend" in chart && typeof fd.show_legend !== 'undefined') { @@ -151,7 +150,7 @@ function nvd3Vis(slice) { } if (viz_type === 'bubble') { chart.xAxis.tickFormat(d3.format('.3s')); - } else if (fd.x_axis_format == 'smart_date') { + } else if (fd.x_axis_format === 'smart_date') { chart.xAxis.tickFormat(px.formatDate); } else if (fd.x_axis_format !== undefined) { chart.xAxis.tickFormat(px.timeFormatFactory(fd.x_axis_format)); @@ -160,7 +159,7 @@ function nvd3Vis(slice) { chart.yAxis.tickFormat(d3.format('.3s')); } - if (fd.contribution || fd.num_period_compare || viz_type == 'compare') { + if (fd.contribution || fd.num_period_compare || viz_type === 'compare') { chart.yAxis.tickFormat(d3.format('.3p')); if (chart.y2Axis !== undefined) { chart.y2Axis.tickFormat(d3.format('.3p')); @@ -173,7 +172,7 @@ function nvd3Vis(slice) { } } - chart.color(function(d, i) { + chart.color(function (d, i) { return px.color.category21(d[colorKey]); }); @@ -189,12 +188,12 @@ function nvd3Vis(slice) { slice.done(payload); }) - .fail(function(xhr) { + .fail(function (xhr) { slice.error(xhr.responseText); }); }; - var update = function() { + var update = function () { if (chart && chart.update) { chart.update(); } @@ -202,7 +201,7 @@ function nvd3Vis(slice) { return { render: render, - resize: update, + resize: update }; } diff --git a/panoramix/assets/visualizations/parallel_coordinates.js b/panoramix/assets/visualizations/parallel_coordinates.js index 575db6d3c1..271989b9f1 100644 --- a/panoramix/assets/visualizations/parallel_coordinates.js +++ b/panoramix/assets/visualizations/parallel_coordinates.js @@ -1,4 +1,5 @@ // JS +var $ = window.$ || require('jquery'); var d3 = window.d3 || require('d3'); d3.parcoords = require('../vendor/parallel_coordinates/d3.parcoords.js'); d3.divgrid = require('../vendor/parallel_coordinates/divgrid.js'); @@ -10,10 +11,10 @@ function parallelCoordVis(slice) { function refresh() { $('#code').attr('rows', '15'); - $.getJSON(slice.jsonEndpoint(), function(payload) { + $.getJSON(slice.jsonEndpoint(), function (payload) { var data = payload.data; var fd = payload.form_data; - var ext = d3.extent(data, function(d) { + var ext = d3.extent(data, function (d) { return d[fd.secondary_metric]; }); ext = [ext[0], (ext[1] - ext[0]) / 2, ext[1]]; @@ -22,13 +23,13 @@ function parallelCoordVis(slice) { .range(['red', 'grey', 'blue']) .interpolate(d3.interpolateLab); - var color = function(d) { + var color = function (d) { return cScale(d[fd.secondary_metric]); }; var container = d3.select(slice.selector); var eff_height = fd.show_datatable ? (slice.height() / 2) : slice.height(); - var div = container.append('div') + container.append('div') .attr('id', 'parcoords_' + slice.container_id) .style('height', eff_height + 'px') .classed("parcoords", true); @@ -56,35 +57,35 @@ function parallelCoordVis(slice) { .classed("parcoords", true) .selectAll(".row") .on({ - "mouseover": function(d) { + mouseover: function (d) { parcoords.highlight([d]); }, - "mouseout": parcoords.unhighlight + mouseout: parcoords.unhighlight }); // update data table on brush event - parcoords.on("brush", function(d) { + parcoords.on("brush", function (d) { d3.select("#grid") .datum(d.slice(0, 10)) .call(grid) .selectAll(".row") .on({ - "mouseover": function(d) { + mouseover: function (d) { parcoords.highlight([d]); }, - "mouseout": parcoords.unhighlight + mouseout: parcoords.unhighlight }); }); } slice.done(); }) - .fail(function(xhr) { + .fail(function (xhr) { slice.error(xhr.responseText); }); } return { render: refresh, - resize: refresh, + resize: refresh }; } diff --git a/panoramix/assets/visualizations/pivot_table.js b/panoramix/assets/visualizations/pivot_table.js index dc74253d60..795adbb297 100644 --- a/panoramix/assets/visualizations/pivot_table.js +++ b/panoramix/assets/visualizations/pivot_table.js @@ -5,27 +5,27 @@ require('datatables'); require('./pivot_table.css'); require('../node_modules/datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css'); -module.exports = function(slice) { +module.exports = function (slice) { var container = slice.container; var form_data = slice.data.form_data; function refresh() { - $.getJSON(slice.jsonEndpoint(), function(json) { + $.getJSON(slice.jsonEndpoint(), function (json) { container.html(json.data); - if (form_data.groupby.length == 1) { + if (form_data.groupby.length === 1) { var table = container.find('table').DataTable({ paging: false, - searching: false, + searching: false }); table.column('-1').order('desc').draw(); } slice.done(json); - }).fail(function(xhr) { + }).fail(function (xhr) { slice.error(xhr.responseText); }); } return { render: refresh, - resize: refresh, + resize: refresh }; }; diff --git a/panoramix/assets/visualizations/sankey.js b/panoramix/assets/visualizations/sankey.js index aeaccd5799..ade452ae47 100644 --- a/panoramix/assets/visualizations/sankey.js +++ b/panoramix/assets/visualizations/sankey.js @@ -8,7 +8,7 @@ d3.sankey = require('d3-sankey').sankey; function sankeyVis(slice) { var div = d3.select(slice.selector); - var render = function() { + var render = function () { var margin = { top: 5, right: 5, @@ -19,7 +19,7 @@ function sankeyVis(slice) { var height = slice.height() - margin.top - margin.bottom; var formatNumber = d3.format(",.0f"), - format = function(d) { + format = function (d) { return formatNumber(d) + " TWh"; }; @@ -36,7 +36,7 @@ function sankeyVis(slice) { var path = sankey.link(); - d3.json(slice.jsonEndpoint(), function(error, json) { + d3.json(slice.jsonEndpoint(), function (error, json) { if (error !== null) { slice.error(error.responseText); return ''; @@ -44,16 +44,10 @@ function sankeyVis(slice) { var links = json.data; var nodes = {}; // Compute the distinct nodes from the links. - links.forEach(function(link) { - link.source = nodes[link.source] || - (nodes[link.source] = { - name: link.source - }); - link.target = nodes[link.target] || - (nodes[link.target] = { - name: link.target - }); - link.value = +link.value; + links.forEach(function (link) { + link.source = nodes[link.source] || (nodes[link.source] = { name: link.source }); + link.target = nodes[link.target] || (nodes[link.target] = { name: link.target }); + link.value = Number(link.value); }); nodes = d3.values(nodes); @@ -67,15 +61,15 @@ function sankeyVis(slice) { .enter().append("path") .attr("class", "link") .attr("d", path) - .style("stroke-width", function(d) { + .style("stroke-width", function (d) { return Math.max(1, d.dy); }) - .sort(function(a, b) { + .sort(function (a, b) { return b.dy - a.dy; }); link.append("title") - .text(function(d) { + .text(function (d) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); }); @@ -83,46 +77,47 @@ function sankeyVis(slice) { .data(nodes) .enter().append("g") .attr("class", "node") - .attr("transform", function(d) { + .attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; }) .call(d3.behavior.drag() - .origin(function(d) { + .origin(function (d) { return d; }) - .on("dragstart", function() { + .on("dragstart", function () { this.parentNode.appendChild(this); }) .on("drag", dragmove)); node.append("rect") - .attr("height", function(d) { + .attr("height", function (d) { return d.dy; }) .attr("width", sankey.nodeWidth()) - .style("fill", function(d) { - return d.color = px.color.category21(d.name.replace(/ .*/, "")); + .style("fill", function (d) { + d.color = px.color.category21(d.name.replace(/ .*/, "")); + return d.color; }) - .style("stroke", function(d) { + .style("stroke", function (d) { return d3.rgb(d.color).darker(2); }) .append("title") - .text(function(d) { + .text(function (d) { return d.name + "\n" + format(d.value); }); node.append("text") .attr("x", -6) - .attr("y", function(d) { + .attr("y", function (d) { return d.dy / 2; }) .attr("dy", ".35em") .attr("text-anchor", "end") .attr("transform", null) - .text(function(d) { + .text(function (d) { return d.name; }) - .filter(function(d) { + .filter(function (d) { return d.x < width / 2; }) .attr("x", 6 + sankey.nodeWidth()) @@ -138,7 +133,7 @@ function sankeyVis(slice) { }; return { render: render, - resize: render, + resize: render }; } diff --git a/panoramix/assets/visualizations/sunburst.js b/panoramix/assets/visualizations/sunburst.js index 07940662e3..9b6157ce2f 100644 --- a/panoramix/assets/visualizations/sunburst.js +++ b/panoramix/assets/visualizations/sunburst.js @@ -1,10 +1,11 @@ +var d3 = window.d3 || require('d3'); require('./sunburst.css'); // Modified from http://bl.ocks.org/kerryrodden/7090426 function sunburstVis(slice) { var container = d3.select(slice.selector); - var render = function() { + var render = function () { var width = slice.width(); var height = slice.height() - 5; @@ -26,26 +27,26 @@ function sunburstVis(slice) { var partition = d3.layout.partition() .size([2 * Math.PI, radius * radius]) - .value(function(d) { + .value(function (d) { return d.m1; }); var arc = d3.svg.arc() - .startAngle(function(d) { + .startAngle(function (d) { return d.x; }) - .endAngle(function(d) { + .endAngle(function (d) { return d.x + d.dx; }) - .innerRadius(function(d) { + .innerRadius(function (d) { return Math.sqrt(d.y); }) - .outerRadius(function(d) { + .outerRadius(function (d) { return Math.sqrt(d.y + d.dy); }); var ext; - d3.json(slice.jsonEndpoint(), function(error, json) { + d3.json(slice.jsonEndpoint(), function (error, json) { if (error !== null) { slice.error(error.responseText); @@ -68,10 +69,10 @@ function sunburstVis(slice) { // For efficiency, filter nodes to keep only those large enough to see. var nodes = partition.nodes(json) - .filter(function(d) { + .filter(function (d) { return (d.dx > 0.005); // 0.005 radians = 0.29 degrees }); - ext = d3.extent(nodes, function(d) { + ext = d3.extent(nodes, function (d) { return d.m2 / d.m1; }); @@ -82,20 +83,19 @@ function sunburstVis(slice) { var path = arcs.data([json]).selectAll("path") .data(nodes) .enter().append("svg:path") - .attr("display", function(d) { + .attr("display", function (d) { return d.depth ? null : "none"; }) .attr("d", arc) .attr("fill-rule", "evenodd") .style("stroke", "grey") .style("stroke-width", "1px") - .style("fill", function(d) { + .style("fill", function (d) { return colorScale(d.m2 / d.m1); }) .style("opacity", 1) .on("mouseenter", mouseenter); - // Add the mouseleave handler to the bounding circle. container.select("#container").on("mouseleave", mouseleave); @@ -116,11 +116,13 @@ function sunburstVis(slice) { .classed("middle", true) .style("font-size", "50px") .text(percentageString); + gMiddleText.append("text") .classed("middle", true) .style("font-size", "20px") .attr("y", "25") .text("m1: " + f(d.m1) + " | m2: " + f(d.m2)); + gMiddleText.append("text") .classed("middle", true) .style("font-size", "15px") @@ -129,21 +131,8 @@ function sunburstVis(slice) { var sequenceArray = getAncestors(d); - function breadcrumbPoints(d, i) { - var points = []; - points.push("0,0"); - points.push(b.w + ",0"); - points.push(b.w + b.t + "," + (b.h / 2)); - points.push(b.w + "," + b.h); - points.push("0," + b.h); - if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex. - points.push(b.t + "," + (b.h / 2)); - } - return points.join(" "); - } - // Update the breadcrumb trail to show the current sequence and percentage. - function updateBreadcrumbs(nodeArray, percentageString) { + function updateBreadcrumbs(nodeArray) { var l = []; for (var i = 0; i < nodeArray.length; i++) { l.push(nodeArray[i].name); @@ -154,7 +143,7 @@ function sunburstVis(slice) { .classed("middle", true) .attr("y", -75); } - updateBreadcrumbs(sequenceArray, percentageString); + updateBreadcrumbs(sequenceArray); // Fade all the segments. arcs.selectAll("path") @@ -163,7 +152,7 @@ function sunburstVis(slice) { // Then highlight only those that are an ancestor of the current segment. arcs.selectAll("path") - .filter(function(node) { + .filter(function (node) { return (sequenceArray.indexOf(node) >= 0); }) .style("opacity", 1) @@ -191,7 +180,7 @@ function sunburstVis(slice) { .style("opacity", 1) .style("stroke", "grey") .style("stroke-width", "1px") - .each("end", function() { + .each("end", function () { d3.select(this).on("mouseenter", mouseenter); }); } @@ -210,13 +199,13 @@ function sunburstVis(slice) { function buildHierarchy(rows) { var root = { - "name": "root", - "children": [] + name: "root", + children: [] }; for (var i = 0; i < rows.length; i++) { var row = rows[i]; - var m1 = +row[row.length - 2]; - var m2 = +row[row.length - 1]; + var m1 = Number(row[row.length - 2]); + var m2 = Number(row[row.length - 1]); var parts = row.slice(0, row.length - 2); if (isNaN(m1)) { // e.g. if this is a header row continue; @@ -230,7 +219,7 @@ function sunburstVis(slice) { // Not yet at the end of the sequence; move down the tree. var foundChild = false; for (var k = 0; k < children.length; k++) { - if (children[k].name == nodeName) { + if (children[k].name === nodeName) { childNode = children[k]; foundChild = true; break; @@ -239,8 +228,8 @@ function sunburstVis(slice) { // If we don't already have a child node for this branch, create it. if (!foundChild) { childNode = { - "name": nodeName, - "children": [] + name: nodeName, + children: [] }; children.push(childNode); } @@ -248,9 +237,9 @@ function sunburstVis(slice) { } else { // Reached the end of the sequence; create a leaf node. childNode = { - "name": nodeName, - "m1": m1, - 'm2': m2 + name: nodeName, + m1: m1, + m2: m2 }; children.push(childNode); } @@ -278,7 +267,7 @@ function sunburstVis(slice) { }; return { render: render, - resize: render, + resize: render }; } diff --git a/panoramix/assets/visualizations/table.js b/panoramix/assets/visualizations/table.js index f1c25fa7f8..62055516b2 100644 --- a/panoramix/assets/visualizations/table.js +++ b/panoramix/assets/visualizations/table.js @@ -1,5 +1,6 @@ var $ = window.$ = require('jquery'); var jQuery = window.jQuery = $; +var d3 = require('d3'); require('datatables'); // CSS @@ -13,7 +14,13 @@ function tableVis(slice) { var fC = d3.format('0,000'); function refresh() { - $.getJSON(slice.jsonEndpoint(), function(json) { + $.getJSON(slice.jsonEndpoint(), onSuccess).fail(onError); + + function onError(xhr) { + slice.error(xhr.responseText); + } + + function onSuccess(json) { var data = json.data; var metrics = json.form_data.metrics; @@ -36,7 +43,7 @@ function tableVis(slice) { .selectAll('th') .data(data.columns).enter() .append('th') - .text(function(d) { + .text(function (d) { return d; }); @@ -45,8 +52,8 @@ function tableVis(slice) { .data(data.records).enter() .append('tr') .selectAll('td') - .data(function(row, i) { - return data.columns.map(function(c) { + .data(function (row, i) { + return data.columns.map(function (c) { return { col: c, val: row[c], @@ -55,21 +62,23 @@ function tableVis(slice) { }); }).enter() .append('td') - .style('background-image', function(d) { + .style('background-image', function (d) { if (d.isMetric) { var perc = Math.round((d.val / maxes[d.col]) * 100); return "linear-gradient(to right, lightgrey, lightgrey " + perc + "%, rgba(0,0,0,0) " + perc + "%"; } }) - .attr('title', function(d) { - if (!isNaN(d.val)) + .attr('title', function (d) { + if (!isNaN(d.val)) { return fC(d.val); + } }) - .attr('data-sort', function(d) { - if (d.isMetric) + .attr('data-sort', function (d) { + if (d.isMetric) { return d.val; + } }) - .on("click", function(d) { + .on("click", function (d) { if (!d.isMetric) { var td = d3.select(this); if (td.classed('filtered')) { @@ -81,20 +90,21 @@ function tableVis(slice) { } } }) - .style("cursor", function(d) { + .style("cursor", function (d) { if (!d.isMetric) { return 'pointer'; } }) - .html(function(d) { - if (d.isMetric) + .html(function (d) { + if (d.isMetric) { return f(d.val); - else + } else { return d.val; + } }); var datatable = slice.container.find('.dataTable').DataTable({ paging: false, - searching: form_data.include_search, + searching: form_data.include_search }); // Sorting table by main column if (form_data.metrics.length > 0) { @@ -103,14 +113,12 @@ function tableVis(slice) { } slice.done(json); slice.container.parents('.widget').find('.tooltip').remove(); - }).fail(function(xhr) { - slice.error(xhr.responseText); - }); + } } return { render: refresh, - resize: function() {}, + resize: function () {} }; } diff --git a/panoramix/assets/visualizations/word_cloud.js b/panoramix/assets/visualizations/word_cloud.js index 7a000693bd..ab370b0bb1 100644 --- a/panoramix/assets/visualizations/word_cloud.js +++ b/panoramix/assets/visualizations/word_cloud.js @@ -6,7 +6,7 @@ function wordCloudChart(slice) { var chart = d3.select(slice.selector); function refresh() { - d3.json(slice.jsonEndpoint(), function(error, json) { + d3.json(slice.jsonEndpoint(), function (error, json) { if (error !== null) { slice.error(error.responseText); return ''; @@ -14,20 +14,20 @@ function wordCloudChart(slice) { var data = json.data; var range = [ json.form_data.size_from, - json.form_data.size_to, + json.form_data.size_to ]; var rotation = json.form_data.rotation; var f_rotation; - if (rotation == "square") { - f_rotation = function() { + if (rotation === "square") { + f_rotation = function () { return ~~(Math.random() * 2) * 90; }; - } else if (rotation == "flat") { - f_rotation = function() { + } else if (rotation === "flat") { + f_rotation = function () { return 0; }; } else { - f_rotation = function() { + f_rotation = function () { return (~~(Math.random() * 6) - 3) * 30; }; } @@ -35,7 +35,7 @@ function wordCloudChart(slice) { var scale = d3.scale.linear() .range(range) - .domain(d3.extent(data, function(d) { + .domain(d3.extent(data, function (d) { return d.size; })); @@ -45,7 +45,7 @@ function wordCloudChart(slice) { .padding(5) .rotate(f_rotation) .font("serif") - .fontSize(function(d) { + .fontSize(function (d) { return scale(d.size); }) .on("end", draw); @@ -63,18 +63,18 @@ function wordCloudChart(slice) { .selectAll("text") .data(words) .enter().append("text") - .style("font-size", function(d) { + .style("font-size", function (d) { return d.size + "px"; }) .style("font-family", "Impact") - .style("fill", function(d, i) { + .style("fill", function (d) { return px.color.category21(d.text); }) .attr("text-anchor", "middle") - .attr("transform", function(d) { + .attr("transform", function (d) { return "translate(" + [d.x, d.y] + ") rotate(" + d.rotate + ")"; }) - .text(function(d) { + .text(function (d) { return d.text; }); } @@ -84,7 +84,7 @@ function wordCloudChart(slice) { return { render: refresh, - resize: refresh, + resize: refresh }; } diff --git a/panoramix/assets/visualizations/world_map.js b/panoramix/assets/visualizations/world_map.js index 986653f0f2..87f09b30be 100644 --- a/panoramix/assets/visualizations/world_map.js +++ b/panoramix/assets/visualizations/world_map.js @@ -7,30 +7,30 @@ var Datamap = require('datamaps'); require('./world_map.css'); function worldMapChart(slice) { - var render = function() { + var render = function () { var container = slice.container; var div = d3.select(slice.selector); container.css('height', slice.height()); - d3.json(slice.jsonEndpoint(), function(error, json) { + d3.json(slice.jsonEndpoint(), function (error, json) { var fd = json.form_data; if (error !== null) { slice.error(error.responseText); return ''; } - var ext = d3.extent(json.data, function(d) { + var ext = d3.extent(json.data, function (d) { return d.m1; }); - var extRadius = d3.extent(json.data, function(d) { + var extRadius = d3.extent(json.data, function (d) { return d.m2; }); var radiusScale = d3.scale.linear() .domain([extRadius[0], extRadius[1]]) .range([1, fd.max_bubble_size]); - json.data.forEach(function(d) { + json.data.forEach(function (d) { d.radius = radiusScale(d.m2); }); @@ -63,9 +63,9 @@ function worldMapChart(slice) { highlightBorderColor: '#fff', highlightFillColor: '#005a63', highlightBorderWidth: 1, - popupTemplate: function(geo, data) { + popupTemplate: function (geo, data) { return '
' + data.name + '
' + f(data.m1) + '
'; - }, + } }, bubblesConfig: { borderWidth: 1, @@ -73,7 +73,7 @@ function worldMapChart(slice) { borderColor: '#005a63', popupOnHover: true, radius: null, - popupTemplate: function(geo, data) { + popupTemplate: function (geo, data) { return '
' + data.name + '
' + f(data.m2) + '
'; }, fillOpacity: 0.5, @@ -86,7 +86,7 @@ function worldMapChart(slice) { highlightFillOpacity: 0.85, exitDelay: 100, key: JSON.stringify - }, + } }); map.updateChoropleth(d); @@ -103,7 +103,7 @@ function worldMapChart(slice) { return { render: render, - resize: render, + resize: render }; } diff --git a/panoramix/assets/webpack.config.js b/panoramix/assets/webpack.config.js index d98211a409..2bc6abafa3 100644 --- a/panoramix/assets/webpack.config.js +++ b/panoramix/assets/webpack.config.js @@ -1,6 +1,4 @@ -var webpack = require('webpack'); -var path = require('path'); - +var path = require('path'); var APP_DIR = path.resolve(__dirname, './'); // input var BUILD_DIR = path.resolve(__dirname, './javascripts/dist'); // output @@ -11,14 +9,14 @@ var config = { explore: APP_DIR + '/javascripts/explore.js', featured: APP_DIR + '/javascripts/featured.js', sql: APP_DIR + '/javascripts/sql.js', - standalone: APP_DIR + '/javascripts/standalone.js', + standalone: APP_DIR + '/javascripts/standalone.js' }, output: { path: BUILD_DIR, filename: '[name].entry.js' }, - module : { - loaders : [ + module: { + loaders: [ { test: /\.jsx?/, include: APP_DIR, @@ -29,7 +27,7 @@ var config = { test: /\.css$/, //exclude: APP_DIR + '/node_modules', loader: "style-loader!css-loader" // load css via require('../*.css') - }, + } ] }, plugins: []
' + p[fd.entity] + ' (' + p.group + ')