From cfd056322942f1c0fa8b77fde18727e698be3383 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Fri, 20 Oct 2017 14:16:59 +0530 Subject: [PATCH 01/21] Working quick-edit UI for box-shadow property Related to thimble.mozilla.org#2508 for creating an extension to open quick edit UI for box-shadow property( similar to color-picker). This is a very early version with bugs, and lot of unnecessary comments, logs. It's a work in progress. --- src/extensions/bramble-extensions.json | 8 + .../InlineBoxShadowEditor/BoxShadowEditor.js | 272 ++++++++++++++++++ .../BoxShadowEditorTemplate.html | 33 +++ .../BoxShadowValueTypes.json | 9 + .../InlineBoxShadowEditor.js | 262 +++++++++++++++++ .../InlineBoxShadowEditor/css/style.less | 96 +++++++ .../default/InlineBoxShadowEditor/main.js | 140 +++++++++ .../thirdparty/tinycolor-min.js | 4 + 8 files changed, 824 insertions(+) create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json create mode 100644 src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/css/style.less create mode 100644 src/extensions/default/InlineBoxShadowEditor/main.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/thirdparty/tinycolor-min.js diff --git a/src/extensions/bramble-extensions.json b/src/extensions/bramble-extensions.json index 3f1f079ae60..fc55005fcfa 100644 --- a/src/extensions/bramble-extensions.json +++ b/src/extensions/bramble-extensions.json @@ -51,6 +51,14 @@ "extensions/default/InlineColorEditor/img/*.png" ] }, + { + "path": "extensions/default/InlineBoxShadowEditor", + "less": { + "dist/extensions/default/InlineBoxShadowEditor/css/style.css": [ + "src/extensions/default/InlineBoxShadowEditor/css/style.less" + ] + } + }, { "path": "extensions/default/Inline3DParametersEditor", "less": { diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js new file mode 100644 index 00000000000..bc9f15f0df1 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -0,0 +1,272 @@ +define(function(require, exports, module) { + "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"), + tinycolor = require("thirdparty/tinycolor-min"); + + /** 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 {!{horizontalOffset: string, verticalOffset: string, blurRadius: string, spreadRadius: 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.$horizontalOffsetValue = this.$element.find("#horizontal-offset-value"); + this.$verticalOffsetValue = this.$element.find("#vertical-offset-value"); + this.$blurRadiusValue = this.$element.find("#blur-radius-value"); + this.$spreadRadiusValue = this.$element.find("#spread-radius-value"); + this.$colorValue = this.$element.find("#color-value"); + + + // Attach event listeners to main UI elements + this._bindInputHandlers(); + + + // Set initial values in the box-shadow editor inputs. + this._setInputValues(); + } + + /** + * A string or tinycolor object representing the currently selected color + * TODO (#2201): type is unpredictable + * @type {tinycolor|string} + */ + 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) { + for(var key in this._values) { + if(this._values.hasOwnProperty(key)) { + if(values[key] && values[key] != this._values[key]) { + this._values[key] = values[key]; + } + } + } + + this._setInputValues(); + }; + + BoxShadowEditor.prototype._setInputValues = function() { + var values = this._values; + var horizontalOffset, verticalOffset, blurRadius, spreadRadius, color; + + horizontalOffset = values["horizontalOffset"] ? parseFloat(values["horizontalOffset"]) : ""; + verticalOffset = values["verticalOffset"] ? parseFloat(values["verticalOffset"]) : ""; + blurRadius = values["blurRadius"] ? parseFloat(values["blurRadius"]) : ""; + spreadRadius = values["spreadRadius"] ? parseFloat(values["spreadRadius"]) : ""; + color = values["color"] ? values["color"] : ""; + + this.$horizontalOffsetValue.val(horizontalOffset); + this.$verticalOffsetValue.val(verticalOffset); + this.$blurRadiusValue.val(blurRadius); + this.$spreadRadiusValue.val(spreadRadius); + this.$colorValue.val(color); + }; + + BoxShadowEditor.prototype._bindInputHandlers = function() { + var self = this; + + this.$horizontalOffsetValue.bind("input", function (event) { + self._handleHorizontalOffsetChange(); + }); + + this.$verticalOffsetValue.bind("input", function (event) { + self._handleVerticalOffsetChange(); + }); + + this.$blurRadiusValue.bind("input", function (event) { + self._handleBlurRadiusChange(); + }); + + this.$spreadRadiusValue.bind("input", function (event) { + self._handleSpreadRadiusChange(); + }); + + this.$colorValue.bind("input", function (event) { + self._handleColorChange(); + }); + } + + BoxShadowEditor.prototype._synchronize = function() { + + } + + BoxShadowEditor.prototype.focus = function() { + this.$horizontalOffsetValue.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); + } + + function _handleChanges($inputElement, propertyName, value) { + console.log(value, typeof value); + if(!_isValidNumber(value)) { + if(!this._values[propertyName]) { + $inputElement.val(""); + return; + } + var curValue = parseFloat(this._values[propertyName]); + $inputElement.val(curValue); + } + + if(value == "") { + // This is to maintain the box-shadow property. + value = "0"; + $inputElement.val(value); + } + + var newValue = value + "px"; + this._commitChanges(propertyName, newValue); + } + + BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { + var self = this; + var newValue = this.$horizontalOffsetValue.val().trim(); + _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); + } + + BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { + var self = this; + var newValue = this.$verticalOffsetValue.val().trim(); + _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); + } + + BoxShadowEditor.prototype._handleBlurRadiusChange = function() { + var self = this; + var newValue = this.$blurRadiusValue.val().trim(); + _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); + } + + BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { + var self = this; + var newValue = this.$spreadRadiusValue.val().trim(); + _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); + } + + /** + * 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. + */ + BoxShadowEditor.prototype._normalizeColorString = function (color) { + 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; + }; + + BoxShadowEditor.prototype._handleColorChange = function() { + var newColor = $.trim(this.$colorValue.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 (newColorOk) { + newColorOk = (newColorObj.toString() === this._normalizeColorString(newColor)); + } + + // Sync only if we have a valid color or we're restoring the previous valid color. + if (newColorOk) { + console.log(newColor); + this._commitChanges("color", newColor); + } + }; + + 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; + } + } + }; + + + BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { + this._values[propertyName] = value; + this._callback(this._values); + } + + + exports.BoxShadowEditor = BoxShadowEditor; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html new file mode 100644 index 00000000000..c651c6e4eb6 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -0,0 +1,33 @@ +
+
+ +
+ : + px +
+
+ : + px +
+
+ : + px +
+
+ : + px +
+
+ : + +
+
+
\ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json new file mode 100644 index 00000000000..17a71f2aea0 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json @@ -0,0 +1,9 @@ +{ + "boxShadowValueTypes": [ + "horizontalOffset", + "verticalOffset", + "blurRadius", + "spreadRadius", + "color" + ] +} \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js new file mode 100644 index 00000000000..35fe0217d04 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -0,0 +1,262 @@ +define(function(require, exports, module) { + "use strict"; + + var InlineWidget = brackets.getModule("editor/InlineWidget").InlineWidget, + BoxShadowEditor = require("BoxShadowEditor").BoxShadowEditor, + ColorUtils = brackets.getModule("utils/ColorUtils"), + boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + + + /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ + var lastOriginId = 1; + + /** + * Inline widget containing a BoxShadowEditor control + * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values Initial set of box-shadow values. + * @param {!CodeMirror.TextMarker} marker + */ + function InlineBoxShadowEditor(values, marker) { + this._values = values; + this._marker = marker; + this._isOwnChange = false; + this._isHostChange = false; + this._origin = "+InlineBoxShadowEditor_" + (lastOriginId++); + + this._handleBoxShadowChange = this._handleBoxShadowChange.bind(this); + this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this); + + InlineWidget.call(this); + } + + InlineBoxShadowEditor.prototype = Object.create(InlineWidget.prototype); + InlineBoxShadowEditor.prototype.constructor = InlineBoxShadowEditor; + InlineBoxShadowEditor.prototype.parentClass = InlineWidget.prototype; + + /** @type {!BoxShadowPicker} BoxShadowPicker instance */ + InlineBoxShadowEditor.prototype.BoxShadowEditor = null; + + /** @type {!{ horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string }} Current value of the BoxShadow editor control */ + InlineBoxShadowEditor.prototype._values = null; + + /** + * Range of code we're attached to; _marker.find() may by null if sync is lost. + * @type {!CodeMirror.TextMarker} + */ + InlineBoxShadowEditor.prototype._marker = null; + + /** @type {boolean} True while we're syncing a BoxShadow editor change into the code editor */ + InlineBoxShadowEditor.prototype._isOwnChange = null; + + /** @type {boolean} True while we're syncing a code editor change into the BoxShadow editor */ + InlineBoxShadowEditor.prototype._isHostChange = null; + + /** @type {number} ID used to identify edits coming from this inline widget for undo batching */ + InlineBoxShadowEditor.prototype._origin = null; + + /** + * Returns the current text range of the color we're attached to, or null if + * we've lost sync with what's in the code. + * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}} + */ + InlineBoxShadowEditor.prototype.getCurrentRange = function () { + var pos, start, end; + + pos = this._marker && this._marker.find(); + + start = pos && pos.from; + if (!start) { + return null; + } + + end = pos.to; + if (!end) { + end = {line: start.line}; + } + + /*-----------Correct this----------*/ + + // Even if we think we have a good range end, we want to run the + // regexp match to see if there's a valid match that extends past the marker. + // This can happen if the user deletes the end of the existing color and then + // types some more. + + // var line = this.hostEditor.document.getLine(start.line), + // matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX); + + // // Note that end.ch is exclusive, so we don't need to add 1 before comparing to + // // the matched length here. + // if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) { + // end.ch = start.ch + matches[0].length; + // this._marker.clear(); + // this._marker = this.hostEditor._codeMirror.markText(start, end); + // } + + // if (end.ch === undefined) { + // // We were unable to resync the marker. + // return null; + // } + // else { + // return {start: start, end: end}; + // } + return {start: start, end: end}; + }; + + InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { + var boxShadowString = boxShadowValueTypes.reduce(function(result, type) { + if(!values[type]) { + return result; + } + if (typeof values[type] === "Number") { + result += " " + values[type] + "px"; + } + else { + result += " " + values[type]; + } + return result; + },""); + + return boxShadowString.trim(); + } + + + /** + * When the BoxShadow editor's values change, update text in code editor + * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values New set of box-shadow values. + */ + InlineBoxShadowEditor.prototype._handleBoxShadowChange = function (values) { + var self = this; + var range = this.getCurrentRange(); + if (!range) { + return; + } + + // update values + for(var key in this._values) { + if(this._values.hasOwnProperty(key)) { + if(values[key] && values[key] != this._values[key]) { + this._values[key] = values[key]; + } + } + } + + // build the box-shadow value as a string. + var boxShadowString = this._buildBoxShadowString(this._values); + console.log(boxShadowString); + + var endPos = { + line: range.start.line, + ch: range.start.ch + boxShadowString.length + }; + this._isOwnChange = true; + this.hostEditor.document.batchOperation(function () { + // Replace old box-shadow in code with the editor's box-shadow values, and select it + self.hostEditor.setSelection(range.start, range.end); + self.hostEditor.document.replaceRange(boxShadowString, range.start, range.end, self._origin); + self.hostEditor.setSelection(range.start, endPos); + if (self._marker) { + self._marker.clear(); + self._marker = self.hostEditor._codeMirror.markText(range.start, endPos); + } + }); + this._isOwnChange = false; + }; + + /** + * @override + * @param {!Editor} hostEditor + */ + InlineBoxShadowEditor.prototype.load = function (hostEditor) { + InlineBoxShadowEditor.prototype.parentClass.load.apply(this, arguments); + + // Create BoxShadow picker control + this.boxShadowEditor = new BoxShadowEditor(this.$htmlContent, this._values, this._handleBoxShadowChange); + }; + + /** + * @override + * Perform sizing & focus once we've been added to Editor's DOM + */ + InlineBoxShadowEditor.prototype.onAdded = function () { + InlineBoxShadowEditor.prototype.parentClass.onAdded.apply(this, arguments); + + var doc = this.hostEditor.document; + doc.addRef(); + doc.on("change", this._handleHostDocumentChange); + + this.hostEditor.setInlineWidgetHeight(this, this.boxShadowEditor.getRootElement().outerHeight(), true); + + this.boxShadowEditor.focus(); + }; + + /** + * @override + * Called whenever the inline widget is closed, whether automatically or explicitly + */ + InlineBoxShadowEditor.prototype.onClosed = function () { + InlineBoxShadowEditor.prototype.parentClass.onClosed.apply(this, arguments); + + if (this._marker) { + this._marker.clear(); + } + + var doc = this.hostEditor.document; + doc.off("change", this._handleHostDocumentChange); + doc.releaseRef(); + this.boxShadowEditor.destroy(); + }; + + function _isValidBoxShadowValue(value) { + // Need to improve this regex. + return (value.match(/\s*(\d+px\s+){0,3}?\d+px(?:\s+|;|)(?:#?[a-z]{3,}\s*)?;?/) !== null); + } + + /** + * When text in the code editor changes, update color picker to reflect it + */ + InlineBoxShadowEditor.prototype._handleHostDocumentChange = function () { + // Don't push the change into the box-shadow editor if it came from the box-shadow editor. + if (this._isOwnChange) { + return; + } + + var range = this.getCurrentRange(); + /*Correct this*/ + if (range) { + var newString = this.hostEditor.document.getRange(range.start, range.end); + console.log(range); + var flag = _isValidBoxShadowValue(newString); + console.log(flag); + if(_isValidBoxShadowValue(newString)) { + // extract values + var newValues = {}; + var boxShadowValueIndex = 0; + newString.split(/\s+/).forEach(function(value, index) { + value = value.trim(); + var colorMatch = value.match(ColorUtils.COLOR_REGEX); + var pixelMatch = value.match(/(\d+)px/); + if(colorMatch) { + newValues["color"] = colorMatch[0]; + } + else if(pixelMatch){ + newValues[boxShadowValueTypes[boxShadowValueIndex++]] = value; + } + }); + console.log(newValues); + + if(newValues !== this._values) { + this._isHostChange = true; + this.boxShadowEditor.setValues(newValues); + this._values = newValues; + this._isHostChange = false; + } + } + + } + else { + // The edit caused our range to become invalid. Close the editor. + this.close(); + } + }; + + exports.InlineBoxShadowEditor = InlineBoxShadowEditor; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/css/style.less b/src/extensions/default/InlineBoxShadowEditor/css/style.less new file mode 100644 index 00000000000..ecd4ae27040 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/css/style.less @@ -0,0 +1,96 @@ +@sansFontFamily: Helvetica, Arial, "Meiryo UI", "MS Pゴシック", "MS PGothic", sans-serif; + +.box-shadow-editor { + font-size: 12px; + min-width: 450px; + height: 190px; + padding: 16px 16px 14px 46px; +} +.box-shadow-editor:focus { + outline: none; +} +.box-shadow-editor section { + display: inline-block; + position: relative; + vertical-align: top; +} +.box-shadow-editor section .box-shadow-input { + display: block; + margin-bottom: 8px; + + label { + display: inline-block; + min-width: 150px; + } +} + +.box-shadow-editor section #horizontal-offset-value, +.box-shadow-editor section #vertical-offset-value, +.box-shadow-editor section #blur-radius-value, +.box-shadow-editor section #spread-radius-value, +.box-shadow-editor section #color-value { + width: 118px; + height: 23px; + margin-right: 5px; + border-box-shadow: #b2b5b5; + box-sizing: border-box; + display: inline-block; + box-shadow: #222; +} +.box-shadow-editor section input { + display: inline-block; + height: 23px; + padding: 0 0 0 4px; + border: 1px solid #b2b5b5; + box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.06); + background: #fff; + font-family: @sansFontFamily; + font-size: 12px; + box-shadow: #454545; + border-radius: 3px; + margin: 0; + vertical-align: middle; +} +.box-shadow-editor section input:focus { + background: #fff; + outline: none; + box-shadow: 0 0 0 1px #94ceff; + border: 1px solid #2893ef; + z-index: 911; +} + +// Dark UI theme + +@dark-bc-bg-highlight: #2a3b50; +@dark-bc-highlight: rgba(255, 255, 255, 0.06); +@dark-bc-text: #ccc; +@dark-bc-text-alt: #fff; +@dark-bc-highlight-hard: rgba(255, 255, 255, 0.2); +@dark-bc-btn-bg: #3f3f3f; +@dark-bc-btn-border: #202020; +@dark-bc-btn-border-focused: #2893ef; +@dark-bc-btn-border-focused-glow: transparent; +@dark-bc-shadow: rgba(0, 0, 0, 0.24); +@dark-bc-shadow-small: rgba(0, 0, 0, 0.06); +@dark-bc-shadow-medium: rgba(0, 0, 0, 0.12); +@dark-bc-input-bg: #555; + +.dark { + .box-shadow-editor section footer .box-shadow-value { + border-box-shadow: @dark-bc-btn-border; + box-shadow: @dark-bc-text; + } + + .box-shadow-editor section footer input { + border: 1px solid @dark-bc-btn-border; + box-shadow: inset 0 1px 0 @dark-bc-shadow-small; + background: @dark-bc-input-bg; + box-shadow: @dark-bc-text; + } + + .box-shadow-editor section footer input:focus { + background: @dark-bc-input-bg; + box-shadow: 0 0 0 1px @dark-bc-btn-border-focused-glow; + border: 1px solid @dark-bc-btn-border-focused; + } +} \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js new file mode 100644 index 00000000000..41aebeb1fbf --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -0,0 +1,140 @@ +define(function(require, exports, module) { + "use strict"; + + var EditorManager = brackets.getModule("editor/EditorManager"), + ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), + InlineBoxShadowEditor = require("InlineBoxShadowEditor").InlineBoxShadowEditor, + ColorUtils = brackets.getModule("utils/ColorUtils"), + boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + + var DEFAULT_VALUES = "0px 0px 0px 0px black"; + /** + * Prepare hostEditor for an InlineBoxShadowEditor at pos if possible. Return + * editor context if so; otherwise null. + * + * @param {Editor} hostEditor + * @param {{line:Number, ch:Number}} pos + * @return {?{values:{}, marker:TextMarker}} + */ + function prepareEditorForProvider(hostEditor, pos) { + var cursorLine = hostEditor.document.getLine(pos.line); + + if(cursorLine.indexOf("box-shadow") === -1) { + return null; + } + + var semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; + values = {}; + + colonPos = cursorLine.indexOf(":"); + semiColonPos = cursorLine.indexOf(";"); + cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); + + console.log(cursorLineSubstring); + + // Get the initial set of values of box-shadow property + isEmptyString = true; + boxShadowValueIndex = 0; + cursorLineSubstring.split(/\s+/).forEach(function(value, index) { + value = value.trim(); + var colorMatch = value.match(ColorUtils.COLOR_REGEX); + var pixelMatch = value.match(/(\d+)px/); + console.log(value, colorMatch, pixelMatch); + if(colorMatch) { + values["color"] = colorMatch[0]; + isEmptyString = false; + } + else if(pixelMatch){ + // Fix here + values[boxShadowValueTypes[boxShadowValueIndex++]] = value; + isEmptyString = false; + } + }); + + console.log(isEmptyString); + + if(isEmptyString) { + //Edit a new css rule. + var newText = " ", from ,to; + newText = newText.concat(DEFAULT_VALUES, ";"); + from = {line: pos.line, ch: colonPos + 1}; + to = {line: pos.line, ch: cursorLine.length}; + hostEditor._codeMirror.replaceRange(newText, from, to); + pos.ch = colonPos + 2; + endPos = {line: pos.line, ch: pos.ch + DEFAULT_VALUES.length}; + values = { + "horizontalOffset": "0px", + "verticalOffset": "0px", + "blurRadius": "0px", + "spreadRadius": "0px", + "color": "black" + }; + } + else { + firstCharacterPos = cursorLineSubstring.search(/\S/); + pos.ch = colonPos + 1 + Math.min(firstCharacterPos,1); + if (semiColonPos !== -1) { + endPos = {line: pos.line, ch: semiColonPos}; + } else { + endPos = {line: pos.line, ch: cursorLine.length}; + } + } + + marker = hostEditor._codeMirror.markText(pos, endPos); + hostEditor.setSelection(pos, endPos); + + console.log(values); + + return { + values, + marker + }; + } + + /** + * Registered as an inline editor provider: creates an InlineBoxShadowEditor when the cursor + * is on a line containing box-shadow property (in any flavor of code). + * + * @param {!Editor} hostEditor + * @param {!{line:Number, ch:Number}} pos + * @return {?$.Promise} synchronously resolved with an InlineWidget, or null if there's + * no box-shadow at pos. + */ + function inlineBoxShadowEditorProvider(hostEditor, pos) { + var context = prepareEditorForProvider(hostEditor, pos), + inlineBoxShadowEditor, + result; + + if(!context) { + return null; + } + else { + inlineBoxShadowEditor = new InlineBoxShadowEditor(context.values, context.marker); + inlineBoxShadowEditor.load(hostEditor); + + result = new $.Deferred(); + result.resolve(inlineBoxShadowEditor); + return result.promise(); + } + } + + function queryInlineBoxShadowEditorProvider(hostEditor, pos) { + var cursorLine = hostEditor.document.getLine(pos.line); + + if(cursorLine.indexOf("box-shadow") !== -1) { + return true; + } + else { + return false; + } + } + + + // Initialize extension + ExtensionUtils.loadStyleSheet(module, "css/style.less"); + + EditorManager.registerInlineEditProvider(inlineBoxShadowEditorProvider, queryInlineBoxShadowEditorProvider); + + // for use by other InlineColorEditors + exports.prepareEditorForProvider = prepareEditorForProvider; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/thirdparty/tinycolor-min.js b/src/extensions/default/InlineBoxShadowEditor/thirdparty/tinycolor-min.js new file mode 100644 index 00000000000..89325118c40 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/thirdparty/tinycolor-min.js @@ -0,0 +1,4 @@ +// TinyColor v1.1.1 +// https://github.com/bgrins/TinyColor +// 2014-12-20, Brian Grinstead, MIT License +!function(){function inputToRGB(color){var rgb={r:0,g:0,b:0},a=1,ok=!1,format=!1;return"string"==typeof color&&(color=stringInputToObject(color)),"object"==typeof color&&(color.hasOwnProperty("r")&&color.hasOwnProperty("g")&&color.hasOwnProperty("b")?(rgb=rgbToRgb(color.r,color.g,color.b),ok=!0,format="%"===String(color.r).substr(-1)?"prgb":"rgb"):color.hasOwnProperty("h")&&color.hasOwnProperty("s")&&color.hasOwnProperty("v")?(color.s=convertToPercentage(color.s),color.v=convertToPercentage(color.v),rgb=hsvToRgb(color.h,color.s,color.v),ok=!0,format="hsv"):color.hasOwnProperty("h")&&color.hasOwnProperty("s")&&color.hasOwnProperty("l")&&(color.s=convertToPercentage(color.s),color.l=convertToPercentage(color.l),rgb=hslToRgb(color.h,color.s,color.l),ok=!0,format="hsl"),color.hasOwnProperty("a")&&(a=color.a)),a=boundAlpha(a),{ok:ok,format:color.format||format,r:mathMin(255,mathMax(rgb.r,0)),g:mathMin(255,mathMax(rgb.g,0)),b:mathMin(255,mathMax(rgb.b,0)),a:a}}function rgbToRgb(r,g,b){return{r:255*bound01(r,255),g:255*bound01(g,255),b:255*bound01(b,255)}}function rgbToHsl(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);var h,s,max=mathMax(r,g,b),min=mathMin(r,g,b),l=(max+min)/2;if(max==min)h=s=0;else{var d=max-min;switch(s=l>.5?d/(2-max-min):d/(max+min),max){case r:h=(g-b)/d+(b>g?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return{h:h,s:s,l:l}}function hslToRgb(h,s,l){function hue2rgb(p,q,t){return 0>t&&(t+=1),t>1&&(t-=1),1/6>t?p+6*(q-p)*t:.5>t?q:2/3>t?p+(q-p)*(2/3-t)*6:p}var r,g,b;if(h=bound01(h,360),s=bound01(s,100),l=bound01(l,100),0===s)r=g=b=l;else{var q=.5>l?l*(1+s):l+s-l*s,p=2*l-q;r=hue2rgb(p,q,h+1/3),g=hue2rgb(p,q,h),b=hue2rgb(p,q,h-1/3)}return{r:255*r,g:255*g,b:255*b}}function rgbToHsv(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);var h,s,max=mathMax(r,g,b),min=mathMin(r,g,b),v=max,d=max-min;if(s=0===max?0:d/max,max==min)h=0;else{switch(max){case r:h=(g-b)/d+(b>g?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return{h:h,s:s,v:v}}function hsvToRgb(h,s,v){h=6*bound01(h,360),s=bound01(s,100),v=bound01(v,100);var i=math.floor(h),f=h-i,p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s),mod=i%6,r=[v,q,p,p,t,v][mod],g=[t,v,v,q,p,p][mod],b=[p,p,t,v,v,q][mod];return{r:255*r,g:255*g,b:255*b}}function rgbToHex(r,g,b,allow3Char){var hex=[pad2(mathRound(r).toString(16)),pad2(mathRound(g).toString(16)),pad2(mathRound(b).toString(16))];return allow3Char&&hex[0].charAt(0)==hex[0].charAt(1)&&hex[1].charAt(0)==hex[1].charAt(1)&&hex[2].charAt(0)==hex[2].charAt(1)?hex[0].charAt(0)+hex[1].charAt(0)+hex[2].charAt(0):hex.join("")}function rgbaToHex(r,g,b,a){var hex=[pad2(convertDecimalToHex(a)),pad2(mathRound(r).toString(16)),pad2(mathRound(g).toString(16)),pad2(mathRound(b).toString(16))];return hex.join("")}function desaturate(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.s-=amount/100,hsl.s=clamp01(hsl.s),tinycolor(hsl)}function saturate(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.s+=amount/100,hsl.s=clamp01(hsl.s),tinycolor(hsl)}function greyscale(color){return tinycolor(color).desaturate(100)}function lighten(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.l+=amount/100,hsl.l=clamp01(hsl.l),tinycolor(hsl)}function brighten(color,amount){amount=0===amount?0:amount||10;var rgb=tinycolor(color).toRgb();return rgb.r=mathMax(0,mathMin(255,rgb.r-mathRound(255*-(amount/100)))),rgb.g=mathMax(0,mathMin(255,rgb.g-mathRound(255*-(amount/100)))),rgb.b=mathMax(0,mathMin(255,rgb.b-mathRound(255*-(amount/100)))),tinycolor(rgb)}function darken(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.l-=amount/100,hsl.l=clamp01(hsl.l),tinycolor(hsl)}function spin(color,amount){var hsl=tinycolor(color).toHsl(),hue=(mathRound(hsl.h)+amount)%360;return hsl.h=0>hue?360+hue:hue,tinycolor(hsl)}function complement(color){var hsl=tinycolor(color).toHsl();return hsl.h=(hsl.h+180)%360,tinycolor(hsl)}function triad(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+120)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+240)%360,s:hsl.s,l:hsl.l})]}function tetrad(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+90)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+180)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+270)%360,s:hsl.s,l:hsl.l})]}function splitcomplement(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+72)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+216)%360,s:hsl.s,l:hsl.l})]}function analogous(color,results,slices){results=results||6,slices=slices||30;var hsl=tinycolor(color).toHsl(),part=360/slices,ret=[tinycolor(color)];for(hsl.h=(hsl.h-(part*results>>1)+720)%360;--results;)hsl.h=(hsl.h+part)%360,ret.push(tinycolor(hsl));return ret}function monochromatic(color,results){results=results||6;for(var hsv=tinycolor(color).toHsv(),h=hsv.h,s=hsv.s,v=hsv.v,ret=[],modification=1/results;results--;)ret.push(tinycolor({h:h,s:s,v:v})),v=(v+modification)%1;return ret}function flip(o){var flipped={};for(var i in o)o.hasOwnProperty(i)&&(flipped[o[i]]=i);return flipped}function boundAlpha(a){return a=parseFloat(a),(isNaN(a)||0>a||a>1)&&(a=1),a}function bound01(n,max){isOnePointZero(n)&&(n="100%");var processPercent=isPercentage(n);return n=mathMin(max,mathMax(0,parseFloat(n))),processPercent&&(n=parseInt(n*max,10)/100),math.abs(n-max)<1e-6?1:n%max/parseFloat(max)}function clamp01(val){return mathMin(1,mathMax(0,val))}function parseIntFromHex(val){return parseInt(val,16)}function isOnePointZero(n){return"string"==typeof n&&-1!=n.indexOf(".")&&1===parseFloat(n)}function isPercentage(n){return"string"==typeof n&&-1!=n.indexOf("%")}function pad2(c){return 1==c.length?"0"+c:""+c}function convertToPercentage(n){return 1>=n&&(n=100*n+"%"),n}function convertDecimalToHex(d){return Math.round(255*parseFloat(d)).toString(16)}function convertHexToDecimal(h){return parseIntFromHex(h)/255}function stringInputToObject(color){color=color.replace(trimLeft,"").replace(trimRight,"").toLowerCase();var named=!1;if(names[color])color=names[color],named=!0;else if("transparent"==color)return{r:0,g:0,b:0,a:0,format:"name"};var match;return(match=matchers.rgb.exec(color))?{r:match[1],g:match[2],b:match[3]}:(match=matchers.rgba.exec(color))?{r:match[1],g:match[2],b:match[3],a:match[4]}:(match=matchers.hsl.exec(color))?{h:match[1],s:match[2],l:match[3]}:(match=matchers.hsla.exec(color))?{h:match[1],s:match[2],l:match[3],a:match[4]}:(match=matchers.hsv.exec(color))?{h:match[1],s:match[2],v:match[3]}:(match=matchers.hsva.exec(color))?{h:match[1],s:match[2],v:match[3],a:match[4]}:(match=matchers.hex8.exec(color))?{a:convertHexToDecimal(match[1]),r:parseIntFromHex(match[2]),g:parseIntFromHex(match[3]),b:parseIntFromHex(match[4]),format:named?"name":"hex8"}:(match=matchers.hex6.exec(color))?{r:parseIntFromHex(match[1]),g:parseIntFromHex(match[2]),b:parseIntFromHex(match[3]),format:named?"name":"hex"}:(match=matchers.hex3.exec(color))?{r:parseIntFromHex(match[1]+""+match[1]),g:parseIntFromHex(match[2]+""+match[2]),b:parseIntFromHex(match[3]+""+match[3]),format:named?"name":"hex"}:!1}var trimLeft=/^[\s,#]+/,trimRight=/\s+$/,tinyCounter=0,math=Math,mathRound=math.round,mathMin=math.min,mathMax=math.max,mathRandom=math.random,tinycolor=function tinycolor(color,opts){if(color=color?color:"",opts=opts||{},color instanceof tinycolor)return color;if(!(this instanceof tinycolor))return new tinycolor(color,opts);var rgb=inputToRGB(color);this._originalInput=color,this._r=rgb.r,this._g=rgb.g,this._b=rgb.b,this._a=rgb.a,this._roundA=mathRound(100*this._a)/100,this._format=opts.format||rgb.format,this._gradientType=opts.gradientType,this._r<1&&(this._r=mathRound(this._r)),this._g<1&&(this._g=mathRound(this._g)),this._b<1&&(this._b=mathRound(this._b)),this._ok=rgb.ok,this._tc_id=tinyCounter++};tinycolor.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var rgb=this.toRgb();return(299*rgb.r+587*rgb.g+114*rgb.b)/1e3},setAlpha:function(value){return this._a=boundAlpha(value),this._roundA=mathRound(100*this._a)/100,this},toHsv:function(){var hsv=rgbToHsv(this._r,this._g,this._b);return{h:360*hsv.h,s:hsv.s,v:hsv.v,a:this._a}},toHsvString:function(){var hsv=rgbToHsv(this._r,this._g,this._b),h=mathRound(360*hsv.h),s=mathRound(100*hsv.s),v=mathRound(100*hsv.v);return 1==this._a?"hsv("+h+", "+s+"%, "+v+"%)":"hsva("+h+", "+s+"%, "+v+"%, "+this._roundA+")"},toHsl:function(){var hsl=rgbToHsl(this._r,this._g,this._b);return{h:360*hsl.h,s:hsl.s,l:hsl.l,a:this._a}},toHslString:function(){var hsl=rgbToHsl(this._r,this._g,this._b),h=mathRound(360*hsl.h),s=mathRound(100*hsl.s),l=mathRound(100*hsl.l);return 1==this._a?"hsl("+h+", "+s+"%, "+l+"%)":"hsla("+h+", "+s+"%, "+l+"%, "+this._roundA+")"},toHex:function(allow3Char){return rgbToHex(this._r,this._g,this._b,allow3Char)},toHexString:function(allow3Char){return"#"+this.toHex(allow3Char)},toHex8:function(){return rgbaToHex(this._r,this._g,this._b,this._a)},toHex8String:function(){return"#"+this.toHex8()},toRgb:function(){return{r:mathRound(this._r),g:mathRound(this._g),b:mathRound(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+mathRound(this._r)+", "+mathRound(this._g)+", "+mathRound(this._b)+")":"rgba("+mathRound(this._r)+", "+mathRound(this._g)+", "+mathRound(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:mathRound(100*bound01(this._r,255))+"%",g:mathRound(100*bound01(this._g,255))+"%",b:mathRound(100*bound01(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+mathRound(100*bound01(this._r,255))+"%, "+mathRound(100*bound01(this._g,255))+"%, "+mathRound(100*bound01(this._b,255))+"%)":"rgba("+mathRound(100*bound01(this._r,255))+"%, "+mathRound(100*bound01(this._g,255))+"%, "+mathRound(100*bound01(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":this._a<1?!1:hexNames[rgbToHex(this._r,this._g,this._b,!0)]||!1},toFilter:function(secondColor){var hex8String="#"+rgbaToHex(this._r,this._g,this._b,this._a),secondHex8String=hex8String,gradientType=this._gradientType?"GradientType = 1, ":"";if(secondColor){var s=tinycolor(secondColor);secondHex8String=s.toHex8String()}return"progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"},toString:function(format){var formatSet=!!format;format=format||this._format;var formattedString=!1,hasAlpha=this._a<1&&this._a>=0,needsAlphaFormat=!formatSet&&hasAlpha&&("hex"===format||"hex6"===format||"hex3"===format||"name"===format);return needsAlphaFormat?"name"===format&&0===this._a?this.toName():this.toRgbString():("rgb"===format&&(formattedString=this.toRgbString()),"prgb"===format&&(formattedString=this.toPercentageRgbString()),("hex"===format||"hex6"===format)&&(formattedString=this.toHexString()),"hex3"===format&&(formattedString=this.toHexString(!0)),"hex8"===format&&(formattedString=this.toHex8String()),"name"===format&&(formattedString=this.toName()),"hsl"===format&&(formattedString=this.toHslString()),"hsv"===format&&(formattedString=this.toHsvString()),formattedString||this.toHexString())},_applyModification:function(fn,args){var color=fn.apply(null,[this].concat([].slice.call(args)));return this._r=color._r,this._g=color._g,this._b=color._b,this.setAlpha(color._a),this},lighten:function(){return this._applyModification(lighten,arguments)},brighten:function(){return this._applyModification(brighten,arguments)},darken:function(){return this._applyModification(darken,arguments)},desaturate:function(){return this._applyModification(desaturate,arguments)},saturate:function(){return this._applyModification(saturate,arguments)},greyscale:function(){return this._applyModification(greyscale,arguments)},spin:function(){return this._applyModification(spin,arguments)},_applyCombination:function(fn,args){return fn.apply(null,[this].concat([].slice.call(args)))},analogous:function(){return this._applyCombination(analogous,arguments)},complement:function(){return this._applyCombination(complement,arguments)},monochromatic:function(){return this._applyCombination(monochromatic,arguments)},splitcomplement:function(){return this._applyCombination(splitcomplement,arguments)},triad:function(){return this._applyCombination(triad,arguments)},tetrad:function(){return this._applyCombination(tetrad,arguments)}},tinycolor.fromRatio=function(color,opts){if("object"==typeof color){var newColor={};for(var i in color)color.hasOwnProperty(i)&&(newColor[i]="a"===i?color[i]:convertToPercentage(color[i]));color=newColor}return tinycolor(color,opts)},tinycolor.equals=function(color1,color2){return color1&&color2?tinycolor(color1).toRgbString()==tinycolor(color2).toRgbString():!1},tinycolor.random=function(){return tinycolor.fromRatio({r:mathRandom(),g:mathRandom(),b:mathRandom()})},tinycolor.mix=function(color1,color2,amount){amount=0===amount?0:amount||50;var w1,rgb1=tinycolor(color1).toRgb(),rgb2=tinycolor(color2).toRgb(),p=amount/100,w=2*p-1,a=rgb2.a-rgb1.a;w1=w*a==-1?w:(w+a)/(1+w*a),w1=(w1+1)/2;var w2=1-w1,rgba={r:rgb2.r*w1+rgb1.r*w2,g:rgb2.g*w1+rgb1.g*w2,b:rgb2.b*w1+rgb1.b*w2,a:rgb2.a*p+rgb1.a*(1-p)};return tinycolor(rgba)},tinycolor.readability=function(color1,color2){var c1=tinycolor(color1),c2=tinycolor(color2),rgb1=c1.toRgb(),rgb2=c2.toRgb(),brightnessA=c1.getBrightness(),brightnessB=c2.getBrightness(),colorDiff=Math.max(rgb1.r,rgb2.r)-Math.min(rgb1.r,rgb2.r)+Math.max(rgb1.g,rgb2.g)-Math.min(rgb1.g,rgb2.g)+Math.max(rgb1.b,rgb2.b)-Math.min(rgb1.b,rgb2.b);return{brightness:Math.abs(brightnessA-brightnessB),color:colorDiff}},tinycolor.isReadable=function(color1,color2){var readability=tinycolor.readability(color1,color2);return readability.brightness>125&&readability.color>500},tinycolor.mostReadable=function(baseColor,colorList){for(var bestColor=null,bestScore=0,bestIsReadable=!1,i=0;i125&&readability.color>500,score=3*(readability.brightness/125)+readability.color/500;(readable&&!bestIsReadable||readable&&bestIsReadable&&score>bestScore||!readable&&!bestIsReadable&&score>bestScore)&&(bestIsReadable=readable,bestScore=score,bestColor=tinycolor(colorList[i]))}return bestColor};var names=tinycolor.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},hexNames=tinycolor.hexNames=flip(names),matchers=function(){var CSS_INTEGER="[-\\+]?\\d+%?",CSS_NUMBER="[-\\+]?\\d*\\.\\d+%?",CSS_UNIT="(?:"+CSS_NUMBER+")|(?:"+CSS_INTEGER+")",PERMISSIVE_MATCH3="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?",PERMISSIVE_MATCH4="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?";return{rgb:new RegExp("rgb"+PERMISSIVE_MATCH3),rgba:new RegExp("rgba"+PERMISSIVE_MATCH4),hsl:new RegExp("hsl"+PERMISSIVE_MATCH3),hsla:new RegExp("hsla"+PERMISSIVE_MATCH4),hsv:new RegExp("hsv"+PERMISSIVE_MATCH3),hsva:new RegExp("hsva"+PERMISSIVE_MATCH4),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();"undefined"!=typeof module&&module.exports?module.exports=tinycolor:"function"==typeof define&&define.amd?define(function(){return tinycolor}):window.tinycolor=tinycolor}(); From cbd036f9d3f313d3e6dfa4316b7e8569b99fe1e4 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Fri, 20 Oct 2017 14:59:41 +0530 Subject: [PATCH 02/21] Fixes eslint errors in InlineBoxShadowEditor --- .../InlineBoxShadowEditor/BoxShadowEditor.js | 34 ++++++++----------- .../InlineBoxShadowEditor.js | 14 ++++---- .../default/InlineBoxShadowEditor/main.js | 4 +-- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index bc9f15f0df1..d14f0555bdd 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -72,7 +72,7 @@ define(function(require, exports, module) { BoxShadowEditor.prototype.setValues = function(values) { for(var key in this._values) { if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] != this._values[key]) { + if(values[key] && values[key] !== this._values[key]) { this._values[key] = values[key]; } } @@ -120,27 +120,23 @@ define(function(require, exports, module) { this.$colorValue.bind("input", function (event) { self._handleColorChange(); }); - } - - BoxShadowEditor.prototype._synchronize = function() { - - } + }; BoxShadowEditor.prototype.focus = function() { this.$horizontalOffsetValue.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); - } + }; function _handleChanges($inputElement, propertyName, value) { console.log(value, typeof value); @@ -153,7 +149,7 @@ define(function(require, exports, module) { $inputElement.val(curValue); } - if(value == "") { + if(value === "") { // This is to maintain the box-shadow property. value = "0"; $inputElement.val(value); @@ -161,31 +157,31 @@ define(function(require, exports, module) { var newValue = value + "px"; this._commitChanges(propertyName, newValue); - } + }; BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { var self = this; var newValue = this.$horizontalOffsetValue.val().trim(); _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); - } + }; BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { var self = this; var newValue = this.$verticalOffsetValue.val().trim(); _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); - } + }; BoxShadowEditor.prototype._handleBlurRadiusChange = function() { var self = this; var newValue = this.$blurRadiusValue.val().trim(); _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); - } + }; BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { var self = this; var newValue = this.$spreadRadiusValue.val().trim(); _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); - } + }; /** * Normalize the given color string into the format used by tinycolor, by adding a space @@ -233,11 +229,11 @@ define(function(require, exports, module) { BoxShadowEditor.prototype._undo = function() { - } + }; BoxShadowEditor.prototype._redo = function() { - } + }; /** * Global handler for keys in the color editor. Catches undo/redo keys and traps @@ -265,7 +261,7 @@ define(function(require, exports, module) { BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { this._values[propertyName] = value; this._callback(this._values); - } + }; exports.BoxShadowEditor = BoxShadowEditor; diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 35fe0217d04..6a518defca8 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -102,21 +102,21 @@ define(function(require, exports, module) { }; InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { - var boxShadowString = boxShadowValueTypes.reduce(function(result, type) { - if(!values[type]) { + var boxShadowString = boxShadowValueTypes.reduce(function(result, boxShadowValueType) { + if(!values[boxShadowValueType]) { return result; } - if (typeof values[type] === "Number") { - result += " " + values[type] + "px"; + if (!isNaN(values[boxShadowValueType]) ) { + result += " " + values[boxShadowValueType] + "px"; } else { - result += " " + values[type]; + result += " " + values[boxShadowValueType]; } return result; },""); return boxShadowString.trim(); - } + }; /** @@ -133,7 +133,7 @@ define(function(require, exports, module) { // update values for(var key in this._values) { if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] != this._values[key]) { + if(values[key] && values[key] !== this._values[key]) { this._values[key] = values[key]; } } diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index 41aebeb1fbf..c057c31155d 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -86,8 +86,8 @@ define(function(require, exports, module) { console.log(values); return { - values, - marker + values: values, + marker: marker }; } From 926e0d6e97c068972f416ae26c8fcf22cbb77f67 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 21 Oct 2017 22:26:08 +0530 Subject: [PATCH 03/21] Changed indent tabs to 4 spaces --- .../InlineBoxShadowEditor/BoxShadowEditor.js | 418 +++++++------- .../BoxShadowEditorTemplate.html | 62 +-- .../BoxShadowValueTypes.json | 14 +- .../InlineBoxShadowEditor.js | 510 +++++++++--------- .../default/InlineBoxShadowEditor/main.js | 230 ++++---- 5 files changed, 617 insertions(+), 617 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index d14f0555bdd..1541c7a8227 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -1,105 +1,105 @@ define(function(require, exports, module) { - "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"), - tinycolor = require("thirdparty/tinycolor-min"); - - /** 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 {!{horizontalOffset: string, verticalOffset: string, blurRadius: string, spreadRadius: 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.$horizontalOffsetValue = this.$element.find("#horizontal-offset-value"); - this.$verticalOffsetValue = this.$element.find("#vertical-offset-value"); - this.$blurRadiusValue = this.$element.find("#blur-radius-value"); - this.$spreadRadiusValue = this.$element.find("#spread-radius-value"); - this.$colorValue = this.$element.find("#color-value"); - - - // Attach event listeners to main UI elements - this._bindInputHandlers(); - - - // Set initial values in the box-shadow editor inputs. - this._setInputValues(); - } - - /** - * A string or tinycolor object representing the currently selected color - * TODO (#2201): type is unpredictable - * @type {tinycolor|string} - */ - 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) { - for(var key in this._values) { - if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] !== this._values[key]) { - this._values[key] = values[key]; - } - } - } - - this._setInputValues(); - }; - - BoxShadowEditor.prototype._setInputValues = function() { - var values = this._values; - var horizontalOffset, verticalOffset, blurRadius, spreadRadius, color; - - horizontalOffset = values["horizontalOffset"] ? parseFloat(values["horizontalOffset"]) : ""; - verticalOffset = values["verticalOffset"] ? parseFloat(values["verticalOffset"]) : ""; - blurRadius = values["blurRadius"] ? parseFloat(values["blurRadius"]) : ""; - spreadRadius = values["spreadRadius"] ? parseFloat(values["spreadRadius"]) : ""; - color = values["color"] ? values["color"] : ""; - - this.$horizontalOffsetValue.val(horizontalOffset); - this.$verticalOffsetValue.val(verticalOffset); - this.$blurRadiusValue.val(blurRadius); - this.$spreadRadiusValue.val(spreadRadius); - this.$colorValue.val(color); - }; - - BoxShadowEditor.prototype._bindInputHandlers = function() { - var self = this; + "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"), + tinycolor = require("thirdparty/tinycolor-min"); + + /** 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 {!{horizontalOffset: string, verticalOffset: string, blurRadius: string, spreadRadius: 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.$horizontalOffsetValue = this.$element.find("#horizontal-offset-value"); + this.$verticalOffsetValue = this.$element.find("#vertical-offset-value"); + this.$blurRadiusValue = this.$element.find("#blur-radius-value"); + this.$spreadRadiusValue = this.$element.find("#spread-radius-value"); + this.$colorValue = this.$element.find("#color-value"); + + + // Attach event listeners to main UI elements + this._bindInputHandlers(); + + + // Set initial values in the box-shadow editor inputs. + this._setInputValues(); + } + + /** + * A string or tinycolor object representing the currently selected color + * TODO (#2201): type is unpredictable + * @type {tinycolor|string} + */ + 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) { + for(var key in this._values) { + if(this._values.hasOwnProperty(key)) { + if(values[key] && values[key] !== this._values[key]) { + this._values[key] = values[key]; + } + } + } + + this._setInputValues(); + }; + + BoxShadowEditor.prototype._setInputValues = function() { + var values = this._values; + var horizontalOffset, verticalOffset, blurRadius, spreadRadius, color; + + horizontalOffset = values["horizontalOffset"] ? parseFloat(values["horizontalOffset"]) : ""; + verticalOffset = values["verticalOffset"] ? parseFloat(values["verticalOffset"]) : ""; + blurRadius = values["blurRadius"] ? parseFloat(values["blurRadius"]) : ""; + spreadRadius = values["spreadRadius"] ? parseFloat(values["spreadRadius"]) : ""; + color = values["color"] ? values["color"] : ""; + + this.$horizontalOffsetValue.val(horizontalOffset); + this.$verticalOffsetValue.val(verticalOffset); + this.$blurRadiusValue.val(blurRadius); + this.$spreadRadiusValue.val(spreadRadius); + this.$colorValue.val(color); + }; + + BoxShadowEditor.prototype._bindInputHandlers = function() { + var self = this; this.$horizontalOffsetValue.bind("input", function (event) { self._handleHorizontalOffsetChange(); @@ -120,70 +120,70 @@ define(function(require, exports, module) { this.$colorValue.bind("input", function (event) { self._handleColorChange(); }); - }; - - BoxShadowEditor.prototype.focus = function() { - this.$horizontalOffsetValue.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); - }; - - function _handleChanges($inputElement, propertyName, value) { - console.log(value, typeof value); - if(!_isValidNumber(value)) { - if(!this._values[propertyName]) { - $inputElement.val(""); - return; - } - var curValue = parseFloat(this._values[propertyName]); - $inputElement.val(curValue); - } - - if(value === "") { - // This is to maintain the box-shadow property. - value = "0"; - $inputElement.val(value); - } - - var newValue = value + "px"; - this._commitChanges(propertyName, newValue); - }; - - BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { - var self = this; - var newValue = this.$horizontalOffsetValue.val().trim(); - _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); - }; - - BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { - var self = this; - var newValue = this.$verticalOffsetValue.val().trim(); - _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); - }; - - BoxShadowEditor.prototype._handleBlurRadiusChange = function() { - var self = this; - var newValue = this.$blurRadiusValue.val().trim(); - _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); - }; - - BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { - var self = this; - var newValue = this.$spreadRadiusValue.val().trim(); - _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); - }; - - /** + }; + + BoxShadowEditor.prototype.focus = function() { + this.$horizontalOffsetValue.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); + }; + + function _handleChanges($inputElement, propertyName, value) { + console.log(value, typeof value); + if(!_isValidNumber(value)) { + if(!this._values[propertyName]) { + $inputElement.val(""); + return; + } + var curValue = parseFloat(this._values[propertyName]); + $inputElement.val(curValue); + } + + if(value === "") { + // This is to maintain the box-shadow property. + value = "0"; + $inputElement.val(value); + } + + var newValue = value + "px"; + this._commitChanges(propertyName, newValue); + }; + + BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { + var self = this; + var newValue = this.$horizontalOffsetValue.val().trim(); + _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); + }; + + BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { + var self = this; + var newValue = this.$verticalOffsetValue.val().trim(); + _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); + }; + + BoxShadowEditor.prototype._handleBlurRadiusChange = function() { + var self = this; + var newValue = this.$blurRadiusValue.val().trim(); + _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); + }; + + BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { + var self = this; + var newValue = this.$spreadRadiusValue.val().trim(); + _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); + }; + + /** * 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. @@ -204,8 +204,8 @@ define(function(require, exports, module) { return normalizedColor; }; - BoxShadowEditor.prototype._handleColorChange = function() { - var newColor = $.trim(this.$colorValue.val()), + BoxShadowEditor.prototype._handleColorChange = function() { + var newColor = $.trim(this.$colorValue.val()), newColorObj = tinycolor(newColor), newColorOk = newColorObj.isValid(); @@ -222,47 +222,47 @@ define(function(require, exports, module) { // Sync only if we have a valid color or we're restoring the previous valid color. if (newColorOk) { - console.log(newColor); - this._commitChanges("color", newColor); + console.log(newColor); + this._commitChanges("color", newColor); } - }; - - 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; - } - } - }; - - - BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { - this._values[propertyName] = value; - this._callback(this._values); - }; - - - exports.BoxShadowEditor = BoxShadowEditor; + }; + + 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; + } + } + }; + + + BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { + this._values[propertyName] = value; + this._callback(this._values); + }; + + + exports.BoxShadowEditor = BoxShadowEditor; }); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html index c651c6e4eb6..e6589853f54 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -1,33 +1,33 @@
-
- -
- : - px -
-
- : - px -
-
- : - px -
-
- : - px -
-
- : - -
-
+
+ +
+ : + px +
+
+ : + px +
+
+ : + px +
+
+ : + px +
+
+ : + +
+
\ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json index 17a71f2aea0..866a25af220 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json @@ -1,9 +1,9 @@ { - "boxShadowValueTypes": [ - "horizontalOffset", - "verticalOffset", - "blurRadius", - "spreadRadius", - "color" - ] + "boxShadowValueTypes": [ + "horizontalOffset", + "verticalOffset", + "blurRadius", + "spreadRadius", + "color" + ] } \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 6a518defca8..e410a4cc45d 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -1,262 +1,262 @@ define(function(require, exports, module) { - "use strict"; + "use strict"; - var InlineWidget = brackets.getModule("editor/InlineWidget").InlineWidget, - BoxShadowEditor = require("BoxShadowEditor").BoxShadowEditor, - ColorUtils = brackets.getModule("utils/ColorUtils"), - boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + var InlineWidget = brackets.getModule("editor/InlineWidget").InlineWidget, + BoxShadowEditor = require("BoxShadowEditor").BoxShadowEditor, + ColorUtils = brackets.getModule("utils/ColorUtils"), + boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; - /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ + /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ var lastOriginId = 1; - /** - * Inline widget containing a BoxShadowEditor control - * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values Initial set of box-shadow values. - * @param {!CodeMirror.TextMarker} marker - */ - function InlineBoxShadowEditor(values, marker) { - this._values = values; - this._marker = marker; - this._isOwnChange = false; - this._isHostChange = false; - this._origin = "+InlineBoxShadowEditor_" + (lastOriginId++); - - this._handleBoxShadowChange = this._handleBoxShadowChange.bind(this); - this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this); - - InlineWidget.call(this); - } - - InlineBoxShadowEditor.prototype = Object.create(InlineWidget.prototype); - InlineBoxShadowEditor.prototype.constructor = InlineBoxShadowEditor; - InlineBoxShadowEditor.prototype.parentClass = InlineWidget.prototype; - - /** @type {!BoxShadowPicker} BoxShadowPicker instance */ - InlineBoxShadowEditor.prototype.BoxShadowEditor = null; - - /** @type {!{ horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string }} Current value of the BoxShadow editor control */ - InlineBoxShadowEditor.prototype._values = null; - - /** - * Range of code we're attached to; _marker.find() may by null if sync is lost. - * @type {!CodeMirror.TextMarker} - */ - InlineBoxShadowEditor.prototype._marker = null; - - /** @type {boolean} True while we're syncing a BoxShadow editor change into the code editor */ - InlineBoxShadowEditor.prototype._isOwnChange = null; - - /** @type {boolean} True while we're syncing a code editor change into the BoxShadow editor */ - InlineBoxShadowEditor.prototype._isHostChange = null; - - /** @type {number} ID used to identify edits coming from this inline widget for undo batching */ - InlineBoxShadowEditor.prototype._origin = null; - - /** - * Returns the current text range of the color we're attached to, or null if - * we've lost sync with what's in the code. - * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}} - */ - InlineBoxShadowEditor.prototype.getCurrentRange = function () { - var pos, start, end; - - pos = this._marker && this._marker.find(); - - start = pos && pos.from; - if (!start) { - return null; - } - - end = pos.to; - if (!end) { - end = {line: start.line}; - } - - /*-----------Correct this----------*/ - - // Even if we think we have a good range end, we want to run the - // regexp match to see if there's a valid match that extends past the marker. - // This can happen if the user deletes the end of the existing color and then - // types some more. - - // var line = this.hostEditor.document.getLine(start.line), - // matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX); - - // // Note that end.ch is exclusive, so we don't need to add 1 before comparing to - // // the matched length here. - // if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) { - // end.ch = start.ch + matches[0].length; - // this._marker.clear(); - // this._marker = this.hostEditor._codeMirror.markText(start, end); - // } - - // if (end.ch === undefined) { - // // We were unable to resync the marker. - // return null; - // } - // else { - // return {start: start, end: end}; - // } - return {start: start, end: end}; - }; - - InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { - var boxShadowString = boxShadowValueTypes.reduce(function(result, boxShadowValueType) { - if(!values[boxShadowValueType]) { - return result; - } - if (!isNaN(values[boxShadowValueType]) ) { - result += " " + values[boxShadowValueType] + "px"; - } - else { - result += " " + values[boxShadowValueType]; - } - return result; - },""); - - return boxShadowString.trim(); - }; - - - /** - * When the BoxShadow editor's values change, update text in code editor - * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values New set of box-shadow values. - */ - InlineBoxShadowEditor.prototype._handleBoxShadowChange = function (values) { - var self = this; - var range = this.getCurrentRange(); - if (!range) { - return; - } - - // update values - for(var key in this._values) { - if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] !== this._values[key]) { - this._values[key] = values[key]; - } - } - } - - // build the box-shadow value as a string. - var boxShadowString = this._buildBoxShadowString(this._values); - console.log(boxShadowString); - - var endPos = { - line: range.start.line, - ch: range.start.ch + boxShadowString.length - }; - this._isOwnChange = true; - this.hostEditor.document.batchOperation(function () { - // Replace old box-shadow in code with the editor's box-shadow values, and select it - self.hostEditor.setSelection(range.start, range.end); - self.hostEditor.document.replaceRange(boxShadowString, range.start, range.end, self._origin); - self.hostEditor.setSelection(range.start, endPos); - if (self._marker) { - self._marker.clear(); - self._marker = self.hostEditor._codeMirror.markText(range.start, endPos); - } - }); - this._isOwnChange = false; - }; - - /** - * @override - * @param {!Editor} hostEditor - */ - InlineBoxShadowEditor.prototype.load = function (hostEditor) { - InlineBoxShadowEditor.prototype.parentClass.load.apply(this, arguments); - - // Create BoxShadow picker control - this.boxShadowEditor = new BoxShadowEditor(this.$htmlContent, this._values, this._handleBoxShadowChange); - }; - - /** - * @override - * Perform sizing & focus once we've been added to Editor's DOM - */ - InlineBoxShadowEditor.prototype.onAdded = function () { - InlineBoxShadowEditor.prototype.parentClass.onAdded.apply(this, arguments); - - var doc = this.hostEditor.document; - doc.addRef(); - doc.on("change", this._handleHostDocumentChange); - - this.hostEditor.setInlineWidgetHeight(this, this.boxShadowEditor.getRootElement().outerHeight(), true); - - this.boxShadowEditor.focus(); - }; - - /** - * @override - * Called whenever the inline widget is closed, whether automatically or explicitly - */ - InlineBoxShadowEditor.prototype.onClosed = function () { - InlineBoxShadowEditor.prototype.parentClass.onClosed.apply(this, arguments); - - if (this._marker) { - this._marker.clear(); - } - - var doc = this.hostEditor.document; - doc.off("change", this._handleHostDocumentChange); - doc.releaseRef(); - this.boxShadowEditor.destroy(); - }; - - function _isValidBoxShadowValue(value) { - // Need to improve this regex. - return (value.match(/\s*(\d+px\s+){0,3}?\d+px(?:\s+|;|)(?:#?[a-z]{3,}\s*)?;?/) !== null); - } - - /** - * When text in the code editor changes, update color picker to reflect it - */ - InlineBoxShadowEditor.prototype._handleHostDocumentChange = function () { - // Don't push the change into the box-shadow editor if it came from the box-shadow editor. - if (this._isOwnChange) { - return; - } - - var range = this.getCurrentRange(); - /*Correct this*/ - if (range) { - var newString = this.hostEditor.document.getRange(range.start, range.end); - console.log(range); - var flag = _isValidBoxShadowValue(newString); - console.log(flag); - if(_isValidBoxShadowValue(newString)) { - // extract values - var newValues = {}; - var boxShadowValueIndex = 0; - newString.split(/\s+/).forEach(function(value, index) { - value = value.trim(); - var colorMatch = value.match(ColorUtils.COLOR_REGEX); - var pixelMatch = value.match(/(\d+)px/); - if(colorMatch) { - newValues["color"] = colorMatch[0]; - } - else if(pixelMatch){ - newValues[boxShadowValueTypes[boxShadowValueIndex++]] = value; - } - }); - console.log(newValues); - - if(newValues !== this._values) { - this._isHostChange = true; - this.boxShadowEditor.setValues(newValues); - this._values = newValues; - this._isHostChange = false; - } - } - - } - else { - // The edit caused our range to become invalid. Close the editor. - this.close(); - } - }; - - exports.InlineBoxShadowEditor = InlineBoxShadowEditor; + /** + * Inline widget containing a BoxShadowEditor control + * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values Initial set of box-shadow values. + * @param {!CodeMirror.TextMarker} marker + */ + function InlineBoxShadowEditor(values, marker) { + this._values = values; + this._marker = marker; + this._isOwnChange = false; + this._isHostChange = false; + this._origin = "+InlineBoxShadowEditor_" + (lastOriginId++); + + this._handleBoxShadowChange = this._handleBoxShadowChange.bind(this); + this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this); + + InlineWidget.call(this); + } + + InlineBoxShadowEditor.prototype = Object.create(InlineWidget.prototype); + InlineBoxShadowEditor.prototype.constructor = InlineBoxShadowEditor; + InlineBoxShadowEditor.prototype.parentClass = InlineWidget.prototype; + + /** @type {!BoxShadowPicker} BoxShadowPicker instance */ + InlineBoxShadowEditor.prototype.BoxShadowEditor = null; + + /** @type {!{ horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string }} Current value of the BoxShadow editor control */ + InlineBoxShadowEditor.prototype._values = null; + + /** + * Range of code we're attached to; _marker.find() may by null if sync is lost. + * @type {!CodeMirror.TextMarker} + */ + InlineBoxShadowEditor.prototype._marker = null; + + /** @type {boolean} True while we're syncing a BoxShadow editor change into the code editor */ + InlineBoxShadowEditor.prototype._isOwnChange = null; + + /** @type {boolean} True while we're syncing a code editor change into the BoxShadow editor */ + InlineBoxShadowEditor.prototype._isHostChange = null; + + /** @type {number} ID used to identify edits coming from this inline widget for undo batching */ + InlineBoxShadowEditor.prototype._origin = null; + + /** + * Returns the current text range of the color we're attached to, or null if + * we've lost sync with what's in the code. + * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}} + */ + InlineBoxShadowEditor.prototype.getCurrentRange = function () { + var pos, start, end; + + pos = this._marker && this._marker.find(); + + start = pos && pos.from; + if (!start) { + return null; + } + + end = pos.to; + if (!end) { + end = {line: start.line}; + } + + /*-----------Correct this----------*/ + + // Even if we think we have a good range end, we want to run the + // regexp match to see if there's a valid match that extends past the marker. + // This can happen if the user deletes the end of the existing color and then + // types some more. + + // var line = this.hostEditor.document.getLine(start.line), + // matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX); + + // // Note that end.ch is exclusive, so we don't need to add 1 before comparing to + // // the matched length here. + // if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) { + // end.ch = start.ch + matches[0].length; + // this._marker.clear(); + // this._marker = this.hostEditor._codeMirror.markText(start, end); + // } + + // if (end.ch === undefined) { + // // We were unable to resync the marker. + // return null; + // } + // else { + // return {start: start, end: end}; + // } + return {start: start, end: end}; + }; + + InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { + var boxShadowString = boxShadowValueTypes.reduce(function(result, boxShadowValueType) { + if(!values[boxShadowValueType]) { + return result; + } + if (!isNaN(values[boxShadowValueType]) ) { + result += " " + values[boxShadowValueType] + "px"; + } + else { + result += " " + values[boxShadowValueType]; + } + return result; + },""); + + return boxShadowString.trim(); + }; + + + /** + * When the BoxShadow editor's values change, update text in code editor + * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values New set of box-shadow values. + */ + InlineBoxShadowEditor.prototype._handleBoxShadowChange = function (values) { + var self = this; + var range = this.getCurrentRange(); + if (!range) { + return; + } + + // update values + for(var key in this._values) { + if(this._values.hasOwnProperty(key)) { + if(values[key] && values[key] !== this._values[key]) { + this._values[key] = values[key]; + } + } + } + + // build the box-shadow value as a string. + var boxShadowString = this._buildBoxShadowString(this._values); + console.log(boxShadowString); + + var endPos = { + line: range.start.line, + ch: range.start.ch + boxShadowString.length + }; + this._isOwnChange = true; + this.hostEditor.document.batchOperation(function () { + // Replace old box-shadow in code with the editor's box-shadow values, and select it + self.hostEditor.setSelection(range.start, range.end); + self.hostEditor.document.replaceRange(boxShadowString, range.start, range.end, self._origin); + self.hostEditor.setSelection(range.start, endPos); + if (self._marker) { + self._marker.clear(); + self._marker = self.hostEditor._codeMirror.markText(range.start, endPos); + } + }); + this._isOwnChange = false; + }; + + /** + * @override + * @param {!Editor} hostEditor + */ + InlineBoxShadowEditor.prototype.load = function (hostEditor) { + InlineBoxShadowEditor.prototype.parentClass.load.apply(this, arguments); + + // Create BoxShadow picker control + this.boxShadowEditor = new BoxShadowEditor(this.$htmlContent, this._values, this._handleBoxShadowChange); + }; + + /** + * @override + * Perform sizing & focus once we've been added to Editor's DOM + */ + InlineBoxShadowEditor.prototype.onAdded = function () { + InlineBoxShadowEditor.prototype.parentClass.onAdded.apply(this, arguments); + + var doc = this.hostEditor.document; + doc.addRef(); + doc.on("change", this._handleHostDocumentChange); + + this.hostEditor.setInlineWidgetHeight(this, this.boxShadowEditor.getRootElement().outerHeight(), true); + + this.boxShadowEditor.focus(); + }; + + /** + * @override + * Called whenever the inline widget is closed, whether automatically or explicitly + */ + InlineBoxShadowEditor.prototype.onClosed = function () { + InlineBoxShadowEditor.prototype.parentClass.onClosed.apply(this, arguments); + + if (this._marker) { + this._marker.clear(); + } + + var doc = this.hostEditor.document; + doc.off("change", this._handleHostDocumentChange); + doc.releaseRef(); + this.boxShadowEditor.destroy(); + }; + + function _isValidBoxShadowValue(value) { + // Need to improve this regex. + return (value.match(/\s*(\d+px\s+){0,3}?\d+px(?:\s+|;|)(?:#?[a-z]{3,}\s*)?;?/) !== null); + } + + /** + * When text in the code editor changes, update color picker to reflect it + */ + InlineBoxShadowEditor.prototype._handleHostDocumentChange = function () { + // Don't push the change into the box-shadow editor if it came from the box-shadow editor. + if (this._isOwnChange) { + return; + } + + var range = this.getCurrentRange(); + /*Correct this*/ + if (range) { + var newString = this.hostEditor.document.getRange(range.start, range.end); + console.log(range); + var flag = _isValidBoxShadowValue(newString); + console.log(flag); + if(_isValidBoxShadowValue(newString)) { + // extract values + var newValues = {}; + var boxShadowValueIndex = 0; + newString.split(/\s+/).forEach(function(value, index) { + value = value.trim(); + var colorMatch = value.match(ColorUtils.COLOR_REGEX); + var pixelMatch = value.match(/(\d+)px/); + if(colorMatch) { + newValues["color"] = colorMatch[0]; + } + else if(pixelMatch){ + newValues[boxShadowValueTypes[boxShadowValueIndex++]] = value; + } + }); + console.log(newValues); + + if(newValues !== this._values) { + this._isHostChange = true; + this.boxShadowEditor.setValues(newValues); + this._values = newValues; + this._isHostChange = false; + } + } + + } + else { + // The edit caused our range to become invalid. Close the editor. + this.close(); + } + }; + + exports.InlineBoxShadowEditor = InlineBoxShadowEditor; }); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index c057c31155d..672a466f3b8 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -1,14 +1,14 @@ define(function(require, exports, module) { - "use strict"; + "use strict"; - var EditorManager = brackets.getModule("editor/EditorManager"), - ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), - InlineBoxShadowEditor = require("InlineBoxShadowEditor").InlineBoxShadowEditor, - ColorUtils = brackets.getModule("utils/ColorUtils"), - boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + var EditorManager = brackets.getModule("editor/EditorManager"), + ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), + InlineBoxShadowEditor = require("InlineBoxShadowEditor").InlineBoxShadowEditor, + ColorUtils = brackets.getModule("utils/ColorUtils"), + boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; - var DEFAULT_VALUES = "0px 0px 0px 0px black"; - /** + var DEFAULT_VALUES = "0px 0px 0px 0px black"; + /** * Prepare hostEditor for an InlineBoxShadowEditor at pos if possible. Return * editor context if so; otherwise null. * @@ -16,82 +16,82 @@ define(function(require, exports, module) { * @param {{line:Number, ch:Number}} pos * @return {?{values:{}, marker:TextMarker}} */ - function prepareEditorForProvider(hostEditor, pos) { - var cursorLine = hostEditor.document.getLine(pos.line); - - if(cursorLine.indexOf("box-shadow") === -1) { - return null; - } - - var semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; - values = {}; - - colonPos = cursorLine.indexOf(":"); - semiColonPos = cursorLine.indexOf(";"); - cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); - - console.log(cursorLineSubstring); - - // Get the initial set of values of box-shadow property - isEmptyString = true; - boxShadowValueIndex = 0; - cursorLineSubstring.split(/\s+/).forEach(function(value, index) { - value = value.trim(); - var colorMatch = value.match(ColorUtils.COLOR_REGEX); - var pixelMatch = value.match(/(\d+)px/); - console.log(value, colorMatch, pixelMatch); - if(colorMatch) { - values["color"] = colorMatch[0]; - isEmptyString = false; - } - else if(pixelMatch){ - // Fix here - values[boxShadowValueTypes[boxShadowValueIndex++]] = value; - isEmptyString = false; - } - }); - - console.log(isEmptyString); - - if(isEmptyString) { - //Edit a new css rule. - var newText = " ", from ,to; - newText = newText.concat(DEFAULT_VALUES, ";"); - from = {line: pos.line, ch: colonPos + 1}; - to = {line: pos.line, ch: cursorLine.length}; - hostEditor._codeMirror.replaceRange(newText, from, to); - pos.ch = colonPos + 2; - endPos = {line: pos.line, ch: pos.ch + DEFAULT_VALUES.length}; - values = { - "horizontalOffset": "0px", - "verticalOffset": "0px", - "blurRadius": "0px", - "spreadRadius": "0px", - "color": "black" - }; - } - else { - firstCharacterPos = cursorLineSubstring.search(/\S/); - pos.ch = colonPos + 1 + Math.min(firstCharacterPos,1); - if (semiColonPos !== -1) { - endPos = {line: pos.line, ch: semiColonPos}; - } else { - endPos = {line: pos.line, ch: cursorLine.length}; - } - } - - marker = hostEditor._codeMirror.markText(pos, endPos); - hostEditor.setSelection(pos, endPos); - - console.log(values); - - return { - values: values, - marker: marker - }; - } - - /** + function prepareEditorForProvider(hostEditor, pos) { + var cursorLine = hostEditor.document.getLine(pos.line); + + if(cursorLine.indexOf("box-shadow") === -1) { + return null; + } + + var semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; + values = {}; + + colonPos = cursorLine.indexOf(":"); + semiColonPos = cursorLine.indexOf(";"); + cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); + + console.log(cursorLineSubstring); + + // Get the initial set of values of box-shadow property + isEmptyString = true; + boxShadowValueIndex = 0; + cursorLineSubstring.split(/\s+/).forEach(function(value, index) { + value = value.trim(); + var colorMatch = value.match(ColorUtils.COLOR_REGEX); + var pixelMatch = value.match(/(\d+)px/); + console.log(value, colorMatch, pixelMatch); + if(colorMatch) { + values["color"] = colorMatch[0]; + isEmptyString = false; + } + else if(pixelMatch){ + // Fix here + values[boxShadowValueTypes[boxShadowValueIndex++]] = value; + isEmptyString = false; + } + }); + + console.log(isEmptyString); + + if(isEmptyString) { + //Edit a new css rule. + var newText = " ", from ,to; + newText = newText.concat(DEFAULT_VALUES, ";"); + from = {line: pos.line, ch: colonPos + 1}; + to = {line: pos.line, ch: cursorLine.length}; + hostEditor._codeMirror.replaceRange(newText, from, to); + pos.ch = colonPos + 2; + endPos = {line: pos.line, ch: pos.ch + DEFAULT_VALUES.length}; + values = { + "horizontalOffset": "0px", + "verticalOffset": "0px", + "blurRadius": "0px", + "spreadRadius": "0px", + "color": "black" + }; + } + else { + firstCharacterPos = cursorLineSubstring.search(/\S/); + pos.ch = colonPos + 1 + Math.min(firstCharacterPos,1); + if (semiColonPos !== -1) { + endPos = {line: pos.line, ch: semiColonPos}; + } else { + endPos = {line: pos.line, ch: cursorLine.length}; + } + } + + marker = hostEditor._codeMirror.markText(pos, endPos); + hostEditor.setSelection(pos, endPos); + + console.log(values); + + return { + values: values, + marker: marker + }; + } + + /** * Registered as an inline editor provider: creates an InlineBoxShadowEditor when the cursor * is on a line containing box-shadow property (in any flavor of code). * @@ -100,37 +100,37 @@ define(function(require, exports, module) { * @return {?$.Promise} synchronously resolved with an InlineWidget, or null if there's * no box-shadow at pos. */ - function inlineBoxShadowEditorProvider(hostEditor, pos) { - var context = prepareEditorForProvider(hostEditor, pos), - inlineBoxShadowEditor, - result; - - if(!context) { - return null; - } - else { - inlineBoxShadowEditor = new InlineBoxShadowEditor(context.values, context.marker); - inlineBoxShadowEditor.load(hostEditor); - - result = new $.Deferred(); - result.resolve(inlineBoxShadowEditor); - return result.promise(); - } - } - - function queryInlineBoxShadowEditorProvider(hostEditor, pos) { - var cursorLine = hostEditor.document.getLine(pos.line); - - if(cursorLine.indexOf("box-shadow") !== -1) { - return true; - } - else { - return false; - } - } - - - // Initialize extension + function inlineBoxShadowEditorProvider(hostEditor, pos) { + var context = prepareEditorForProvider(hostEditor, pos), + inlineBoxShadowEditor, + result; + + if(!context) { + return null; + } + else { + inlineBoxShadowEditor = new InlineBoxShadowEditor(context.values, context.marker); + inlineBoxShadowEditor.load(hostEditor); + + result = new $.Deferred(); + result.resolve(inlineBoxShadowEditor); + return result.promise(); + } + } + + function queryInlineBoxShadowEditorProvider(hostEditor, pos) { + var cursorLine = hostEditor.document.getLine(pos.line); + + if(cursorLine.indexOf("box-shadow") !== -1) { + return true; + } + else { + return false; + } + } + + + // Initialize extension ExtensionUtils.loadStyleSheet(module, "css/style.less"); EditorManager.registerInlineEditProvider(inlineBoxShadowEditorProvider, queryInlineBoxShadowEditorProvider); From bb10ee680ff7f6ced6664c15cc90a3dceea8dcb7 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 9 Dec 2017 21:09:48 +0530 Subject: [PATCH 04/21] Changed input textboxes to input range --- .../InlineBoxShadowEditor/BoxShadowEditor.js | 12 ++-- .../BoxShadowEditorTemplate.html | 17 ++---- .../InlineBoxShadowEditor.js | 60 ++++++++----------- .../default/InlineBoxShadowEditor/main.js | 12 ++-- 4 files changed, 42 insertions(+), 59 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index 1541c7a8227..422ababecb4 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -45,9 +45,8 @@ define(function(require, exports, module) { } /** - * A string or tinycolor object representing the currently selected color - * TODO (#2201): type is unpredictable - * @type {tinycolor|string} + * A object representing the current set of box-shadow values + * @type {} */ BoxShadowEditor.prototype._values = null; @@ -221,9 +220,14 @@ define(function(require, exports, module) { } // Sync only if we have a valid color or we're restoring the previous valid color. + this._commitChanges("color", newColor); if (newColorOk) { console.log(newColor); - this._commitChanges("color", newColor); + this.$colorValue.css("border", "initial"); + } + else { + console.warn("Wrong colour value"); + this.$colorValue.css("border", "2px solid red"); } }; diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html index e6589853f54..675caed43e0 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -1,29 +1,20 @@
-
: - px + px
: - px + px
: - px + px
: - px + px
: diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index e410a4cc45d..23c7c1864dc 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -54,12 +54,12 @@ define(function(require, exports, module) { InlineBoxShadowEditor.prototype._origin = null; /** - * Returns the current text range of the color we're attached to, or null if + * Returns the current text range of the box-shadow value we're attached to, or null if * we've lost sync with what's in the code. * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}} */ InlineBoxShadowEditor.prototype.getCurrentRange = function () { - var pos, start, end; + var pos, start, end, line; pos = this._marker && this._marker.find(); @@ -69,36 +69,27 @@ define(function(require, exports, module) { } end = pos.to; - if (!end) { - end = {line: start.line}; + + line = this.hostEditor.document.getLine(start.line); + + start.ch = line.indexOf(':') + 1; + while(line[start.ch] == ' ') start.ch++; + + end.line = start.line; + end.ch = line.indexOf(';'); + + if(end.ch === -1) { + end.ch = line.length; + while(end.ch > start.ch && line[end.ch] != ';') end.ch--; } - /*-----------Correct this----------*/ - - // Even if we think we have a good range end, we want to run the - // regexp match to see if there's a valid match that extends past the marker. - // This can happen if the user deletes the end of the existing color and then - // types some more. - - // var line = this.hostEditor.document.getLine(start.line), - // matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX); - - // // Note that end.ch is exclusive, so we don't need to add 1 before comparing to - // // the matched length here. - // if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) { - // end.ch = start.ch + matches[0].length; - // this._marker.clear(); - // this._marker = this.hostEditor._codeMirror.markText(start, end); - // } - - // if (end.ch === undefined) { - // // We were unable to resync the marker. - // return null; - // } - // else { - // return {start: start, end: end}; - // } - return {start: start, end: end}; + if (end.ch === undefined) { + // We were unable to resync the marker. + return null; + } + else { + return {start: start, end: end}; + } }; InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { @@ -211,7 +202,7 @@ define(function(require, exports, module) { } /** - * When text in the code editor changes, update color picker to reflect it + * When text in the code editor changes, update quick edit to reflect it */ InlineBoxShadowEditor.prototype._handleHostDocumentChange = function () { // Don't push the change into the box-shadow editor if it came from the box-shadow editor. @@ -220,20 +211,21 @@ define(function(require, exports, module) { } var range = this.getCurrentRange(); - /*Correct this*/ if (range) { var newString = this.hostEditor.document.getRange(range.start, range.end); - console.log(range); + var flag = _isValidBoxShadowValue(newString); - console.log(flag); + if(_isValidBoxShadowValue(newString)) { // extract values var newValues = {}; var boxShadowValueIndex = 0; + newString.split(/\s+/).forEach(function(value, index) { value = value.trim(); var colorMatch = value.match(ColorUtils.COLOR_REGEX); var pixelMatch = value.match(/(\d+)px/); + console.log(colorMatch); if(colorMatch) { newValues["color"] = colorMatch[0]; } diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index 672a466f3b8..f3bd8db3c83 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -8,6 +8,7 @@ define(function(require, exports, module) { boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; var DEFAULT_VALUES = "0px 0px 0px 0px black"; + /** * Prepare hostEditor for an InlineBoxShadowEditor at pos if possible. Return * editor context if so; otherwise null. @@ -17,21 +18,18 @@ define(function(require, exports, module) { * @return {?{values:{}, marker:TextMarker}} */ function prepareEditorForProvider(hostEditor, pos) { - var cursorLine = hostEditor.document.getLine(pos.line); - - if(cursorLine.indexOf("box-shadow") === -1) { + if(queryInlineBoxShadowEditorProvider(hostEditor, pos) == false) { return null; } - var semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; + var cursorLine, semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; values = {}; + cursorLine = hostEditor.document.getLine(pos.line); colonPos = cursorLine.indexOf(":"); semiColonPos = cursorLine.indexOf(";"); cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); - console.log(cursorLineSubstring); - // Get the initial set of values of box-shadow property isEmptyString = true; boxShadowValueIndex = 0; @@ -45,7 +43,6 @@ define(function(require, exports, module) { isEmptyString = false; } else if(pixelMatch){ - // Fix here values[boxShadowValueTypes[boxShadowValueIndex++]] = value; isEmptyString = false; } @@ -129,7 +126,6 @@ define(function(require, exports, module) { } } - // Initialize extension ExtensionUtils.loadStyleSheet(module, "css/style.less"); From 207d69bcb0282d53a572d9dc31b95005f10e0b20 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 9 Dec 2017 21:24:32 +0530 Subject: [PATCH 05/21] Fixed eslint errors --- .../InlineBoxShadowEditor/InlineBoxShadowEditor.js | 8 ++++++-- src/extensions/default/InlineBoxShadowEditor/main.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 23c7c1864dc..7728dee3f92 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -73,14 +73,18 @@ define(function(require, exports, module) { line = this.hostEditor.document.getLine(start.line); start.ch = line.indexOf(':') + 1; - while(line[start.ch] == ' ') start.ch++; + while(line[start.ch] === ' ') { + start.ch++; + } end.line = start.line; end.ch = line.indexOf(';'); if(end.ch === -1) { end.ch = line.length; - while(end.ch > start.ch && line[end.ch] != ';') end.ch--; + while(end.ch > start.ch && line[end.ch] !== ';') { + end.ch--; + } } if (end.ch === undefined) { diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index f3bd8db3c83..bacd03e5b81 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -18,7 +18,7 @@ define(function(require, exports, module) { * @return {?{values:{}, marker:TextMarker}} */ function prepareEditorForProvider(hostEditor, pos) { - if(queryInlineBoxShadowEditorProvider(hostEditor, pos) == false) { + if(queryInlineBoxShadowEditorProvider(hostEditor, pos) === false) { return null; } From d8083ab40fad3c4f09bf9bd6ad272acf97e45716 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Fri, 20 Oct 2017 14:16:59 +0530 Subject: [PATCH 06/21] Working quick-edit UI for box-shadow property Related to thimble.mozilla.org#2508 for creating an extension to open quick edit UI for box-shadow property( similar to color-picker). This is a very early version with bugs, and lot of unnecessary comments, logs. It's a work in progress. --- src/extensions/bramble-extensions.json | 8 + .../InlineBoxShadowEditor/BoxShadowEditor.js | 272 ++++++++++++++++++ .../BoxShadowEditorTemplate.html | 33 +++ .../BoxShadowValueTypes.json | 9 + .../InlineBoxShadowEditor.js | 262 +++++++++++++++++ .../InlineBoxShadowEditor/css/style.less | 96 +++++++ .../default/InlineBoxShadowEditor/main.js | 140 +++++++++ .../thirdparty/tinycolor-min.js | 4 + 8 files changed, 824 insertions(+) create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json create mode 100644 src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/css/style.less create mode 100644 src/extensions/default/InlineBoxShadowEditor/main.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/thirdparty/tinycolor-min.js diff --git a/src/extensions/bramble-extensions.json b/src/extensions/bramble-extensions.json index 0ec6b119e04..189ec96ce0a 100644 --- a/src/extensions/bramble-extensions.json +++ b/src/extensions/bramble-extensions.json @@ -81,6 +81,14 @@ "extensions/default/InlinePaddingEditor/PaddingEditorTemplate.html" ] }, + { + "path": "extensions/default/InlineBoxShadowEditor", + "less": { + "dist/extensions/default/InlineBoxShadowEditor/css/style.css": [ + "src/extensions/default/InlineBoxShadowEditor/css/style.less" + ] + } + }, { "path": "extensions/default/Inline3DParametersEditor", "less": { diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js new file mode 100644 index 00000000000..bc9f15f0df1 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -0,0 +1,272 @@ +define(function(require, exports, module) { + "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"), + tinycolor = require("thirdparty/tinycolor-min"); + + /** 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 {!{horizontalOffset: string, verticalOffset: string, blurRadius: string, spreadRadius: 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.$horizontalOffsetValue = this.$element.find("#horizontal-offset-value"); + this.$verticalOffsetValue = this.$element.find("#vertical-offset-value"); + this.$blurRadiusValue = this.$element.find("#blur-radius-value"); + this.$spreadRadiusValue = this.$element.find("#spread-radius-value"); + this.$colorValue = this.$element.find("#color-value"); + + + // Attach event listeners to main UI elements + this._bindInputHandlers(); + + + // Set initial values in the box-shadow editor inputs. + this._setInputValues(); + } + + /** + * A string or tinycolor object representing the currently selected color + * TODO (#2201): type is unpredictable + * @type {tinycolor|string} + */ + 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) { + for(var key in this._values) { + if(this._values.hasOwnProperty(key)) { + if(values[key] && values[key] != this._values[key]) { + this._values[key] = values[key]; + } + } + } + + this._setInputValues(); + }; + + BoxShadowEditor.prototype._setInputValues = function() { + var values = this._values; + var horizontalOffset, verticalOffset, blurRadius, spreadRadius, color; + + horizontalOffset = values["horizontalOffset"] ? parseFloat(values["horizontalOffset"]) : ""; + verticalOffset = values["verticalOffset"] ? parseFloat(values["verticalOffset"]) : ""; + blurRadius = values["blurRadius"] ? parseFloat(values["blurRadius"]) : ""; + spreadRadius = values["spreadRadius"] ? parseFloat(values["spreadRadius"]) : ""; + color = values["color"] ? values["color"] : ""; + + this.$horizontalOffsetValue.val(horizontalOffset); + this.$verticalOffsetValue.val(verticalOffset); + this.$blurRadiusValue.val(blurRadius); + this.$spreadRadiusValue.val(spreadRadius); + this.$colorValue.val(color); + }; + + BoxShadowEditor.prototype._bindInputHandlers = function() { + var self = this; + + this.$horizontalOffsetValue.bind("input", function (event) { + self._handleHorizontalOffsetChange(); + }); + + this.$verticalOffsetValue.bind("input", function (event) { + self._handleVerticalOffsetChange(); + }); + + this.$blurRadiusValue.bind("input", function (event) { + self._handleBlurRadiusChange(); + }); + + this.$spreadRadiusValue.bind("input", function (event) { + self._handleSpreadRadiusChange(); + }); + + this.$colorValue.bind("input", function (event) { + self._handleColorChange(); + }); + } + + BoxShadowEditor.prototype._synchronize = function() { + + } + + BoxShadowEditor.prototype.focus = function() { + this.$horizontalOffsetValue.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); + } + + function _handleChanges($inputElement, propertyName, value) { + console.log(value, typeof value); + if(!_isValidNumber(value)) { + if(!this._values[propertyName]) { + $inputElement.val(""); + return; + } + var curValue = parseFloat(this._values[propertyName]); + $inputElement.val(curValue); + } + + if(value == "") { + // This is to maintain the box-shadow property. + value = "0"; + $inputElement.val(value); + } + + var newValue = value + "px"; + this._commitChanges(propertyName, newValue); + } + + BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { + var self = this; + var newValue = this.$horizontalOffsetValue.val().trim(); + _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); + } + + BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { + var self = this; + var newValue = this.$verticalOffsetValue.val().trim(); + _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); + } + + BoxShadowEditor.prototype._handleBlurRadiusChange = function() { + var self = this; + var newValue = this.$blurRadiusValue.val().trim(); + _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); + } + + BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { + var self = this; + var newValue = this.$spreadRadiusValue.val().trim(); + _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); + } + + /** + * 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. + */ + BoxShadowEditor.prototype._normalizeColorString = function (color) { + 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; + }; + + BoxShadowEditor.prototype._handleColorChange = function() { + var newColor = $.trim(this.$colorValue.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 (newColorOk) { + newColorOk = (newColorObj.toString() === this._normalizeColorString(newColor)); + } + + // Sync only if we have a valid color or we're restoring the previous valid color. + if (newColorOk) { + console.log(newColor); + this._commitChanges("color", newColor); + } + }; + + 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; + } + } + }; + + + BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { + this._values[propertyName] = value; + this._callback(this._values); + } + + + exports.BoxShadowEditor = BoxShadowEditor; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html new file mode 100644 index 00000000000..c651c6e4eb6 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -0,0 +1,33 @@ +
+
+ +
+ : + px +
+
+ : + px +
+
+ : + px +
+
+ : + px +
+
+ : + +
+
+
\ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json new file mode 100644 index 00000000000..17a71f2aea0 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json @@ -0,0 +1,9 @@ +{ + "boxShadowValueTypes": [ + "horizontalOffset", + "verticalOffset", + "blurRadius", + "spreadRadius", + "color" + ] +} \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js new file mode 100644 index 00000000000..35fe0217d04 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -0,0 +1,262 @@ +define(function(require, exports, module) { + "use strict"; + + var InlineWidget = brackets.getModule("editor/InlineWidget").InlineWidget, + BoxShadowEditor = require("BoxShadowEditor").BoxShadowEditor, + ColorUtils = brackets.getModule("utils/ColorUtils"), + boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + + + /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ + var lastOriginId = 1; + + /** + * Inline widget containing a BoxShadowEditor control + * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values Initial set of box-shadow values. + * @param {!CodeMirror.TextMarker} marker + */ + function InlineBoxShadowEditor(values, marker) { + this._values = values; + this._marker = marker; + this._isOwnChange = false; + this._isHostChange = false; + this._origin = "+InlineBoxShadowEditor_" + (lastOriginId++); + + this._handleBoxShadowChange = this._handleBoxShadowChange.bind(this); + this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this); + + InlineWidget.call(this); + } + + InlineBoxShadowEditor.prototype = Object.create(InlineWidget.prototype); + InlineBoxShadowEditor.prototype.constructor = InlineBoxShadowEditor; + InlineBoxShadowEditor.prototype.parentClass = InlineWidget.prototype; + + /** @type {!BoxShadowPicker} BoxShadowPicker instance */ + InlineBoxShadowEditor.prototype.BoxShadowEditor = null; + + /** @type {!{ horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string }} Current value of the BoxShadow editor control */ + InlineBoxShadowEditor.prototype._values = null; + + /** + * Range of code we're attached to; _marker.find() may by null if sync is lost. + * @type {!CodeMirror.TextMarker} + */ + InlineBoxShadowEditor.prototype._marker = null; + + /** @type {boolean} True while we're syncing a BoxShadow editor change into the code editor */ + InlineBoxShadowEditor.prototype._isOwnChange = null; + + /** @type {boolean} True while we're syncing a code editor change into the BoxShadow editor */ + InlineBoxShadowEditor.prototype._isHostChange = null; + + /** @type {number} ID used to identify edits coming from this inline widget for undo batching */ + InlineBoxShadowEditor.prototype._origin = null; + + /** + * Returns the current text range of the color we're attached to, or null if + * we've lost sync with what's in the code. + * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}} + */ + InlineBoxShadowEditor.prototype.getCurrentRange = function () { + var pos, start, end; + + pos = this._marker && this._marker.find(); + + start = pos && pos.from; + if (!start) { + return null; + } + + end = pos.to; + if (!end) { + end = {line: start.line}; + } + + /*-----------Correct this----------*/ + + // Even if we think we have a good range end, we want to run the + // regexp match to see if there's a valid match that extends past the marker. + // This can happen if the user deletes the end of the existing color and then + // types some more. + + // var line = this.hostEditor.document.getLine(start.line), + // matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX); + + // // Note that end.ch is exclusive, so we don't need to add 1 before comparing to + // // the matched length here. + // if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) { + // end.ch = start.ch + matches[0].length; + // this._marker.clear(); + // this._marker = this.hostEditor._codeMirror.markText(start, end); + // } + + // if (end.ch === undefined) { + // // We were unable to resync the marker. + // return null; + // } + // else { + // return {start: start, end: end}; + // } + return {start: start, end: end}; + }; + + InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { + var boxShadowString = boxShadowValueTypes.reduce(function(result, type) { + if(!values[type]) { + return result; + } + if (typeof values[type] === "Number") { + result += " " + values[type] + "px"; + } + else { + result += " " + values[type]; + } + return result; + },""); + + return boxShadowString.trim(); + } + + + /** + * When the BoxShadow editor's values change, update text in code editor + * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values New set of box-shadow values. + */ + InlineBoxShadowEditor.prototype._handleBoxShadowChange = function (values) { + var self = this; + var range = this.getCurrentRange(); + if (!range) { + return; + } + + // update values + for(var key in this._values) { + if(this._values.hasOwnProperty(key)) { + if(values[key] && values[key] != this._values[key]) { + this._values[key] = values[key]; + } + } + } + + // build the box-shadow value as a string. + var boxShadowString = this._buildBoxShadowString(this._values); + console.log(boxShadowString); + + var endPos = { + line: range.start.line, + ch: range.start.ch + boxShadowString.length + }; + this._isOwnChange = true; + this.hostEditor.document.batchOperation(function () { + // Replace old box-shadow in code with the editor's box-shadow values, and select it + self.hostEditor.setSelection(range.start, range.end); + self.hostEditor.document.replaceRange(boxShadowString, range.start, range.end, self._origin); + self.hostEditor.setSelection(range.start, endPos); + if (self._marker) { + self._marker.clear(); + self._marker = self.hostEditor._codeMirror.markText(range.start, endPos); + } + }); + this._isOwnChange = false; + }; + + /** + * @override + * @param {!Editor} hostEditor + */ + InlineBoxShadowEditor.prototype.load = function (hostEditor) { + InlineBoxShadowEditor.prototype.parentClass.load.apply(this, arguments); + + // Create BoxShadow picker control + this.boxShadowEditor = new BoxShadowEditor(this.$htmlContent, this._values, this._handleBoxShadowChange); + }; + + /** + * @override + * Perform sizing & focus once we've been added to Editor's DOM + */ + InlineBoxShadowEditor.prototype.onAdded = function () { + InlineBoxShadowEditor.prototype.parentClass.onAdded.apply(this, arguments); + + var doc = this.hostEditor.document; + doc.addRef(); + doc.on("change", this._handleHostDocumentChange); + + this.hostEditor.setInlineWidgetHeight(this, this.boxShadowEditor.getRootElement().outerHeight(), true); + + this.boxShadowEditor.focus(); + }; + + /** + * @override + * Called whenever the inline widget is closed, whether automatically or explicitly + */ + InlineBoxShadowEditor.prototype.onClosed = function () { + InlineBoxShadowEditor.prototype.parentClass.onClosed.apply(this, arguments); + + if (this._marker) { + this._marker.clear(); + } + + var doc = this.hostEditor.document; + doc.off("change", this._handleHostDocumentChange); + doc.releaseRef(); + this.boxShadowEditor.destroy(); + }; + + function _isValidBoxShadowValue(value) { + // Need to improve this regex. + return (value.match(/\s*(\d+px\s+){0,3}?\d+px(?:\s+|;|)(?:#?[a-z]{3,}\s*)?;?/) !== null); + } + + /** + * When text in the code editor changes, update color picker to reflect it + */ + InlineBoxShadowEditor.prototype._handleHostDocumentChange = function () { + // Don't push the change into the box-shadow editor if it came from the box-shadow editor. + if (this._isOwnChange) { + return; + } + + var range = this.getCurrentRange(); + /*Correct this*/ + if (range) { + var newString = this.hostEditor.document.getRange(range.start, range.end); + console.log(range); + var flag = _isValidBoxShadowValue(newString); + console.log(flag); + if(_isValidBoxShadowValue(newString)) { + // extract values + var newValues = {}; + var boxShadowValueIndex = 0; + newString.split(/\s+/).forEach(function(value, index) { + value = value.trim(); + var colorMatch = value.match(ColorUtils.COLOR_REGEX); + var pixelMatch = value.match(/(\d+)px/); + if(colorMatch) { + newValues["color"] = colorMatch[0]; + } + else if(pixelMatch){ + newValues[boxShadowValueTypes[boxShadowValueIndex++]] = value; + } + }); + console.log(newValues); + + if(newValues !== this._values) { + this._isHostChange = true; + this.boxShadowEditor.setValues(newValues); + this._values = newValues; + this._isHostChange = false; + } + } + + } + else { + // The edit caused our range to become invalid. Close the editor. + this.close(); + } + }; + + exports.InlineBoxShadowEditor = InlineBoxShadowEditor; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/css/style.less b/src/extensions/default/InlineBoxShadowEditor/css/style.less new file mode 100644 index 00000000000..ecd4ae27040 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/css/style.less @@ -0,0 +1,96 @@ +@sansFontFamily: Helvetica, Arial, "Meiryo UI", "MS Pゴシック", "MS PGothic", sans-serif; + +.box-shadow-editor { + font-size: 12px; + min-width: 450px; + height: 190px; + padding: 16px 16px 14px 46px; +} +.box-shadow-editor:focus { + outline: none; +} +.box-shadow-editor section { + display: inline-block; + position: relative; + vertical-align: top; +} +.box-shadow-editor section .box-shadow-input { + display: block; + margin-bottom: 8px; + + label { + display: inline-block; + min-width: 150px; + } +} + +.box-shadow-editor section #horizontal-offset-value, +.box-shadow-editor section #vertical-offset-value, +.box-shadow-editor section #blur-radius-value, +.box-shadow-editor section #spread-radius-value, +.box-shadow-editor section #color-value { + width: 118px; + height: 23px; + margin-right: 5px; + border-box-shadow: #b2b5b5; + box-sizing: border-box; + display: inline-block; + box-shadow: #222; +} +.box-shadow-editor section input { + display: inline-block; + height: 23px; + padding: 0 0 0 4px; + border: 1px solid #b2b5b5; + box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.06); + background: #fff; + font-family: @sansFontFamily; + font-size: 12px; + box-shadow: #454545; + border-radius: 3px; + margin: 0; + vertical-align: middle; +} +.box-shadow-editor section input:focus { + background: #fff; + outline: none; + box-shadow: 0 0 0 1px #94ceff; + border: 1px solid #2893ef; + z-index: 911; +} + +// Dark UI theme + +@dark-bc-bg-highlight: #2a3b50; +@dark-bc-highlight: rgba(255, 255, 255, 0.06); +@dark-bc-text: #ccc; +@dark-bc-text-alt: #fff; +@dark-bc-highlight-hard: rgba(255, 255, 255, 0.2); +@dark-bc-btn-bg: #3f3f3f; +@dark-bc-btn-border: #202020; +@dark-bc-btn-border-focused: #2893ef; +@dark-bc-btn-border-focused-glow: transparent; +@dark-bc-shadow: rgba(0, 0, 0, 0.24); +@dark-bc-shadow-small: rgba(0, 0, 0, 0.06); +@dark-bc-shadow-medium: rgba(0, 0, 0, 0.12); +@dark-bc-input-bg: #555; + +.dark { + .box-shadow-editor section footer .box-shadow-value { + border-box-shadow: @dark-bc-btn-border; + box-shadow: @dark-bc-text; + } + + .box-shadow-editor section footer input { + border: 1px solid @dark-bc-btn-border; + box-shadow: inset 0 1px 0 @dark-bc-shadow-small; + background: @dark-bc-input-bg; + box-shadow: @dark-bc-text; + } + + .box-shadow-editor section footer input:focus { + background: @dark-bc-input-bg; + box-shadow: 0 0 0 1px @dark-bc-btn-border-focused-glow; + border: 1px solid @dark-bc-btn-border-focused; + } +} \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js new file mode 100644 index 00000000000..41aebeb1fbf --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -0,0 +1,140 @@ +define(function(require, exports, module) { + "use strict"; + + var EditorManager = brackets.getModule("editor/EditorManager"), + ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), + InlineBoxShadowEditor = require("InlineBoxShadowEditor").InlineBoxShadowEditor, + ColorUtils = brackets.getModule("utils/ColorUtils"), + boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + + var DEFAULT_VALUES = "0px 0px 0px 0px black"; + /** + * Prepare hostEditor for an InlineBoxShadowEditor at pos if possible. Return + * editor context if so; otherwise null. + * + * @param {Editor} hostEditor + * @param {{line:Number, ch:Number}} pos + * @return {?{values:{}, marker:TextMarker}} + */ + function prepareEditorForProvider(hostEditor, pos) { + var cursorLine = hostEditor.document.getLine(pos.line); + + if(cursorLine.indexOf("box-shadow") === -1) { + return null; + } + + var semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; + values = {}; + + colonPos = cursorLine.indexOf(":"); + semiColonPos = cursorLine.indexOf(";"); + cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); + + console.log(cursorLineSubstring); + + // Get the initial set of values of box-shadow property + isEmptyString = true; + boxShadowValueIndex = 0; + cursorLineSubstring.split(/\s+/).forEach(function(value, index) { + value = value.trim(); + var colorMatch = value.match(ColorUtils.COLOR_REGEX); + var pixelMatch = value.match(/(\d+)px/); + console.log(value, colorMatch, pixelMatch); + if(colorMatch) { + values["color"] = colorMatch[0]; + isEmptyString = false; + } + else if(pixelMatch){ + // Fix here + values[boxShadowValueTypes[boxShadowValueIndex++]] = value; + isEmptyString = false; + } + }); + + console.log(isEmptyString); + + if(isEmptyString) { + //Edit a new css rule. + var newText = " ", from ,to; + newText = newText.concat(DEFAULT_VALUES, ";"); + from = {line: pos.line, ch: colonPos + 1}; + to = {line: pos.line, ch: cursorLine.length}; + hostEditor._codeMirror.replaceRange(newText, from, to); + pos.ch = colonPos + 2; + endPos = {line: pos.line, ch: pos.ch + DEFAULT_VALUES.length}; + values = { + "horizontalOffset": "0px", + "verticalOffset": "0px", + "blurRadius": "0px", + "spreadRadius": "0px", + "color": "black" + }; + } + else { + firstCharacterPos = cursorLineSubstring.search(/\S/); + pos.ch = colonPos + 1 + Math.min(firstCharacterPos,1); + if (semiColonPos !== -1) { + endPos = {line: pos.line, ch: semiColonPos}; + } else { + endPos = {line: pos.line, ch: cursorLine.length}; + } + } + + marker = hostEditor._codeMirror.markText(pos, endPos); + hostEditor.setSelection(pos, endPos); + + console.log(values); + + return { + values, + marker + }; + } + + /** + * Registered as an inline editor provider: creates an InlineBoxShadowEditor when the cursor + * is on a line containing box-shadow property (in any flavor of code). + * + * @param {!Editor} hostEditor + * @param {!{line:Number, ch:Number}} pos + * @return {?$.Promise} synchronously resolved with an InlineWidget, or null if there's + * no box-shadow at pos. + */ + function inlineBoxShadowEditorProvider(hostEditor, pos) { + var context = prepareEditorForProvider(hostEditor, pos), + inlineBoxShadowEditor, + result; + + if(!context) { + return null; + } + else { + inlineBoxShadowEditor = new InlineBoxShadowEditor(context.values, context.marker); + inlineBoxShadowEditor.load(hostEditor); + + result = new $.Deferred(); + result.resolve(inlineBoxShadowEditor); + return result.promise(); + } + } + + function queryInlineBoxShadowEditorProvider(hostEditor, pos) { + var cursorLine = hostEditor.document.getLine(pos.line); + + if(cursorLine.indexOf("box-shadow") !== -1) { + return true; + } + else { + return false; + } + } + + + // Initialize extension + ExtensionUtils.loadStyleSheet(module, "css/style.less"); + + EditorManager.registerInlineEditProvider(inlineBoxShadowEditorProvider, queryInlineBoxShadowEditorProvider); + + // for use by other InlineColorEditors + exports.prepareEditorForProvider = prepareEditorForProvider; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/thirdparty/tinycolor-min.js b/src/extensions/default/InlineBoxShadowEditor/thirdparty/tinycolor-min.js new file mode 100644 index 00000000000..89325118c40 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/thirdparty/tinycolor-min.js @@ -0,0 +1,4 @@ +// TinyColor v1.1.1 +// https://github.com/bgrins/TinyColor +// 2014-12-20, Brian Grinstead, MIT License +!function(){function inputToRGB(color){var rgb={r:0,g:0,b:0},a=1,ok=!1,format=!1;return"string"==typeof color&&(color=stringInputToObject(color)),"object"==typeof color&&(color.hasOwnProperty("r")&&color.hasOwnProperty("g")&&color.hasOwnProperty("b")?(rgb=rgbToRgb(color.r,color.g,color.b),ok=!0,format="%"===String(color.r).substr(-1)?"prgb":"rgb"):color.hasOwnProperty("h")&&color.hasOwnProperty("s")&&color.hasOwnProperty("v")?(color.s=convertToPercentage(color.s),color.v=convertToPercentage(color.v),rgb=hsvToRgb(color.h,color.s,color.v),ok=!0,format="hsv"):color.hasOwnProperty("h")&&color.hasOwnProperty("s")&&color.hasOwnProperty("l")&&(color.s=convertToPercentage(color.s),color.l=convertToPercentage(color.l),rgb=hslToRgb(color.h,color.s,color.l),ok=!0,format="hsl"),color.hasOwnProperty("a")&&(a=color.a)),a=boundAlpha(a),{ok:ok,format:color.format||format,r:mathMin(255,mathMax(rgb.r,0)),g:mathMin(255,mathMax(rgb.g,0)),b:mathMin(255,mathMax(rgb.b,0)),a:a}}function rgbToRgb(r,g,b){return{r:255*bound01(r,255),g:255*bound01(g,255),b:255*bound01(b,255)}}function rgbToHsl(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);var h,s,max=mathMax(r,g,b),min=mathMin(r,g,b),l=(max+min)/2;if(max==min)h=s=0;else{var d=max-min;switch(s=l>.5?d/(2-max-min):d/(max+min),max){case r:h=(g-b)/d+(b>g?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return{h:h,s:s,l:l}}function hslToRgb(h,s,l){function hue2rgb(p,q,t){return 0>t&&(t+=1),t>1&&(t-=1),1/6>t?p+6*(q-p)*t:.5>t?q:2/3>t?p+(q-p)*(2/3-t)*6:p}var r,g,b;if(h=bound01(h,360),s=bound01(s,100),l=bound01(l,100),0===s)r=g=b=l;else{var q=.5>l?l*(1+s):l+s-l*s,p=2*l-q;r=hue2rgb(p,q,h+1/3),g=hue2rgb(p,q,h),b=hue2rgb(p,q,h-1/3)}return{r:255*r,g:255*g,b:255*b}}function rgbToHsv(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);var h,s,max=mathMax(r,g,b),min=mathMin(r,g,b),v=max,d=max-min;if(s=0===max?0:d/max,max==min)h=0;else{switch(max){case r:h=(g-b)/d+(b>g?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return{h:h,s:s,v:v}}function hsvToRgb(h,s,v){h=6*bound01(h,360),s=bound01(s,100),v=bound01(v,100);var i=math.floor(h),f=h-i,p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s),mod=i%6,r=[v,q,p,p,t,v][mod],g=[t,v,v,q,p,p][mod],b=[p,p,t,v,v,q][mod];return{r:255*r,g:255*g,b:255*b}}function rgbToHex(r,g,b,allow3Char){var hex=[pad2(mathRound(r).toString(16)),pad2(mathRound(g).toString(16)),pad2(mathRound(b).toString(16))];return allow3Char&&hex[0].charAt(0)==hex[0].charAt(1)&&hex[1].charAt(0)==hex[1].charAt(1)&&hex[2].charAt(0)==hex[2].charAt(1)?hex[0].charAt(0)+hex[1].charAt(0)+hex[2].charAt(0):hex.join("")}function rgbaToHex(r,g,b,a){var hex=[pad2(convertDecimalToHex(a)),pad2(mathRound(r).toString(16)),pad2(mathRound(g).toString(16)),pad2(mathRound(b).toString(16))];return hex.join("")}function desaturate(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.s-=amount/100,hsl.s=clamp01(hsl.s),tinycolor(hsl)}function saturate(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.s+=amount/100,hsl.s=clamp01(hsl.s),tinycolor(hsl)}function greyscale(color){return tinycolor(color).desaturate(100)}function lighten(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.l+=amount/100,hsl.l=clamp01(hsl.l),tinycolor(hsl)}function brighten(color,amount){amount=0===amount?0:amount||10;var rgb=tinycolor(color).toRgb();return rgb.r=mathMax(0,mathMin(255,rgb.r-mathRound(255*-(amount/100)))),rgb.g=mathMax(0,mathMin(255,rgb.g-mathRound(255*-(amount/100)))),rgb.b=mathMax(0,mathMin(255,rgb.b-mathRound(255*-(amount/100)))),tinycolor(rgb)}function darken(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.l-=amount/100,hsl.l=clamp01(hsl.l),tinycolor(hsl)}function spin(color,amount){var hsl=tinycolor(color).toHsl(),hue=(mathRound(hsl.h)+amount)%360;return hsl.h=0>hue?360+hue:hue,tinycolor(hsl)}function complement(color){var hsl=tinycolor(color).toHsl();return hsl.h=(hsl.h+180)%360,tinycolor(hsl)}function triad(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+120)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+240)%360,s:hsl.s,l:hsl.l})]}function tetrad(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+90)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+180)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+270)%360,s:hsl.s,l:hsl.l})]}function splitcomplement(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+72)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+216)%360,s:hsl.s,l:hsl.l})]}function analogous(color,results,slices){results=results||6,slices=slices||30;var hsl=tinycolor(color).toHsl(),part=360/slices,ret=[tinycolor(color)];for(hsl.h=(hsl.h-(part*results>>1)+720)%360;--results;)hsl.h=(hsl.h+part)%360,ret.push(tinycolor(hsl));return ret}function monochromatic(color,results){results=results||6;for(var hsv=tinycolor(color).toHsv(),h=hsv.h,s=hsv.s,v=hsv.v,ret=[],modification=1/results;results--;)ret.push(tinycolor({h:h,s:s,v:v})),v=(v+modification)%1;return ret}function flip(o){var flipped={};for(var i in o)o.hasOwnProperty(i)&&(flipped[o[i]]=i);return flipped}function boundAlpha(a){return a=parseFloat(a),(isNaN(a)||0>a||a>1)&&(a=1),a}function bound01(n,max){isOnePointZero(n)&&(n="100%");var processPercent=isPercentage(n);return n=mathMin(max,mathMax(0,parseFloat(n))),processPercent&&(n=parseInt(n*max,10)/100),math.abs(n-max)<1e-6?1:n%max/parseFloat(max)}function clamp01(val){return mathMin(1,mathMax(0,val))}function parseIntFromHex(val){return parseInt(val,16)}function isOnePointZero(n){return"string"==typeof n&&-1!=n.indexOf(".")&&1===parseFloat(n)}function isPercentage(n){return"string"==typeof n&&-1!=n.indexOf("%")}function pad2(c){return 1==c.length?"0"+c:""+c}function convertToPercentage(n){return 1>=n&&(n=100*n+"%"),n}function convertDecimalToHex(d){return Math.round(255*parseFloat(d)).toString(16)}function convertHexToDecimal(h){return parseIntFromHex(h)/255}function stringInputToObject(color){color=color.replace(trimLeft,"").replace(trimRight,"").toLowerCase();var named=!1;if(names[color])color=names[color],named=!0;else if("transparent"==color)return{r:0,g:0,b:0,a:0,format:"name"};var match;return(match=matchers.rgb.exec(color))?{r:match[1],g:match[2],b:match[3]}:(match=matchers.rgba.exec(color))?{r:match[1],g:match[2],b:match[3],a:match[4]}:(match=matchers.hsl.exec(color))?{h:match[1],s:match[2],l:match[3]}:(match=matchers.hsla.exec(color))?{h:match[1],s:match[2],l:match[3],a:match[4]}:(match=matchers.hsv.exec(color))?{h:match[1],s:match[2],v:match[3]}:(match=matchers.hsva.exec(color))?{h:match[1],s:match[2],v:match[3],a:match[4]}:(match=matchers.hex8.exec(color))?{a:convertHexToDecimal(match[1]),r:parseIntFromHex(match[2]),g:parseIntFromHex(match[3]),b:parseIntFromHex(match[4]),format:named?"name":"hex8"}:(match=matchers.hex6.exec(color))?{r:parseIntFromHex(match[1]),g:parseIntFromHex(match[2]),b:parseIntFromHex(match[3]),format:named?"name":"hex"}:(match=matchers.hex3.exec(color))?{r:parseIntFromHex(match[1]+""+match[1]),g:parseIntFromHex(match[2]+""+match[2]),b:parseIntFromHex(match[3]+""+match[3]),format:named?"name":"hex"}:!1}var trimLeft=/^[\s,#]+/,trimRight=/\s+$/,tinyCounter=0,math=Math,mathRound=math.round,mathMin=math.min,mathMax=math.max,mathRandom=math.random,tinycolor=function tinycolor(color,opts){if(color=color?color:"",opts=opts||{},color instanceof tinycolor)return color;if(!(this instanceof tinycolor))return new tinycolor(color,opts);var rgb=inputToRGB(color);this._originalInput=color,this._r=rgb.r,this._g=rgb.g,this._b=rgb.b,this._a=rgb.a,this._roundA=mathRound(100*this._a)/100,this._format=opts.format||rgb.format,this._gradientType=opts.gradientType,this._r<1&&(this._r=mathRound(this._r)),this._g<1&&(this._g=mathRound(this._g)),this._b<1&&(this._b=mathRound(this._b)),this._ok=rgb.ok,this._tc_id=tinyCounter++};tinycolor.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var rgb=this.toRgb();return(299*rgb.r+587*rgb.g+114*rgb.b)/1e3},setAlpha:function(value){return this._a=boundAlpha(value),this._roundA=mathRound(100*this._a)/100,this},toHsv:function(){var hsv=rgbToHsv(this._r,this._g,this._b);return{h:360*hsv.h,s:hsv.s,v:hsv.v,a:this._a}},toHsvString:function(){var hsv=rgbToHsv(this._r,this._g,this._b),h=mathRound(360*hsv.h),s=mathRound(100*hsv.s),v=mathRound(100*hsv.v);return 1==this._a?"hsv("+h+", "+s+"%, "+v+"%)":"hsva("+h+", "+s+"%, "+v+"%, "+this._roundA+")"},toHsl:function(){var hsl=rgbToHsl(this._r,this._g,this._b);return{h:360*hsl.h,s:hsl.s,l:hsl.l,a:this._a}},toHslString:function(){var hsl=rgbToHsl(this._r,this._g,this._b),h=mathRound(360*hsl.h),s=mathRound(100*hsl.s),l=mathRound(100*hsl.l);return 1==this._a?"hsl("+h+", "+s+"%, "+l+"%)":"hsla("+h+", "+s+"%, "+l+"%, "+this._roundA+")"},toHex:function(allow3Char){return rgbToHex(this._r,this._g,this._b,allow3Char)},toHexString:function(allow3Char){return"#"+this.toHex(allow3Char)},toHex8:function(){return rgbaToHex(this._r,this._g,this._b,this._a)},toHex8String:function(){return"#"+this.toHex8()},toRgb:function(){return{r:mathRound(this._r),g:mathRound(this._g),b:mathRound(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+mathRound(this._r)+", "+mathRound(this._g)+", "+mathRound(this._b)+")":"rgba("+mathRound(this._r)+", "+mathRound(this._g)+", "+mathRound(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:mathRound(100*bound01(this._r,255))+"%",g:mathRound(100*bound01(this._g,255))+"%",b:mathRound(100*bound01(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+mathRound(100*bound01(this._r,255))+"%, "+mathRound(100*bound01(this._g,255))+"%, "+mathRound(100*bound01(this._b,255))+"%)":"rgba("+mathRound(100*bound01(this._r,255))+"%, "+mathRound(100*bound01(this._g,255))+"%, "+mathRound(100*bound01(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":this._a<1?!1:hexNames[rgbToHex(this._r,this._g,this._b,!0)]||!1},toFilter:function(secondColor){var hex8String="#"+rgbaToHex(this._r,this._g,this._b,this._a),secondHex8String=hex8String,gradientType=this._gradientType?"GradientType = 1, ":"";if(secondColor){var s=tinycolor(secondColor);secondHex8String=s.toHex8String()}return"progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"},toString:function(format){var formatSet=!!format;format=format||this._format;var formattedString=!1,hasAlpha=this._a<1&&this._a>=0,needsAlphaFormat=!formatSet&&hasAlpha&&("hex"===format||"hex6"===format||"hex3"===format||"name"===format);return needsAlphaFormat?"name"===format&&0===this._a?this.toName():this.toRgbString():("rgb"===format&&(formattedString=this.toRgbString()),"prgb"===format&&(formattedString=this.toPercentageRgbString()),("hex"===format||"hex6"===format)&&(formattedString=this.toHexString()),"hex3"===format&&(formattedString=this.toHexString(!0)),"hex8"===format&&(formattedString=this.toHex8String()),"name"===format&&(formattedString=this.toName()),"hsl"===format&&(formattedString=this.toHslString()),"hsv"===format&&(formattedString=this.toHsvString()),formattedString||this.toHexString())},_applyModification:function(fn,args){var color=fn.apply(null,[this].concat([].slice.call(args)));return this._r=color._r,this._g=color._g,this._b=color._b,this.setAlpha(color._a),this},lighten:function(){return this._applyModification(lighten,arguments)},brighten:function(){return this._applyModification(brighten,arguments)},darken:function(){return this._applyModification(darken,arguments)},desaturate:function(){return this._applyModification(desaturate,arguments)},saturate:function(){return this._applyModification(saturate,arguments)},greyscale:function(){return this._applyModification(greyscale,arguments)},spin:function(){return this._applyModification(spin,arguments)},_applyCombination:function(fn,args){return fn.apply(null,[this].concat([].slice.call(args)))},analogous:function(){return this._applyCombination(analogous,arguments)},complement:function(){return this._applyCombination(complement,arguments)},monochromatic:function(){return this._applyCombination(monochromatic,arguments)},splitcomplement:function(){return this._applyCombination(splitcomplement,arguments)},triad:function(){return this._applyCombination(triad,arguments)},tetrad:function(){return this._applyCombination(tetrad,arguments)}},tinycolor.fromRatio=function(color,opts){if("object"==typeof color){var newColor={};for(var i in color)color.hasOwnProperty(i)&&(newColor[i]="a"===i?color[i]:convertToPercentage(color[i]));color=newColor}return tinycolor(color,opts)},tinycolor.equals=function(color1,color2){return color1&&color2?tinycolor(color1).toRgbString()==tinycolor(color2).toRgbString():!1},tinycolor.random=function(){return tinycolor.fromRatio({r:mathRandom(),g:mathRandom(),b:mathRandom()})},tinycolor.mix=function(color1,color2,amount){amount=0===amount?0:amount||50;var w1,rgb1=tinycolor(color1).toRgb(),rgb2=tinycolor(color2).toRgb(),p=amount/100,w=2*p-1,a=rgb2.a-rgb1.a;w1=w*a==-1?w:(w+a)/(1+w*a),w1=(w1+1)/2;var w2=1-w1,rgba={r:rgb2.r*w1+rgb1.r*w2,g:rgb2.g*w1+rgb1.g*w2,b:rgb2.b*w1+rgb1.b*w2,a:rgb2.a*p+rgb1.a*(1-p)};return tinycolor(rgba)},tinycolor.readability=function(color1,color2){var c1=tinycolor(color1),c2=tinycolor(color2),rgb1=c1.toRgb(),rgb2=c2.toRgb(),brightnessA=c1.getBrightness(),brightnessB=c2.getBrightness(),colorDiff=Math.max(rgb1.r,rgb2.r)-Math.min(rgb1.r,rgb2.r)+Math.max(rgb1.g,rgb2.g)-Math.min(rgb1.g,rgb2.g)+Math.max(rgb1.b,rgb2.b)-Math.min(rgb1.b,rgb2.b);return{brightness:Math.abs(brightnessA-brightnessB),color:colorDiff}},tinycolor.isReadable=function(color1,color2){var readability=tinycolor.readability(color1,color2);return readability.brightness>125&&readability.color>500},tinycolor.mostReadable=function(baseColor,colorList){for(var bestColor=null,bestScore=0,bestIsReadable=!1,i=0;i125&&readability.color>500,score=3*(readability.brightness/125)+readability.color/500;(readable&&!bestIsReadable||readable&&bestIsReadable&&score>bestScore||!readable&&!bestIsReadable&&score>bestScore)&&(bestIsReadable=readable,bestScore=score,bestColor=tinycolor(colorList[i]))}return bestColor};var names=tinycolor.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},hexNames=tinycolor.hexNames=flip(names),matchers=function(){var CSS_INTEGER="[-\\+]?\\d+%?",CSS_NUMBER="[-\\+]?\\d*\\.\\d+%?",CSS_UNIT="(?:"+CSS_NUMBER+")|(?:"+CSS_INTEGER+")",PERMISSIVE_MATCH3="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?",PERMISSIVE_MATCH4="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?";return{rgb:new RegExp("rgb"+PERMISSIVE_MATCH3),rgba:new RegExp("rgba"+PERMISSIVE_MATCH4),hsl:new RegExp("hsl"+PERMISSIVE_MATCH3),hsla:new RegExp("hsla"+PERMISSIVE_MATCH4),hsv:new RegExp("hsv"+PERMISSIVE_MATCH3),hsva:new RegExp("hsva"+PERMISSIVE_MATCH4),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();"undefined"!=typeof module&&module.exports?module.exports=tinycolor:"function"==typeof define&&define.amd?define(function(){return tinycolor}):window.tinycolor=tinycolor}(); From af5643e99ffa86f17c3edaecf16b4ee2a7fe7b49 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Fri, 20 Oct 2017 14:59:41 +0530 Subject: [PATCH 07/21] Fixes eslint errors in InlineBoxShadowEditor --- .../InlineBoxShadowEditor/BoxShadowEditor.js | 34 ++++++++----------- .../InlineBoxShadowEditor.js | 14 ++++---- .../default/InlineBoxShadowEditor/main.js | 4 +-- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index bc9f15f0df1..d14f0555bdd 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -72,7 +72,7 @@ define(function(require, exports, module) { BoxShadowEditor.prototype.setValues = function(values) { for(var key in this._values) { if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] != this._values[key]) { + if(values[key] && values[key] !== this._values[key]) { this._values[key] = values[key]; } } @@ -120,27 +120,23 @@ define(function(require, exports, module) { this.$colorValue.bind("input", function (event) { self._handleColorChange(); }); - } - - BoxShadowEditor.prototype._synchronize = function() { - - } + }; BoxShadowEditor.prototype.focus = function() { this.$horizontalOffsetValue.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); - } + }; function _handleChanges($inputElement, propertyName, value) { console.log(value, typeof value); @@ -153,7 +149,7 @@ define(function(require, exports, module) { $inputElement.val(curValue); } - if(value == "") { + if(value === "") { // This is to maintain the box-shadow property. value = "0"; $inputElement.val(value); @@ -161,31 +157,31 @@ define(function(require, exports, module) { var newValue = value + "px"; this._commitChanges(propertyName, newValue); - } + }; BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { var self = this; var newValue = this.$horizontalOffsetValue.val().trim(); _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); - } + }; BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { var self = this; var newValue = this.$verticalOffsetValue.val().trim(); _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); - } + }; BoxShadowEditor.prototype._handleBlurRadiusChange = function() { var self = this; var newValue = this.$blurRadiusValue.val().trim(); _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); - } + }; BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { var self = this; var newValue = this.$spreadRadiusValue.val().trim(); _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); - } + }; /** * Normalize the given color string into the format used by tinycolor, by adding a space @@ -233,11 +229,11 @@ define(function(require, exports, module) { BoxShadowEditor.prototype._undo = function() { - } + }; BoxShadowEditor.prototype._redo = function() { - } + }; /** * Global handler for keys in the color editor. Catches undo/redo keys and traps @@ -265,7 +261,7 @@ define(function(require, exports, module) { BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { this._values[propertyName] = value; this._callback(this._values); - } + }; exports.BoxShadowEditor = BoxShadowEditor; diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 35fe0217d04..6a518defca8 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -102,21 +102,21 @@ define(function(require, exports, module) { }; InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { - var boxShadowString = boxShadowValueTypes.reduce(function(result, type) { - if(!values[type]) { + var boxShadowString = boxShadowValueTypes.reduce(function(result, boxShadowValueType) { + if(!values[boxShadowValueType]) { return result; } - if (typeof values[type] === "Number") { - result += " " + values[type] + "px"; + if (!isNaN(values[boxShadowValueType]) ) { + result += " " + values[boxShadowValueType] + "px"; } else { - result += " " + values[type]; + result += " " + values[boxShadowValueType]; } return result; },""); return boxShadowString.trim(); - } + }; /** @@ -133,7 +133,7 @@ define(function(require, exports, module) { // update values for(var key in this._values) { if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] != this._values[key]) { + if(values[key] && values[key] !== this._values[key]) { this._values[key] = values[key]; } } diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index 41aebeb1fbf..c057c31155d 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -86,8 +86,8 @@ define(function(require, exports, module) { console.log(values); return { - values, - marker + values: values, + marker: marker }; } From f4324320ec6af7e2113d788f3451b1172a73b975 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 21 Oct 2017 22:26:08 +0530 Subject: [PATCH 08/21] Changed indent tabs to 4 spaces --- .../InlineBoxShadowEditor/BoxShadowEditor.js | 418 +++++++------- .../BoxShadowEditorTemplate.html | 62 +-- .../BoxShadowValueTypes.json | 14 +- .../InlineBoxShadowEditor.js | 510 +++++++++--------- .../default/InlineBoxShadowEditor/main.js | 230 ++++---- 5 files changed, 617 insertions(+), 617 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index d14f0555bdd..1541c7a8227 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -1,105 +1,105 @@ define(function(require, exports, module) { - "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"), - tinycolor = require("thirdparty/tinycolor-min"); - - /** 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 {!{horizontalOffset: string, verticalOffset: string, blurRadius: string, spreadRadius: 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.$horizontalOffsetValue = this.$element.find("#horizontal-offset-value"); - this.$verticalOffsetValue = this.$element.find("#vertical-offset-value"); - this.$blurRadiusValue = this.$element.find("#blur-radius-value"); - this.$spreadRadiusValue = this.$element.find("#spread-radius-value"); - this.$colorValue = this.$element.find("#color-value"); - - - // Attach event listeners to main UI elements - this._bindInputHandlers(); - - - // Set initial values in the box-shadow editor inputs. - this._setInputValues(); - } - - /** - * A string or tinycolor object representing the currently selected color - * TODO (#2201): type is unpredictable - * @type {tinycolor|string} - */ - 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) { - for(var key in this._values) { - if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] !== this._values[key]) { - this._values[key] = values[key]; - } - } - } - - this._setInputValues(); - }; - - BoxShadowEditor.prototype._setInputValues = function() { - var values = this._values; - var horizontalOffset, verticalOffset, blurRadius, spreadRadius, color; - - horizontalOffset = values["horizontalOffset"] ? parseFloat(values["horizontalOffset"]) : ""; - verticalOffset = values["verticalOffset"] ? parseFloat(values["verticalOffset"]) : ""; - blurRadius = values["blurRadius"] ? parseFloat(values["blurRadius"]) : ""; - spreadRadius = values["spreadRadius"] ? parseFloat(values["spreadRadius"]) : ""; - color = values["color"] ? values["color"] : ""; - - this.$horizontalOffsetValue.val(horizontalOffset); - this.$verticalOffsetValue.val(verticalOffset); - this.$blurRadiusValue.val(blurRadius); - this.$spreadRadiusValue.val(spreadRadius); - this.$colorValue.val(color); - }; - - BoxShadowEditor.prototype._bindInputHandlers = function() { - var self = this; + "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"), + tinycolor = require("thirdparty/tinycolor-min"); + + /** 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 {!{horizontalOffset: string, verticalOffset: string, blurRadius: string, spreadRadius: 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.$horizontalOffsetValue = this.$element.find("#horizontal-offset-value"); + this.$verticalOffsetValue = this.$element.find("#vertical-offset-value"); + this.$blurRadiusValue = this.$element.find("#blur-radius-value"); + this.$spreadRadiusValue = this.$element.find("#spread-radius-value"); + this.$colorValue = this.$element.find("#color-value"); + + + // Attach event listeners to main UI elements + this._bindInputHandlers(); + + + // Set initial values in the box-shadow editor inputs. + this._setInputValues(); + } + + /** + * A string or tinycolor object representing the currently selected color + * TODO (#2201): type is unpredictable + * @type {tinycolor|string} + */ + 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) { + for(var key in this._values) { + if(this._values.hasOwnProperty(key)) { + if(values[key] && values[key] !== this._values[key]) { + this._values[key] = values[key]; + } + } + } + + this._setInputValues(); + }; + + BoxShadowEditor.prototype._setInputValues = function() { + var values = this._values; + var horizontalOffset, verticalOffset, blurRadius, spreadRadius, color; + + horizontalOffset = values["horizontalOffset"] ? parseFloat(values["horizontalOffset"]) : ""; + verticalOffset = values["verticalOffset"] ? parseFloat(values["verticalOffset"]) : ""; + blurRadius = values["blurRadius"] ? parseFloat(values["blurRadius"]) : ""; + spreadRadius = values["spreadRadius"] ? parseFloat(values["spreadRadius"]) : ""; + color = values["color"] ? values["color"] : ""; + + this.$horizontalOffsetValue.val(horizontalOffset); + this.$verticalOffsetValue.val(verticalOffset); + this.$blurRadiusValue.val(blurRadius); + this.$spreadRadiusValue.val(spreadRadius); + this.$colorValue.val(color); + }; + + BoxShadowEditor.prototype._bindInputHandlers = function() { + var self = this; this.$horizontalOffsetValue.bind("input", function (event) { self._handleHorizontalOffsetChange(); @@ -120,70 +120,70 @@ define(function(require, exports, module) { this.$colorValue.bind("input", function (event) { self._handleColorChange(); }); - }; - - BoxShadowEditor.prototype.focus = function() { - this.$horizontalOffsetValue.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); - }; - - function _handleChanges($inputElement, propertyName, value) { - console.log(value, typeof value); - if(!_isValidNumber(value)) { - if(!this._values[propertyName]) { - $inputElement.val(""); - return; - } - var curValue = parseFloat(this._values[propertyName]); - $inputElement.val(curValue); - } - - if(value === "") { - // This is to maintain the box-shadow property. - value = "0"; - $inputElement.val(value); - } - - var newValue = value + "px"; - this._commitChanges(propertyName, newValue); - }; - - BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { - var self = this; - var newValue = this.$horizontalOffsetValue.val().trim(); - _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); - }; - - BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { - var self = this; - var newValue = this.$verticalOffsetValue.val().trim(); - _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); - }; - - BoxShadowEditor.prototype._handleBlurRadiusChange = function() { - var self = this; - var newValue = this.$blurRadiusValue.val().trim(); - _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); - }; - - BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { - var self = this; - var newValue = this.$spreadRadiusValue.val().trim(); - _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); - }; - - /** + }; + + BoxShadowEditor.prototype.focus = function() { + this.$horizontalOffsetValue.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); + }; + + function _handleChanges($inputElement, propertyName, value) { + console.log(value, typeof value); + if(!_isValidNumber(value)) { + if(!this._values[propertyName]) { + $inputElement.val(""); + return; + } + var curValue = parseFloat(this._values[propertyName]); + $inputElement.val(curValue); + } + + if(value === "") { + // This is to maintain the box-shadow property. + value = "0"; + $inputElement.val(value); + } + + var newValue = value + "px"; + this._commitChanges(propertyName, newValue); + }; + + BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { + var self = this; + var newValue = this.$horizontalOffsetValue.val().trim(); + _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); + }; + + BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { + var self = this; + var newValue = this.$verticalOffsetValue.val().trim(); + _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); + }; + + BoxShadowEditor.prototype._handleBlurRadiusChange = function() { + var self = this; + var newValue = this.$blurRadiusValue.val().trim(); + _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); + }; + + BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { + var self = this; + var newValue = this.$spreadRadiusValue.val().trim(); + _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); + }; + + /** * 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. @@ -204,8 +204,8 @@ define(function(require, exports, module) { return normalizedColor; }; - BoxShadowEditor.prototype._handleColorChange = function() { - var newColor = $.trim(this.$colorValue.val()), + BoxShadowEditor.prototype._handleColorChange = function() { + var newColor = $.trim(this.$colorValue.val()), newColorObj = tinycolor(newColor), newColorOk = newColorObj.isValid(); @@ -222,47 +222,47 @@ define(function(require, exports, module) { // Sync only if we have a valid color or we're restoring the previous valid color. if (newColorOk) { - console.log(newColor); - this._commitChanges("color", newColor); + console.log(newColor); + this._commitChanges("color", newColor); } - }; - - 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; - } - } - }; - - - BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { - this._values[propertyName] = value; - this._callback(this._values); - }; - - - exports.BoxShadowEditor = BoxShadowEditor; + }; + + 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; + } + } + }; + + + BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { + this._values[propertyName] = value; + this._callback(this._values); + }; + + + exports.BoxShadowEditor = BoxShadowEditor; }); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html index c651c6e4eb6..e6589853f54 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -1,33 +1,33 @@
-
- -
- : - px -
-
- : - px -
-
- : - px -
-
- : - px -
-
- : - -
-
+
+ +
+ : + px +
+
+ : + px +
+
+ : + px +
+
+ : + px +
+
+ : + +
+
\ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json index 17a71f2aea0..866a25af220 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json @@ -1,9 +1,9 @@ { - "boxShadowValueTypes": [ - "horizontalOffset", - "verticalOffset", - "blurRadius", - "spreadRadius", - "color" - ] + "boxShadowValueTypes": [ + "horizontalOffset", + "verticalOffset", + "blurRadius", + "spreadRadius", + "color" + ] } \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 6a518defca8..e410a4cc45d 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -1,262 +1,262 @@ define(function(require, exports, module) { - "use strict"; + "use strict"; - var InlineWidget = brackets.getModule("editor/InlineWidget").InlineWidget, - BoxShadowEditor = require("BoxShadowEditor").BoxShadowEditor, - ColorUtils = brackets.getModule("utils/ColorUtils"), - boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + var InlineWidget = brackets.getModule("editor/InlineWidget").InlineWidget, + BoxShadowEditor = require("BoxShadowEditor").BoxShadowEditor, + ColorUtils = brackets.getModule("utils/ColorUtils"), + boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; - /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ + /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ var lastOriginId = 1; - /** - * Inline widget containing a BoxShadowEditor control - * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values Initial set of box-shadow values. - * @param {!CodeMirror.TextMarker} marker - */ - function InlineBoxShadowEditor(values, marker) { - this._values = values; - this._marker = marker; - this._isOwnChange = false; - this._isHostChange = false; - this._origin = "+InlineBoxShadowEditor_" + (lastOriginId++); - - this._handleBoxShadowChange = this._handleBoxShadowChange.bind(this); - this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this); - - InlineWidget.call(this); - } - - InlineBoxShadowEditor.prototype = Object.create(InlineWidget.prototype); - InlineBoxShadowEditor.prototype.constructor = InlineBoxShadowEditor; - InlineBoxShadowEditor.prototype.parentClass = InlineWidget.prototype; - - /** @type {!BoxShadowPicker} BoxShadowPicker instance */ - InlineBoxShadowEditor.prototype.BoxShadowEditor = null; - - /** @type {!{ horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string }} Current value of the BoxShadow editor control */ - InlineBoxShadowEditor.prototype._values = null; - - /** - * Range of code we're attached to; _marker.find() may by null if sync is lost. - * @type {!CodeMirror.TextMarker} - */ - InlineBoxShadowEditor.prototype._marker = null; - - /** @type {boolean} True while we're syncing a BoxShadow editor change into the code editor */ - InlineBoxShadowEditor.prototype._isOwnChange = null; - - /** @type {boolean} True while we're syncing a code editor change into the BoxShadow editor */ - InlineBoxShadowEditor.prototype._isHostChange = null; - - /** @type {number} ID used to identify edits coming from this inline widget for undo batching */ - InlineBoxShadowEditor.prototype._origin = null; - - /** - * Returns the current text range of the color we're attached to, or null if - * we've lost sync with what's in the code. - * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}} - */ - InlineBoxShadowEditor.prototype.getCurrentRange = function () { - var pos, start, end; - - pos = this._marker && this._marker.find(); - - start = pos && pos.from; - if (!start) { - return null; - } - - end = pos.to; - if (!end) { - end = {line: start.line}; - } - - /*-----------Correct this----------*/ - - // Even if we think we have a good range end, we want to run the - // regexp match to see if there's a valid match that extends past the marker. - // This can happen if the user deletes the end of the existing color and then - // types some more. - - // var line = this.hostEditor.document.getLine(start.line), - // matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX); - - // // Note that end.ch is exclusive, so we don't need to add 1 before comparing to - // // the matched length here. - // if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) { - // end.ch = start.ch + matches[0].length; - // this._marker.clear(); - // this._marker = this.hostEditor._codeMirror.markText(start, end); - // } - - // if (end.ch === undefined) { - // // We were unable to resync the marker. - // return null; - // } - // else { - // return {start: start, end: end}; - // } - return {start: start, end: end}; - }; - - InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { - var boxShadowString = boxShadowValueTypes.reduce(function(result, boxShadowValueType) { - if(!values[boxShadowValueType]) { - return result; - } - if (!isNaN(values[boxShadowValueType]) ) { - result += " " + values[boxShadowValueType] + "px"; - } - else { - result += " " + values[boxShadowValueType]; - } - return result; - },""); - - return boxShadowString.trim(); - }; - - - /** - * When the BoxShadow editor's values change, update text in code editor - * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values New set of box-shadow values. - */ - InlineBoxShadowEditor.prototype._handleBoxShadowChange = function (values) { - var self = this; - var range = this.getCurrentRange(); - if (!range) { - return; - } - - // update values - for(var key in this._values) { - if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] !== this._values[key]) { - this._values[key] = values[key]; - } - } - } - - // build the box-shadow value as a string. - var boxShadowString = this._buildBoxShadowString(this._values); - console.log(boxShadowString); - - var endPos = { - line: range.start.line, - ch: range.start.ch + boxShadowString.length - }; - this._isOwnChange = true; - this.hostEditor.document.batchOperation(function () { - // Replace old box-shadow in code with the editor's box-shadow values, and select it - self.hostEditor.setSelection(range.start, range.end); - self.hostEditor.document.replaceRange(boxShadowString, range.start, range.end, self._origin); - self.hostEditor.setSelection(range.start, endPos); - if (self._marker) { - self._marker.clear(); - self._marker = self.hostEditor._codeMirror.markText(range.start, endPos); - } - }); - this._isOwnChange = false; - }; - - /** - * @override - * @param {!Editor} hostEditor - */ - InlineBoxShadowEditor.prototype.load = function (hostEditor) { - InlineBoxShadowEditor.prototype.parentClass.load.apply(this, arguments); - - // Create BoxShadow picker control - this.boxShadowEditor = new BoxShadowEditor(this.$htmlContent, this._values, this._handleBoxShadowChange); - }; - - /** - * @override - * Perform sizing & focus once we've been added to Editor's DOM - */ - InlineBoxShadowEditor.prototype.onAdded = function () { - InlineBoxShadowEditor.prototype.parentClass.onAdded.apply(this, arguments); - - var doc = this.hostEditor.document; - doc.addRef(); - doc.on("change", this._handleHostDocumentChange); - - this.hostEditor.setInlineWidgetHeight(this, this.boxShadowEditor.getRootElement().outerHeight(), true); - - this.boxShadowEditor.focus(); - }; - - /** - * @override - * Called whenever the inline widget is closed, whether automatically or explicitly - */ - InlineBoxShadowEditor.prototype.onClosed = function () { - InlineBoxShadowEditor.prototype.parentClass.onClosed.apply(this, arguments); - - if (this._marker) { - this._marker.clear(); - } - - var doc = this.hostEditor.document; - doc.off("change", this._handleHostDocumentChange); - doc.releaseRef(); - this.boxShadowEditor.destroy(); - }; - - function _isValidBoxShadowValue(value) { - // Need to improve this regex. - return (value.match(/\s*(\d+px\s+){0,3}?\d+px(?:\s+|;|)(?:#?[a-z]{3,}\s*)?;?/) !== null); - } - - /** - * When text in the code editor changes, update color picker to reflect it - */ - InlineBoxShadowEditor.prototype._handleHostDocumentChange = function () { - // Don't push the change into the box-shadow editor if it came from the box-shadow editor. - if (this._isOwnChange) { - return; - } - - var range = this.getCurrentRange(); - /*Correct this*/ - if (range) { - var newString = this.hostEditor.document.getRange(range.start, range.end); - console.log(range); - var flag = _isValidBoxShadowValue(newString); - console.log(flag); - if(_isValidBoxShadowValue(newString)) { - // extract values - var newValues = {}; - var boxShadowValueIndex = 0; - newString.split(/\s+/).forEach(function(value, index) { - value = value.trim(); - var colorMatch = value.match(ColorUtils.COLOR_REGEX); - var pixelMatch = value.match(/(\d+)px/); - if(colorMatch) { - newValues["color"] = colorMatch[0]; - } - else if(pixelMatch){ - newValues[boxShadowValueTypes[boxShadowValueIndex++]] = value; - } - }); - console.log(newValues); - - if(newValues !== this._values) { - this._isHostChange = true; - this.boxShadowEditor.setValues(newValues); - this._values = newValues; - this._isHostChange = false; - } - } - - } - else { - // The edit caused our range to become invalid. Close the editor. - this.close(); - } - }; - - exports.InlineBoxShadowEditor = InlineBoxShadowEditor; + /** + * Inline widget containing a BoxShadowEditor control + * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values Initial set of box-shadow values. + * @param {!CodeMirror.TextMarker} marker + */ + function InlineBoxShadowEditor(values, marker) { + this._values = values; + this._marker = marker; + this._isOwnChange = false; + this._isHostChange = false; + this._origin = "+InlineBoxShadowEditor_" + (lastOriginId++); + + this._handleBoxShadowChange = this._handleBoxShadowChange.bind(this); + this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this); + + InlineWidget.call(this); + } + + InlineBoxShadowEditor.prototype = Object.create(InlineWidget.prototype); + InlineBoxShadowEditor.prototype.constructor = InlineBoxShadowEditor; + InlineBoxShadowEditor.prototype.parentClass = InlineWidget.prototype; + + /** @type {!BoxShadowPicker} BoxShadowPicker instance */ + InlineBoxShadowEditor.prototype.BoxShadowEditor = null; + + /** @type {!{ horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string }} Current value of the BoxShadow editor control */ + InlineBoxShadowEditor.prototype._values = null; + + /** + * Range of code we're attached to; _marker.find() may by null if sync is lost. + * @type {!CodeMirror.TextMarker} + */ + InlineBoxShadowEditor.prototype._marker = null; + + /** @type {boolean} True while we're syncing a BoxShadow editor change into the code editor */ + InlineBoxShadowEditor.prototype._isOwnChange = null; + + /** @type {boolean} True while we're syncing a code editor change into the BoxShadow editor */ + InlineBoxShadowEditor.prototype._isHostChange = null; + + /** @type {number} ID used to identify edits coming from this inline widget for undo batching */ + InlineBoxShadowEditor.prototype._origin = null; + + /** + * Returns the current text range of the color we're attached to, or null if + * we've lost sync with what's in the code. + * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}} + */ + InlineBoxShadowEditor.prototype.getCurrentRange = function () { + var pos, start, end; + + pos = this._marker && this._marker.find(); + + start = pos && pos.from; + if (!start) { + return null; + } + + end = pos.to; + if (!end) { + end = {line: start.line}; + } + + /*-----------Correct this----------*/ + + // Even if we think we have a good range end, we want to run the + // regexp match to see if there's a valid match that extends past the marker. + // This can happen if the user deletes the end of the existing color and then + // types some more. + + // var line = this.hostEditor.document.getLine(start.line), + // matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX); + + // // Note that end.ch is exclusive, so we don't need to add 1 before comparing to + // // the matched length here. + // if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) { + // end.ch = start.ch + matches[0].length; + // this._marker.clear(); + // this._marker = this.hostEditor._codeMirror.markText(start, end); + // } + + // if (end.ch === undefined) { + // // We were unable to resync the marker. + // return null; + // } + // else { + // return {start: start, end: end}; + // } + return {start: start, end: end}; + }; + + InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { + var boxShadowString = boxShadowValueTypes.reduce(function(result, boxShadowValueType) { + if(!values[boxShadowValueType]) { + return result; + } + if (!isNaN(values[boxShadowValueType]) ) { + result += " " + values[boxShadowValueType] + "px"; + } + else { + result += " " + values[boxShadowValueType]; + } + return result; + },""); + + return boxShadowString.trim(); + }; + + + /** + * When the BoxShadow editor's values change, update text in code editor + * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values New set of box-shadow values. + */ + InlineBoxShadowEditor.prototype._handleBoxShadowChange = function (values) { + var self = this; + var range = this.getCurrentRange(); + if (!range) { + return; + } + + // update values + for(var key in this._values) { + if(this._values.hasOwnProperty(key)) { + if(values[key] && values[key] !== this._values[key]) { + this._values[key] = values[key]; + } + } + } + + // build the box-shadow value as a string. + var boxShadowString = this._buildBoxShadowString(this._values); + console.log(boxShadowString); + + var endPos = { + line: range.start.line, + ch: range.start.ch + boxShadowString.length + }; + this._isOwnChange = true; + this.hostEditor.document.batchOperation(function () { + // Replace old box-shadow in code with the editor's box-shadow values, and select it + self.hostEditor.setSelection(range.start, range.end); + self.hostEditor.document.replaceRange(boxShadowString, range.start, range.end, self._origin); + self.hostEditor.setSelection(range.start, endPos); + if (self._marker) { + self._marker.clear(); + self._marker = self.hostEditor._codeMirror.markText(range.start, endPos); + } + }); + this._isOwnChange = false; + }; + + /** + * @override + * @param {!Editor} hostEditor + */ + InlineBoxShadowEditor.prototype.load = function (hostEditor) { + InlineBoxShadowEditor.prototype.parentClass.load.apply(this, arguments); + + // Create BoxShadow picker control + this.boxShadowEditor = new BoxShadowEditor(this.$htmlContent, this._values, this._handleBoxShadowChange); + }; + + /** + * @override + * Perform sizing & focus once we've been added to Editor's DOM + */ + InlineBoxShadowEditor.prototype.onAdded = function () { + InlineBoxShadowEditor.prototype.parentClass.onAdded.apply(this, arguments); + + var doc = this.hostEditor.document; + doc.addRef(); + doc.on("change", this._handleHostDocumentChange); + + this.hostEditor.setInlineWidgetHeight(this, this.boxShadowEditor.getRootElement().outerHeight(), true); + + this.boxShadowEditor.focus(); + }; + + /** + * @override + * Called whenever the inline widget is closed, whether automatically or explicitly + */ + InlineBoxShadowEditor.prototype.onClosed = function () { + InlineBoxShadowEditor.prototype.parentClass.onClosed.apply(this, arguments); + + if (this._marker) { + this._marker.clear(); + } + + var doc = this.hostEditor.document; + doc.off("change", this._handleHostDocumentChange); + doc.releaseRef(); + this.boxShadowEditor.destroy(); + }; + + function _isValidBoxShadowValue(value) { + // Need to improve this regex. + return (value.match(/\s*(\d+px\s+){0,3}?\d+px(?:\s+|;|)(?:#?[a-z]{3,}\s*)?;?/) !== null); + } + + /** + * When text in the code editor changes, update color picker to reflect it + */ + InlineBoxShadowEditor.prototype._handleHostDocumentChange = function () { + // Don't push the change into the box-shadow editor if it came from the box-shadow editor. + if (this._isOwnChange) { + return; + } + + var range = this.getCurrentRange(); + /*Correct this*/ + if (range) { + var newString = this.hostEditor.document.getRange(range.start, range.end); + console.log(range); + var flag = _isValidBoxShadowValue(newString); + console.log(flag); + if(_isValidBoxShadowValue(newString)) { + // extract values + var newValues = {}; + var boxShadowValueIndex = 0; + newString.split(/\s+/).forEach(function(value, index) { + value = value.trim(); + var colorMatch = value.match(ColorUtils.COLOR_REGEX); + var pixelMatch = value.match(/(\d+)px/); + if(colorMatch) { + newValues["color"] = colorMatch[0]; + } + else if(pixelMatch){ + newValues[boxShadowValueTypes[boxShadowValueIndex++]] = value; + } + }); + console.log(newValues); + + if(newValues !== this._values) { + this._isHostChange = true; + this.boxShadowEditor.setValues(newValues); + this._values = newValues; + this._isHostChange = false; + } + } + + } + else { + // The edit caused our range to become invalid. Close the editor. + this.close(); + } + }; + + exports.InlineBoxShadowEditor = InlineBoxShadowEditor; }); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index c057c31155d..672a466f3b8 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -1,14 +1,14 @@ define(function(require, exports, module) { - "use strict"; + "use strict"; - var EditorManager = brackets.getModule("editor/EditorManager"), - ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), - InlineBoxShadowEditor = require("InlineBoxShadowEditor").InlineBoxShadowEditor, - ColorUtils = brackets.getModule("utils/ColorUtils"), - boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + var EditorManager = brackets.getModule("editor/EditorManager"), + ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), + InlineBoxShadowEditor = require("InlineBoxShadowEditor").InlineBoxShadowEditor, + ColorUtils = brackets.getModule("utils/ColorUtils"), + boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; - var DEFAULT_VALUES = "0px 0px 0px 0px black"; - /** + var DEFAULT_VALUES = "0px 0px 0px 0px black"; + /** * Prepare hostEditor for an InlineBoxShadowEditor at pos if possible. Return * editor context if so; otherwise null. * @@ -16,82 +16,82 @@ define(function(require, exports, module) { * @param {{line:Number, ch:Number}} pos * @return {?{values:{}, marker:TextMarker}} */ - function prepareEditorForProvider(hostEditor, pos) { - var cursorLine = hostEditor.document.getLine(pos.line); - - if(cursorLine.indexOf("box-shadow") === -1) { - return null; - } - - var semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; - values = {}; - - colonPos = cursorLine.indexOf(":"); - semiColonPos = cursorLine.indexOf(";"); - cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); - - console.log(cursorLineSubstring); - - // Get the initial set of values of box-shadow property - isEmptyString = true; - boxShadowValueIndex = 0; - cursorLineSubstring.split(/\s+/).forEach(function(value, index) { - value = value.trim(); - var colorMatch = value.match(ColorUtils.COLOR_REGEX); - var pixelMatch = value.match(/(\d+)px/); - console.log(value, colorMatch, pixelMatch); - if(colorMatch) { - values["color"] = colorMatch[0]; - isEmptyString = false; - } - else if(pixelMatch){ - // Fix here - values[boxShadowValueTypes[boxShadowValueIndex++]] = value; - isEmptyString = false; - } - }); - - console.log(isEmptyString); - - if(isEmptyString) { - //Edit a new css rule. - var newText = " ", from ,to; - newText = newText.concat(DEFAULT_VALUES, ";"); - from = {line: pos.line, ch: colonPos + 1}; - to = {line: pos.line, ch: cursorLine.length}; - hostEditor._codeMirror.replaceRange(newText, from, to); - pos.ch = colonPos + 2; - endPos = {line: pos.line, ch: pos.ch + DEFAULT_VALUES.length}; - values = { - "horizontalOffset": "0px", - "verticalOffset": "0px", - "blurRadius": "0px", - "spreadRadius": "0px", - "color": "black" - }; - } - else { - firstCharacterPos = cursorLineSubstring.search(/\S/); - pos.ch = colonPos + 1 + Math.min(firstCharacterPos,1); - if (semiColonPos !== -1) { - endPos = {line: pos.line, ch: semiColonPos}; - } else { - endPos = {line: pos.line, ch: cursorLine.length}; - } - } - - marker = hostEditor._codeMirror.markText(pos, endPos); - hostEditor.setSelection(pos, endPos); - - console.log(values); - - return { - values: values, - marker: marker - }; - } - - /** + function prepareEditorForProvider(hostEditor, pos) { + var cursorLine = hostEditor.document.getLine(pos.line); + + if(cursorLine.indexOf("box-shadow") === -1) { + return null; + } + + var semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; + values = {}; + + colonPos = cursorLine.indexOf(":"); + semiColonPos = cursorLine.indexOf(";"); + cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); + + console.log(cursorLineSubstring); + + // Get the initial set of values of box-shadow property + isEmptyString = true; + boxShadowValueIndex = 0; + cursorLineSubstring.split(/\s+/).forEach(function(value, index) { + value = value.trim(); + var colorMatch = value.match(ColorUtils.COLOR_REGEX); + var pixelMatch = value.match(/(\d+)px/); + console.log(value, colorMatch, pixelMatch); + if(colorMatch) { + values["color"] = colorMatch[0]; + isEmptyString = false; + } + else if(pixelMatch){ + // Fix here + values[boxShadowValueTypes[boxShadowValueIndex++]] = value; + isEmptyString = false; + } + }); + + console.log(isEmptyString); + + if(isEmptyString) { + //Edit a new css rule. + var newText = " ", from ,to; + newText = newText.concat(DEFAULT_VALUES, ";"); + from = {line: pos.line, ch: colonPos + 1}; + to = {line: pos.line, ch: cursorLine.length}; + hostEditor._codeMirror.replaceRange(newText, from, to); + pos.ch = colonPos + 2; + endPos = {line: pos.line, ch: pos.ch + DEFAULT_VALUES.length}; + values = { + "horizontalOffset": "0px", + "verticalOffset": "0px", + "blurRadius": "0px", + "spreadRadius": "0px", + "color": "black" + }; + } + else { + firstCharacterPos = cursorLineSubstring.search(/\S/); + pos.ch = colonPos + 1 + Math.min(firstCharacterPos,1); + if (semiColonPos !== -1) { + endPos = {line: pos.line, ch: semiColonPos}; + } else { + endPos = {line: pos.line, ch: cursorLine.length}; + } + } + + marker = hostEditor._codeMirror.markText(pos, endPos); + hostEditor.setSelection(pos, endPos); + + console.log(values); + + return { + values: values, + marker: marker + }; + } + + /** * Registered as an inline editor provider: creates an InlineBoxShadowEditor when the cursor * is on a line containing box-shadow property (in any flavor of code). * @@ -100,37 +100,37 @@ define(function(require, exports, module) { * @return {?$.Promise} synchronously resolved with an InlineWidget, or null if there's * no box-shadow at pos. */ - function inlineBoxShadowEditorProvider(hostEditor, pos) { - var context = prepareEditorForProvider(hostEditor, pos), - inlineBoxShadowEditor, - result; - - if(!context) { - return null; - } - else { - inlineBoxShadowEditor = new InlineBoxShadowEditor(context.values, context.marker); - inlineBoxShadowEditor.load(hostEditor); - - result = new $.Deferred(); - result.resolve(inlineBoxShadowEditor); - return result.promise(); - } - } - - function queryInlineBoxShadowEditorProvider(hostEditor, pos) { - var cursorLine = hostEditor.document.getLine(pos.line); - - if(cursorLine.indexOf("box-shadow") !== -1) { - return true; - } - else { - return false; - } - } - - - // Initialize extension + function inlineBoxShadowEditorProvider(hostEditor, pos) { + var context = prepareEditorForProvider(hostEditor, pos), + inlineBoxShadowEditor, + result; + + if(!context) { + return null; + } + else { + inlineBoxShadowEditor = new InlineBoxShadowEditor(context.values, context.marker); + inlineBoxShadowEditor.load(hostEditor); + + result = new $.Deferred(); + result.resolve(inlineBoxShadowEditor); + return result.promise(); + } + } + + function queryInlineBoxShadowEditorProvider(hostEditor, pos) { + var cursorLine = hostEditor.document.getLine(pos.line); + + if(cursorLine.indexOf("box-shadow") !== -1) { + return true; + } + else { + return false; + } + } + + + // Initialize extension ExtensionUtils.loadStyleSheet(module, "css/style.less"); EditorManager.registerInlineEditProvider(inlineBoxShadowEditorProvider, queryInlineBoxShadowEditorProvider); From b21a416f3644ba74c71e4260ea8fcfd51530de78 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 9 Dec 2017 21:09:48 +0530 Subject: [PATCH 09/21] Changed input textboxes to input range --- .../InlineBoxShadowEditor/BoxShadowEditor.js | 12 ++-- .../BoxShadowEditorTemplate.html | 17 ++---- .../InlineBoxShadowEditor.js | 60 ++++++++----------- .../default/InlineBoxShadowEditor/main.js | 12 ++-- 4 files changed, 42 insertions(+), 59 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index 1541c7a8227..422ababecb4 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -45,9 +45,8 @@ define(function(require, exports, module) { } /** - * A string or tinycolor object representing the currently selected color - * TODO (#2201): type is unpredictable - * @type {tinycolor|string} + * A object representing the current set of box-shadow values + * @type {} */ BoxShadowEditor.prototype._values = null; @@ -221,9 +220,14 @@ define(function(require, exports, module) { } // Sync only if we have a valid color or we're restoring the previous valid color. + this._commitChanges("color", newColor); if (newColorOk) { console.log(newColor); - this._commitChanges("color", newColor); + this.$colorValue.css("border", "initial"); + } + else { + console.warn("Wrong colour value"); + this.$colorValue.css("border", "2px solid red"); } }; diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html index e6589853f54..675caed43e0 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -1,29 +1,20 @@
-
: - px + px
: - px + px
: - px + px
: - px + px
: diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index e410a4cc45d..23c7c1864dc 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -54,12 +54,12 @@ define(function(require, exports, module) { InlineBoxShadowEditor.prototype._origin = null; /** - * Returns the current text range of the color we're attached to, or null if + * Returns the current text range of the box-shadow value we're attached to, or null if * we've lost sync with what's in the code. * @return {?{start:{line:number, ch:number}, end:{line:number, ch:number}}} */ InlineBoxShadowEditor.prototype.getCurrentRange = function () { - var pos, start, end; + var pos, start, end, line; pos = this._marker && this._marker.find(); @@ -69,36 +69,27 @@ define(function(require, exports, module) { } end = pos.to; - if (!end) { - end = {line: start.line}; + + line = this.hostEditor.document.getLine(start.line); + + start.ch = line.indexOf(':') + 1; + while(line[start.ch] == ' ') start.ch++; + + end.line = start.line; + end.ch = line.indexOf(';'); + + if(end.ch === -1) { + end.ch = line.length; + while(end.ch > start.ch && line[end.ch] != ';') end.ch--; } - /*-----------Correct this----------*/ - - // Even if we think we have a good range end, we want to run the - // regexp match to see if there's a valid match that extends past the marker. - // This can happen if the user deletes the end of the existing color and then - // types some more. - - // var line = this.hostEditor.document.getLine(start.line), - // matches = line.substr(start.ch).match(ColorUtils.COLOR_REGEX); - - // // Note that end.ch is exclusive, so we don't need to add 1 before comparing to - // // the matched length here. - // if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) { - // end.ch = start.ch + matches[0].length; - // this._marker.clear(); - // this._marker = this.hostEditor._codeMirror.markText(start, end); - // } - - // if (end.ch === undefined) { - // // We were unable to resync the marker. - // return null; - // } - // else { - // return {start: start, end: end}; - // } - return {start: start, end: end}; + if (end.ch === undefined) { + // We were unable to resync the marker. + return null; + } + else { + return {start: start, end: end}; + } }; InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { @@ -211,7 +202,7 @@ define(function(require, exports, module) { } /** - * When text in the code editor changes, update color picker to reflect it + * When text in the code editor changes, update quick edit to reflect it */ InlineBoxShadowEditor.prototype._handleHostDocumentChange = function () { // Don't push the change into the box-shadow editor if it came from the box-shadow editor. @@ -220,20 +211,21 @@ define(function(require, exports, module) { } var range = this.getCurrentRange(); - /*Correct this*/ if (range) { var newString = this.hostEditor.document.getRange(range.start, range.end); - console.log(range); + var flag = _isValidBoxShadowValue(newString); - console.log(flag); + if(_isValidBoxShadowValue(newString)) { // extract values var newValues = {}; var boxShadowValueIndex = 0; + newString.split(/\s+/).forEach(function(value, index) { value = value.trim(); var colorMatch = value.match(ColorUtils.COLOR_REGEX); var pixelMatch = value.match(/(\d+)px/); + console.log(colorMatch); if(colorMatch) { newValues["color"] = colorMatch[0]; } diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index 672a466f3b8..f3bd8db3c83 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -8,6 +8,7 @@ define(function(require, exports, module) { boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; var DEFAULT_VALUES = "0px 0px 0px 0px black"; + /** * Prepare hostEditor for an InlineBoxShadowEditor at pos if possible. Return * editor context if so; otherwise null. @@ -17,21 +18,18 @@ define(function(require, exports, module) { * @return {?{values:{}, marker:TextMarker}} */ function prepareEditorForProvider(hostEditor, pos) { - var cursorLine = hostEditor.document.getLine(pos.line); - - if(cursorLine.indexOf("box-shadow") === -1) { + if(queryInlineBoxShadowEditorProvider(hostEditor, pos) == false) { return null; } - var semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; + var cursorLine, semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; values = {}; + cursorLine = hostEditor.document.getLine(pos.line); colonPos = cursorLine.indexOf(":"); semiColonPos = cursorLine.indexOf(";"); cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); - console.log(cursorLineSubstring); - // Get the initial set of values of box-shadow property isEmptyString = true; boxShadowValueIndex = 0; @@ -45,7 +43,6 @@ define(function(require, exports, module) { isEmptyString = false; } else if(pixelMatch){ - // Fix here values[boxShadowValueTypes[boxShadowValueIndex++]] = value; isEmptyString = false; } @@ -129,7 +126,6 @@ define(function(require, exports, module) { } } - // Initialize extension ExtensionUtils.loadStyleSheet(module, "css/style.less"); From 34198094171f21972e512adbeb79bcbc0ad2228c Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 9 Dec 2017 21:24:32 +0530 Subject: [PATCH 10/21] Fixed eslint errors --- .../InlineBoxShadowEditor/InlineBoxShadowEditor.js | 8 ++++++-- src/extensions/default/InlineBoxShadowEditor/main.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 23c7c1864dc..7728dee3f92 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -73,14 +73,18 @@ define(function(require, exports, module) { line = this.hostEditor.document.getLine(start.line); start.ch = line.indexOf(':') + 1; - while(line[start.ch] == ' ') start.ch++; + while(line[start.ch] === ' ') { + start.ch++; + } end.line = start.line; end.ch = line.indexOf(';'); if(end.ch === -1) { end.ch = line.length; - while(end.ch > start.ch && line[end.ch] != ';') end.ch--; + while(end.ch > start.ch && line[end.ch] !== ';') { + end.ch--; + } } if (end.ch === undefined) { diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index f3bd8db3c83..bacd03e5b81 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -18,7 +18,7 @@ define(function(require, exports, module) { * @return {?{values:{}, marker:TextMarker}} */ function prepareEditorForProvider(hostEditor, pos) { - if(queryInlineBoxShadowEditorProvider(hostEditor, pos) == false) { + if(queryInlineBoxShadowEditorProvider(hostEditor, pos) === false) { return null; } From 709e9fbe5ba030dda8e8bfc4f349ecd3a4ad50d7 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Thu, 8 Mar 2018 13:57:03 +0530 Subject: [PATCH 11/21] Input sliders working with added styles Rewrote most of the code from a huge procedural chunk to objects of type BoxShadowInput viz. BoxShadowLength, BoxShadowColor. The new responsibilities are - + InlineBoxShadowEditor - It initialises the widget and acts as intermediary for propagating values between text editor and box-shadow editor + BoxShadowEditor - The overall manager for different BoxShadowInputs. Gets values from InlineBoxShadowEditor and passes them to the appropriate BoxShadowInput. +BoxShadowLength - BoxShadowInput for length types +BoxShadowColor - BoxShadowInput for color value --- .../InlineBoxShadowEditor/BoxShadowEditor.js | 190 ++------ .../BoxShadowEditorTemplate.html | 144 +++++- .../InlineBoxShadowEditor/BoxShadowInputs.js | 236 ++++++++++ .../InlineBoxShadowEditor/BoxShadowUtils.js | 19 + .../InlineBoxShadowEditor.js | 137 +++--- .../InlineBoxShadowEditor/css/style.less | 416 ++++++++++++++++-- .../default/InlineBoxShadowEditor/main.js | 65 ++- 7 files changed, 890 insertions(+), 317 deletions(-) create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index 422ababecb4..7f738d46c24 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -6,15 +6,19 @@ define(function(require, exports, module) { StringUtils = brackets.getModule("utils/StringUtils"), Strings = brackets.getModule("strings"), Mustache = brackets.getModule("thirdparty/mustache/mustache"), - tinycolor = require("thirdparty/tinycolor-min"); + BoxShadowInputs = require("BoxShadowInputs"), + BoxShadowUtils = require("BoxShadowUtils"); /** Mustache template that forms the bare DOM structure of the UI */ var BoxShadowEditorTemplate = require("text!BoxShadowEditorTemplate.html"); + var BoxShadowLength = BoxShadowInputs.BoxShadowLength, + BoxShadowColor = BoxShadowInputs.BoxShadowColor; + /** * 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 {!{horizontalOffset: string, verticalOffset: string, blurRadius: string, spreadRadius: string, color: string}} values Initial set of box-shadow values. + * @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) { @@ -23,25 +27,12 @@ define(function(require, exports, module) { $parent.append(this.$element); this._callback = callback; - this._values = values; this._originalValues = values; this._redoValues = null; // Get references - this.$horizontalOffsetValue = this.$element.find("#horizontal-offset-value"); - this.$verticalOffsetValue = this.$element.find("#vertical-offset-value"); - this.$blurRadiusValue = this.$element.find("#blur-radius-value"); - this.$spreadRadiusValue = this.$element.find("#spread-radius-value"); - this.$colorValue = this.$element.find("#color-value"); - - - // Attach event listeners to main UI elements - this._bindInputHandlers(); - - - // Set initial values in the box-shadow editor inputs. - this._setInputValues(); + this._initializeInputs(values); } /** @@ -69,60 +60,28 @@ define(function(require, exports, module) { }; BoxShadowEditor.prototype.setValues = function(values) { - for(var key in this._values) { - if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] !== this._values[key]) { - this._values[key] = values[key]; - } - } - } - - this._setInputValues(); + 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"]); }; - BoxShadowEditor.prototype._setInputValues = function() { - var values = this._values; - var horizontalOffset, verticalOffset, blurRadius, spreadRadius, color; - - horizontalOffset = values["horizontalOffset"] ? parseFloat(values["horizontalOffset"]) : ""; - verticalOffset = values["verticalOffset"] ? parseFloat(values["verticalOffset"]) : ""; - blurRadius = values["blurRadius"] ? parseFloat(values["blurRadius"]) : ""; - spreadRadius = values["spreadRadius"] ? parseFloat(values["spreadRadius"]) : ""; - color = values["color"] ? values["color"] : ""; - - this.$horizontalOffsetValue.val(horizontalOffset); - this.$verticalOffsetValue.val(verticalOffset); - this.$blurRadiusValue.val(blurRadius); - this.$spreadRadiusValue.val(spreadRadius); - this.$colorValue.val(color); - }; + BoxShadowEditor.prototype._initializeInputs = function(values) { + this.hShadow = new BoxShadowLength(this, this.$element, "h-shadow", values.lengths["h-shadow"], this.handleChanges); - BoxShadowEditor.prototype._bindInputHandlers = function() { - var self = this; + this.vShadow = new BoxShadowLength(this, this.$element, "v-shadow", values.lengths["v-shadow"], this.handleChanges); - this.$horizontalOffsetValue.bind("input", function (event) { - self._handleHorizontalOffsetChange(); - }); + this.blur = new BoxShadowLength(this, this.$element, "blur", values.lengths["blur"], this.handleChanges); - this.$verticalOffsetValue.bind("input", function (event) { - self._handleVerticalOffsetChange(); - }); + this.spread = new BoxShadowLength(this, this.$element, "spread", values.lengths["spread"], this.handleChanges); - this.$blurRadiusValue.bind("input", function (event) { - self._handleBlurRadiusChange(); - }); - - this.$spreadRadiusValue.bind("input", function (event) { - self._handleSpreadRadiusChange(); - }); - - this.$colorValue.bind("input", function (event) { - self._handleColorChange(); - }); + this.color = new BoxShadowColor(this, this.$element, "color", values["color"], this.handleChanges); + // this.$inset = this.$element.find("#inset"); }; BoxShadowEditor.prototype.focus = function() { - this.$horizontalOffsetValue.focus(); + this.hShadow.focus(); }; BoxShadowEditor.prototype.destroy = function() { @@ -137,106 +96,24 @@ define(function(require, exports, module) { return (data.match(/\-?\d*/) !== null); }; - function _handleChanges($inputElement, propertyName, value) { - console.log(value, typeof value); - if(!_isValidNumber(value)) { - if(!this._values[propertyName]) { - $inputElement.val(""); - return; - } - var curValue = parseFloat(this._values[propertyName]); - $inputElement.val(curValue); - } - - if(value === "") { - // This is to maintain the box-shadow property. - value = "0"; - $inputElement.val(value); - } - - var newValue = value + "px"; - this._commitChanges(propertyName, newValue); - }; - - BoxShadowEditor.prototype._handleHorizontalOffsetChange = function() { - var self = this; - var newValue = this.$horizontalOffsetValue.val().trim(); - _handleChanges.call(self, this.$horizontalOffsetValue, "horizontalOffset", newValue); - }; - - BoxShadowEditor.prototype._handleVerticalOffsetChange = function() { - var self = this; - var newValue = this.$verticalOffsetValue.val().trim(); - _handleChanges.call(self, this.$verticalOffsetValue, "verticalOffset", newValue); - }; - - BoxShadowEditor.prototype._handleBlurRadiusChange = function() { - var self = this; - var newValue = this.$blurRadiusValue.val().trim(); - _handleChanges.call(self, this.$blurRadiusValue, "blurRadius", newValue); - }; - - BoxShadowEditor.prototype._handleSpreadRadiusChange = function() { - var self = this; - var newValue = this.$spreadRadiusValue.val().trim(); - _handleChanges.call(self, this.$spreadRadiusValue, "spreadRadius", newValue); - }; - - /** - * 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. - */ - BoxShadowEditor.prototype._normalizeColorString = function (color) { - 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(); + BoxShadowEditor.prototype.handleChanges = function(type, name, value) { + if(type === "lengths") { + this._values.lengths[name] = value; } - if (color.match(/^(rgb|hsl)/i)) { - normalizedColor = normalizedColor.replace(/,\s*/g, ", "); - normalizedColor = normalizedColor.replace(/\(\s+/, "("); - normalizedColor = normalizedColor.replace(/\s+\)/, ")"); + else if(type === "color") { + this._values[name] = value; } - return normalizedColor; - }; - - BoxShadowEditor.prototype._handleColorChange = function() { - var newColor = $.trim(this.$colorValue.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 (newColorOk) { - newColorOk = (newColorObj.toString() === this._normalizeColorString(newColor)); + else if(type === "inset") { + this._values[name] = value; } - // Sync only if we have a valid color or we're restoring the previous valid color. - this._commitChanges("color", newColor); - if (newColorOk) { - console.log(newColor); - this.$colorValue.css("border", "initial"); - } - else { - console.warn("Wrong colour value"); - this.$colorValue.css("border", "2px solid red"); - } + this._callback(this._values); }; - BoxShadowEditor.prototype._undo = function() { - + BoxShadowEditor.prototype._undo = function() { }; - BoxShadowEditor.prototype._redo = function() { - + BoxShadowEditor.prototype._redo = function() { }; /** @@ -261,12 +138,5 @@ define(function(require, exports, module) { } }; - - BoxShadowEditor.prototype._commitChanges = function(propertyName, value) { - this._values[propertyName] = value; - this._callback(this._values); - }; - - exports.BoxShadowEditor = BoxShadowEditor; }); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html index 675caed43e0..86bc7b565e6 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -1,24 +1,124 @@
-
-
- : - px -
-
- : - px -
-
- : - px -
-
- : - px -
-
- : - -
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Horizontal + + + + + +
    +
  • + px +
  • +
  • + % +
  • +
  • + em +
  • +
+
+ Vertical + + + + + +
    +
  • + px +
  • +
  • + % +
  • +
  • + em +
  • +
+
+ Blur + + + + + +
    +
  • + px +
  • +
  • + % +
  • +
  • + em +
  • +
+
+ Spread + + + + + +
    +
  • + px +
  • +
  • + % +
  • +
  • + em +
  • +
+
+ Color + + +
+
\ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js new file mode 100644 index 00000000000..7f2ac41cf71 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js @@ -0,0 +1,236 @@ +define(function(require, exports, module) { + "use strict"; + + var BoxShadowUtils = require("BoxShadowUtils"), + ColorUtils = brackets.getModule("utils/ColorUtils"), + tinycolor = require("thirdparty/tinycolor-min"); + + var units = BoxShadowUtils.UNITS; + + var DEFAULT_COLOR = "black"; + + function BoxShadowInput($parent, name) { + this.name = name; + this.$parent = $parent; + this.$el = $parent.find("#" + this.name); + this.$input = this.$el.find("input"); + }; + + /** + * @Override + * Method to handle input events. + */ + BoxShadowInput.prototype.handleInput = function() { + }; + + /** + * @Override + * Sets the value to the input + */ + BoxShadowInput.prototype.setValue = function(string) { + }; + + /** + * Get value method + * @Override + */ + BoxShadowInput.prototype.getValue = function() { + } + + /** + * Set focus to the input element + */ + BoxShadowInput.prototype.focus = function() { + this.$input.focus(); + }; + + function BoxShadowLength(parentRef, $parent, name, value, callback) { + BoxShadowInput.call(this, $parent, name); + + this.type = "lengths"; + this.$units = this.$el.find(".units-container li"); + this.$value = this.$el.find(".slider-value"); + this.num = 0; + this.unit = "px"; + this._callback = callback.bind(parentRef); + this._init(value); + }; + + BoxShadowLength.prototype = Object.create(BoxShadowInput.prototype); + BoxShadowLength.prototype.constructor = BoxShadowLength; + + /** + * Takes care of initialization stuff. !!Improve this comment. + */ + BoxShadowLength.prototype._init = function(value) { + this.setValue(value); + this.bindEvents(); + }; + + BoxShadowLength.prototype.bindEvents = function() { + var self = this; + self.$input.bind("input", function() { + self.handleInput(); + }); + + self.$units.bind("click", function() { + self.handleUnitChange(this); + }); + } + + /** + * @Override + * Method to handle input events. + */ + BoxShadowLength.prototype.handleInput = function() { + var value = this.$input.val().trim(); + this.num = value; + this._updateView(); + this._callback(this.type, this.name, this.getValue()); + }; + + BoxShadowLength.prototype.handleUnitChange = function(target) { + this.$units.removeClass("selected"); + + var newUnit = $(target).attr("class").split(" ")[0]; + $(target).addClass("selected"); + + this.unit = newUnit; + this._updateView(); + this._callback(this.type, this.name, this.getValue()); + }; + + /** + * @Override + * Sets the value to the input + */ + BoxShadowLength.prototype.setValue = function(value) { + + if(value) { + var num, unit, matches, lengthRegex; + lengthRegex = new RegExp(BoxShadowUtils.LENGTH_REGEX); + matches = lengthRegex.exec(value); + this.num = parseInt(matches[1]); + this.unit = matches[2]; + } + else { + this.num = 0; + this.unit = "px"; + } + + this._updateView(); + }; + + /** + * Get value method + * @Override + */ + BoxShadowLength.prototype.getValue = function() { + var result; + result = "".concat(this.num, this.unit); + return result; + } + + BoxShadowLength.prototype._updateView = function() { + this.$input.val(this.num); + + this.$value.text(this.getValue()); + + this.$units.removeClass("selected"); + + var targetClass = this.unit; + this.$units.each(function() { + if($(this).hasClass(targetClass)) { + $(this).addClass("selected"); + } + }); + } + + 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) { + 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 (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.BoxShadowInput = BoxShadowInput; + exports.BoxShadowLength = BoxShadowLength; + exports.BoxShadowColor = BoxShadowColor; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js new file mode 100644 index 00000000000..f49975fa759 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js @@ -0,0 +1,19 @@ +define(function(require, exports, module) { + "use strict"; + + var DEFAULT_BOX_SHADOW_VALUE = " 0px 0px 0px 0px black"; + + var BOX_SHADOW_REGEX = /((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))(\s+([a-z]+))?(\s+inset)?/g; + + var LENGTH_REGEX = /(?:(-?\d+)(px|em|%))/g; + + var LENGTH_TYPES = ["h-shadow", "v-shadow", "blur", "spread"]; + + var UNITS = ["px", "em", "%"]; + + exports.DEFAULT_BOX_SHADOW_VALUE = DEFAULT_BOX_SHADOW_VALUE; + exports.BOX_SHADOW_REGEX = BOX_SHADOW_REGEX; + exports.LENGTH_REGEX = LENGTH_REGEX; + exports.LENGTH_TYPES = LENGTH_TYPES; + exports.UNITS = UNITS; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 7728dee3f92..eae96ca3cd1 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -4,24 +4,30 @@ define(function(require, exports, module) { var InlineWidget = brackets.getModule("editor/InlineWidget").InlineWidget, BoxShadowEditor = require("BoxShadowEditor").BoxShadowEditor, ColorUtils = brackets.getModule("utils/ColorUtils"), + BoxShadowUtils = require("BoxShadowUtils"), boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; - /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ var lastOriginId = 1; /** * Inline widget containing a BoxShadowEditor control - * @param {!{horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string}} values Initial set of box-shadow values. + * The widget responds to changes in the text editor to the box-shadow string. Also, it is responsible for propagating changes + * from the box-shadow editor GUI to the text editor. + * @param {!String} boxShadowString Initial box-shadow string. * @param {!CodeMirror.TextMarker} marker */ - function InlineBoxShadowEditor(values, marker) { - this._values = values; + function InlineBoxShadowEditor(boxShadowString, marker) { + this._boxShadowString = boxShadowString; this._marker = marker; this._isOwnChange = false; this._isHostChange = false; this._origin = "+InlineBoxShadowEditor_" + (lastOriginId++); + // this._orderOfValues = ["lengths", "color", "inset"]; require to match the user's written values + this._values = {}; + this._extractValues(); + this._handleBoxShadowChange = this._handleBoxShadowChange.bind(this); this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this); @@ -35,7 +41,7 @@ define(function(require, exports, module) { /** @type {!BoxShadowPicker} BoxShadowPicker instance */ InlineBoxShadowEditor.prototype.BoxShadowEditor = null; - /** @type {!{ horizontalOffset: Number, verticalOffset: Number, blurRadius: Number, spreadRadius: Number, color: string }} Current value of the BoxShadow editor control */ + /** @type {!String} Current value of the box-shadow editor control */ InlineBoxShadowEditor.prototype._values = null; /** @@ -96,23 +102,74 @@ define(function(require, exports, module) { } }; - InlineBoxShadowEditor.prototype._buildBoxShadowString = function (values) { - var boxShadowString = boxShadowValueTypes.reduce(function(result, boxShadowValueType) { - if(!values[boxShadowValueType]) { - return result; + InlineBoxShadowEditor.prototype._extractValues = function() { + if(_isValidBoxShadowValue(this._boxShadowString) === false) { + return; + } + + var values = this._boxShadowString.trim().split(" "); + + var lengthTypes, lengthTypesIter, lengthType; + lengthTypes = BoxShadowUtils.LENGTH_TYPES; + lengthTypesIter = lengthTypes[Symbol.iterator](); + + // Default case of box-shadows. + this._values.inset = false; + this._values.lengths = {}; + + this._values = values.reduce(function(accumulator, currentValue, currentIndex) { + currentValue = currentValue.trim(); + + // Check for inset + if(currentValue === "inset") { + // **Feature to be added** + // accumulator.inset = true; } - if (!isNaN(values[boxShadowValueType]) ) { - result += " " + values[boxShadowValueType] + "px"; + // Check for color + else if(currentValue.match(ColorUtils.COLOR_REGEX)) { + accumulator.color = currentValue; } - else { - result += " " + values[boxShadowValueType]; + // Check for a length + else if(currentValue.match(BoxShadowUtils.LENGTH_REGEX)) { + lengthType = lengthTypesIter.next().value; + accumulator.lengths[lengthType] = currentValue; } - return result; - },""); - return boxShadowString.trim(); + return accumulator; + }, this._values); + + for(lengthType of lengthTypesIter) { + // this._values.lengths[lengthType] = "0px"; + // delete this._values.lengths[lengthType]; + } }; + InlineBoxShadowEditor.prototype._buildBoxShadowString = function () { + var self = this; + + var lengthTypes, boxShadowArr, boxShadowString; + lengthTypes = BoxShadowUtils.LENGTH_TYPES; + + boxShadowArr = lengthTypes.map(function(currentValue){ + return self._values.lengths[currentValue]; + }); + + // Filter out undefined values. + boxShadowArr = boxShadowArr.filter(function(currentValue) { + return currentValue; + }); + + if(self._values.color) { + boxShadowArr.push(self._values.color); + } + + if(self._values.inset === true) { + boxShadowArr.push("inset"); + } + + boxShadowString = boxShadowArr.join(" "); + return boxShadowString; + }; /** * When the BoxShadow editor's values change, update text in code editor @@ -125,23 +182,16 @@ define(function(require, exports, module) { return; } - // update values - for(var key in this._values) { - if(this._values.hasOwnProperty(key)) { - if(values[key] && values[key] !== this._values[key]) { - this._values[key] = values[key]; - } - } - } + this._values = values; // build the box-shadow value as a string. - var boxShadowString = this._buildBoxShadowString(this._values); - console.log(boxShadowString); + var boxShadowString = this._buildBoxShadowString(); var endPos = { line: range.start.line, ch: range.start.ch + boxShadowString.length }; + this._isOwnChange = true; this.hostEditor.document.batchOperation(function () { // Replace old box-shadow in code with the editor's box-shadow values, and select it @@ -201,8 +251,8 @@ define(function(require, exports, module) { }; function _isValidBoxShadowValue(value) { - // Need to improve this regex. - return (value.match(/\s*(\d+px\s+){0,3}?\d+px(?:\s+|;|)(?:#?[a-z]{3,}\s*)?;?/) !== null); + var boxShadowRegex = new RegExp(BoxShadowUtils.BOX_SHADOW_REGEX); + return boxShadowRegex.test(value); } /** @@ -217,34 +267,13 @@ define(function(require, exports, module) { var range = this.getCurrentRange(); if (range) { var newString = this.hostEditor.document.getRange(range.start, range.end); - - var flag = _isValidBoxShadowValue(newString); - if(_isValidBoxShadowValue(newString)) { // extract values - var newValues = {}; - var boxShadowValueIndex = 0; - - newString.split(/\s+/).forEach(function(value, index) { - value = value.trim(); - var colorMatch = value.match(ColorUtils.COLOR_REGEX); - var pixelMatch = value.match(/(\d+)px/); - console.log(colorMatch); - if(colorMatch) { - newValues["color"] = colorMatch[0]; - } - else if(pixelMatch){ - newValues[boxShadowValueTypes[boxShadowValueIndex++]] = value; - } - }); - console.log(newValues); - - if(newValues !== this._values) { - this._isHostChange = true; - this.boxShadowEditor.setValues(newValues); - this._values = newValues; - this._isHostChange = false; - } + this._boxShadowString = newString; + this._extractValues(); + this._isHostChange = true; + this.boxShadowEditor.setValues(this._values); + this._isHostChange = false; } } diff --git a/src/extensions/default/InlineBoxShadowEditor/css/style.less b/src/extensions/default/InlineBoxShadowEditor/css/style.less index ecd4ae27040..47593ae666d 100644 --- a/src/extensions/default/InlineBoxShadowEditor/css/style.less +++ b/src/extensions/default/InlineBoxShadowEditor/css/style.less @@ -1,62 +1,253 @@ @sansFontFamily: Helvetica, Arial, "Meiryo UI", "MS Pゴシック", "MS PGothic", sans-serif; .box-shadow-editor { - font-size: 12px; - min-width: 450px; - height: 190px; - padding: 16px 16px 14px 46px; -} -.box-shadow-editor:focus { - outline: none; + padding: 18px 16px 0 16px; + font-family: @sansFontFamily; + min-height: 220px; + + &:focus { + outline: none; + } + + header { + margin-bottom: 5px; + padding-bottom: 10px; + font-size: 14px; + } + + input { + margin: 0; + vertical-align: middle; + box-shadow: none; + width: 100%; + + &:focus { + outline: none; + } + } } -.box-shadow-editor section { - display: inline-block; - position: relative; - vertical-align: top; + +.box-shadow-editor table { + table-layout: fixed; + + tr:hover { + td { + background: rgba(0,0,0,.07); + } + + .corner-icon:after { + animation: pulse .3s ease-in-out infinite; + + @keyframes pulse { + 50% { + transform: scale(1.25); + } + } + } + } + + td { + padding: 10px; + border: none; + vertical-align: middle; + margin: 0; + font-size: 13px; + white-space: nowrap; + + &:first-child { + border-radius: 24px 0 0 24px; + } + + &:last-child { + border-radius: 0 24px 24px 0; + } + } + + td.slider-value { + width: 50px; + } + + td .button-bar { + position: relative; + top: -1px; + + li.selected a { + background-color: rgba(0,0,0,.4); + } + } + + .label-container { + width: 80px; + position: relative; + } + + .corner-icon { + width: 16px; + height: 11px; + border: solid 2px rgba(0,0,0,.2); + display: block; + margin: 0 5px 0 10px; + position: relative; + + &:not(.all):after { + content: ""; + position: absolute; + background: black; + width: 4px; + height: 4px; + border-radius: 50%; + } + + &.top-left:after { + top: -3px; + left: -3px; + } + + &.top-right:after { + top: -3px; + right: -3px; + } + + &.bottom-left:after { + bottom: -3px; + left: -3px; + } + + &.bottom-right:after { + bottom: -3px; + right: -3px; + } + + &.all .dot { + position: absolute; + background: black; + width: 4px; + height: 4px; + border-radius: 50%; + + &:nth-child(1) { + top: -3px; + left: -3px; + } + &:nth-child(2) { + top: -3px; + right: -3px; + } + &:nth-child(3) { + bottom: -3px; + left: -3px; + } + &:nth-child(4) { + bottom: -3px; + right: -3px; + } + + } + } + + .units-container { + padding-left: 0; + width: 120px; + + .button-bar { + li { + a { + padding: 5px 6px 6px 6px; + min-width: 18px; + } + } + } + } + + td label { + margin: 0; + cursor: default; + } } -.box-shadow-editor section .box-shadow-input { - display: block; - margin-bottom: 8px; - label { - display: inline-block; - min-width: 150px; +// Dark theme for the corner Icons +.dark .box-shadow-editor .corner-icon { + border: solid 2px rgba(255,255,255,.2); + + &:not(.all):after { + background: white; + } + + &.all .dot { + background: white; } } -.box-shadow-editor section #horizontal-offset-value, -.box-shadow-editor section #vertical-offset-value, -.box-shadow-editor section #blur-radius-value, -.box-shadow-editor section #spread-radius-value, -.box-shadow-editor section #color-value { - width: 118px; - height: 23px; - margin-right: 5px; - border-box-shadow: #b2b5b5; - box-sizing: border-box; - display: inline-block; - box-shadow: #222; +.dark .box-shadow-editor table { + td .button-bar li.selected a { + background-color: #404040; + } + + tr:hover { + td { + background: rgba(255,255,255,.08); + } + } + } -.box-shadow-editor section input { + +.box-shadow-editor ul.button-bar { display: inline-block; - height: 23px; - padding: 0 0 0 4px; - border: 1px solid #b2b5b5; - box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.06); - background: #fff; - font-family: @sansFontFamily; - font-size: 12px; - box-shadow: #454545; - border-radius: 3px; + padding: 0; margin: 0; - vertical-align: middle; + + li { + display: inline-block; + text-align: center; + } + + a { + text-decoration: none; + color: rgba(0,0,0,.4); + cursor: default; + display: block; + padding: 5px 12px 6px 12px; + border-radius: 14px; + transition: all .1s ease-out; + + + &:hover { + cursor: pointer; + } + } + + li:not(.selected) a { + &:hover { + color: rgba(0,0,0,.8); + background: rgba(0,0,0,.1); + } + } } -.box-shadow-editor section input:focus { - background: #fff; + +.dark .box-shadow-editor ul.button-bar { + a { + color: rgba(255,255,255,.4); + } + + li:not(.selected) a { + &:hover { + color: rgba(255,255,255,.8); + background: rgba(0,0,0,.4); + } + } +} + +.box-shadow-editor .button-bar a:focus, +.box-shadow-editor .button-bar li.selected a:focus { outline: none; - box-shadow: 0 0 0 1px #94ceff; - border: 1px solid #2893ef; - z-index: 911; + position: relative; + z-index: 999; +} + + +.box-shadow-editor .button-bar li.selected a { + background-color: #2492ba; + color: white; } // Dark UI theme @@ -93,4 +284,137 @@ box-shadow: 0 0 0 1px @dark-bc-btn-border-focused-glow; border: 1px solid @dark-bc-btn-border-focused; } -} \ No newline at end of file +} + +// Styles for custom Slider + +@track-color-dark: #444; +@track-color: rgba(0,0,0,.2); +@thumb-color: white; + +@thumb-radius: 12px; +@thumb-height: 24px; +@thumb-width: 24px; +@thumb-shadow-size: 1px; +@thumb-shadow-blur: 1px; +@thumb-shadow-color: #111; +@thumb-border-width: 1px; +@thumb-border-color: white; + +@track-width: 100%; +@track-height: 6px; +@track-shadow-size: 2px; +@track-shadow-blur: 2px; +@track-shadow-color: #222; +@track-border-width: 1px; +@track-border-color: black; + +@track-radius: 5px; +@contrast: 5%; + + +.track() { + width: @track-width; + height: @track-height; + cursor: pointer; + animate: 0.2s; +} + +.thumb() { + height: @thumb-height; + width: @thumb-width; + border-radius: @thumb-radius; + background: @thumb-color; + cursor: pointer; +} + +.box-shadow-editor input[type=range] { + -webkit-appearance: none; + margin: @thumb-height/2 0; + width: @track-width; + background-color: transparent; + + &:focus { + outline: none; + } + + &::-webkit-slider-runnable-track { + .track(); + background: @track-color; + border-radius: @track-radius; + } + + &::-webkit-slider-thumb { + .thumb(); + -webkit-appearance: none; + margin-top: ((-@track-border-width * 2 + @track-height) / 2) - (@thumb-height / 2); + } + + &:focus::-webkit-slider-runnable-track { + background: lighten(@track-color, @contrast); + } + + &::-moz-range-track { + .track(); + background: @track-color; + border-radius: @track-radius; + border: @track-border-width solid @track-border-color; + } + &::-moz-range-thumb { + .thumb(); + } + + &::-ms-track { + .track(); + background: transparent; + border-color: transparent; + border-width: @thumb-width 0; + color: transparent; + } + + &::-ms-fill-lower { + background: darken(@track-color, @contrast); + border: @track-border-width solid @track-border-color; + border-radius: @track-radius*2; + } + &::-ms-fill-upper { + background: @track-color; + border: @track-border-width solid @track-border-color; + border-radius: @track-radius*2; + } + &::-ms-thumb { + .thumb(); + } + &:focus::-ms-fill-lower { + background: @track-color; + } + &:focus::-ms-fill-upper { + background: lighten(@track-color, @contrast); + } +} + +.dark .box-shadow-editor input[type=range] { + + &::-webkit-slider-runnable-track { + background: @track-color-dark; + } + + + &::-moz-range-track { + background: @track-color-dark; + } + + + &::-ms-fill-lower { + background: darken(@track-color-dark, @contrast); + } + &::-ms-fill-upper { + background: @track-color-dark; + } + &:focus::-ms-fill-lower { + background: @track-color-dark; + } + &:focus::-ms-fill-upper { + background: lighten(@track-color-dark, @contrast); + } +} diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index bacd03e5b81..97987bc8211 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -5,10 +5,9 @@ define(function(require, exports, module) { ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), InlineBoxShadowEditor = require("InlineBoxShadowEditor").InlineBoxShadowEditor, ColorUtils = brackets.getModule("utils/ColorUtils"), + BoxShadowUtils = require("BoxShadowUtils"), boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; - var DEFAULT_VALUES = "0px 0px 0px 0px black"; - /** * Prepare hostEditor for an InlineBoxShadowEditor at pos if possible. Return * editor context if so; otherwise null. @@ -22,50 +21,48 @@ define(function(require, exports, module) { return null; } - var cursorLine, semiColonPos, colonPos, cursorLineSubstring, marker, values, isEmptyString, pos, firstCharacterPos, endPos, boxShadowValueIndex; - values = {}; + var cursorLine, semiColonPos, colonPos, endPos, cursorLineSubstring, marker, boxShadowString, isEmptyString, pos, firstCharacterPos, endPos, + boxShadowRegex; + + boxShadowRegex = new RegExp(BoxShadowUtils.BOX_SHADOW_REGEX); cursorLine = hostEditor.document.getLine(pos.line); colonPos = cursorLine.indexOf(":"); semiColonPos = cursorLine.indexOf(";"); - cursorLineSubstring = cursorLine.substring(colonPos + 1, cursorLine.length); + if(semiColonPos !== -1) { + endPos = semiColonPos; + } + else { + endPos = cursorLine.length; + } + + cursorLineSubstring = cursorLine.substring(colonPos + 1, endPos).trim(); // Get the initial set of values of box-shadow property - isEmptyString = true; - boxShadowValueIndex = 0; - cursorLineSubstring.split(/\s+/).forEach(function(value, index) { - value = value.trim(); - var colorMatch = value.match(ColorUtils.COLOR_REGEX); - var pixelMatch = value.match(/(\d+)px/); - console.log(value, colorMatch, pixelMatch); - if(colorMatch) { - values["color"] = colorMatch[0]; - isEmptyString = false; + isEmptyString = false; + + if(cursorLineSubstring.length === 0) { + isEmptyString = true; + boxShadowString = BoxShadowUtils.DEFAULT_BOX_SHADOW_VALUE; + } + else { + if(boxShadowRegex.test(cursorLineSubstring) === true) { + boxShadowString = cursorLineSubstring; } - else if(pixelMatch){ - values[boxShadowValueTypes[boxShadowValueIndex++]] = value; - isEmptyString = false; + else { + return null; } - }); - - console.log(isEmptyString); + } if(isEmptyString) { //Edit a new css rule. - var newText = " ", from ,to; - newText = newText.concat(DEFAULT_VALUES, ";"); + var from ,to, newText; from = {line: pos.line, ch: colonPos + 1}; to = {line: pos.line, ch: cursorLine.length}; + newText = boxShadowString.concat(";"); hostEditor._codeMirror.replaceRange(newText, from, to); pos.ch = colonPos + 2; - endPos = {line: pos.line, ch: pos.ch + DEFAULT_VALUES.length}; - values = { - "horizontalOffset": "0px", - "verticalOffset": "0px", - "blurRadius": "0px", - "spreadRadius": "0px", - "color": "black" - }; + endPos = {line: pos.line, ch: pos.ch + boxShadowString.length}; } else { firstCharacterPos = cursorLineSubstring.search(/\S/); @@ -80,10 +77,8 @@ define(function(require, exports, module) { marker = hostEditor._codeMirror.markText(pos, endPos); hostEditor.setSelection(pos, endPos); - console.log(values); - return { - values: values, + string: boxShadowString, marker: marker }; } @@ -106,7 +101,7 @@ define(function(require, exports, module) { return null; } else { - inlineBoxShadowEditor = new InlineBoxShadowEditor(context.values, context.marker); + inlineBoxShadowEditor = new InlineBoxShadowEditor(context.string, context.marker); inlineBoxShadowEditor.load(hostEditor); result = new $.Deferred(); From 27bfa8d72a7c034a1d90c28e053d9c59b45f71b3 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Thu, 8 Mar 2018 17:48:08 +0530 Subject: [PATCH 12/21] Fixed build errors --- .../default/InlineBoxShadowEditor/BoxShadowInputs.js | 8 ++++---- .../InlineBoxShadowEditor/InlineBoxShadowEditor.js | 5 ----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js index 7f2ac41cf71..efb5f320513 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js @@ -35,7 +35,7 @@ define(function(require, exports, module) { * @Override */ BoxShadowInput.prototype.getValue = function() { - } + }; /** * Set focus to the input element @@ -76,7 +76,7 @@ define(function(require, exports, module) { self.$units.bind("click", function() { self.handleUnitChange(this); }); - } + }; /** * @Override @@ -129,7 +129,7 @@ define(function(require, exports, module) { var result; result = "".concat(this.num, this.unit); return result; - } + }; BoxShadowLength.prototype._updateView = function() { this.$input.val(this.num); @@ -144,7 +144,7 @@ define(function(require, exports, module) { $(this).addClass("selected"); } }); - } + }; function BoxShadowColor(parentRef, $parent, name, value, callback) { BoxShadowInput.call(this, $parent, name); diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index eae96ca3cd1..b90fc9ca262 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -137,11 +137,6 @@ define(function(require, exports, module) { return accumulator; }, this._values); - - for(lengthType of lengthTypesIter) { - // this._values.lengths[lengthType] = "0px"; - // delete this._values.lengths[lengthType]; - } }; InlineBoxShadowEditor.prototype._buildBoxShadowString = function () { From 7bbd1443d02a57119976be1ffe2625b1e61683cb Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Thu, 8 Mar 2018 18:57:24 +0530 Subject: [PATCH 13/21] Changes to bramble-extensions.json file --- src/extensions/bramble-extensions.json | 37 ++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/extensions/bramble-extensions.json b/src/extensions/bramble-extensions.json index c10d7da17fc..ac5f31d3fc3 100644 --- a/src/extensions/bramble-extensions.json +++ b/src/extensions/bramble-extensions.json @@ -58,7 +58,41 @@ ] }, { + "path": "extensions/default/InlineBorderRadiusEditor", + "less": { + "dist/extensions/default/InlineBorderRadiusEditor/css/main.css": [ + "src/extensions/default/InlineBorderRadiusEditor/css/main.less" + ] + }, + "copy": [ + "extensions/default/InlineBorderRadiusEditor/img/*.png", + "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": { + "dist/extensions/default/InlineBoxModelEditor/css/main.css": [ + "src/extensions/default/InlineBoxModelEditor/css/main.less" ] + }, + "copy": [ + "extensions/default/InlineBoxModelEditor/img/*.png", + "extensions/default/InlineBoxModelEditor/BoxModelEditorTemplate.html" + ] + }, + { "path": "extensions/default/Inline3DParametersEditor", "less": { "dist/extensions/default/Inline3DParametersEditor/css/main.css": [ @@ -195,5 +229,4 @@ ] } } -] - +] \ No newline at end of file From 411be2bc5dc5086a7d970166b30cae90a9e6cd1b Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Thu, 8 Mar 2018 19:23:03 +0530 Subject: [PATCH 14/21] Removed unnecessary file - boxShadowValueTypes.json and changed Symbol.iterator to simple counter over array --- .../InlineBoxShadowEditor/BoxShadowValueTypes.json | 9 --------- .../InlineBoxShadowEditor/InlineBoxShadowEditor.js | 11 ++++++----- src/extensions/default/InlineBoxShadowEditor/main.js | 3 +-- 3 files changed, 7 insertions(+), 16 deletions(-) delete mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json b/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json deleted file mode 100644 index 866a25af220..00000000000 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowValueTypes.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "boxShadowValueTypes": [ - "horizontalOffset", - "verticalOffset", - "blurRadius", - "spreadRadius", - "color" - ] -} \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index b90fc9ca262..dfd0f7dc58f 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -4,8 +4,7 @@ define(function(require, exports, module) { var InlineWidget = brackets.getModule("editor/InlineWidget").InlineWidget, BoxShadowEditor = require("BoxShadowEditor").BoxShadowEditor, ColorUtils = brackets.getModule("utils/ColorUtils"), - BoxShadowUtils = require("BoxShadowUtils"), - boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + BoxShadowUtils = require("BoxShadowUtils"); /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ var lastOriginId = 1; @@ -111,7 +110,7 @@ define(function(require, exports, module) { var lengthTypes, lengthTypesIter, lengthType; lengthTypes = BoxShadowUtils.LENGTH_TYPES; - lengthTypesIter = lengthTypes[Symbol.iterator](); + lengthTypesIter = 0; // Default case of box-shadows. this._values.inset = false; @@ -131,8 +130,10 @@ define(function(require, exports, module) { } // Check for a length else if(currentValue.match(BoxShadowUtils.LENGTH_REGEX)) { - lengthType = lengthTypesIter.next().value; - accumulator.lengths[lengthType] = currentValue; + if(lengthTypesIter < lengthTypes.length) { + lengthType = lengthTypes[lengthTypesIter++]; + accumulator.lengths[lengthType] = currentValue; + } } return accumulator; diff --git a/src/extensions/default/InlineBoxShadowEditor/main.js b/src/extensions/default/InlineBoxShadowEditor/main.js index 97987bc8211..ac96f0b1e29 100644 --- a/src/extensions/default/InlineBoxShadowEditor/main.js +++ b/src/extensions/default/InlineBoxShadowEditor/main.js @@ -5,8 +5,7 @@ define(function(require, exports, module) { ExtensionUtils = brackets.getModule("utils/ExtensionUtils"), InlineBoxShadowEditor = require("InlineBoxShadowEditor").InlineBoxShadowEditor, ColorUtils = brackets.getModule("utils/ColorUtils"), - BoxShadowUtils = require("BoxShadowUtils"), - boxShadowValueTypes = JSON.parse(require("text!BoxShadowValueTypes.json")).boxShadowValueTypes; + BoxShadowUtils = require("BoxShadowUtils"); /** * Prepare hostEditor for an InlineBoxShadowEditor at pos if possible. Return From a63b2336c7e78a336c5ddc1d5ee43246dc83d35f Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 10 Mar 2018 11:35:45 +0530 Subject: [PATCH 15/21] Increased slider width and reduced the input range --- .../InlineBoxShadowEditor/BoxShadowEditorTemplate.html | 8 ++++---- .../default/InlineBoxShadowEditor/css/style.less | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html index 86bc7b565e6..73388568343 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -6,7 +6,7 @@ Horizontal - + @@ -31,7 +31,7 @@ Vertical - + @@ -56,7 +56,7 @@ Blur - + @@ -81,7 +81,7 @@ Spread - + diff --git a/src/extensions/default/InlineBoxShadowEditor/css/style.less b/src/extensions/default/InlineBoxShadowEditor/css/style.less index 47593ae666d..385e6bbc473 100644 --- a/src/extensions/default/InlineBoxShadowEditor/css/style.less +++ b/src/extensions/default/InlineBoxShadowEditor/css/style.less @@ -29,6 +29,7 @@ .box-shadow-editor table { table-layout: fixed; + width: 100%; tr:hover { td { From b3f04f1972137cda2b2fce98c8cb8edc406cc1c3 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 10 Mar 2018 12:27:20 +0530 Subject: [PATCH 16/21] Separated BoxShadowLength and Color into different files --- .../InlineBoxShadowEditor/BoxShadowColor.js | 95 +++++++ .../InlineBoxShadowEditor/BoxShadowEditor.js | 6 +- .../InlineBoxShadowEditor/BoxShadowInput.js | 40 +++ .../InlineBoxShadowEditor/BoxShadowInputs.js | 236 ------------------ .../InlineBoxShadowEditor/BoxShadowLength.js | 113 +++++++++ 5 files changed, 250 insertions(+), 240 deletions(-) create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowInput.js delete mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js new file mode 100644 index 00000000000..2dc2da960a7 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js @@ -0,0 +1,95 @@ +define(function(require, exports, module) { + "use strict"; + + var BoxShadowInput = require("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) { + 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 (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; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index 7f738d46c24..9becdf8905c 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -6,15 +6,13 @@ define(function(require, exports, module) { StringUtils = brackets.getModule("utils/StringUtils"), Strings = brackets.getModule("strings"), Mustache = brackets.getModule("thirdparty/mustache/mustache"), - BoxShadowInputs = require("BoxShadowInputs"), + BoxShadowLength = require("BoxShadowLength"), + BoxShadowColor = require("BoxShadowColor"), BoxShadowUtils = require("BoxShadowUtils"); /** Mustache template that forms the bare DOM structure of the UI */ var BoxShadowEditorTemplate = require("text!BoxShadowEditorTemplate.html"); - var BoxShadowLength = BoxShadowInputs.BoxShadowLength, - BoxShadowColor = BoxShadowInputs.BoxShadowColor; - /** * 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 diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowInput.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInput.js new file mode 100644 index 00000000000..ef20b488cce --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInput.js @@ -0,0 +1,40 @@ +define(function(require, exports, module) { + "use strict"; + + function BoxShadowInput($parent, name) { + this.name = name; + this.$parent = $parent; + this.$el = $parent.find("#" + this.name); + this.$input = this.$el.find("input"); + }; + + /** + * @Override + * Method to handle input events. + */ + BoxShadowInput.prototype.handleInput = function() { + }; + + /** + * @Override + * Sets the value to the input + */ + BoxShadowInput.prototype.setValue = function(string) { + }; + + /** + * Get value method + * @Override + */ + BoxShadowInput.prototype.getValue = function() { + }; + + /** + * Set focus to the input element + */ + BoxShadowInput.prototype.focus = function() { + this.$input.focus(); + }; + + exports.BoxShadowInput = BoxShadowInput; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js deleted file mode 100644 index efb5f320513..00000000000 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowInputs.js +++ /dev/null @@ -1,236 +0,0 @@ -define(function(require, exports, module) { - "use strict"; - - var BoxShadowUtils = require("BoxShadowUtils"), - ColorUtils = brackets.getModule("utils/ColorUtils"), - tinycolor = require("thirdparty/tinycolor-min"); - - var units = BoxShadowUtils.UNITS; - - var DEFAULT_COLOR = "black"; - - function BoxShadowInput($parent, name) { - this.name = name; - this.$parent = $parent; - this.$el = $parent.find("#" + this.name); - this.$input = this.$el.find("input"); - }; - - /** - * @Override - * Method to handle input events. - */ - BoxShadowInput.prototype.handleInput = function() { - }; - - /** - * @Override - * Sets the value to the input - */ - BoxShadowInput.prototype.setValue = function(string) { - }; - - /** - * Get value method - * @Override - */ - BoxShadowInput.prototype.getValue = function() { - }; - - /** - * Set focus to the input element - */ - BoxShadowInput.prototype.focus = function() { - this.$input.focus(); - }; - - function BoxShadowLength(parentRef, $parent, name, value, callback) { - BoxShadowInput.call(this, $parent, name); - - this.type = "lengths"; - this.$units = this.$el.find(".units-container li"); - this.$value = this.$el.find(".slider-value"); - this.num = 0; - this.unit = "px"; - this._callback = callback.bind(parentRef); - this._init(value); - }; - - BoxShadowLength.prototype = Object.create(BoxShadowInput.prototype); - BoxShadowLength.prototype.constructor = BoxShadowLength; - - /** - * Takes care of initialization stuff. !!Improve this comment. - */ - BoxShadowLength.prototype._init = function(value) { - this.setValue(value); - this.bindEvents(); - }; - - BoxShadowLength.prototype.bindEvents = function() { - var self = this; - self.$input.bind("input", function() { - self.handleInput(); - }); - - self.$units.bind("click", function() { - self.handleUnitChange(this); - }); - }; - - /** - * @Override - * Method to handle input events. - */ - BoxShadowLength.prototype.handleInput = function() { - var value = this.$input.val().trim(); - this.num = value; - this._updateView(); - this._callback(this.type, this.name, this.getValue()); - }; - - BoxShadowLength.prototype.handleUnitChange = function(target) { - this.$units.removeClass("selected"); - - var newUnit = $(target).attr("class").split(" ")[0]; - $(target).addClass("selected"); - - this.unit = newUnit; - this._updateView(); - this._callback(this.type, this.name, this.getValue()); - }; - - /** - * @Override - * Sets the value to the input - */ - BoxShadowLength.prototype.setValue = function(value) { - - if(value) { - var num, unit, matches, lengthRegex; - lengthRegex = new RegExp(BoxShadowUtils.LENGTH_REGEX); - matches = lengthRegex.exec(value); - this.num = parseInt(matches[1]); - this.unit = matches[2]; - } - else { - this.num = 0; - this.unit = "px"; - } - - this._updateView(); - }; - - /** - * Get value method - * @Override - */ - BoxShadowLength.prototype.getValue = function() { - var result; - result = "".concat(this.num, this.unit); - return result; - }; - - BoxShadowLength.prototype._updateView = function() { - this.$input.val(this.num); - - this.$value.text(this.getValue()); - - this.$units.removeClass("selected"); - - var targetClass = this.unit; - this.$units.each(function() { - if($(this).hasClass(targetClass)) { - $(this).addClass("selected"); - } - }); - }; - - 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) { - 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 (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.BoxShadowInput = BoxShadowInput; - exports.BoxShadowLength = BoxShadowLength; - exports.BoxShadowColor = BoxShadowColor; -}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js new file mode 100644 index 00000000000..369abe55bb8 --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js @@ -0,0 +1,113 @@ +define(function(require, exports, module) { + "use strict"; + + var BoxShadowInput = require("BoxShadowInput"), + BoxShadowUtils = require("BoxShadowUtils"); + + var units = BoxShadowUtils.UNITS; + + function BoxShadowLength(parentRef, $parent, name, value, callback) { + BoxShadowInput.call(this, $parent, name); + + this.type = "lengths"; + this.$units = this.$el.find(".units-container li"); + this.$value = this.$el.find(".slider-value"); + this.num = 0; + this.unit = "px"; + this._callback = callback.bind(parentRef); + this._init(value); + }; + + BoxShadowLength.prototype = Object.create(BoxShadowInput.prototype); + BoxShadowLength.prototype.constructor = BoxShadowLength; + + /** + * Takes care of initialization stuff. !!Improve this comment. + */ + BoxShadowLength.prototype._init = function(value) { + this.setValue(value); + this.bindEvents(); + }; + + BoxShadowLength.prototype.bindEvents = function() { + var self = this; + self.$input.bind("input", function() { + self.handleInput(); + }); + + self.$units.bind("click", function() { + self.handleUnitChange(this); + }); + }; + + /** + + * @Override + * Method to handle input events. + */ + BoxShadowLength.prototype.handleInput = function() { + var value = this.$input.val().trim(); + this.num = value; + this._updateView(); + this._callback(this.type, this.name, this.getValue()); + }; + + BoxShadowLength.prototype.handleUnitChange = function(target) { + this.$units.removeClass("selected"); + + var newUnit = $(target).attr("class").split(" ")[0]; + $(target).addClass("selected"); + + this.unit = newUnit; + this._updateView(); + this._callback(this.type, this.name, this.getValue()); + }; + + /** + * @Override + * Sets the value to the input + */ + BoxShadowLength.prototype.setValue = function(value) { + + if(value) { + var num, unit, matches, lengthRegex; + lengthRegex = new RegExp(BoxShadowUtils.LENGTH_REGEX); + matches = lengthRegex.exec(value); + this.num = parseInt(matches[1]); + this.unit = matches[2]; + } + else { + this.num = 0; + this.unit = "px"; + } + + this._updateView(); + }; + + /** + * Get value method + * @Override + */ + BoxShadowLength.prototype.getValue = function() { + var result; + result = "".concat(this.num, this.unit); + return result; + }; + + BoxShadowLength.prototype._updateView = function() { + this.$input.val(this.num); + + this.$value.text(this.getValue()); + + this.$units.removeClass("selected"); + + var targetClass = this.unit; + this.$units.each(function() { + if($(this).hasClass(targetClass)) { + $(this).addClass("selected"); + } + }); + }; + + exports.BoxShadowLength = BoxShadowLength; +}); \ No newline at end of file From ec3c64f308fa6b14426c2fd25603c0bf0b4763b1 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 10 Mar 2018 13:17:43 +0530 Subject: [PATCH 17/21] Fixed imports Earlier, the BoxShadowEditor, BoxShadowLength, BoxShadowColor were importing and using the complete exports objects. Fixed by requiring only the component. eg. changed `require("BoxShadowInput")` to `require("BoxShadowInput").BoxShadowInput`; --- .../default/InlineBoxShadowEditor/BoxShadowColor.js | 2 +- .../default/InlineBoxShadowEditor/BoxShadowEditor.js | 4 ++-- .../default/InlineBoxShadowEditor/BoxShadowLength.js | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js index 2dc2da960a7..95cabbdfc6b 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js @@ -1,7 +1,7 @@ define(function(require, exports, module) { "use strict"; - var BoxShadowInput = require("BoxShadowInput"), + var BoxShadowInput = require("BoxShadowInput").BoxShadowInput, ColorUtils = brackets.getModule("utils/ColorUtils"), tinycolor = require("thirdparty/tinycolor-min"); diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index 9becdf8905c..975eec5c3fc 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -6,8 +6,8 @@ define(function(require, exports, module) { StringUtils = brackets.getModule("utils/StringUtils"), Strings = brackets.getModule("strings"), Mustache = brackets.getModule("thirdparty/mustache/mustache"), - BoxShadowLength = require("BoxShadowLength"), - BoxShadowColor = require("BoxShadowColor"), + BoxShadowLength = require("BoxShadowLength").BoxShadowLength, + BoxShadowColor = require("BoxShadowColor").BoxShadowColor, BoxShadowUtils = require("BoxShadowUtils"); /** Mustache template that forms the bare DOM structure of the UI */ diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js index 369abe55bb8..d8944d97404 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js @@ -1,7 +1,7 @@ define(function(require, exports, module) { "use strict"; - var BoxShadowInput = require("BoxShadowInput"), + var BoxShadowInput = require("BoxShadowInput").BoxShadowInput, BoxShadowUtils = require("BoxShadowUtils"); var units = BoxShadowUtils.UNITS; @@ -18,6 +18,7 @@ define(function(require, exports, module) { this._init(value); }; + console.log(BoxShadowInput); BoxShadowLength.prototype = Object.create(BoxShadowInput.prototype); BoxShadowLength.prototype.constructor = BoxShadowLength; From 3d1a4c5a956bd35db08f20075cabfd3a8cd02fae Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 10 Mar 2018 22:11:06 +0530 Subject: [PATCH 18/21] Added inset functionality to box-shadow editor Created BoxShadowInset that responds and provides control over `inset` property in box-shadow --- .../InlineBoxShadowEditor/BoxShadowEditor.js | 5 +- .../BoxShadowEditorTemplate.html | 13 +- .../InlineBoxShadowEditor/BoxShadowInset.js | 74 +++++++++++ .../InlineBoxShadowEditor/BoxShadowLength.js | 1 - .../InlineBoxShadowEditor.js | 3 +- .../InlineBoxShadowEditor/css/style.less | 118 ++++++++---------- 6 files changed, 140 insertions(+), 74 deletions(-) create mode 100644 src/extensions/default/InlineBoxShadowEditor/BoxShadowInset.js diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js index 975eec5c3fc..f870017b490 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditor.js @@ -8,6 +8,7 @@ define(function(require, exports, module) { 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 */ @@ -63,6 +64,7 @@ define(function(require, exports, module) { 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) { @@ -75,7 +77,8 @@ define(function(require, exports, module) { 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 = this.$element.find("#inset"); + + this.inset = new BoxShadowInset(this, this.$element, "inset", values["inset"], this.handleChanges); }; BoxShadowEditor.prototype.focus = function() { diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html index 73388568343..aec305b4072 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -110,15 +110,16 @@ - + -
\ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowInset.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInset.js new file mode 100644 index 00000000000..6225f6e5b0b --- /dev/null +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowInset.js @@ -0,0 +1,74 @@ +define(function(require, exports, module) { + "use strict"; + + var BoxShadowInput = require("BoxShadowInput").BoxShadowInput, + BoxShadowUtils = require("BoxShadowUtils"); + + var units = BoxShadowUtils.UNITS; + + function BoxShadowInset(parentRef, $parent, name, value, callback) { + BoxShadowInput.call(this, $parent, name); + + this.type = "inset"; + this.value = false; + + this._callback = callback.bind(parentRef); + this._init(value); + }; + + BoxShadowInset.prototype = Object.create(BoxShadowInput.prototype); + BoxShadowInset.prototype.constructor = BoxShadowInset; + + /** + * Takes care of initialization stuff. !!Improve this comment. + */ + BoxShadowInset.prototype._init = function(value) { + this.setValue(value); + this.bindEvents(); + }; + + BoxShadowInset.prototype.bindEvents = function() { + var self = this; + self.$input.bind("change", function() { + self.handleInput(); + }); + }; + + /** + + * @Override + * Method to handle input events. + */ + BoxShadowInset.prototype.handleInput = function(value) { + if(this.$input.is(":checked") === true) { + this.value = true; + } + else { + this.value = false; + } + this._callback(this.type, this.name, this.getValue()); + }; + + /** + * @Override + * Sets the value to the input + */ + BoxShadowInset.prototype.setValue = function(value) { + this.value = value; + this._updateView(); + }; + + /** + * Get value method + * @Override + */ + BoxShadowInset.prototype.getValue = function() { + return this.value; + }; + + BoxShadowInset.prototype._updateView = function() { + this.$input.prop("checked", this.value); + }; + + exports.BoxShadowInset = BoxShadowInset; +}); \ No newline at end of file diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js index d8944d97404..6c0776893b2 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowLength.js @@ -18,7 +18,6 @@ define(function(require, exports, module) { this._init(value); }; - console.log(BoxShadowInput); BoxShadowLength.prototype = Object.create(BoxShadowInput.prototype); BoxShadowLength.prototype.constructor = BoxShadowLength; diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index dfd0f7dc58f..4c6af92ee20 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -121,8 +121,7 @@ define(function(require, exports, module) { // Check for inset if(currentValue === "inset") { - // **Feature to be added** - // accumulator.inset = true; + accumulator.inset = true; } // Check for color else if(currentValue.match(ColorUtils.COLOR_REGEX)) { diff --git a/src/extensions/default/InlineBoxShadowEditor/css/style.less b/src/extensions/default/InlineBoxShadowEditor/css/style.less index 385e6bbc473..559dbb90d2d 100644 --- a/src/extensions/default/InlineBoxShadowEditor/css/style.less +++ b/src/extensions/default/InlineBoxShadowEditor/css/style.less @@ -82,70 +82,6 @@ position: relative; } - .corner-icon { - width: 16px; - height: 11px; - border: solid 2px rgba(0,0,0,.2); - display: block; - margin: 0 5px 0 10px; - position: relative; - - &:not(.all):after { - content: ""; - position: absolute; - background: black; - width: 4px; - height: 4px; - border-radius: 50%; - } - - &.top-left:after { - top: -3px; - left: -3px; - } - - &.top-right:after { - top: -3px; - right: -3px; - } - - &.bottom-left:after { - bottom: -3px; - left: -3px; - } - - &.bottom-right:after { - bottom: -3px; - right: -3px; - } - - &.all .dot { - position: absolute; - background: black; - width: 4px; - height: 4px; - border-radius: 50%; - - &:nth-child(1) { - top: -3px; - left: -3px; - } - &:nth-child(2) { - top: -3px; - right: -3px; - } - &:nth-child(3) { - bottom: -3px; - left: -3px; - } - &:nth-child(4) { - bottom: -3px; - right: -3px; - } - - } - } - .units-container { padding-left: 0; width: 120px; @@ -313,6 +249,7 @@ @track-radius: 5px; @contrast: 5%; +@toggle-width: 48px; .track() { width: @track-width; @@ -394,6 +331,59 @@ } } +.box-shadow-editor .toggle-switch-container { + .toggle-switch { + position: relative; + display: inline-block; + width: @toggle-width; + height: @thumb-height; + } + + input { + display: none; + } + + .toggle-switch-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + border-radius: 24px; + -webkit-transition: .4s; + transition: .4s; + } + + .toggle-switch-slider:before { + position: absolute; + content: ""; + height: @thumb-height - 4px; + width: @thumb-width - 4px; + top: 2px; + left: 2px; + background-color: white; + border-radius: 50%; + -webkit-transition: .4s; + transition: .4s; + } + + input:checked + .toggle-switch-slider { + background-color: #2196F3; + } + + input:focus + .toggle-switch-slider { + box-shadow: 0 0 1px #2196F3; + } + + input:checked + .toggle-switch-slider:before { + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); + } +} + .dark .box-shadow-editor input[type=range] { &::-webkit-slider-runnable-track { From 8b22e23dbf62c2c8644e35340077bdaa6c700037 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sat, 10 Mar 2018 23:41:40 +0530 Subject: [PATCH 19/21] Modified regex --- src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js index f49975fa759..08cdbce7056 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js @@ -3,7 +3,7 @@ define(function(require, exports, module) { var DEFAULT_BOX_SHADOW_VALUE = " 0px 0px 0px 0px black"; - var BOX_SHADOW_REGEX = /((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))(\s+([a-z]+))?(\s+inset)?/g; + var BOX_SHADOW_REGEX = /((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))(\s+([a-z]+))?(\s+inset)?|(inset\s+)?((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))(\s+([a-z]+))?|(([a-z]+)\s+)?((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))(\s+inset)?|(inset\s+)?(([a-z]+)\s+)?((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))/g; var LENGTH_REGEX = /(?:(-?\d+)(px|em|%))/g; From 431bf6ada6fda44ec0b2821bc1428e8fdf26a2c2 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Sun, 11 Mar 2018 00:25:39 +0530 Subject: [PATCH 20/21] User provided order of values is preserved while changing value in the box-shadow editor InlineBoxShadowEditor uses a `orderOfValues` to preseve the user provided order of values while building the boxShadowString when changes are made in widget. Note: Changes to BoxShadowEditorTemplate.html - renaming `slider-container` to `color-container` for color input Changes to style.less - translation of toggle by amount of its width --- .../BoxShadowEditorTemplate.html | 2 +- .../InlineBoxShadowEditor/BoxShadowUtils.js | 3 + .../InlineBoxShadowEditor.js | 56 ++++++++++++++----- .../InlineBoxShadowEditor/css/style.less | 6 +- 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html index aec305b4072..93468a7c809 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowEditorTemplate.html @@ -105,7 +105,7 @@ Color - + diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js index 08cdbce7056..d488d42c0d7 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowUtils.js @@ -2,6 +2,8 @@ define(function(require, exports, module) { "use strict"; var DEFAULT_BOX_SHADOW_VALUE = " 0px 0px 0px 0px black"; + + var DEFAULT_ORDER_OF_VALUES = ["lengths", "color", "inset"]; var BOX_SHADOW_REGEX = /((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))(\s+([a-z]+))?(\s+inset)?|(inset\s+)?((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))(\s+([a-z]+))?|(([a-z]+)\s+)?((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))(\s+inset)?|(inset\s+)?(([a-z]+)\s+)?((-?\d+)(px|em|%)\s+){1,3}?((-?\d+)(px|em|%))/g; @@ -12,6 +14,7 @@ define(function(require, exports, module) { var UNITS = ["px", "em", "%"]; exports.DEFAULT_BOX_SHADOW_VALUE = DEFAULT_BOX_SHADOW_VALUE; + exports.DEFAULT_ORDER_OF_VALUES = DEFAULT_ORDER_OF_VALUES; exports.BOX_SHADOW_REGEX = BOX_SHADOW_REGEX; exports.LENGTH_REGEX = LENGTH_REGEX; exports.LENGTH_TYPES = LENGTH_TYPES; diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 4c6af92ee20..008286e7719 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -9,6 +9,8 @@ define(function(require, exports, module) { /** @type {number} Global var used to provide a unique ID for each box-shadow editor instance's _origin field. */ var lastOriginId = 1; + var defaultOrder = BoxShadowUtils.DEFAULT_ORDER_OF_VALUES; + /** * Inline widget containing a BoxShadowEditor control * The widget responds to changes in the text editor to the box-shadow string. Also, it is responsible for propagating changes @@ -23,8 +25,9 @@ define(function(require, exports, module) { this._isHostChange = false; this._origin = "+InlineBoxShadowEditor_" + (lastOriginId++); - // this._orderOfValues = ["lengths", "color", "inset"]; require to match the user's written values this._values = {}; + // orderOfValues can be either "lengths", "color" or "inset" + this._orderOfValues = []; this._extractValues(); this._handleBoxShadowChange = this._handleBoxShadowChange.bind(this); @@ -102,6 +105,8 @@ define(function(require, exports, module) { }; InlineBoxShadowEditor.prototype._extractValues = function() { + var self = this; + if(_isValidBoxShadowValue(this._boxShadowString) === false) { return; } @@ -115,53 +120,74 @@ define(function(require, exports, module) { // Default case of box-shadows. this._values.inset = false; this._values.lengths = {}; - + this._orderOfValues = []; this._values = values.reduce(function(accumulator, currentValue, currentIndex) { currentValue = currentValue.trim(); // Check for inset if(currentValue === "inset") { + self._orderOfValues.push("inset"); accumulator.inset = true; } // Check for color else if(currentValue.match(ColorUtils.COLOR_REGEX)) { + self._orderOfValues.push("color"); accumulator.color = currentValue; } // Check for a length else if(currentValue.match(BoxShadowUtils.LENGTH_REGEX)) { if(lengthTypesIter < lengthTypes.length) { + if(self._orderOfValues.includes("lengths") === false) { + self._orderOfValues.push("lengths"); + } lengthType = lengthTypes[lengthTypesIter++]; accumulator.lengths[lengthType] = currentValue; } + else { + console.error("InlineBoxShadowEditor:: Too many length values for box-shadow."); + } } return accumulator; }, this._values); + + for(var i = 0;i < defaultOrder.length;i++) { + var orderValue = defaultOrder[i]; + if(this._orderOfValues.includes(orderValue) === false) { + this._orderOfValues.push(orderValue); + } + } }; InlineBoxShadowEditor.prototype._buildBoxShadowString = function () { var self = this; - var lengthTypes, boxShadowArr, boxShadowString; - lengthTypes = BoxShadowUtils.LENGTH_TYPES; + var boxShadowArr = []; - boxShadowArr = lengthTypes.map(function(currentValue){ - return self._values.lengths[currentValue]; - }); + for(var i = 0;i < this._orderOfValues.length;i++) { + var orderValue = this._orderOfValues[i]; + if(orderValue === "lengths") { + var lengthTypes, boxShadowArr, boxShadowString; + lengthTypes = BoxShadowUtils.LENGTH_TYPES; + + boxShadowArr = lengthTypes.reduce(function(accumulator, currentValue){ + accumulator.push(self._values.lengths[currentValue]); + return accumulator; + }, boxShadowArr); + } + else if(orderValue === "color" && self._values.color) { + boxShadowArr.push(self._values.color); + } + else if(orderValue === "inset" && self._values.inset === true) { + boxShadowArr.push("inset"); + } + } // Filter out undefined values. boxShadowArr = boxShadowArr.filter(function(currentValue) { return currentValue; }); - if(self._values.color) { - boxShadowArr.push(self._values.color); - } - - if(self._values.inset === true) { - boxShadowArr.push("inset"); - } - boxShadowString = boxShadowArr.join(" "); return boxShadowString; }; diff --git a/src/extensions/default/InlineBoxShadowEditor/css/style.less b/src/extensions/default/InlineBoxShadowEditor/css/style.less index 559dbb90d2d..ca4cbbc6cbf 100644 --- a/src/extensions/default/InlineBoxShadowEditor/css/style.less +++ b/src/extensions/default/InlineBoxShadowEditor/css/style.less @@ -378,9 +378,9 @@ } input:checked + .toggle-switch-slider:before { - -webkit-transform: translateX(26px); - -ms-transform: translateX(26px); - transform: translateX(26px); + -webkit-transform: translateX(@thumb-width); + -ms-transform: translateX(@thumb-width); + transform: translateX(@thumb-width); } } From b82cfb48e32d8f207798bf65e5955507cf10c769 Mon Sep 17 00:00:00 2001 From: Yogesh Gupta Date: Fri, 23 Mar 2018 00:24:16 +0530 Subject: [PATCH 21/21] Added fixes to handle cases where `color` property is equal to `""` --- .../default/InlineBoxShadowEditor/BoxShadowColor.js | 8 +++++++- .../InlineBoxShadowEditor/InlineBoxShadowEditor.js | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js b/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js index 95cabbdfc6b..4c9b684be7d 100644 --- a/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js +++ b/src/extensions/default/InlineBoxShadowEditor/BoxShadowColor.js @@ -50,6 +50,9 @@ define(function(require, exports, module) { * @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) @@ -76,7 +79,10 @@ define(function(require, exports, module) { // 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 (newColorOk) { + if(newColor.length === 0) { + newColorOk = true; + } + else if (newColorOk) { newColorOk = (newColorObj.toString() === this._normalizeColorString(newColor)); } diff --git a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js index 008286e7719..7369bae1663 100644 --- a/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js +++ b/src/extensions/default/InlineBoxShadowEditor/InlineBoxShadowEditor.js @@ -119,6 +119,7 @@ define(function(require, exports, module) { // Default case of box-shadows. this._values.inset = false; + this._values.color = ""; this._values.lengths = {}; this._orderOfValues = []; this._values = values.reduce(function(accumulator, currentValue, currentIndex) {