Bug 1199579 - Eslint cleanup of inplace-editor r=pbro

This commit is contained in:
Gabriel Luong 2015-08-28 21:23:51 -07:00
Родитель 9cf6796e0e
Коммит d16bce4b19
1 изменённых файлов: 210 добавлений и 227 удалений

Просмотреть файл

@ -1,11 +1,12 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals focusManager, CSSPropertyList, domUtils */
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Basic use:
* let spanToEdit = document.getElementById("somespan");
*
@ -48,28 +49,28 @@ Cu.import("resource://gre/modules/devtools/event-emitter.js");
* Changes will be committed when the InlineEditor's input is blurred
* or dropped when the user presses escape.
*
* @param {object} aOptions
* @param {object} options
* Options for the editable field, including:
* {Element} element:
* (required) The span to be edited on focus.
* {function} canEdit:
* {Function} canEdit:
* Will be called before creating the inplace editor. Editor
* won't be created if canEdit returns false.
* {function} start:
* {Function} start:
* Will be called when the inplace editor is initialized.
* {function} change:
* {Function} change:
* Will be called when the text input changes. Will be called
* with the current value of the text input.
* {function} done:
* {Function} done:
* Called when input is committed or blurred. Called with
* current value, a boolean telling the caller whether to
* commit the change, and the direction of the next element to be
* selected. Direction may be one of nsIFocusManager.MOVEFOCUS_FORWARD,
* nsIFocusManager.MOVEFOCUS_BACKWARD, or null (no movement).
* This function is called before the editor has been torn down.
* {function} destroy:
* {Function} destroy:
* Called when the editor is destroyed and has been torn down.
* {object} advanceChars:
* {Object} advanceChars:
* This can be either a string or a function.
* If it is a string, then if any characters in it are typed,
* focus will advance to the next element.
@ -78,27 +79,26 @@ Cu.import("resource://gre/modules/devtools/event-emitter.js");
* and the insertion point. If the function returns true,
* then the focus advance takes place. If it returns false,
* then the character is inserted instead.
* {boolean} stopOnReturn:
* {Boolean} stopOnReturn:
* If true, the return key will not advance the editor to the next
* focusable element.
* {boolean} stopOnTab:
* {Boolean} stopOnTab:
* If true, the tab key will not advance the editor to the next
* focusable element.
* {boolean} stopOnShiftTab:
* {Boolean} stopOnShiftTab:
* If true, shift tab will not advance the editor to the previous
* focusable element.
* {string} trigger: The DOM event that should trigger editing,
* {String} trigger: The DOM event that should trigger editing,
* defaults to "click"
* {boolean} multiline: Should the editor be a multiline textarea?
* {Boolean} multiline: Should the editor be a multiline textarea?
* defaults to false
* {boolean} trimOutput: Should the returned string be trimmed?
* {Boolean} trimOutput: Should the returned string be trimmed?
* defaults to true
*/
function editableField(aOptions)
{
return editableItem(aOptions, function(aElement, aEvent) {
if (!aOptions.element.inplaceEditor) {
new InplaceEditor(aOptions, aEvent);
function editableField(options) {
return editableItem(options, function(element, event) {
if (!options.element.inplaceEditor) {
new InplaceEditor(options, event);
}
});
}
@ -110,25 +110,24 @@ exports.editableField = editableField;
* clicks and sit in the editing tab order, and call
* a callback when it is activated.
*
* @param {object} aOptions
* @param {Object} options
* The options for this editor, including:
* {Element} element: The DOM element.
* {string} trigger: The DOM event that should trigger editing,
* {String} trigger: The DOM event that should trigger editing,
* defaults to "click"
* @param {function} aCallback
* @param {Function} callback
* Called when the editor is activated.
* @return {function} function which calls aCallback
* @return {Function} function which calls callback
*/
function editableItem(aOptions, aCallback)
{
let trigger = aOptions.trigger || "click"
let element = aOptions.element;
function editableItem(options, callback) {
let trigger = options.trigger || "click";
let element = options.element;
element.addEventListener(trigger, function(evt) {
if (evt.target.nodeName !== "a") {
let win = this.ownerDocument.defaultView;
let selection = win.getSelection();
if (trigger != "click" || selection.isCollapsed) {
aCallback(element, evt);
callback(element, evt);
}
evt.stopPropagation();
}
@ -139,7 +138,7 @@ function editableItem(aOptions, aCallback)
element.addEventListener("keypress", function(evt) {
if (evt.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN ||
evt.charCode === Ci.nsIDOMKeyEvent.DOM_VK_SPACE) {
aCallback(element);
callback(element);
}
}, true);
@ -168,8 +167,8 @@ function editableItem(aOptions, aCallback)
element._trigger = trigger;
return function turnOnEditMode() {
aCallback(element);
}
callback(element);
};
}
exports.editableItem = this.editableItem;
@ -181,31 +180,32 @@ exports.editableItem = this.editableItem;
* within this JSM. So we provide a little workaround here.
*/
function getInplaceEditorForSpan(aSpan)
{
return aSpan.inplaceEditor;
};
function getInplaceEditorForSpan(span) {
return span.inplaceEditor;
}
exports.getInplaceEditorForSpan = getInplaceEditorForSpan;
function InplaceEditor(aOptions, aEvent)
{
this.elt = aOptions.element;
function InplaceEditor(options, event) {
this.elt = options.element;
let doc = this.elt.ownerDocument;
this.doc = doc;
this.elt.inplaceEditor = this;
this.change = aOptions.change;
this.done = aOptions.done;
this.destroy = aOptions.destroy;
this.initial = aOptions.initial ? aOptions.initial : this.elt.textContent;
this.multiline = aOptions.multiline || false;
this.trimOutput = aOptions.trimOutput === undefined ? true : !!aOptions.trimOutput;
this.stopOnShiftTab = !!aOptions.stopOnShiftTab;
this.stopOnTab = !!aOptions.stopOnTab;
this.stopOnReturn = !!aOptions.stopOnReturn;
this.contentType = aOptions.contentType || CONTENT_TYPES.PLAIN_TEXT;
this.property = aOptions.property;
this.popup = aOptions.popup;
this.change = options.change;
this.done = options.done;
this.destroy = options.destroy;
this.initial = options.initial ? options.initial : this.elt.textContent;
this.multiline = options.multiline || false;
this.trimOutput = options.trimOutput === undefined
? true
: !!options.trimOutput;
this.stopOnShiftTab = !!options.stopOnShiftTab;
this.stopOnTab = !!options.stopOnTab;
this.stopOnReturn = !!options.stopOnReturn;
this.contentType = options.contentType || CONTENT_TYPES.PLAIN_TEXT;
this.property = options.property;
this.popup = options.popup;
this._onBlur = this._onBlur.bind(this);
this._onKeyPress = this._onKeyPress.bind(this);
@ -218,11 +218,11 @@ function InplaceEditor(aOptions, aEvent)
// Pull out character codes for advanceChars, listing the
// characters that should trigger a blur.
if (typeof(aOptions.advanceChars) === "function") {
this._advanceChars = aOptions.advanceChars;
if (typeof options.advanceChars === "function") {
this._advanceChars = options.advanceChars;
} else {
let advanceCharcodes = {};
let advanceChars = aOptions.advanceChars || '';
let advanceChars = options.advanceChars || "";
for (let i = 0; i < advanceChars.length; i++) {
advanceCharcodes[advanceChars.charCodeAt(i)] = true;
}
@ -236,7 +236,7 @@ function InplaceEditor(aOptions, aEvent)
this.input.focus();
if (typeof(aOptions.selectAll) == "undefined" || aOptions.selectAll) {
if (typeof options.selectAll == "undefined" || options.selectAll) {
this.input.select();
}
@ -253,7 +253,7 @@ function InplaceEditor(aOptions, aEvent)
this.input.addEventListener("mousedown",
(e) => { e.stopPropagation(); }, false);
this.validate = aOptions.validate;
this.validate = options.validate;
if (this.validate) {
this.input.addEventListener("keyup", this._onKeyup, false);
@ -261,8 +261,8 @@ function InplaceEditor(aOptions, aEvent)
this._updateSize();
if (aOptions.start) {
aOptions.start(this, aEvent);
if (options.start) {
options.start(this, event);
}
EventEmitter.decorate(this);
@ -279,8 +279,7 @@ InplaceEditor.prototype = {
return val;
},
_createInput: function InplaceEditor_createEditor()
{
_createInput: function() {
this.input =
this.doc.createElementNS(HTML_NS, this.multiline ? "textarea" : "input");
this.input.inplaceEditor = this;
@ -293,8 +292,7 @@ InplaceEditor.prototype = {
/**
* Get rid of the editor.
*/
_clear: function InplaceEditor_clear()
{
_clear: function() {
if (!this.input) {
// Already cleared.
return;
@ -327,8 +325,7 @@ InplaceEditor.prototype = {
* Keeps the editor close to the size of its input string. This is pretty
* crappy, suggestions for improvement welcome.
*/
_autosize: function InplaceEditor_autosize()
{
_autosize: function() {
// Create a hidden, absolutely-positioned span to measure the text
// in the input. Boo.
@ -352,8 +349,7 @@ InplaceEditor.prototype = {
/**
* Clean up the mess created by _autosize().
*/
_stopAutosize: function InplaceEditor_stopAutosize()
{
_stopAutosize: function() {
if (!this._measurement) {
return;
}
@ -364,12 +360,11 @@ InplaceEditor.prototype = {
/**
* Size the editor to fit its current contents.
*/
_updateSize: function InplaceEditor_updateSize()
{
_updateSize: function() {
// Replace spaces with non-breaking spaces. Otherwise setting
// the span's textContent will collapse spaces and the measurement
// will be wrong.
this._measurement.textContent = this.input.value.replace(/ /g, '\u00a0');
this._measurement.textContent = this.input.value.replace(/ /g, "\u00a0");
// We add a bit of padding to the end. Should be enough to fit
// any letter that could be typed, otherwise we'll scroll before
@ -391,8 +386,7 @@ InplaceEditor.prototype = {
* Get the width of a single character in the input to properly position the
* autocompletion popup.
*/
_getInputCharWidth: function InplaceEditor_getInputCharWidth()
{
_getInputCharWidth: function() {
// Just make the text content to be 'x' to get the width of any character in
// a monospace font.
this._measurement.textContent = "x";
@ -402,12 +396,11 @@ InplaceEditor.prototype = {
/**
* Increment property values in rule view.
*
* @param {number} increment
* @param {Number} increment
* The amount to increase/decrease the property value.
* @return {bool} true if value has been incremented.
* @return {Boolean} true if value has been incremented.
*/
_incrementValue: function InplaceEditor_incrementValue(increment)
{
_incrementValue: function(increment) {
let value = this.input.value;
let selectionStart = this.input.selectionStart;
let selectionEnd = this.input.selectionEnd;
@ -434,19 +427,17 @@ InplaceEditor.prototype = {
/**
* Increment the property value based on the property type.
*
* @param {string} value
* @param {String} value
* Property value.
* @param {number} increment
* @param {Number} increment
* Amount to increase/decrease the property value.
* @param {number} selStart
* @param {Number} selStart
* Starting index of the value.
* @param {number} selEnd
* @param {Number} selEnd
* Ending index of the value.
* @return {object} object with properties 'value', 'start', and 'end'.
* @return {Object} object with properties 'value', 'start', and 'end'.
*/
_incrementCSSValue: function InplaceEditor_incrementCSSValue(value, increment,
selStart, selEnd)
{
_incrementCSSValue: function(value, increment, selStart, selEnd) {
let range = this._parseCSSValue(value, selStart);
let type = (range && range.type) || "";
let rawValue = (range ? value.substring(range.start, range.end) : "");
@ -489,11 +480,12 @@ InplaceEditor.prototype = {
}
}
}
return this._incrementGenericValue(value, increment, selStart, selEnd, info);
return this._incrementGenericValue(value, increment, selStart, selEnd,
info);
}
if (incrementedValue === null) {
return;
return null;
}
let preRawValue = value.substr(0, range.start);
@ -509,14 +501,14 @@ InplaceEditor.prototype = {
/**
* Parses the property value and type.
*
* @param {string} value
* @param {String} value
* Property value.
* @param {number} offset
* @param {Number} offset
* Starting index of value.
* @return {object} object with properties 'value', 'start', 'end', and 'type'.
* @return {Object} object with properties 'value', 'start', 'end', and
* 'type'.
*/
_parseCSSValue: function InplaceEditor_parseCSSValue(value, offset)
{
_parseCSSValue: function(value, offset) {
const reSplitCSS = /(url\("?[^"\)]+"?\)?)|(rgba?\([^)]*\)?)|(hsla?\([^)]*\)?)|(#[\dA-Fa-f]+)|(-?\d*\.?\d+(%|[a-z]{1,4})?)|"([^"]*)"?|'([^']*)'?|([^,\s\/!\(\)]+)|(!(.*)?)/;
let start = 0;
let m;
@ -530,7 +522,7 @@ InplaceEditor.prototype = {
}
if (!m) {
return;
return null;
}
let type;
@ -558,22 +550,19 @@ InplaceEditor.prototype = {
* Increment the property value for types other than
* number or hex, such as rgb, hsl, and file names.
*
* @param {string} value
* @param {String} value
* Property value.
* @param {number} increment
* @param {Number} increment
* Amount to increment/decrement.
* @param {number} offset
* @param {Number} offset
* Starting index of the property value.
* @param {number} offsetEnd
* @param {Number} offsetEnd
* Ending index of the property value.
* @param {object} info
* @param {Object} info
* Object with details about the property value.
* @return {object} object with properties 'value', 'start', and 'end'.
* @return {Object} object with properties 'value', 'start', and 'end'.
*/
_incrementGenericValue:
function InplaceEditor_incrementGenericValue(value, increment, offset,
offsetEnd, info)
{
_incrementGenericValue: function(value, increment, offset, offsetEnd, info) {
// Try to find a number around the cursor to increment.
let start, end;
// Check if we are incrementing in a non-number context (such as a URL)
@ -585,8 +574,8 @@ InplaceEditor.prototype = {
start = offset;
end = offsetEnd;
} else {
// Parse periods as belonging to the number only if we are in a known number
// context. (This makes incrementing the 1 in 'image1.gif' work.)
// Parse periods as belonging to the number only if we are in a known
// number context. (This makes incrementing the 1 in 'image1.gif' work.)
let pattern = "[" + (info ? "0-9." : "0-9") + "]*";
let before = new RegExp(pattern + "$").exec(value.substr(0, offset))[0].length;
let after = new RegExp("^" + pattern).exec(value.substr(offset))[0].length;
@ -602,8 +591,7 @@ InplaceEditor.prototype = {
}
}
if (start !== end)
{
if (start !== end) {
// Include percentages as part of the incremented number (they are
// common enough).
if (value.charAt(end) === "%") {
@ -629,17 +617,15 @@ InplaceEditor.prototype = {
/**
* Increment the property value for numbers.
*
* @param {string} rawValue
* @param {String} rawValue
* Raw value to increment.
* @param {number} increment
* @param {Number} increment
* Amount to increase/decrease the raw value.
* @param {object} info
* @param {Object} info
* Object with info about the property value.
* @return {string} the incremented value.
* @return {String} the incremented value.
*/
_incrementRawValue:
function InplaceEditor_incrementRawValue(rawValue, increment, info)
{
_incrementRawValue: function(rawValue, increment, info) {
let num = parseFloat(rawValue);
if (isNaN(num)) {
@ -667,25 +653,23 @@ InplaceEditor.prototype = {
/**
* Increment the property value for hex.
*
* @param {string} value
* @param {String} value
* Property value.
* @param {number} increment
* @param {Number} increment
* Amount to increase/decrease the property value.
* @param {number} offset
* @param {Number} offset
* Starting index of the property value.
* @param {number} offsetEnd
* @param {Number} offsetEnd
* Ending index of the property value.
* @return {object} object with properties 'value' and 'selection'.
* @return {Object} object with properties 'value' and 'selection'.
*/
_incHexColor:
function InplaceEditor_incHexColor(rawValue, increment, offset, offsetEnd)
{
_incHexColor: function(rawValue, increment, offset, offsetEnd) {
// Return early if no part of the rawValue is selected.
if (offsetEnd > rawValue.length && offset >= rawValue.length) {
return;
return null;
}
if (offset < 1 && offsetEnd <= 1) {
return;
return null;
}
// Ignore the leading #.
rawValue = rawValue.substr(1);
@ -707,7 +691,7 @@ InplaceEditor.prototype = {
}
if (rawValue.length !== 6) {
return;
return null;
}
// If no selection, increment an adjacent color, preferably one to the left.
@ -724,7 +708,7 @@ InplaceEditor.prototype = {
offsetEnd += offsetEnd % 2;
// Remap the increments from [0.1, 1, 10] to [1, 1, 16].
if (-1 < increment && increment < 1) {
if (increment > -1 && increment < 1) {
increment = (increment < 0 ? -1 : 1);
}
if (Math.abs(increment) === 10) {
@ -739,7 +723,7 @@ InplaceEditor.prototype = {
let value = parseInt(mid, 16);
if (isNaN(value)) {
return;
return null;
}
mid = Math.min(Math.max(value + increment, 0), 255).toString(16);
@ -763,43 +747,46 @@ InplaceEditor.prototype = {
/**
* Cycle through the autocompletion suggestions in the popup.
*
* @param {boolean} aReverse
* @param {Boolean} reverse
* true to select previous item from the popup.
* @param {boolean} aNoSelect
* @param {Boolean} noSelect
* true to not select the text after selecting the newly selectedItem
* from the popup.
*/
_cycleCSSSuggestion:
function InplaceEditor_cycleCSSSuggestion(aReverse, aNoSelect)
{
_cycleCSSSuggestion: function(reverse, noSelect) {
// selectedItem can be null when nothing is selected in an empty editor.
let {label, preLabel} = this.popup.selectedItem || {label: "", preLabel: ""};
if (aReverse) {
let {label, preLabel} = this.popup.selectedItem ||
{label: "", preLabel: ""};
if (reverse) {
this.popup.selectPreviousItem();
} else {
this.popup.selectNextItem();
}
this._selectedIndex = this.popup.selectedIndex;
let input = this.input;
let pre = "";
if (input.selectionStart < input.selectionEnd) {
pre = input.value.slice(0, input.selectionStart);
}
else {
} else {
pre = input.value.slice(0, input.selectionStart - label.length +
preLabel.length);
preLabel.length);
}
let post = input.value.slice(input.selectionEnd, input.value.length);
let item = this.popup.selectedItem;
let toComplete = item.label.slice(item.preLabel.length);
input.value = pre + toComplete + post;
if (!aNoSelect) {
if (!noSelect) {
input.setSelectionRange(pre.length, pre.length + toComplete.length);
}
else {
} else {
input.setSelectionRange(pre.length + toComplete.length,
pre.length + toComplete.length);
}
this._updateSize();
// This emit is mainly for the purpose of making the test flow simpler.
this.emit("after-suggest");
@ -808,10 +795,9 @@ InplaceEditor.prototype = {
/**
* Call the client's done handler and clear out.
*/
_apply: function InplaceEditor_apply(aEvent, direction)
{
_apply: function(event, direction) {
if (this._applied) {
return;
return null;
}
this._applied = true;
@ -827,26 +813,28 @@ InplaceEditor.prototype = {
/**
* Handle loss of focus by calling done if it hasn't been called yet.
*/
_onBlur: function InplaceEditor_onBlur(aEvent, aDoNotClear)
{
if (aEvent && this.popup && this.popup.isOpen &&
_onBlur: function(event, doNotClear) {
if (event && this.popup && this.popup.isOpen &&
this.popup.selectedIndex >= 0) {
let label, preLabel;
if (this._selectedIndex === undefined) {
({label, preLabel} = this.popup.getItemAtIndex(this.popup.selectedIndex));
}
else {
if (!this._selectedIndex) {
({label, preLabel} =
this.popup.getItemAtIndex(this.popup.selectedIndex));
} else {
({label, preLabel} = this.popup.getItemAtIndex(this._selectedIndex));
}
let input = this.input;
let pre = "";
if (input.selectionStart < input.selectionEnd) {
pre = input.value.slice(0, input.selectionStart);
}
else {
} else {
pre = input.value.slice(0, input.selectionStart - label.length +
preLabel.length);
preLabel.length);
}
let post = input.value.slice(input.selectionEnd, input.value.length);
let item = this.popup.selectedItem;
this._selectedIndex = this.popup.selectedIndex;
@ -873,8 +861,9 @@ InplaceEditor.prototype = {
}
return;
}
this._apply();
if (!aDoNotClear) {
if (!doNotClear) {
this._clear();
}
},
@ -882,8 +871,7 @@ InplaceEditor.prototype = {
/**
* Handle the input field's keypress event.
*/
_onKeyPress: function InplaceEditor_onKeyPress(aEvent)
{
_onKeyPress: function(event) {
let prevent = false;
const largeIncrement = 100;
@ -892,35 +880,35 @@ InplaceEditor.prototype = {
let increment = 0;
if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_UP
|| aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP) {
if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_UP ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP) {
increment = 1;
} else if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_DOWN
|| aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
} else if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_DOWN ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
increment = -1;
}
if (aEvent.shiftKey && !aEvent.altKey) {
if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP
|| aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
if (event.shiftKey && !event.altKey) {
if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
increment *= largeIncrement;
} else {
increment *= mediumIncrement;
}
} else if (aEvent.altKey && !aEvent.shiftKey) {
} else if (event.altKey && !event.shiftKey) {
increment *= smallIncrement;
}
// Use default cursor movement rather than providing auto-suggestions.
if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_HOME
|| aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_END
|| aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP
|| aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_HOME ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_END ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
this._preventSuggestions = true;
}
let cycling = false;
if (increment && this._incrementValue(increment) ) {
if (increment && this._incrementValue(increment)) {
this._updateSize();
prevent = true;
cycling = true;
@ -931,30 +919,30 @@ InplaceEditor.prototype = {
this._doValidation();
}
if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_BACK_SPACE ||
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_DELETE ||
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_LEFT ||
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RIGHT) {
if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_BACK_SPACE ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_DELETE ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_LEFT ||
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RIGHT) {
if (this.popup && this.popup.isOpen) {
this.popup.hidePopup();
}
} else if (!cycling && !aEvent.metaKey && !aEvent.altKey && !aEvent.ctrlKey) {
} else if (!cycling && !event.metaKey && !event.altKey && !event.ctrlKey) {
this._maybeSuggestCompletion();
}
if (this.multiline &&
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN &&
aEvent.shiftKey) {
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN &&
event.shiftKey) {
prevent = false;
} else if (this._advanceChars(aEvent.charCode, this.input.value,
} else if (this._advanceChars(event.charCode, this.input.value,
this.input.selectionStart)
|| aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN
|| aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB) {
|| event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN
|| event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB) {
prevent = true;
let direction = FOCUS_FORWARD;
if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
aEvent.shiftKey) {
if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
event.shiftKey) {
if (this.stopOnShiftTab) {
direction = null;
} else {
@ -962,9 +950,9 @@ InplaceEditor.prototype = {
}
}
if ((this.stopOnReturn &&
aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN) ||
(this.stopOnTab && aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
!aEvent.shiftKey)) {
event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN) ||
(this.stopOnTab && event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
!event.shiftKey)) {
direction = null;
}
@ -979,22 +967,21 @@ InplaceEditor.prototype = {
let input = this.input;
if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
this.contentType == CONTENT_TYPES.CSS_MIXED) {
if (this.popup && input.selectionStart < input.selectionEnd) {
aEvent.preventDefault();
event.preventDefault();
input.setSelectionRange(input.selectionEnd, input.selectionEnd);
this.emit("after-suggest");
return;
}
else if (this.popup && this.popup.isOpen) {
aEvent.preventDefault();
this._cycleCSSSuggestion(aEvent.shiftKey, true);
} else if (this.popup && this.popup.isOpen) {
event.preventDefault();
this._cycleCSSSuggestion(event.shiftKey, true);
return;
}
}
this._apply(aEvent, direction);
this._apply(event, direction);
// Close the popup if open
if (this.popup && this.popup.isOpen) {
@ -1009,14 +996,14 @@ InplaceEditor.prototype = {
// If the next node to be focused has been tagged as an editable
// node, trigger editing using the configured event
if (next && next.ownerDocument === this.doc && next._editable) {
let e = this.doc.createEvent('Event');
let e = this.doc.createEvent("Event");
e.initEvent(next._trigger, true, true);
next.dispatchEvent(e);
}
}
this._clear();
} else if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE) {
} else if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE) {
// Cancel and blur ourselves.
// Now we don't want to suggest anything as we are moving out.
this._preventSuggestions = true;
@ -1028,8 +1015,8 @@ InplaceEditor.prototype = {
this.cancelled = true;
this._apply();
this._clear();
aEvent.stopPropagation();
} else if (aEvent.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_SPACE) {
event.stopPropagation();
} else if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_SPACE) {
// No need for leading spaces here. This is particularly
// noticable when adding a property: it's very natural to type
// <name>: (which advances to the next property) then spacebar.
@ -1037,22 +1024,21 @@ InplaceEditor.prototype = {
}
if (prevent) {
aEvent.preventDefault();
event.preventDefault();
}
},
/**
* Handle the input field's keyup event.
*/
_onKeyup: function(aEvent) {
_onKeyup: function() {
this._applied = false;
},
/**
* Handle changes to the input text.
*/
_onInput: function InplaceEditor_onInput(aEvent)
{
_onInput: function() {
// Validate the entered value.
this._doValidation();
@ -1070,8 +1056,7 @@ InplaceEditor.prototype = {
/**
* Fire validation callback with current input
*/
_doValidation: function()
{
_doValidation: function() {
if (this.validate && this.input) {
this.validate(this.input.value);
}
@ -1080,14 +1065,15 @@ InplaceEditor.prototype = {
/**
* Handles displaying suggestions based on the current input.
*
* @param {boolean} aNoAutoInsert
* @param {Boolean} noAutoInsert
* true if you don't want to automatically insert the first suggestion
*/
_maybeSuggestCompletion: function(aNoAutoInsert) {
_maybeSuggestCompletion: function(noAutoInsert) {
// Input can be null in cases when you intantaneously switch out of it.
if (!this.input) {
return;
}
let preTimeoutQuery = this.input.value;
// Since we are calling this method from a keypress event handler, the
// |input.value| does not include currently typed character. Thus we perform
@ -1134,8 +1120,8 @@ InplaceEditor.prototype = {
startCheckQuery = "";
}
list =
["!important", ...domUtils.getCSSValuesForProperty(this.property.name)];
list = ["!important",
...domUtils.getCSSValuesForProperty(this.property.name)];
if (query == "") {
// Do not suggest '!important' without any manually typed character.
@ -1146,11 +1132,12 @@ InplaceEditor.prototype = {
// Detecting if cursor is at property or value;
let match = query.match(/([:;"'=]?)\s*([^"';:=]+)?$/);
if (match && match.length >= 2) {
if (match[1] == ":") { // We are in CSS value completion
// We are in CSS value completion
if (match[1] == ":") {
let propertyName =
query.match(/[;"'=]\s*([^"';:= ]+)\s*:\s*[^"';:=]*$/)[1];
list =
["!important;", ...domUtils.getCSSValuesForProperty(propertyName)];
list = ["!important;",
...domUtils.getCSSValuesForProperty(propertyName)];
let matchLastQuery = /([^\s,.\/]+$)/.exec(match[2] || "");
if (matchLastQuery) {
startCheckQuery = matchLastQuery[0];
@ -1161,7 +1148,8 @@ InplaceEditor.prototype = {
// Don't suggest '!important' without any manually typed character
list.splice(0, 1);
}
} else if (match[1]) { // We are in CSS property name completion
} else if (match[1]) {
// We are in CSS property name completion
list = CSSPropertyList;
startCheckQuery = match[2];
}
@ -1172,7 +1160,7 @@ InplaceEditor.prototype = {
}
}
}
if (!aNoAutoInsert) {
if (!noAutoInsert) {
list.some(item => {
if (startCheckQuery != null && item.startsWith(startCheckQuery)) {
input.value = query + item.slice(startCheckQuery.length) +
@ -1199,13 +1187,11 @@ InplaceEditor.prototype = {
preLabel: startCheckQuery,
label: list[i]
});
}
else if (count > 0) {
} else if (count > 0) {
// Since count was incremented, we had already crossed the entries
// which would have started with query, assuming that list is sorted.
break;
}
else if (startCheckQuery != null && list[i][0] > startCheckQuery[0]) {
} else if (startCheckQuery != null && list[i][0] > startCheckQuery[0]) {
// We have crossed all possible matches alphabetically.
break;
}
@ -1217,7 +1203,7 @@ InplaceEditor.prototype = {
this.inputCharWidth;
this.popup.setItems(finalList);
this.popup.openPopup(this.input, x);
if (aNoAutoInsert) {
if (noAutoInsert) {
this.popup.selectedIndex = -1;
}
} else {
@ -1233,25 +1219,22 @@ InplaceEditor.prototype = {
/**
* Copy text-related styles from one element to another.
*/
function copyTextStyles(aFrom, aTo)
{
let win = aFrom.ownerDocument.defaultView;
let style = win.getComputedStyle(aFrom);
aTo.style.fontFamily = style.getPropertyCSSValue("font-family").cssText;
aTo.style.fontSize = style.getPropertyCSSValue("font-size").cssText;
aTo.style.fontWeight = style.getPropertyCSSValue("font-weight").cssText;
aTo.style.fontStyle = style.getPropertyCSSValue("font-style").cssText;
function copyTextStyles(from, to) {
let win = from.ownerDocument.defaultView;
let style = win.getComputedStyle(from);
to.style.fontFamily = style.getPropertyCSSValue("font-family").cssText;
to.style.fontSize = style.getPropertyCSSValue("font-size").cssText;
to.style.fontWeight = style.getPropertyCSSValue("font-weight").cssText;
to.style.fontStyle = style.getPropertyCSSValue("font-style").cssText;
}
/**
* Trigger a focus change similar to pressing tab/shift-tab.
*/
function moveFocus(aWin, aDirection)
{
return focusManager.moveFocus(aWin, null, aDirection, 0);
function moveFocus(win, direction) {
return focusManager.moveFocus(win, null, direction, 0);
}
XPCOMUtils.defineLazyGetter(this, "focusManager", function() {
return Services.focus;
});