Bug 1210796 - Part 12: Unite common codes into utils.js and use. r=pbro
MozReview-Commit-ID: AXzA9aEOc8N
--- a/devtools/client/animationinspector/components/animation-details.js
+++ b/devtools/client/animationinspector/components/animation-details.js
@@ -3,17 +3,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {Task} = require("devtools/shared/task");
const EventEmitter = require("devtools/shared/event-emitter");
-const {createNode} = require("devtools/client/animationinspector/utils");
+const {createNode, getCssPropertyName} =
+ require("devtools/client/animationinspector/utils");
const {Keyframes} = require("devtools/client/animationinspector/components/keyframes");
const { LocalizationHelper } = require("devtools/shared/l10n");
const L10N =
new LocalizationHelper("devtools/client/locales/animationinspector.properties");
/**
* UI component responsible for displaying detailed information for a given
@@ -323,19 +324,8 @@ AnimationDetails.prototype = {
this.progressIndicatorEl.style.left =
`${ this.dummyAnimation.effect.getComputedTiming().progress * 100 }%`;
},
get win() {
return this.containerEl.ownerDocument.defaultView;
}
};
-
-/**
- * Turn propertyName into property-name.
- * @param {String} jsPropertyName A camelcased CSS property name. Typically
- * something that comes out of computed styles. E.g. borderBottomColor
- * @return {String} The corresponding CSS property name: border-bottom-color
- */
-function getCssPropertyName(jsPropertyName) {
- return jsPropertyName.replace(/[A-Z]/g, "-$&").toLowerCase();
-}
-exports.getCssPropertyName = getCssPropertyName;
--- a/devtools/client/animationinspector/components/animation-time-block.js
+++ b/devtools/client/animationinspector/components/animation-time-block.js
@@ -2,42 +2,28 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const EventEmitter = require("devtools/shared/event-emitter");
-const {createNode, TimeScale, getFormattedAnimationTitle} =
+const {createNode, createSVGNode, TimeScale, getFormattedAnimationTitle} =
require("devtools/client/animationinspector/utils");
+const {createPathSegments, appendPathElement, DEFAULT_MIN_PROGRESS_THRESHOLD} =
+ require("devtools/client/animationinspector/graph-helper");
const { LocalizationHelper } = require("devtools/shared/l10n");
const L10N =
new LocalizationHelper("devtools/client/locales/animationinspector.properties");
-// In the createPathSegments function, an animation duration is divided by
-// DURATION_RESOLUTION in order to draw the way the animation progresses.
-// But depending on the timing-function, we may be not able to make the graph
-// smoothly progress if this resolution is not high enough.
-// So, if the difference of animation progress between 2 divisions is more than
-// MIN_PROGRESS_THRESHOLD, then createPathSegments re-divides
-// by DURATION_RESOLUTION.
-// DURATION_RESOLUTION shoud be integer and more than 2.
-const DURATION_RESOLUTION = 4;
-// MIN_PROGRESS_THRESHOLD shoud be between more than 0 to 1.
-const MIN_PROGRESS_THRESHOLD = 0.1;
-// BOUND_EXCLUDING_TIME should be less than 1ms and is used to exclude start
-// and end bounds when dividing duration in createPathSegments.
-const BOUND_EXCLUDING_TIME = 0.001;
// Show max 10 iterations for infinite animations
// to give users a clue that the animation does repeat.
const MAX_INFINITE_ANIMATIONS_ITERATIONS = 10;
-// SVG namespace
-const SVG_NS = "http://www.w3.org/2000/svg";
/**
* UI component responsible for displaying a single animation timeline, which
* basically looks like a rectangle that shows the delay and iterations.
*/
function AnimationTimeBlock() {
EventEmitter.decorate(this);
this.onClick = this.onClick.bind(this);
@@ -72,19 +58,18 @@ AnimationTimeBlock.prototype = {
// Create a container element to hold the delay and iterations.
// It is positioned according to its delay (divided by the playbackrate),
// and its width is according to its duration (divided by the playbackrate).
const {x, delayX, delayW, endDelayX, endDelayW} =
TimeScale.getAnimationDimensions(animation);
// Animation summary graph element.
- const summaryEl = createNode({
+ const summaryEl = createSVGNode({
parent: this.containerEl,
- namespace: "http://www.w3.org/2000/svg",
nodeType: "svg",
attributes: {
"class": "summary",
"preserveAspectRatio": "none",
"style": `left: ${ x - (state.delay > 0 ? delayW : 0) }%`
}
});
@@ -103,17 +88,17 @@ AnimationTimeBlock.prototype = {
// Get a helper function that returns the path segment of timing-function.
const segmentHelper = getSegmentHelper(state, this.win);
// Minimum segment duration is the duration of one pixel.
const minSegmentDuration =
totalDisplayedDuration / this.containerEl.clientWidth;
// Minimum progress threshold.
- let minProgressThreshold = MIN_PROGRESS_THRESHOLD;
+ let minProgressThreshold = DEFAULT_MIN_PROGRESS_THRESHOLD;
// If the easing is step function,
// minProgressThreshold should be changed by the steps.
const stepFunction = state.easing.match(/steps\((\d+)/);
if (stepFunction) {
minProgressThreshold = 1 / (parseInt(stepFunction[1], 10) + 1);
}
// Starting time of main iteration.
@@ -610,91 +595,8 @@ function getSegmentHelper(state, win) {
} else {
this.animation.currentTime = time;
}
const progress = this.animation.effect.getComputedTiming().progress;
return { x: time, y: Math.max(progress, 0) };
}
};
}
-
-/**
- * Create the path segments from given parameters.
- * @param {Number} startTime - Starting time of animation.
- * @param {Number} endTime - Ending time of animation.
- * @param {Number} minSegmentDuration - Minimum segment duration.
- * @param {Number} minProgressThreshold - Minimum progress threshold.
- * @param {Object} segmentHelper - The object of getSegmentHelper.
- * @return {Array} path segments -
- * [{x: {Number} time, y: {Number} progress}, ...]
- */
-function createPathSegments(startTime, endTime, minSegmentDuration,
- minProgressThreshold, segmentHelper) {
- // If the duration is too short, early return.
- if (endTime - startTime < minSegmentDuration) {
- return [segmentHelper.getSegment(startTime),
- segmentHelper.getSegment(endTime)];
- }
-
- // Otherwise, start creating segments.
- let pathSegments = [];
-
- // Append the segment for the startTime position.
- const startTimeSegment = segmentHelper.getSegment(startTime);
- pathSegments.push(startTimeSegment);
- let previousSegment = startTimeSegment;
-
- // Split the duration in equal intervals, and iterate over them.
- // See the definition of DURATION_RESOLUTION for more information about this.
- const interval = (endTime - startTime) / DURATION_RESOLUTION;
- for (let index = 1; index <= DURATION_RESOLUTION; index++) {
- // Create a segment for this interval.
- const currentSegment =
- segmentHelper.getSegment(startTime + index * interval);
-
- // If the distance between the Y coordinate (the animation's progress) of
- // the previous segment and the Y coordinate of the current segment is too
- // large, then recurse with a smaller duration to get more details
- // in the graph.
- if (Math.abs(currentSegment.y - previousSegment.y) > minProgressThreshold) {
- // Divide the current interval (excluding start and end bounds
- // by adding/subtracting BOUND_EXCLUDING_TIME).
- pathSegments = pathSegments.concat(
- createPathSegments(previousSegment.x + BOUND_EXCLUDING_TIME,
- currentSegment.x - BOUND_EXCLUDING_TIME,
- minSegmentDuration, minProgressThreshold,
- segmentHelper));
- }
-
- pathSegments.push(currentSegment);
- previousSegment = currentSegment;
- }
-
- return pathSegments;
-}
-
-/**
- * Append path element.
- * @param {Element} parentEl - Parent element of this appended path element.
- * @param {Array} pathSegments - Path segments. Please see createPathSegments.
- * @param {String} cls - Class name.
- * @return {Element} path element.
- */
-function appendPathElement(parentEl, pathSegments, cls) {
- // Create path string.
- let path = `M${ pathSegments[0].x },0`;
- pathSegments.forEach(pathSegment => {
- path += ` L${ pathSegment.x },${ pathSegment.y }`;
- });
- path += ` L${ pathSegments[pathSegments.length - 1].x },0 Z`;
- // Append and return the path element.
- return createNode({
- parent: parentEl,
- namespace: SVG_NS,
- nodeType: "path",
- attributes: {
- "d": path,
- "class": cls,
- "vector-effect": "non-scaling-stroke",
- "transform": "scale(1, -1)"
- }
- });
-}
--- a/devtools/client/animationinspector/test/unit/test_getCssPropertyName.js
+++ b/devtools/client/animationinspector/test/unit/test_getCssPropertyName.js
@@ -2,17 +2,17 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var Cu = Components.utils;
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
-const {getCssPropertyName} = require("devtools/client/animationinspector/components/animation-details");
+const {getCssPropertyName} = require("devtools/client/animationinspector/utils");
const TEST_DATA = [{
jsName: "alllowercase",
cssName: "alllowercase"
}, {
jsName: "borderWidth",
cssName: "border-width"
}, {
--- a/devtools/client/animationinspector/utils.js
+++ b/devtools/client/animationinspector/utils.js
@@ -305,16 +305,27 @@ function getJsPropertyName(cssPropertyNa
// https://drafts.csswg.org/cssom/#css-property-to-idl-attribute
return cssPropertyName.replace(/-([a-z])/gi, (str, group) => {
return group.toUpperCase();
});
}
exports.getJsPropertyName = getJsPropertyName;
/**
+ * Turn propertyName into property-name.
+ * @param {String} jsPropertyName A camelcased CSS property name. Typically
+ * something that comes out of computed styles. E.g. borderBottomColor
+ * @return {String} The corresponding CSS property name: border-bottom-color
+ */
+function getCssPropertyName(jsPropertyName) {
+ return jsPropertyName.replace(/[A-Z]/g, "-$&").toLowerCase();
+}
+exports.getCssPropertyName = getCssPropertyName;
+
+/**
* Get a formatted title for this animation. This will be either:
* "some-name", "some-name : CSS Transition", "some-name : CSS Animation",
* "some-name : Script Animation", or "Script Animation", depending
* if the server provides the type, what type it is and if the animation
* has a name
* @param {AnimationPlayerFront} animation
*/
function getFormattedAnimationTitle({state}) {