Commit 3af18dc8 authored by M Parker's avatar M Parker

Add a module with basic functionality.

parent c382271b
{
"extends": "eslint:recommended",
"env": {
"browser": true
},
"globals": {
"Drupal": true,
"drupalSettings": true,
"drupalTranslations": true,
"domready": true,
"jQuery": true,
"_": true,
"matchMedia": true,
"Backbone": true,
"Modernizr": true,
"CKEDITOR": true
},
"rules": {
// Errors.
"array-bracket-spacing": [2, "never"],
"block-scoped-var": 2,
"brace-style": [2, "stroustrup", {"allowSingleLine": true}],
"comma-dangle": [2, "never"],
"comma-spacing": 2,
"comma-style": [2, "last"],
"computed-property-spacing": [2, "never"],
"curly": [2, "all"],
"eol-last": 2,
"eqeqeq": [2, "smart"],
"guard-for-in": 2,
"indent": [2, 2, {"SwitchCase": 1}],
"key-spacing": [2, {"beforeColon": false, "afterColon": true}],
"keyword-spacing": [2, {"before": true, "after": true}],
"linebreak-style": [2, "unix"],
"lines-around-comment": [2, {"beforeBlockComment": true, "afterBlockComment": false}],
"new-parens": 2,
"no-array-constructor": 2,
"no-caller": 2,
"no-catch-shadow": 2,
"no-eval": 2,
"no-extend-native": 2,
"no-extra-bind": 2,
"no-extra-parens": [2, "functions"],
"no-implied-eval": 2,
"no-iterator": 2,
"no-label-var": 2,
"no-labels": 2,
"no-lone-blocks": 2,
"no-loop-func": 2,
"no-multi-spaces": 2,
"no-multi-str": 2,
"no-native-reassign": 2,
"no-nested-ternary": 2,
"no-new-func": 2,
"no-new-object": 2,
"no-new-wrappers": 2,
"no-octal-escape": 2,
"no-process-exit": 2,
"no-proto": 2,
"no-return-assign": 2,
"no-script-url": 2,
"no-sequences": 2,
"no-shadow-restricted-names": 2,
"no-spaced-func": 2,
"no-trailing-spaces": 2,
"no-undef-init": 2,
"no-undefined": 2,
"no-unused-expressions": 2,
"no-unused-vars": [2, {"vars": "all", "args": "none"}],
"no-with": 2,
"object-curly-spacing": [2, "never"],
"one-var": [2, "never"],
"quote-props": [2, "consistent-as-needed"],
"quotes": [2, "single", "avoid-escape"],
"semi": [2, "always"],
"semi-spacing": [2, {"before": false, "after": true}],
"space-before-blocks": [2, "always"],
"space-before-function-paren": [2, {"anonymous": "always", "named": "never"}],
"space-in-parens": [2, "never"],
"space-infix-ops": 2,
"space-unary-ops": [2, { "words": true, "nonwords": false }],
"spaced-comment": [2, "always"],
"strict": 2,
"yoda": [2, "never"],
// Warnings.
"max-nested-callbacks": [1, 3],
"valid-jsdoc": [1, {
"prefer": {
"returns": "return",
"property": "prop"
},
"requireReturn": false
}]
}
}
name = D3 Sankey
description = Creates sankey diagrams with D3 library.
core = 7.x
package = Visualization
dependencies[] = libraries (>=2.0)
dependencies[] = d3
<?php
/**
* @file
* Install, update, uninstall the d3_sankey module.
*/
/**
* Implements hook_requirements().
*/
function d3_sankey_requirements($phase) {
$requirements = array();
$t = get_t();
if ($phase === 'runtime') {
// A requirements row for the d3-plugins-sankey library.
$requirements['d3_plugins_sankey'] = array('title' => $t('d3-sankey'));
$library = libraries_detect('d3-plugins-sankey');
if ($library['installed']) {
$requirements['d3_plugins_sankey']['severity'] = REQUIREMENT_OK;
$requirements['d3_plugins_sankey']['value'] = $library['version'];
}
else {
$requirements['d3_plugins_sankey']['severity'] = REQUIREMENT_ERROR;
$requirements['d3_plugins_sankey']['value'] = $library['error'];
$requirements['d3_plugins_sankey']['description'] = $library['error message'];
}
// A requirements row for the d3.chart library.
$requirements['d3_charts'] = array('title' => $t('D3: Chart'));
$library = libraries_detect('d3.chart');
if ($library['installed']) {
$requirements['d3_charts']['severity'] = REQUIREMENT_OK;
$requirements['d3_charts']['value'] = $library['version'];
}
else {
$requirements['d3_charts']['severity'] = REQUIREMENT_ERROR;
$requirements['d3_charts']['value'] = $library['error'];
$requirements['d3_charts']['description'] = $library['error message'];
}
// A requirements row for the d3.chart.sankey library.
$requirements['d3_charts_sankey'] = array('title' => $t('D3: Sankey'));
$library = libraries_detect('d3.chart.sankey');
if ($library['installed']) {
$requirements['d3_charts_sankey']['severity'] = REQUIREMENT_OK;
$requirements['d3_charts_sankey']['value'] = $library['version'];
}
else {
$requirements['d3_charts_sankey']['severity'] = REQUIREMENT_ERROR;
$requirements['d3_charts_sankey']['value'] = $library['error'];
$requirements['d3_charts_sankey']['description'] = $library['error message'];
}
}
return $requirements;
}
/**
* Installs d3_sankey module.
*/
function d3_sankey_update_7000(&$sandbox) {
// Noop to ensure Drupal stores a schema version in the database.
}
<?php
/**
* @file
* Hooks and helper functions for the d3_sankey module.
*
* To get the D3 module to recognize that this module defines a plugin for it,
* we need a JS library that begins with 'd3.', contains no further dots in the
* name, and depends on the 'd3-plugins-sankey', 'd3.chart', and
* 'd3.chart.sankey' libraries we define in d3_sankey_libraries_info().
*
* From experience, the 'd3.chart.sankey' module won't work because it contains
* an extra dot in the name. So we have to make a dummy library.
*/
/* Constants. */
/**
* A type of Sankey chart that does not select nodes or links on hover.
*
* Set the 'sankeyType' setting to this value in order to create a chart of this
* type. This type will also be selected if a 'sankeyType' is not specified.
*/
define('D3_SANKEY_SANKEYTYPE_DEFAULT', 'Sankey');
/**
* A type of Sankey chart that only selects the current node or link on hover.
*
* Set the 'sankeyType' setting to this value in order to create a chart of this
* type.
*/
define('D3_SANKEY_SANKEYTYPE_SELECTION', 'Sankey.Selection');
/**
* A type of Sankey chart that selects the current node/link and its siblings.
*
* Set the 'sankeyType' setting to this value in order to create a chart of this
* type.
*/
define('D3_SANKEY_SANKEYTYPE_PATH', 'Sankey.Path');
/**
* A setting to align node labels automatically.
*
* You probably want this alignment unless you are prepared to write custom CSS
* to handle labels overflowing one side of the diagram and being clipped.
*
* Set the 'alignLabel' setting to this value in order to create a chart of this
* type. This type will also be selected if a 'alignLabel' is not specified.
*/
define('D3_SANKEY_ALIGNLABEL_AUTO', 'auto');
/**
* A setting to align node labels to the start of paths connecting from them.
*
* In LTR languages, this setting will result in the labels for the right-most
* column of nodes overflowing on the right-hand side of the chart; default CSS
* causes these labels to be clipped (i.e.: not visible).
*
* Set the 'alignLabel' setting to this value in order to create a chart of this
* type.
*/
define('D3_SANKEY_ALIGNLABEL_START', 'start');
/**
* A setting to align node labels to the end of paths connecting to them.
*
* In LTR languages, this setting will result in the labels for the left-most
* column of nodes overflowing on the left-hand side of the chart; default CSS
* causes these labels to be clipped (i.e.: not visible).
*
* Set the 'alignLabel' setting to this value in order to create a chart of this
* type.
*/
define('D3_SANKEY_ALIGNLABEL_END', 'end');
/* Hooks. */
/**
* Implements hook_libraries_info().
*/
function d3_sankey_libraries_info() {
$libraries = array();
// The d3-plugins-sankey library: New Relic's fork of the default D3 Sankey
// plugin. New Relic's fork displays nodes even if they don't have links to
// them, has Bower support, interpolated numbers, and uses the D3 API more
// consistently.
$libraries['d3-plugins-sankey'] = array(
'name' => 'd3-sankey',
'vendor url' => 'https://github.com/newrelic-forks/d3-plugins-sankey',
'download url' => 'https://github.com/newrelic-forks/d3-plugins-sankey/releases',
'download file url' => 'https://github.com/newrelic-forks/d3-plugins-sankey/archive/v1.1.0.tar.gz',
'version arguments' => array(
'file' => 'bower.json',
'pattern' => '@"version"[\s]*:[\s]*"([0-9a-zA-Z\.-]+)"@',
),
'files' => array(
'js' => array('sankey.js'),
),
'dependencies' => array('d3'),
);
// The d3.chart library.
$libraries['d3.chart'] = array(
'name' => 'd3.chart',
'vendor url' => 'https://github.com/misoproject/d3.chart',
'download url' => 'https://github.com/misoproject/d3.chart/releases',
'download file url' => 'https://github.com/misoproject/d3.chart/archive/v0.2.1.tar.gz',
'version arguments' => array(
'file' => 'd3.chart.js',
'pattern' => '@d3\.chart[\s]+-[\s]+v([0-9a-zA-Z\.-]+)@',
),
'files' => array(
'js' => array('d3.chart.js'),
),
'variants' => array(
'minified' => array(
'js' => array('d3.chart.min.js'),
),
),
'dependencies' => array('d3'),
);
// The d3.chart.sankey library.
$libraries['d3.chart.sankey'] = array(
'name' => 'd3.chart.sankey',
'vendor url' => 'https://github.com/q-m/d3.chart.sankey',
'download url' => 'https://github.com/q-m/d3.chart.sankey/releases',
'download file url' => 'https://github.com/q-m/d3.chart.sankey/archive/v0.2.0.tar.gz',
'version arguments' => array(
'file' => 'd3.chart.sankey.js',
'pattern' => '@d3\.chart\.sankey[\s]+-[\s]+v([0-9a-zA-Z\.-]+)@',
),
'files' => array(
'js' => array('d3.chart.sankey.js'),
),
'variants' => array(
'minified' => array(
'js' => array('d3.chart.sankey.min.js'),
),
),
'dependencies' => array('d3-plugins-sankey', 'd3.chart'),
'integration files' => array(
'd3_charts_sankey' => array(
'js' => array('d3_charts_sankey.js'),
),
),
);
return $libraries;
}
/**
* Implements hook_libraries_info_file_paths().
*/
function d3_sankey_libraries_info_file_paths() {
$paths = array();
// See the file doc comment for context. Since we are defining a dummy JS
// library that exists solely for the purpose of making this module work with
// the D3 Drupal module, and also because D3 expects us to include it in this
// module, we need to tell the Libraries API module where to find the library
// file.
$paths[] = _d3_sankey_js_library_path_prefix() . 'd3.sankey';
return $paths;
}
/**
* Implements hook_libraries_info_alter().
*/
function d3_sankey_libraries_info_alter(&$libraries) {
// See the file doc comment for context. By a convention set by the D3 Drupal
// module and also used by the d3_charts module (a separate project that also
// defines a plugin for the D3 Drupal module), we are putting the
// .libraries.info file that defines a library to the Libraries API inside the
// folder that contains the library. So we also have to tell the Libraries API
// where to look for the .libraries.info file.
$libraries['d3.sankey']['library path'] = _d3_sankey_js_library_path_prefix()
. 'd3.sankey';
}
/* Helper functions. */
/**
* Helper function to return the path to the libraries contained in this module.
*
* @param bool $reset
* Reset the static cache of the path.
*
* @return string
* A string representing the path to the libraries contained in this module.
*/
function _d3_sankey_js_library_path_prefix($reset = FALSE) {
$path = &drupal_static(__FUNCTION__);
if (!isset($path) || $reset) {
$path = drupal_get_path('module', 'd3_sankey') . '/libraries/';
}
return (string) $path;
}
name = Sankey
files[js][] = sankey.js
files[css][] = sankey.css
version = 0.1
dependencies[] = d3-plugins-sankey
dependencies[] = d3.chart
dependencies[] = d3.chart.sankey
.sankey .node rect {
fill-opacity: .9;
shape-rendering: crispEdges;
stroke-width: 0;
}
.sankey .node text {
text-shadow: 0 1px 0 #fff;
}
.sankey .link {
fill: none;
stroke: #000;
stroke-opacity: .2;
}
/**
* @file
* D3 Sankey library.
*/
(function ($, Drupal, d3) {
'use strict';
Drupal.d3.sankey = function (select, settings) {
var chartCanvas;
var chart;
// Grab settings from the settings object passed to us by the D3 module. Use
// defaults if the settings we want do not exist in the settings object.
var sankeyType = (settings.sankeyType || 'Sankey');
var width = (settings.width || 700);
var height = (settings.height || 400);
var nodeWidth = (settings.nodeWidth || 24);
var nodePadding = (settings.nodePadding || 8);
var spread = (settings.spread || true);
var iterations = (settings.iterations || 1);
var alignLabel = (settings.alignLabel || 'auto');
// Grab data for the chart if it exists in it's raw form; if not, use empty
// arrays for now.
var nodes = (settings.nodes || []);
var links = (settings.links || []);
// In the chart element, add an SVG tag with the correct classes, width, and
// height; and inside that, a group for the chart itself.
chartCanvas = d3.select('#' + settings.id)
.append('svg').attr('class', 'sankey').attr('width', width).attr('height', height);
// Set up the chart.
chart = chartCanvas.chart(sankeyType);
chart.nodeWidth(nodeWidth)
.nodePadding(nodePadding)
.iterations(iterations)
.spread(spread)
.alignLabel(alignLabel);
// Draw a sankey chart with the data.
chart.draw({nodes: nodes, links: links});
};
})(jQuery, Drupal, d3);
name = D3 Sankey Examples
description = Several functions that outline the different uses of the d3.sankey API.
core = 7.x
package = Visualization
dependencies[] = d3_sankey
<?php
/**
* @file
* Install, update, uninstall the d3_sankey_examples module.
*/
/**
* Implements hook_requirements().
*/
function d3_sankey_examples_requirements($phase) {
$requirements = array();
$t = get_t();
if ($phase === 'runtime') {
// Remind users to disable this module on the live site.
$requirements['d3_sankey_examples'] = array('title' => $t('D3 Sankey Examples module'));
$requirements['d3_sankey_examples']['severity'] = REQUIREMENT_WARNING;
$requirements['d3_sankey_examples']['value'] = $t('Publicly-visible example page at <a href="@link_href"><code>@link_text</code></a>!', array(
'@link_href' => url('d3/examples/sankey'),
'@link_text' => 'd3/examples/sankey',
));
$requirements['d3_sankey_examples']['description'] = $t('The D3 Sankey Examples module is only intended to be used as a developer reference: you should disable it on any site that can be seen by the general public, because it defines an example page that has no access control!');
}
return $requirements;
}
/**
* Installs d3_sankey_examples module.
*/
function d3_sankey_examples_update_7000(&$sandbox) {
// Noop to ensure Drupal stores a schema version in the database.
}
<?php
/**
* @file
* Hooks and helper functions for the d3_sankey_examples module.
*/
/* Hooks. */
/**
* Implements hook_menu().
*/
function d3_sankey_examples_menu() {
$items = array();
// Uses d3_sankey module to create a sample Sankey chart.
$items['d3/examples/sankey'] = array(
'title' => 'Sankey chart',
'description' => 'Uses d3_sankey module to create a sample Sankey chart.',
'access callback' => TRUE,
'page callback' => '_d3_sankey_examples_sankey',
'type' => MENU_LOCAL_TASK,
);
return $items;
}
/* Menu callbacks. */
/**
* Menu callback: Uses d3_sankey module to create a sample Sankey chart.
*/
function _d3_sankey_examples_sankey() {
$chart = array(
'type' => 'sankey',
// This will be the HTML id attribute of the div that will contain the
// chart.
'id' => 'visualization',
// You can (optionally) specify the type of Sankey chart:
// - D3_SANKEY_SANKEYTYPE_DEFAULT will not "select" the nodes or link when a
// user hovers over them.
// - D3_SANKEY_SANKEYTYPE_SELECTION will "select" a node or link when a user
// hovers over it, but that selection will be limited only to only one
// node/link - the one being hovered.
// - D3_SANKEY_SANKEYTYPE_PATH will "select" a node or link, as well as any
// nodes or links connected to it when a user hovers over it.
'sankeyType' => D3_SANKEY_SANKEYTYPE_PATH,
// You can (optionally) specify the width and/or height of the chart in
// pixels. These numbers must be positive integers. If you do not specify a
// width, sankey.js will choose 700px. If you do not specify a height,
// sankey.js will choose 400px.
'width' => '700',
'height' => '400',
// You can (optionally) specify the width and padding of nodes. These
// numbers must be positive integers. If you do not specify a nodeWidth,
// sankey.js will choose 24px. If you do not specify a padding, sankey.js
// will choose 8px.
'nodeWidth' => 24,
'nodePadding' => 8,
// You can (optionally) choose whether or not to spread the nodes across the
// full height of the chart. You must specify a boolean. If you do not set
// this setting, sankey.js will assume that you want to do so, as that looks
// better.
//
// See https://github.com/q-m/d3.chart.sankey for more information.
'spread' => TRUE,
// You can (optionally) specify how many additional times the Sankey library
// should pass over the diagram to try to make things look better. You must
// specify zero, or positive integer. Note that higher numbers will make the
// chart take longer to render. If you do not set this setting, sankey.js
// will assume 1.
'iterations' => 1,
// You can (optionally) specify how labels will be attached to nodes:
// - D3_SANKEY_ALIGNLABEL_AUTO will align node labels automatically. You
// probably want this alignment unless you are prepared to write custom
// CSS to handle labels overflowing one side of the diagram and being
// clipped.
// - D3_SANKEY_ALIGNLABEL_START will align node labels to the start of paths
// connecting from them. In LTR languages, this setting will result in the
// labels for the right-most column of nodes overflowing on the right-hand
// side of the chart; default CSS causes these labels to be clipped (i.e.:
// not visible).
// - D3_SANKEY_ALIGNLABEL_END will align node labels to the end of paths
// connecting to them. In LTR languages, this setting will result in the
// labels for the left-most column of nodes overflowing on the left-hand
// side of the chart; default CSS causes these labels to be clipped (i.e.:
// not visible).
'alignLabel' => D3_SANKEY_ALIGNLABEL_AUTO,
// The nodes are the boxes that appear in the diagram. You can define each
// node as an associative PHP array (which will get turned into a JS
// object). The D3, d3-plugins-sankey, d3.chart, and d3.chart.sankey source
// code does not explicitly specify what keys are valid in node objects, but
// the following keys are known to work:
// - 'name' (optional): A label for the node.
// - 'id' (optional): An SVG ID attribute (similar to an HTML ID attribute)
// to add to the node.
//
// It is important to note that the Sankey charting library *only identifies
// nodes using their array index*: you cannot use the 'id' attribute to
// define links between nodes! I have explicitly set the array indicies in
// the example below, but you don't need to.
//
// Note also that the Sankey charting library arranges nodes on the page
// based on how they link together (see the 'links' key below); you do not
// get control over this!
//
// The order that you specify the nodes doesn't really affect the final
// layout, but does matter, because their index is what you use to define
// the links between them (see below). You will probably want to add nodes
// to the bottom of the array so that you don't have to re-calculate all the
// link sources/targets.
'nodes' => array(
0 => array('name' => 'Revenue', 'id' => 'revenue'),
1 => array('name' => 'New work', 'id' => 'lob_new_work'),
2 => array('name' => 'Service level agreements', 'id' => 'lob_sla'),
3 => array('name' => 'Tech support', 'id' => 'lob_techsupport'),
4 => array('name' => 'Client 1', 'id' => 'client_1'),
5 => array('name' => 'Client 2', 'id' => 'client_2'),
),
// The links are the paths between the nodes. You can define each link as an
// associative PHP array (which will get turned into a JS object). The D3,
// d3-plugins-sankey, d3.chart, and d3.chart.sankey source code does not
// explicitly specify what keys are valid in link objects, but the following
// keys are known to work:
// - source (required): The array index of the node to connect from.
// - target (required): The array index of the node to connect to.
// - value (optional): A number representing how big the link is. If you do
// not specify a value, the actual size of the link will depend on how
// many other links are connected to the source and target nodes. You can
// specify any number (integer, float; positive or negative): the Sankey
// charting library will assume that the value of all links are all in the
// same unit (e.g.: dollars, percentage points, etc.).
//
// The order of the links do not matter. I have visually grouped the links
// with blank lines to illustrate each path from one side of the Sankey
// diagram to the other.
'links' => array(
array('value' => 10000, 'source' => 0, 'target' => 1),
array('value' => 7000, 'source' => 1, 'target' => 4),
array('value' => 3000, 'source' => 1, 'target' => 5),
array('value' => 15000, 'source' => 0, 'target' => 2),
array('value' => 7500, 'source' => 2, 'target' => 4),
array('value' => 7500, 'source' => 2, 'target' => 5),
array('value' => 8000, 'source' => 0, 'target' => 3),
array('value' => 4000, 'source' => 3, 'target' => 4),
array('value' => 4000, 'source' => 3, 'target' => 5),
),
);
return d3_draw($chart);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment