Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit 0442881

Browse files
Woriepetetnt
authored andcommitted
#7276 Live Preview highlight customization (#12949)
* Live Preview visual customization (colors of highlight can be customized via user preferences) * PR improvements Remove trailing spaces, use Object.assign instead of manually iterating over remoteHighlight properties and remove quotes from object properties in default configuration of remoteHighlight * Allow to animate transform property via transition * Remove old vendor prefixes from transitionValues in RemoteFunctions.js * updateConfig RemoteFunctions.js method Enable injecting new config into remoteFunction when user changed preferences, without the need to restart the live preview session. * Show margin and paddings in live preview. * Do not show element if it has width or height equal to 0. A little bit of clean up * PR improvements calculateSize is renamed to sum. (better naming conventions are welcome). sum now takes an array as argument. It returns sum of parsed array elements, suffixed with „px”. * Redraw via requestAnimationFrame if element has transition / animation on it. * PR improvements. Set experimental to false by default, if no config specified (caused the test to crash). Minor code quality improvements, removed duplicated variables. * Fix ESLINT errors. * drawMarginRect and drawPaddingRect functions now calculate the require size of highlight elements instead of manaul calculations on each element. The code is shorter and more readable. Also, it’ll be easier to move drawing functions into separate file if necessary. * Temporary workaround for transform issue. * Formatting improvements
1 parent 24e79f7 commit 0442881

3 files changed

Lines changed: 207 additions & 21 deletions

File tree

src/LiveDevelopment/Agents/RemoteAgent.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ define(function RemoteAgent(require, exports, module) {
131131
_stopKeepAliveInterval();
132132

133133
// inject RemoteFunctions
134-
var command = "window._LD=" + RemoteFunctions + "(" + LiveDevelopment.config.experimental + "," + PreferencesManager.get("livedev.wsPort") + ");";
134+
var command = "window._LD=" + RemoteFunctions + "(" + JSON.stringify(LiveDevelopment.config) + "," + PreferencesManager.get("livedev.wsPort") + ");";
135135

136136
Inspector.Runtime.evaluate(command, function onEvaluate(response) {
137137
if (response.error || response.wasThrown) {

src/LiveDevelopment/Agents/RemoteFunctions.js

Lines changed: 169 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,29 @@
3030
* modules should define a single function that returns an object of all
3131
* exported functions.
3232
*/
33-
function RemoteFunctions(experimental, remoteWSPort) {
33+
function RemoteFunctions(config, remoteWSPort) {
3434
"use strict";
3535

36+
var experimental;
37+
if (!config) {
38+
experimental = false;
39+
} else {
40+
experimental = config.experimental;
41+
}
3642
var lastKeepAliveTime = Date.now();
43+
var req, timeout;
44+
var animateHighlight = function (time) {
45+
if(req) {
46+
window.cancelAnimationFrame(req);
47+
window.clearTimeout(timeout);
48+
}
49+
req = window.requestAnimationFrame(redrawHighlights);
50+
51+
timeout = setTimeout(function () {
52+
window.cancelAnimationFrame(req);
53+
req = null;
54+
}, time * 1000);
55+
};
3756

3857
/**
3958
* @type {DOMEditHandler}
@@ -250,17 +269,147 @@ function RemoteFunctions(experimental, remoteWSPort) {
250269
}
251270
return false;
252271
},
253-
254272
_makeHighlightDiv: function (element, doAnimation) {
255273
var elementBounds = element.getBoundingClientRect(),
256274
highlight = window.document.createElement("div"),
257-
styles = window.getComputedStyle(element);
275+
elementStyling = window.getComputedStyle(element),
276+
transitionDuration = parseFloat(elementStyling.getPropertyValue('transition-duration')),
277+
animationDuration = parseFloat(elementStyling.getPropertyValue('animation-duration'));
278+
279+
if (transitionDuration) {
280+
animateHighlight(transitionDuration);
281+
}
282+
283+
if (animationDuration) {
284+
animateHighlight(animationDuration);
285+
}
258286

259287
// Don't highlight elements with 0 width & height
260288
if (elementBounds.width === 0 && elementBounds.height === 0) {
261289
return;
262290
}
291+
292+
var realElBorder = {
293+
right: elementStyling.getPropertyValue('border-right-width'),
294+
left: elementStyling.getPropertyValue('border-left-width'),
295+
top: elementStyling.getPropertyValue('border-top-width'),
296+
bottom: elementStyling.getPropertyValue('border-bottom-width')
297+
};
298+
299+
var innerWidth = elementBounds.width - parseInt(realElBorder.left) - parseInt(realElBorder.right);
300+
var innerHeight = elementBounds.height - parseInt(realElBorder.top) - parseInt(realElBorder.bottom);
301+
302+
var visualisations = {
303+
horizontal: "left, right",
304+
vertical: "top, bottom"
305+
};
306+
307+
var drawPaddingRect = function(side) {
308+
var elStyling = {};
309+
310+
if (visualisations.horizontal.indexOf(side) >= 0) {
311+
elStyling['width'] = elementStyling.getPropertyValue('padding-' + side);
312+
elStyling['height'] = innerHeight + "px";
313+
elStyling['top'] = realElBorder.top;
314+
315+
} else {
316+
elStyling['height'] = elementStyling.getPropertyValue('padding-' + side);
317+
elStyling['width'] = innerWidth + "px";
318+
elStyling['left'] = realElBorder.left;
319+
}
320+
321+
elStyling[side] = realElBorder[side];
322+
elStyling['position'] = 'absolute';
323+
324+
return elStyling;
325+
};
326+
327+
var drawMarginRect = function(side) {
328+
var elStyling = {};
329+
330+
var margin = [];
331+
margin['right'] = parseInt(elementStyling.getPropertyValue('margin-right'));
332+
margin['top'] = parseInt(elementStyling.getPropertyValue('margin-top'));
333+
margin['bottom'] = parseInt(elementStyling.getPropertyValue('margin-bottom'));
334+
margin['left'] = parseInt(elementStyling.getPropertyValue('margin-left'));
335+
336+
337+
if(visualisations['horizontal'].indexOf(side) >= 0) {
338+
elStyling['width'] = elementStyling.getPropertyValue('margin-' + side);
339+
elStyling['height'] = elementBounds.height + margin['top'] + margin['bottom'] + "px";
340+
elStyling['top'] = "-" + margin['top'] + "px";
341+
342+
} else {
343+
elStyling['height'] = elementStyling.getPropertyValue('margin-' + side);
344+
elStyling['width'] = elementBounds.width + "px";
345+
elStyling['left'] = 0;
346+
}
263347

348+
elStyling[side] = "-" + margin[side] + "px";
349+
elStyling['position'] = 'absolute';
350+
351+
return elStyling;
352+
};
353+
354+
var setVisibility = function (el) {
355+
if (
356+
!config.remoteHighlight.showPaddingMargin ||
357+
parseInt(el.height, 10) <= 0 ||
358+
parseInt(el.width, 10) <= 0
359+
) {
360+
el.display = 'none';
361+
} else {
362+
el.display = 'block';
363+
}
364+
};
365+
366+
var mainBoxStyles = config.remoteHighlight.stylesToSet;
367+
mainBoxStyles['border'] = 'none';
368+
369+
var paddingVisualisations = [
370+
drawPaddingRect('top'),
371+
drawPaddingRect('right'),
372+
drawPaddingRect('bottom'),
373+
drawPaddingRect('left')
374+
];
375+
376+
var marginVisualisations = [
377+
drawMarginRect('top'),
378+
drawMarginRect('right'),
379+
drawMarginRect('bottom'),
380+
drawMarginRect('left')
381+
];
382+
383+
var setupVisualisations = function (arr, config) {
384+
var i;
385+
for (i = 0; i < arr.length; i++) {
386+
setVisibility(arr[i]);
387+
388+
// Applies to every visualisationElement (padding or margin div)
389+
arr[i]["box-sizing"] = "border-box";
390+
arr[i]["transform"] = "none";
391+
var el = window.document.createElement("div"),
392+
styles = Object.assign(
393+
{},
394+
config,
395+
arr[i]
396+
);
397+
398+
_setStyleValues(styles, el.style);
399+
400+
highlight.appendChild(el);
401+
}
402+
};
403+
404+
setupVisualisations(
405+
marginVisualisations,
406+
config.remoteHighlight.marginStyling
407+
);
408+
setupVisualisations(
409+
paddingVisualisations,
410+
config.remoteHighlight.paddingStyling
411+
);
412+
264413
highlight.className = HIGHLIGHT_CLASSNAME;
265414

266415
var offset = _screenOffset(element);
@@ -275,31 +424,25 @@ function RemoteFunctions(experimental, remoteWSPort) {
275424
"padding": 0,
276425
"position": "absolute",
277426
"pointer-events": "none",
278-
"border-top-left-radius": styles.borderTopLeftRadius,
279-
"border-top-right-radius": styles.borderTopRightRadius,
280-
"border-bottom-left-radius": styles.borderBottomLeftRadius,
281-
"border-bottom-right-radius": styles.borderBottomRightRadius,
427+
"border-top-left-radius": elementStyling.borderTopLeftRadius,
428+
"border-top-right-radius": elementStyling.borderTopRightRadius,
429+
"border-bottom-left-radius": elementStyling.borderBottomLeftRadius,
430+
"border-bottom-right-radius": elementStyling.borderBottomRightRadius,
282431
"border-style": "solid",
283432
"border-width": "1px",
284433
"border-color": "#00a2ff",
285434
"box-shadow": "0 0 1px #fff",
286435
"box-sizing": "border-box"
287436
};
437+
438+
var mergedStyles = Object.assign({}, stylesToSet, config.remoteHighlight.stylesToSet);
288439

289-
var animateStartValues = {
290-
"background-color": "rgba(0, 162, 255, 0.5)",
291-
"opacity": 0
292-
};
440+
var animateStartValues = config.remoteHighlight.animateStartValue;
293441

294-
var animateEndValues = {
295-
"background-color": "rgba(0, 162, 255, 0)",
296-
"opacity": 1
297-
};
442+
var animateEndValues = config.remoteHighlight.animateEndValue;
298443

299444
var transitionValues = {
300-
"-webkit-transition-property": "opacity, background-color",
301-
"-webkit-transition-duration": "300ms, 2.3s",
302-
"transition-property": "opacity, background-color",
445+
"transition-property": "opacity, background-color, transform",
303446
"transition-duration": "300ms, 2.3s"
304447
};
305448

@@ -311,7 +454,7 @@ function RemoteFunctions(experimental, remoteWSPort) {
311454
}
312455
}
313456

314-
_setStyleValues(stylesToSet, highlight.style);
457+
_setStyleValues(mergedStyles, highlight.style);
315458
_setStyleValues(
316459
doAnimation ? animateStartValues : animateEndValues,
317460
highlight.style
@@ -842,6 +985,11 @@ function RemoteFunctions(experimental, remoteWSPort) {
842985
function getSimpleDOM() {
843986
return JSON.stringify(_domElementToJSON(window.document.documentElement));
844987
}
988+
989+
function updateConfig(newConfig) {
990+
config = JSON.parse(newConfig);
991+
return JSON.stringify(config);
992+
}
845993

846994
// init
847995
_editHandler = new DOMEditHandler(window.document);
@@ -894,6 +1042,7 @@ function RemoteFunctions(experimental, remoteWSPort) {
8941042
"highlightRule" : highlightRule,
8951043
"redrawHighlights" : redrawHighlights,
8961044
"applyDOMEdits" : applyDOMEdits,
897-
"getSimpleDOM" : getSimpleDOM
1045+
"getSimpleDOM" : getSimpleDOM,
1046+
"updateConfig" : updateConfig
8981047
};
8991048
}

src/LiveDevelopment/main.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,33 @@ define(function main(require, exports, module) {
7979
description: Strings.DESCRIPTION_LIVE_DEV_MULTIBROWSER
8080
});
8181

82+
// "livedev.remoteHighlight" preference
83+
var PREF_REMOTEHIGHLIGHT = "remoteHighlight";
84+
var remoteHighlightPref = prefs.definePreference(PREF_REMOTEHIGHLIGHT, "object", {
85+
animateStartValue: {
86+
"background-color": "rgba(0, 162, 255, 0.5)",
87+
"opacity": 0
88+
},
89+
animateEndValue: {
90+
"background-color": "rgba(0, 162, 255, 0)",
91+
"opacity": 0.6
92+
},
93+
"paddingStyling": {
94+
"border-width": "1px",
95+
"border-style": "dashed",
96+
"border-color": "rgba(0, 162, 255, 0.5)"
97+
},
98+
"marginStyling": {
99+
"background-color": "rgba(21, 165, 255, 0.58)"
100+
},
101+
"stylesToSet": {
102+
"border-width": "1px"
103+
},
104+
"showPaddingMargin": true
105+
}, {
106+
description: "LivePreview highlight settings"
107+
});
108+
82109
/** Toggles or sets the preference **/
83110
function _togglePref(key, value) {
84111
var val,
@@ -302,6 +329,7 @@ define(function main(require, exports, module) {
302329
/** Initialize LiveDevelopment */
303330
AppInit.appReady(function () {
304331
params.parse();
332+
config.remoteHighlight = prefs.get(PREF_REMOTEHIGHLIGHT);
305333

306334
Inspector.init(config);
307335
LiveDevelopment.init(config);
@@ -353,6 +381,15 @@ define(function main(require, exports, module) {
353381
_setImplementation(prefs.get(PREF_MULTIBROWSER));
354382
}
355383
});
384+
385+
remoteHighlightPref
386+
.on("change", function () {
387+
config.remoteHighlight = prefs.get(PREF_REMOTEHIGHLIGHT);
388+
389+
if (LiveDevImpl && LiveDevImpl.status >= LiveDevImpl.STATUS_ACTIVE) {
390+
LiveDevImpl.agents.remote.call("updateConfig",JSON.stringify(config));
391+
}
392+
});
356393

357394
});
358395

0 commit comments

Comments
 (0)