http://git-wip-us.apache.org/repos/asf/ambari/blob/fc28f7ee/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric3_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric3_view.js b/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric3_view.js deleted file mode 100644 index 66e7917..0000000 --- a/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric3_view.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -/** - * @class - * - * This is a view for showing cluster CPU metrics - * - * @extends App.ChartView - * @extends Ember.Object - * @extends Ember.View - */ -App.Metric3View = App.ChartView.extend({ - id: "service-metrics-hdfs-file-operations", - title: 'File Operations', - renderer: 'line', - - ajaxIndex: 'metrics3', - yAxisFormatter: App.ChartView.CreateRateFormatter('ops', App.ChartView.DefaultFormatter), - - transformToSeries: function (jsonData) { - var seriesArray = []; - if (jsonData && jsonData.metrics && jsonData.metrics.dfs && jsonData.metrics.dfs.namenode) { - for ( var name in jsonData.metrics.dfs.namenode) { - var displayName; - var seriesData = jsonData.metrics.dfs.namenode[name]; - switch (name) { - case "FileInfoOps": - displayName = 'File Info Ops'; - break; - case "DeleteFileOps": - displayName = 'Delete File Ops'; - break; - case "CreateFileOps": - displayName = 'Create File Ops'; - break; - default: - break; - } - if (seriesData) { - seriesArray.push(this.transformData(seriesData, displayName)); - } - } - } - return seriesArray; - } -});
http://git-wip-us.apache.org/repos/asf/ambari/blob/fc28f7ee/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric4_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric4_view.js b/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric4_view.js deleted file mode 100644 index 9f9298b..0000000 --- a/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric4_view.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -/** - * @class - * - * This is a view for showing cluster CPU metrics - * - * @extends App.ChartView - * @extends Ember.Object - * @extends Ember.View - */ -App.Metric4View = App.ChartView.extend({ - id: "service-metrics-hdfs-rpc", - title: 'RPC', - yAxisFormatter: App.ChartView.TimeElapsedFormatter, - - ajaxIndex: 'metrics4', - - transformToSeries: function (jsonData) { - var seriesArray = []; - if (jsonData && jsonData.metrics && jsonData.metrics.rpc) { - for ( var name in jsonData.metrics.rpc) { - var displayName; - var seriesData = jsonData.metrics.rpc[name]; - switch (name) { - case "RpcQueueTime_avg_time": - displayName = 'RPC Queue Time Avg Time'; - break; - default: - break; - } - if (seriesData) { - seriesArray.push(this.transformData(seriesData, displayName)); - } - } - } - return seriesArray; - } -}); http://git-wip-us.apache.org/repos/asf/ambari/blob/fc28f7ee/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric_view.js b/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric_view.js deleted file mode 100644 index 61a5739..0000000 --- a/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/metrics/metric_view.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with this - * work for additional information regarding copyright ownership. The ASF - * licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -/** - * @class - * - * This is a view for showing cluster CPU metrics - * - * @extends App.ChartView - * @extends Ember.Object - * @extends Ember.View - */ -App.MetricView = App.ChartView.extend({ - - id: "service-metrics-hdfs-space-utilization", - - title: 'Space Utilization', - - yAxisFormatter: App.ChartView.BytesFormatter, - - renderer: 'line', - - ajaxIndex: 'metrics', - - transformToSeries: function (jsonData) { - var seriesArray = []; - var GB = Math.pow(2, 30); - if (jsonData && jsonData.metrics && jsonData.metrics.dfs && jsonData.metrics.dfs.FSNamesystem) { - for ( var name in jsonData.metrics.dfs.FSNamesystem) { - var displayName; - var seriesData = jsonData.metrics.dfs.FSNamesystem[name]; - switch (name) { - case "CapacityRemainingGB": - displayName = 'Capacity Remaining GB'; - break; - case "CapacityUsedGB": - displayName = 'Capacity Used GB'; - break; - case "CapacityTotalGB": - displayName = 'Capacity Total GB'; - break; - default: - break; - } - if (seriesData) { - var s = this.transformData(seriesData, displayName); - for (var i = 0; i < s.data.length; i++) { - s.data[i].y *= GB; - } - seriesArray.push(s); - } - } - } - return seriesArray; - } -}); http://git-wip-us.apache.org/repos/asf/ambari/blob/fc28f7ee/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/summary_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/summary_view.js b/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/summary_view.js deleted file mode 100644 index bad2eb9..0000000 --- a/ambari-web/contrib/views/slider/src/main/resources/ui/app/views/slider_app/summary_view.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -App.SliderAppSummaryView = Ember.View.extend({ - - classNames: ['app_summary'], - - graphs: [ - [App.MetricView, App.Metric2View, App.Metric3View, App.Metric4View] - ] - -}); http://git-wip-us.apache.org/repos/asf/ambari/blob/fc28f7ee/ambari-web/contrib/views/slider/src/main/resources/ui/vendor/scripts/common/cubism.v1.js ---------------------------------------------------------------------- diff --git a/ambari-web/contrib/views/slider/src/main/resources/ui/vendor/scripts/common/cubism.v1.js b/ambari-web/contrib/views/slider/src/main/resources/ui/vendor/scripts/common/cubism.v1.js deleted file mode 100644 index be9ff4d..0000000 --- a/ambari-web/contrib/views/slider/src/main/resources/ui/vendor/scripts/common/cubism.v1.js +++ /dev/null @@ -1,1085 +0,0 @@ -(function (exports) { - var cubism = exports.cubism = {version:"1.2.0"}; - var cubism_id = 0; - - function cubism_identity(d) { - return d; - } - - cubism.option = function (name, defaultValue) { - var values = cubism.options(name); - return values.length ? values[0] : defaultValue; - }; - - cubism.options = function (name, defaultValues) { - var options = location.search.substring(1).split("&"), - values = [], - i = -1, - n = options.length, - o; - while (++i < n) { - if ((o = options[i].split("="))[0] == name) { - values.push(decodeURIComponent(o[1])); - } - } - return values.length || arguments.length < 2 ? values : defaultValues; - }; - cubism.context = function () { - var context = new cubism_context, - step = 1e4, // ten seconds, in milliseconds - size = 1440, // four hours at ten seconds, in pixels - start0, stop0, // the start and stop for the previous change event - start1, stop1, // the start and stop for the next prepare event - serverDelay = 5e3, - clientDelay = 5e3, - event = d3.dispatch("prepare", "beforechange", "change", "focus"), - scale = context.scale = d3.time.scale().range([0, size]), - timeout, - focus; - - function update() { - var now = Date.now(); - stop0 = new Date(Math.floor((now - serverDelay - clientDelay) / step) * step); - start0 = new Date(stop0 - size * step); - stop1 = new Date(Math.floor((now - serverDelay) / step) * step); - start1 = new Date(stop1 - size * step); - scale.domain([start0, stop0]); - return context; - } - - context.start = function () { - if (timeout) clearTimeout(timeout); - var delay = +stop1 + serverDelay - Date.now(); - - // If we're too late for the first prepare event, skip it. - if (delay < clientDelay) delay += step; - - timeout = setTimeout(function prepare() { - stop1 = new Date(Math.floor((Date.now() - serverDelay) / step) * step); - start1 = new Date(stop1 - size * step); - event.prepare.call(context, start1, stop1); - - setTimeout(function () { - scale.domain([start0 = start1, stop0 = stop1]); - event.beforechange.call(context, start1, stop1); - event.change.call(context, start1, stop1); - event.focus.call(context, focus); - }, clientDelay); - - timeout = setTimeout(prepare, step); - }, delay); - return context; - }; - - context.stop = function () { - timeout = clearTimeout(timeout); - return context; - }; - - timeout = setTimeout(context.start, 10); - - // Set or get the step interval in milliseconds. - // Defaults to ten seconds. - context.step = function (_) { - if (!arguments.length) return step; - step = +_; - return update(); - }; - - // Set or get the context size (the count of metric values). - // Defaults to 1440 (four hours at ten seconds). - context.size = function (_) { - if (!arguments.length) return size; - scale.range([0, size = +_]); - return update(); - }; - - // The server delay is the amount of time we wait for the server to compute a - // metric. This delay may result from clock skew or from delays collecting - // metrics from various hosts. Defaults to 4 seconds. - context.serverDelay = function (_) { - if (!arguments.length) return serverDelay; - serverDelay = +_; - return update(); - }; - - // The client delay is the amount of additional time we wait to fetch those - // metrics from the server. The client and server delay combined represent the - // age of the most recent displayed metric. Defaults to 1 second. - context.clientDelay = function (_) { - if (!arguments.length) return clientDelay; - clientDelay = +_; - return update(); - }; - - // Sets the focus to the specified index, and dispatches a "focus" event. - context.focus = function (i) { - event.focus.call(context, focus = i); - return context; - }; - - // Add, remove or get listeners for events. - context.on = function (type, listener) { - if (arguments.length < 2) return event.on(type); - - event.on(type, listener); - - // Notify the listener of the current start and stop time, as appropriate. - // This way, metrics can make requests for data immediately, - // and likewise the axis can display itself synchronously. - if (listener != null) { - if (/^prepare(\.|$)/.test(type)) listener.call(context, start1, stop1); - if (/^beforechange(\.|$)/.test(type)) listener.call(context, start0, stop0); - if (/^change(\.|$)/.test(type)) listener.call(context, start0, stop0); - if (/^focus(\.|$)/.test(type)) listener.call(context, focus); - } - - return context; - }; - - d3.select(window).on("keydown.context-" + ++cubism_id, function () { - switch (!d3.event.metaKey && d3.event.keyCode) { - case 37: // left - if (focus == null) focus = size - 1; - if (focus > 0) context.focus(--focus); - break; - case 39: // right - if (focus == null) focus = size - 2; - if (focus < size - 1) context.focus(++focus); - break; - default: - return; - } - d3.event.preventDefault(); - }); - - return update(); - }; - - function cubism_context() { - } - - var cubism_contextPrototype = cubism.context.prototype = cubism_context.prototype; - - cubism_contextPrototype.constant = function (value) { - return new cubism_metricConstant(this, +value); - }; - cubism_contextPrototype.cube = function (host) { - if (!arguments.length) host = ""; - var source = {}, - context = this; - - source.metric = function (expression) { - return context.metric(function (start, stop, step, callback) { - d3.json(host + "/1.0/metric" - + "?expression=" + encodeURIComponent(expression) - + "&start=" + cubism_cubeFormatDate(start) - + "&stop=" + cubism_cubeFormatDate(stop) - + "&step=" + step, function (data) { - if (!data) return callback(new Error("unable to load data")); - callback(null, data.map(function (d) { - return d.value; - })); - }); - }, expression += ""); - }; - - // Returns the Cube host. - source.toString = function () { - return host; - }; - - return source; - }; - - var cubism_cubeFormatDate = d3.time.format.iso; - cubism_contextPrototype.graphite = function (host) { - if (!arguments.length) host = ""; - var source = {}, - context = this; - - source.metric = function (expression) { - var sum = "sum"; - - var metric = context.metric(function (start, stop, step, callback) { - var target = expression; - - // Apply the summarize, if necessary. - if (step !== 1e4) target = "summarize(" + target + ",'" - + (!(step % 36e5) ? step / 36e5 + "hour" : !(step % 6e4) ? step / 6e4 + "min" : step + "sec") - + "','" + sum + "')"; - - d3.text(host + "/render?format=raw" - + "&target=" + encodeURIComponent("alias(" + target + ",'')") - + "&from=" + cubism_graphiteFormatDate(start - 2 * step) // off-by-two? - + "&until=" + cubism_graphiteFormatDate(stop - 1000), function (text) { - if (!text) return callback(new Error("unable to load data")); - callback(null, cubism_graphiteParse(text)); - }); - }, expression += ""); - - metric.summarize = function (_) { - sum = _; - return metric; - }; - - return metric; - }; - - source.find = function (pattern, callback) { - d3.json(host + "/metrics/find?format=completer" - + "&query=" + encodeURIComponent(pattern), function (result) { - if (!result) return callback(new Error("unable to find metrics")); - callback(null, result.metrics.map(function (d) { - return d.path; - })); - }); - }; - - // Returns the graphite host. - source.toString = function () { - return host; - }; - - return source; - }; - -// Graphite understands seconds since UNIX epoch. - function cubism_graphiteFormatDate(time) { - return Math.floor(time / 1000); - } - -// Helper method for parsing graphite's raw format. - function cubism_graphiteParse(text) { - var i = text.indexOf("|"), - meta = text.substring(0, i), - c = meta.lastIndexOf(","), - b = meta.lastIndexOf(",", c - 1), - a = meta.lastIndexOf(",", b - 1), - start = meta.substring(a + 1, b) * 1000, - step = meta.substring(c + 1) * 1000; - return text - .substring(i + 1) - .split(",") - .slice(1)// the first value is always None? - .map(function (d) { - return +d; - }); - } - - function cubism_metric(context) { - if (!(context instanceof cubism_context)) throw new Error("invalid context"); - this.context = context; - } - - var cubism_metricPrototype = cubism_metric.prototype; - - cubism.metric = cubism_metric; - - cubism_metricPrototype.valueAt = function () { - return NaN; - }; - - cubism_metricPrototype.alias = function (name) { - this.toString = function () { - return name; - }; - return this; - }; - - cubism_metricPrototype.extent = function () { - var i = 0, - n = this.context.size(), - value, - min = Infinity, - max = -Infinity; - while (++i < n) { - value = this.valueAt(i); - if (value < min) min = value; - if (value > max) max = value; - } - return [min, max]; - }; - - cubism_metricPrototype.on = function (type, listener) { - return arguments.length < 2 ? null : this; - }; - - cubism_metricPrototype.shift = function () { - return this; - }; - - cubism_metricPrototype.on = function () { - return arguments.length < 2 ? null : this; - }; - - cubism_contextPrototype.metric = function (request, name) { - var context = this, - metric = new cubism_metric(context), - id = ".metric-" + ++cubism_id, - start = -Infinity, - stop, - step = context.step(), - size = context.size(), - values = [], - event = d3.dispatch("change"), - listening = 0, - fetching; - - // Prefetch new data into a temporary array. - function prepare(start1, stop) { - var steps = Math.min(size, Math.round((start1 - start) / step)); - if (!steps || fetching) return; // already fetched, or fetching! - fetching = true; - steps = Math.min(size, steps + cubism_metricOverlap); - var start0 = new Date(stop - steps * step); - request(start0, stop, step, function (error, data) { - fetching = false; - if (error) return console.warn(error); - var i = isFinite(start) ? Math.round((start0 - start) / step) : 0; - for (var j = 0, m = data.length; j < m; ++j) values[j + i] = data[j]; - event.change.call(metric, start, stop); - }); - } - - // When the context changes, switch to the new data, ready-or-not! - function beforechange(start1, stop1) { - if (!isFinite(start)) start = start1; - values.splice(0, Math.max(0, Math.min(size, Math.round((start1 - start) / step)))); - start = start1; - stop = stop1; - } - - // - metric.valueAt = function (i) { - return values[i]; - }; - - // - metric.shift = function (offset) { - return context.metric(cubism_metricShift(request, +offset)); - }; - - // - metric.on = function (type, listener) { - if (!arguments.length) return event.on(type); - - // If there are no listeners, then stop listening to the context, - // and avoid unnecessary fetches. - if (listener == null) { - if (event.on(type) != null && --listening == 0) { - context.on("prepare" + id, null).on("beforechange" + id, null); - } - } else { - if (event.on(type) == null && ++listening == 1) { - context.on("prepare" + id, prepare).on("beforechange" + id, beforechange); - } - } - - event.on(type, listener); - - // Notify the listener of the current start and stop time, as appropriate. - // This way, charts can display synchronous metrics immediately. - if (listener != null) { - if (/^change(\.|$)/.test(type)) listener.call(context, start, stop); - } - - return metric; - }; - - // - if (arguments.length > 1) metric.toString = function () { - return name; - }; - - return metric; - }; - -// Number of metric to refetch each period, in case of lag. - var cubism_metricOverlap = 6; - -// Wraps the specified request implementation, and shifts time by the given offset. - function cubism_metricShift(request, offset) { - return function (start, stop, step, callback) { - request(new Date(+start + offset), new Date(+stop + offset), step, callback); - }; - } - - function cubism_metricConstant(context, value) { - cubism_metric.call(this, context); - value = +value; - var name = value + ""; - this.valueOf = function () { - return value; - }; - this.toString = function () { - return name; - }; - } - - var cubism_metricConstantPrototype = cubism_metricConstant.prototype = Object.create(cubism_metric.prototype); - - cubism_metricConstantPrototype.valueAt = function () { - return +this; - }; - - cubism_metricConstantPrototype.extent = function () { - return [+this, +this]; - }; - function cubism_metricOperator(name, operate) { - - function cubism_metricOperator(left, right) { - if (!(right instanceof cubism_metric)) right = new cubism_metricConstant(left.context, right); - else if (left.context !== right.context) throw new Error("mismatch context"); - cubism_metric.call(this, left.context); - this.left = left; - this.right = right; - this.toString = function () { - return left + " " + name + " " + right; - }; - } - - var cubism_metricOperatorPrototype = cubism_metricOperator.prototype = Object.create(cubism_metric.prototype); - - cubism_metricOperatorPrototype.valueAt = function (i) { - return operate(this.left.valueAt(i), this.right.valueAt(i)); - }; - - cubism_metricOperatorPrototype.shift = function (offset) { - return new cubism_metricOperator(this.left.shift(offset), this.right.shift(offset)); - }; - - cubism_metricOperatorPrototype.on = function (type, listener) { - if (arguments.length < 2) return this.left.on(type); - this.left.on(type, listener); - this.right.on(type, listener); - return this; - }; - - return function (right) { - return new cubism_metricOperator(this, right); - }; - } - - cubism_metricPrototype.add = cubism_metricOperator("+", function (left, right) { - return left + right; - }); - - cubism_metricPrototype.subtract = cubism_metricOperator("-", function (left, right) { - return left - right; - }); - - cubism_metricPrototype.multiply = cubism_metricOperator("*", function (left, right) { - return left * right; - }); - - cubism_metricPrototype.divide = cubism_metricOperator("/", function (left, right) { - return left / right; - }); - cubism_contextPrototype.horizon = function () { - var context = this, - mode = "offset", - buffer = document.createElement("canvas"), - width = buffer.width = context.size(), - height = buffer.height = 30, - scale = d3.scale.linear().interpolate(d3.interpolateRound), - metric = cubism_identity, - extent = null, - title = cubism_identity, - format = d3.format(".2s"), - colors = ["#08519c", "#3182bd", "#6baed6", "#bdd7e7", "#bae4b3", "#74c476", "#31a354", "#006d2c"]; - - function horizon(selection) { - - selection - .on("mousemove.horizon", function () { - context.focus(d3.mouse(this)[0]); - }) - .on("mouseout.horizon", function () { - context.focus(null); - }); - - selection.append("canvas") - .attr("width", width) - .attr("height", height); - - selection.append("span") - .attr("class", "title") - .text(title); - - selection.append("span") - .attr("class", "value"); - - selection.each(function (d, i) { - var that = this, - id = ++cubism_id, - metric_ = typeof metric === "function" ? metric.call(that, d, i) : metric, - colors_ = typeof colors === "function" ? colors.call(that, d, i) : colors, - extent_ = typeof extent === "function" ? extent.call(that, d, i) : extent, - start = -Infinity, - step = context.step(), - canvas = d3.select(that).select("canvas"), - span = d3.select(that).select(".value"), - max_, - m = colors_.length >> 1, - ready; - - canvas.datum({id:id, metric:metric_}); - canvas = canvas.node().getContext("2d"); - - function change(start1, stop) { - canvas.save(); - - // compute the new extent and ready flag - var extent = metric_.extent(); - ready = extent.every(isFinite); - if (extent_ != null) extent = extent_; - - // if this is an update (with no extent change), copy old values! - var i0 = 0, max = Math.max(-extent[0], extent[1]); - if (this === context) { - if (max == max_) { - i0 = width - cubism_metricOverlap; - var dx = (start1 - start) / step; - if (dx < width) { - var canvas0 = buffer.getContext("2d"); - canvas0.clearRect(0, 0, width, height); - canvas0.drawImage(canvas.canvas, dx, 0, width - dx, height, 0, 0, width - dx, height); - canvas.clearRect(0, 0, width, height); - canvas.drawImage(canvas0.canvas, 0, 0); - } - } - start = start1; - } - - // update the domain - scale.domain([0, max_ = max]); - - // clear for the new data - canvas.clearRect(i0, 0, width - i0, height); - - // record whether there are negative values to display - var negative; - - // positive bands - for (var j = 0; j < m; ++j) { - canvas.fillStyle = colors_[m + j]; - - // Adjust the range based on the current band index. - var y0 = (j - m + 1) * height; - scale.range([m * height + y0, y0]); - y0 = scale(0); - - for (var i = i0, n = width, y1; i < n; ++i) { - y1 = metric_.valueAt(i); - if (y1 <= 0) { - negative = true; - continue; - } - canvas.fillRect(i, y1 = scale(y1), 1, y0 - y1); - } - } - - if (negative) { - // enable offset mode - if (mode === "offset") { - canvas.translate(0, height); - canvas.scale(1, -1); - } - - // negative bands - for (var j = 0; j < m; ++j) { - canvas.fillStyle = colors_[m - 1 - j]; - - // Adjust the range based on the current band index. - var y0 = (j - m + 1) * height; - scale.range([m * height + y0, y0]); - y0 = scale(0); - - for (var i = i0, n = width, y1; i < n; ++i) { - y1 = metric_.valueAt(i); - if (y1 >= 0) continue; - canvas.fillRect(i, scale(-y1), 1, y0 - scale(-y1)); - } - } - } - - canvas.restore(); - } - - function focus(i) { - if (i == null) i = width - 1; - var value = metric_.valueAt(i); - span.datum(value).text(isNaN(value) ? null : format); - } - - // Update the chart when the context changes. - context.on("change.horizon-" + id, change); - context.on("focus.horizon-" + id, focus); - - // Display the first metric change immediately, - // but defer subsequent updates to the canvas change. - // Note that someone still needs to listen to the metric, - // so that it continues to update automatically. - metric_.on("change.horizon-" + id, function (start, stop) { - change(start, stop), focus(); - if (ready) metric_.on("change.horizon-" + id, cubism_identity); - }); - }); - } - - horizon.remove = function (selection) { - - selection - .on("mousemove.horizon", null) - .on("mouseout.horizon", null); - - selection.selectAll("canvas") - .each(remove) - .remove(); - - selection.selectAll(".title,.value") - .remove(); - - function remove(d) { - d.metric.on("change.horizon-" + d.id, null); - context.on("change.horizon-" + d.id, null); - context.on("focus.horizon-" + d.id, null); - } - }; - - horizon.mode = function (_) { - if (!arguments.length) return mode; - mode = _ + ""; - return horizon; - }; - - horizon.height = function (_) { - if (!arguments.length) return height; - buffer.height = height = +_; - return horizon; - }; - - horizon.metric = function (_) { - if (!arguments.length) return metric; - metric = _; - return horizon; - }; - - horizon.scale = function (_) { - if (!arguments.length) return scale; - scale = _; - return horizon; - }; - - horizon.extent = function (_) { - if (!arguments.length) return extent; - extent = _; - return horizon; - }; - - horizon.title = function (_) { - if (!arguments.length) return title; - title = _; - return horizon; - }; - - horizon.format = function (_) { - if (!arguments.length) return format; - format = _; - return horizon; - }; - - horizon.colors = function (_) { - if (!arguments.length) return colors; - colors = _; - return horizon; - }; - - return horizon; - }; - cubism_contextPrototype.comparison = function () { - var context = this, - width = context.size(), - height = 120, - scale = d3.scale.linear().interpolate(d3.interpolateRound), - primary = function (d) { - return d[0]; - }, - secondary = function (d) { - return d[1]; - }, - extent = null, - title = cubism_identity, - formatPrimary = cubism_comparisonPrimaryFormat, - formatChange = cubism_comparisonChangeFormat, - colors = ["#9ecae1", "#225b84", "#a1d99b", "#22723a"], - strokeWidth = 1.5; - - function comparison(selection) { - - selection - .on("mousemove.comparison", function () { - context.focus(d3.mouse(this)[0]); - }) - .on("mouseout.comparison", function () { - context.focus(null); - }); - - selection.append("canvas") - .attr("width", width) - .attr("height", height); - - selection.append("span") - .attr("class", "title") - .text(title); - - selection.append("span") - .attr("class", "value primary"); - - selection.append("span") - .attr("class", "value change"); - - selection.each(function (d, i) { - var that = this, - id = ++cubism_id, - primary_ = typeof primary === "function" ? primary.call(that, d, i) : primary, - secondary_ = typeof secondary === "function" ? secondary.call(that, d, i) : secondary, - extent_ = typeof extent === "function" ? extent.call(that, d, i) : extent, - div = d3.select(that), - canvas = div.select("canvas"), - spanPrimary = div.select(".value.primary"), - spanChange = div.select(".value.change"), - ready; - - canvas.datum({id:id, primary:primary_, secondary:secondary_}); - canvas = canvas.node().getContext("2d"); - - function change(start, stop) { - canvas.save(); - canvas.clearRect(0, 0, width, height); - - // update the scale - var primaryExtent = primary_.extent(), - secondaryExtent = secondary_.extent(), - extent = extent_ == null ? primaryExtent : extent_; - scale.domain(extent).range([height, 0]); - ready = primaryExtent.concat(secondaryExtent).every(isFinite); - - // consistent overplotting - var round = start / context.step() & 1 - ? cubism_comparisonRoundOdd - : cubism_comparisonRoundEven; - - // positive changes - canvas.fillStyle = colors[2]; - for (var i = 0, n = width; i < n; ++i) { - var y0 = scale(primary_.valueAt(i)), - y1 = scale(secondary_.valueAt(i)); - if (y0 < y1) canvas.fillRect(round(i), y0, 1, y1 - y0); - } - - // negative changes - canvas.fillStyle = colors[0]; - for (i = 0; i < n; ++i) { - var y0 = scale(primary_.valueAt(i)), - y1 = scale(secondary_.valueAt(i)); - if (y0 > y1) canvas.fillRect(round(i), y1, 1, y0 - y1); - } - - // positive values - canvas.fillStyle = colors[3]; - for (i = 0; i < n; ++i) { - var y0 = scale(primary_.valueAt(i)), - y1 = scale(secondary_.valueAt(i)); - if (y0 <= y1) canvas.fillRect(round(i), y0, 1, strokeWidth); - } - - // negative values - canvas.fillStyle = colors[1]; - for (i = 0; i < n; ++i) { - var y0 = scale(primary_.valueAt(i)), - y1 = scale(secondary_.valueAt(i)); - if (y0 > y1) canvas.fillRect(round(i), y0 - strokeWidth, 1, strokeWidth); - } - - canvas.restore(); - } - - function focus(i) { - if (i == null) i = width - 1; - var valuePrimary = primary_.valueAt(i), - valueSecondary = secondary_.valueAt(i), - valueChange = (valuePrimary - valueSecondary) / valueSecondary; - - spanPrimary - .datum(valuePrimary) - .text(isNaN(valuePrimary) ? null : formatPrimary); - - spanChange - .datum(valueChange) - .text(isNaN(valueChange) ? null : formatChange) - .attr("class", "value change " + (valueChange > 0 ? "positive" : valueChange < 0 ? "negative" : "")); - } - - // Display the first primary change immediately, - // but defer subsequent updates to the context change. - // Note that someone still needs to listen to the metric, - // so that it continues to update automatically. - primary_.on("change.comparison-" + id, firstChange); - secondary_.on("change.comparison-" + id, firstChange); - function firstChange(start, stop) { - change(start, stop), focus(); - if (ready) { - primary_.on("change.comparison-" + id, cubism_identity); - secondary_.on("change.comparison-" + id, cubism_identity); - } - } - - // Update the chart when the context changes. - context.on("change.comparison-" + id, change); - context.on("focus.comparison-" + id, focus); - }); - } - - comparison.remove = function (selection) { - - selection - .on("mousemove.comparison", null) - .on("mouseout.comparison", null); - - selection.selectAll("canvas") - .each(remove) - .remove(); - - selection.selectAll(".title,.value") - .remove(); - - function remove(d) { - d.primary.on("change.comparison-" + d.id, null); - d.secondary.on("change.comparison-" + d.id, null); - context.on("change.comparison-" + d.id, null); - context.on("focus.comparison-" + d.id, null); - } - }; - - comparison.height = function (_) { - if (!arguments.length) return height; - height = +_; - return comparison; - }; - - comparison.primary = function (_) { - if (!arguments.length) return primary; - primary = _; - return comparison; - }; - - comparison.secondary = function (_) { - if (!arguments.length) return secondary; - secondary = _; - return comparison; - }; - - comparison.scale = function (_) { - if (!arguments.length) return scale; - scale = _; - return comparison; - }; - - comparison.extent = function (_) { - if (!arguments.length) return extent; - extent = _; - return comparison; - }; - - comparison.title = function (_) { - if (!arguments.length) return title; - title = _; - return comparison; - }; - - comparison.formatPrimary = function (_) { - if (!arguments.length) return formatPrimary; - formatPrimary = _; - return comparison; - }; - - comparison.formatChange = function (_) { - if (!arguments.length) return formatChange; - formatChange = _; - return comparison; - }; - - comparison.colors = function (_) { - if (!arguments.length) return colors; - colors = _; - return comparison; - }; - - comparison.strokeWidth = function (_) { - if (!arguments.length) return strokeWidth; - strokeWidth = _; - return comparison; - }; - - return comparison; - }; - - var cubism_comparisonPrimaryFormat = d3.format(".2s"), - cubism_comparisonChangeFormat = d3.format("+.0%"); - - function cubism_comparisonRoundEven(i) { - return i & 0xfffffe; - } - - function cubism_comparisonRoundOdd(i) { - return ((i + 1) & 0xfffffe) - 1; - } - - cubism_contextPrototype.axis = function () { - var context = this, - scale = context.scale, - axis_ = d3.svg.axis().scale(scale); - - var format = context.step() < 6e4 ? cubism_axisFormatSeconds - : context.step() < 864e5 ? cubism_axisFormatMinutes - : cubism_axisFormatDays; - - function axis(selection) { - var id = ++cubism_id, - tick; - - var g = selection.append("svg") - .datum({id:id}) - .attr("width", context.size()) - .attr("height", Math.max(28, -axis.tickSize())) - .append("g") - .attr("transform", "translate(0," + (axis_.orient() === "top" ? 27 : 4) + ")") - .call(axis_); - - context.on("change.axis-" + id, function () { - g.call(axis_); - if (!tick) tick = d3.select(g.node().appendChild(g.selectAll("text").node().cloneNode(true))) - .style("display", "none") - .text(null); - }); - - context.on("focus.axis-" + id, function (i) { - if (tick) { - if (i == null) { - tick.style("display", "none"); - g.selectAll("text").style("fill-opacity", null); - } else { - tick.style("display", null).attr("x", i).text(format(scale.invert(i))); - var dx = tick.node().getComputedTextLength() + 6; - g.selectAll("text").style("fill-opacity", function (d) { - return Math.abs(scale(d) - i) < dx ? 0 : 1; - }); - } - } - }); - } - - axis.remove = function (selection) { - - selection.selectAll("svg") - .each(remove) - .remove(); - - function remove(d) { - context.on("change.axis-" + d.id, null); - context.on("focus.axis-" + d.id, null); - } - }; - - return d3.rebind(axis, axis_, - "orient", - "ticks", - "tickSubdivide", - "tickSize", - "tickPadding", - "tickFormat"); - }; - - var cubism_axisFormatSeconds = d3.time.format("%I:%M:%S %p"), - cubism_axisFormatMinutes = d3.time.format("%I:%M %p"), - cubism_axisFormatDays = d3.time.format("%B %d"); - cubism_contextPrototype.rule = function () { - var context = this, - metric = cubism_identity; - - function rule(selection) { - var id = ++cubism_id; - - var line = selection.append("div") - .datum({id:id}) - .attr("class", "line") - .call(cubism_ruleStyle); - - selection.each(function (d, i) { - var that = this, - id = ++cubism_id, - metric_ = typeof metric === "function" ? metric.call(that, d, i) : metric; - - if (!metric_) return; - - function change(start, stop) { - var values = []; - - for (var i = 0, n = context.size(); i < n; ++i) { - if (metric_.valueAt(i)) { - values.push(i); - } - } - - var lines = selection.selectAll(".metric").data(values); - lines.exit().remove(); - lines.enter().append("div").attr("class", "metric line").call(cubism_ruleStyle); - lines.style("left", cubism_ruleLeft); - } - - context.on("change.rule-" + id, change); - metric_.on("change.rule-" + id, change); - }); - - context.on("focus.rule-" + id, function (i) { - line.datum(i) - .style("display", i == null ? "none" : null) - .style("left", cubism_ruleLeft); - }); - } - - rule.remove = function (selection) { - - selection.selectAll(".line") - .each(remove) - .remove(); - - function remove(d) { - context.on("focus.rule-" + d.id, null); - } - }; - - rule.metric = function (_) { - if (!arguments.length) return metric; - metric = _; - return rule; - }; - - return rule; - }; - - function cubism_ruleStyle(line) { - line - .style("position", "absolute") - .style("top", 0) - .style("bottom", 0) - .style("width", "1px") - .style("pointer-events", "none"); - } - - function cubism_ruleLeft(i) { - return i + "px"; - } -})(this);
