Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for thimble.mozilla.org#2508 - Quick Edit UI for box-shadow property #888

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cfd0563
Working quick-edit UI for box-shadow property
Cryzek Oct 20, 2017
cbd036f
Fixes eslint errors in InlineBoxShadowEditor
Cryzek Oct 20, 2017
926e0d6
Changed indent tabs to 4 spaces
Cryzek Oct 21, 2017
bb10ee6
Changed input textboxes to input range
Cryzek Dec 9, 2017
207d69b
Fixed eslint errors
Cryzek Dec 9, 2017
d8083ab
Working quick-edit UI for box-shadow property
Cryzek Oct 20, 2017
af5643e
Fixes eslint errors in InlineBoxShadowEditor
Cryzek Oct 20, 2017
f432432
Changed indent tabs to 4 spaces
Cryzek Oct 21, 2017
b21a416
Changed input textboxes to input range
Cryzek Dec 9, 2017
3419809
Fixed eslint errors
Cryzek Dec 9, 2017
709e9fb
Input sliders working with added styles
Cryzek Mar 8, 2018
d1679dc
Merge remote-tracking branch 'origin/thimble-issue-2508' into thimble…
Cryzek Mar 8, 2018
27bfa8d
Fixed build errors
Cryzek Mar 8, 2018
7bbd144
Changes to bramble-extensions.json file
Cryzek Mar 8, 2018
65afbaf
Merge branch 'master' into thimble-issue-2508
Cryzek Mar 8, 2018
411be2b
Removed unnecessary file - boxShadowValueTypes.json and changed Symbo…
Cryzek Mar 8, 2018
a63b233
Increased slider width and reduced the input range
Cryzek Mar 10, 2018
b3f04f1
Separated BoxShadowLength and Color into different files
Cryzek Mar 10, 2018
ec3c64f
Fixed imports
Cryzek Mar 10, 2018
3d1a4c5
Added inset functionality to box-shadow editor
Cryzek Mar 10, 2018
8b22e23
Modified regex
Cryzek Mar 10, 2018
431bf6a
User provided order of values is preserved while changing value in th…
Cryzek Mar 10, 2018
b82cfb4
Added fixes to handle cases where `color` property is equal to `""`
Cryzek Mar 22, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/extensions/bramble-extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@
"extensions/default/InlineBorderRadiusEditor/BorderRadiusEditorTemplate.html"
]
},
{
"path": "extensions/default/InlineBoxShadowEditor",
"less": {
"dist/extensions/default/InlineBoxShadowEditor/css/style.css": [
"src/extensions/default/InlineBoxShadowEditor/css/style.less"
]
},
"copy": [
"extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html"
]
},
{
"path": "extensions/default/InlineBoxModelEditor",
"less": {
Expand Down Expand Up @@ -218,5 +229,4 @@
]
}
}
]

]
101 changes: 101 additions & 0 deletions src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
define(function(require, exports, module) {
"use strict";

var BoxShadowInput = require("BoxShadowInput").BoxShadowInput,
ColorUtils = brackets.getModule("utils/ColorUtils"),
tinycolor = require("thirdparty/tinycolor-min");

var DEFAULT_COLOR = "black";

function BoxShadowColor(parentRef, $parent, name, value, callback) {
BoxShadowInput.call(this, $parent, name);

this.type = "color";
this.color = DEFAULT_COLOR;
this._callback = callback.bind(parentRef);
this._init(value);
};

BoxShadowColor.prototype = Object.create(BoxShadowInput.prototype);
BoxShadowColor.prototype.constructor = BoxShadowColor;

BoxShadowColor.prototype._init = function(value) {
this.setValue(value);
this.bindEvents();
};

BoxShadowColor.prototype.setValue = function(value) {
var color = this._normalizeColorString(value);
this.color = color;

this._updateView();
};

BoxShadowColor.prototype.bindEvents = function() {
var self = this;

this.$input.bind("input", function() {
self._handleColorChange();
});
};

BoxShadowColor.prototype._updateView = function() {
this.$input.val(this.color);
};

/**
* Normalize the given color string into the format used by tinycolor, by adding a space
* after commas.
* @param {string} color The color to be corrected if it looks like an RGB or HSL color.
* @return {string} a normalized color string.
*/
BoxShadowColor.prototype._normalizeColorString = function(color) {
if(color.length === 0) {
return "";
}
var normalizedColor = color;

// Convert 6-digit hex to 3-digit hex as TinyColor (#ffaacc -> #fac)
if (color.match(/^#[0-9a-fA-F]{6}/)) {
return tinycolor(color).toString();
}
if (color.match(/^(rgb|hsl)/i)) {
normalizedColor = normalizedColor.replace(/,\s*/g, ", ");
normalizedColor = normalizedColor.replace(/\(\s+/, "(");
normalizedColor = normalizedColor.replace(/\s+\)/, ")");
}
return normalizedColor;
};

BoxShadowColor.prototype._handleColorChange = function() {
var newColor = $.trim(this.$input.val()),
newColorObj = tinycolor(newColor),
newColorOk = newColorObj.isValid();

// TinyColor will auto correct an incomplete rgb or hsl value into a valid color value.
// eg. rgb(0,0,0 -> rgb(0, 0, 0)
// We want to avoid having TinyColor do this, because we don't want to sync the color
// to the UI if it's incomplete. To accomplish this, we first normalize the original
// color string into the format TinyColor would generate, and then compare it to what
// TinyColor actually generates to see if it's different. If so, then we assume the color
// was incomplete to begin with.
if(newColor.length === 0) {
newColorOk = true;
}
else if (newColorOk) {
newColorOk = (newColorObj.toString() === this._normalizeColorString(newColor));
}

this.color = newColor;

if (newColorOk) {
this.$input.css("border", "initial");
this._callback(this.type, this.name, this.color);
}
else {
this.$input.css("border", "2px solid red");
}
};

exports.BoxShadowColor = BoxShadowColor;
});
143 changes: 143 additions & 0 deletions src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
define(function(require, exports, module) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix all new files to use 4-space indents please? There are some other indent issues below as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tinycolor-min is used in the InlineColorEditor at a stage for detecting if the color value is valid.
I didn't get the complete hang of it's but I used it anyway.

"use strict";

var KeyEvent = brackets.getModule("utils/KeyEvent"),
PreferencesManager = brackets.getModule("preferences/PreferencesManager"),
StringUtils = brackets.getModule("utils/StringUtils"),
Strings = brackets.getModule("strings"),
Mustache = brackets.getModule("thirdparty/mustache/mustache"),
BoxShadowLength = require("BoxShadowLength").BoxShadowLength,
BoxShadowColor = require("BoxShadowColor").BoxShadowColor,
BoxShadowInset = require("BoxShadowInset").BoxShadowInset,
BoxShadowUtils = require("BoxShadowUtils");

/** Mustache template that forms the bare DOM structure of the UI */
var BoxShadowEditorTemplate = require("text!BoxShadowEditorTemplate.html");

/**
* Box shadow editor control; may be used standalone or within an InlineBoxShadowEditor inline widget.
* @param {!jQuery} $parent DOM node into which to append the root of the box-shadow editor UI
* @param {!{h-shadow: string, v-shadow: string, blur: string, spread: string, color: string}} values Initial set of box-shadow values.
* @param {!function(string)} callback Called whenever values change
*/
function BoxShadowEditor($parent, values, callback) {
// Create the DOM structure, filling in localized strings via Mustache
this.$element = $(Mustache.render(BoxShadowEditorTemplate, Strings));
$parent.append(this.$element);

this._callback = callback;
this._values = values;
this._originalValues = values;
this._redoValues = null;

// Get references
this._initializeInputs(values);
}

/**
* A object representing the current set of box-shadow values
* @type {}
*/
BoxShadowEditor.prototype._values = null;

/**
* box shadow values that was selected before undo(), if undo was the last change made. Else null.
* @type {?string}
*/
BoxShadowEditor.prototype._redoValues = null;

/**
* Initial value the BoxShadow picker was opened with
* @type {!string}
*/
BoxShadowEditor.prototype._originalValues = null;


/** Returns the root DOM node of the BoxShadowPicker UI */
BoxShadowEditor.prototype.getRootElement = function () {
return this.$element;
};

BoxShadowEditor.prototype.setValues = function(values) {
this.hShadow.setValue(values.lengths["h-shadow"]);
this.vShadow.setValue(values.lengths["v-shadow"]);
this.blur.setValue(values.lengths["blur"]);
this.spread.setValue(values.lengths["spread"]);
this.color.setValue(values["color"]);
this.inset.setValue(values["inset"]);
};

BoxShadowEditor.prototype._initializeInputs = function(values) {
this.hShadow = new BoxShadowLength(this, this.$element, "h-shadow", values.lengths["h-shadow"], this.handleChanges);

this.vShadow = new BoxShadowLength(this, this.$element, "v-shadow", values.lengths["v-shadow"], this.handleChanges);

this.blur = new BoxShadowLength(this, this.$element, "blur", values.lengths["blur"], this.handleChanges);

this.spread = new BoxShadowLength(this, this.$element, "spread", values.lengths["spread"], this.handleChanges);

this.color = new BoxShadowColor(this, this.$element, "color", values["color"], this.handleChanges);

this.inset = new BoxShadowInset(this, this.$element, "inset", values["inset"], this.handleChanges);
};

BoxShadowEditor.prototype.focus = function() {
this.hShadow.focus();
};

BoxShadowEditor.prototype.destroy = function() {
};

BoxShadowEditor.prototype.getValues = function() {
return this._values;
};

// Utilty function to check if data is of correct format.
function _isValidNumber(data) {
return (data.match(/\-?\d*/) !== null);
};

BoxShadowEditor.prototype.handleChanges = function(type, name, value) {
if(type === "lengths") {
this._values.lengths[name] = value;
}
else if(type === "color") {
this._values[name] = value;
}
else if(type === "inset") {
this._values[name] = value;
}

this._callback(this._values);
};

BoxShadowEditor.prototype._undo = function() {
};

BoxShadowEditor.prototype._redo = function() {
};

/**
* Global handler for keys in the color editor. Catches undo/redo keys and traps
* arrow keys that would be handled by the scroller.
*/
BoxShadowEditor.prototype._handleKeydown = function (event) {
var hasCtrl = (brackets.platform === "win") ? (event.ctrlKey) : (event.metaKey);
if (hasCtrl) {
switch (event.keyCode) {
case KeyEvent.DOM_VK_Z:
if (event.shiftKey) {
this.redo();
} else {
this.undo();
}
return false;
case KeyEvent.DOM_VK_Y:
this.redo();
return false;
}
}
};

exports.BoxShadowEditor = BoxShadowEditor;
});
Loading