Skip to content

Commit

Permalink
Fix issue #550 The change event is sent twice on change
Browse files Browse the repository at this point in the history
Fix the bug when an input with the `negativeBracketsTypeOnBlur` options was focused then blurred, it would dispatch a `change` event.

Signed-off-by: Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>
  • Loading branch information
AlexandreBonneau committed Mar 2, 2018
1 parent 7c9ac47 commit cc04b41
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,9 @@
## Changelog for autoNumeric

### 4.2.5
+ Fix issue #550 The `change` event is sent twice on change
+ Fix the bug when an input with the `negativeBracketsTypeOnBlur` options was focused then blurred, it would dispatch a `change` event.

### 4.2.4
+ Fix issue #558 Switch the webpack 4

Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "autonumeric",
"version": "4.2.4",
"version": "4.2.5",
"description": "autoNumeric is a standalone Javascript library that provides live *as-you-type* formatting for international numbers and currencies. It supports most international numeric formats and currencies including those used in Europe, Asia, and North and South America.",
"main": "dist/autoNumeric.js",
"readmeFilename": "README.md",
Expand Down
28 changes: 15 additions & 13 deletions src/AutoNumeric.js
@@ -1,8 +1,8 @@
/**
* AutoNumeric.js
*
* @version 4.2.4
* @date 2018-02-27 UTC 21:00
* @version 4.2.5
* @date 2018-03-02 UTC 06:15
*
* @authors Bob Knothe, Alexandre Bonneau
* @contributors Sokolov Yura and others, cf. AUTHORS
Expand Down Expand Up @@ -176,6 +176,8 @@ export default class AutoNumeric {
this.isDropEvent = false;
// Keep track if the user is currently editing the element
this.isEditing = false;
// Keep track of the rawValue (needed to define if a change event must be sent on blur or enter key)
this.rawValueOnFocus = void(0);
// Watch any external changes to the element value/textContent/nodeValue and `set()` the new value so that it gets formatted/saved in the history
this.internalModification = false; // This is temporarily set to `true` only when the AutoNumeric object does update the element value
this.attributeToWatch = this._getAttributeToWatch();
Expand Down Expand Up @@ -881,7 +883,7 @@ export default class AutoNumeric {
* @returns {string}
*/
static version() {
return '4.2.4';
return '4.2.5';
}

/**
Expand Down Expand Up @@ -5991,8 +5993,9 @@ To solve that, you'd need to either set \`decimalPlacesRawValue\` to \`null\`, o
* @private
*/
_onFocusInAndMouseEnter(e) {
this.isEditing = false; // Just in case no `keyUp` event have been sent (ie. if the user lost the focus from the current window while typing)
//TODO Create separate handlers for the focus and mouseenter events
this.isEditing = false; // Just in case no `keyUp` event have been sent (ie. if the user lost the focus from the current window while typing)
this.rawValueOnFocus = this.rawValue; // Keep track of the initial rawValue. This is needed to define if a change event must be dispatched later

if (this.settings.unformatOnHover && e.type === 'mouseenter' && e.altKey) {
this.constructor._unformatAltHovered(this);
Expand Down Expand Up @@ -6191,11 +6194,12 @@ To solve that, you'd need to either set \`decimalPlacesRawValue\` to \`null\`, o
//TODO Add an option to select either the integer or decimal part with `Esc`
}

// The "enter" key throws a `change` event if the value has changed since the `focus` event
// The "enter" key throws a `change` event if the raw value has changed since the `focus` event
let targetValue = AutoNumericHelper.getElementValue(e.target);
if (this.eventKey === AutoNumericEnum.keyName.Enter && this.valueOnFocus !== targetValue) {
if (this.eventKey === AutoNumericEnum.keyName.Enter && this.rawValue !== this.rawValueOnFocus) {
this._triggerEvent(AutoNumeric.events.native.change, e.target);
this.valueOnFocus = targetValue;
this.rawValueOnFocus = this.rawValue;

if (this.settings.isCancellable) {
// If the user activated the 'cancellable' feature, we save the validated value when 'Enter' is hit
Expand Down Expand Up @@ -6432,9 +6436,9 @@ To solve that, you'd need to either set \`decimalPlacesRawValue\` to \`null\`, o
* @param {Event} e
*/
_onFocusOutAndMouseLeave(e) {
//TODO Create separate handlers for blur and mouseleave
this.isEditing = false; // Just in case no `keyUp` event have been sent (if the user lost the focus to the window while typing)

//TODO Create separate handlers for blur and mouseleave
//FIXME Do not call `set()` if the current raw value is the same as the one we are trying to set (currently, on focus out, `set()` is always called, even if the value has not changed
if (this.settings.unformatOnHover && e.type === 'mouseleave' && this.hoveredWithAlt) {
this.constructor._reformatAltHovered(this);
Expand Down Expand Up @@ -6525,11 +6529,6 @@ To solve that, you'd need to either set \`decimalPlacesRawValue\` to \`null\`, o

this._setElementValue(groupedValue);
}

if (groupedValue !== this.valueOnFocus) {
this._triggerEvent(AutoNumeric.events.native.change, this.domElement);
delete this.valueOnFocus;
}
}

this._onBlur(e);
Expand Down Expand Up @@ -6980,9 +6979,12 @@ To solve that, you'd need to either set \`decimalPlacesRawValue\` to \`null\`, o
// Keep track if the user is currently editing the element
this.isEditing = false;

if (AutoNumericHelper.getElementValue(e.target) !== this.valueOnFocus) {
// Send a `change` event if the raw value has been changed since the last focus or 'enter' validation
if (this.rawValue !== this.rawValueOnFocus) {
this._triggerEvent(AutoNumeric.events.native.change, e.target);
}

this.rawValueOnFocus = void(0); // Reset the tracker
}

/**
Expand Down
41 changes: 40 additions & 1 deletion test/e2e/index.html
Expand Up @@ -925,6 +925,18 @@ <h5 id="tag_h5">12345.67</h5>
</div>
</div>
</div>

<div class="testSuite">
<div class="test">
<p class="description">Issue #550</p>
<div>
<input id="issue_550" type="text" placeholder="" value="-1357246.81">
<input id="issue_550_blur" type="text" placeholder="Click here to blur">
<input id="issue_550_change_detector" type="text">
<button id="issue_550_button">Reset the change event tracker</button>
</div>
</div>
</div>
</div>
<script>
//-------------- Classic input
Expand Down Expand Up @@ -1751,7 +1763,9 @@ <h5 id="tag_h5">12345.67</h5>
new AutoNumeric('#selectOnFocus40').french().update(doNotSelectOption).update(case40);

//-------------- AutoNumeric events
new AutoNumeric('#autoNumericEventInput');
new AutoNumeric('#autoNumericEventInput', {
negativeBracketsTypeOnBlur: AutoNumeric.options.negativeBracketsTypeOnBlur.parentheses,
});
// .update({ valuesToStrings : AutoNumeric.options.valuesToStrings.zeroDash }); //DEBUG
const autoNumericEventInput = document.querySelector('#autoNumericEventInput');
autoNumericEventInput.addEventListener(AutoNumeric.events.formatted, e => {
Expand All @@ -1760,6 +1774,12 @@ <h5 id="tag_h5">12345.67</h5>
autoNumericEventInput.addEventListener(AutoNumeric.events.rawValueModified, e => {
console.log(`'${AutoNumeric.events.rawValueModified}' sent with`, e); //DEBUG
});
autoNumericEventInput.addEventListener(AutoNumeric.events.native.change, e => {
console.log(`'${AutoNumeric.events.native.change}' sent with`, e); //DEBUG
});
autoNumericEventInput.addEventListener(AutoNumeric.events.native.input, e => {
console.log(`'${AutoNumeric.events.native.input}' sent with`, e); //DEBUG
});

//-------------- Issue #442 & #457
new AutoNumeric('#issue_442_1', { unformatOnSubmit: AutoNumeric.options.unformatOnSubmit.unformat }).french();
Expand Down Expand Up @@ -1974,6 +1994,25 @@ <h5 id="tag_h5">12345.67</h5>
//-------------- Issue #553
new AutoNumeric('#issue_553_one', 1.23e-13, { decimalPlaces: 2 });
new AutoNumeric('#issue_553_two', -123.4567e-6, { decimalPlaces: 10 });

//-------------- Issue #550
new AutoNumeric('#issue_550', {
negativeBracketsTypeOnBlur: AutoNumeric.options.negativeBracketsTypeOnBlur.parentheses,
});
const issue550 = document.querySelector('#issue_550');
const issue550ChangeDetector = document.querySelector('#issue_550_change_detector');
const issue550Button = document.querySelector('#issue_550_button');

let issue550ChangeCount = 0;
issue550ChangeDetector.value = 0;

issue550.addEventListener('change', () => {
issue550ChangeDetector.value = ++issue550ChangeCount;
});
issue550Button.addEventListener('click', () => {
issue550ChangeCount = 0;
issue550ChangeDetector.value = 0;
});
</script>
</body>
</html>
67 changes: 67 additions & 0 deletions test/e2e/specs/autoNumeric.e2e.spec.js
Expand Up @@ -205,6 +205,10 @@ const selectors = {
issue432dot : '#issue_432_dot',
issue432none : '#issue_432_none',
issue535 : '#issue_535',
issue550 : '#issue_550',
issue550Blur : '#issue_550_blur',
issue550ChangeDetector : '#issue_550_change_detector',
issue550Button : '#issue_550_button',
};

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -3835,4 +3839,67 @@ describe('Issue #535', () => {
});
});

describe('Issue #550', () => {
it('should test for default values, and focus on it', () => {
browser.url(testUrl);

expect(browser.getValue(selectors.issue550)).toEqual('(1,357,246.81)');
});

it(`should not send a 'change' event when focusing then blurring the input`, () => {
const input = $(selectors.issue550);
input.click();
const inputBlur = $(selectors.issue550Blur);
inputBlur.click();

expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('0');

// Reset the change event counter
$(selectors.issue550Button).click();
expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('0');
});

it(`should send a single 'change' event when modifying the value, then blurring`, () => {
const input = $(selectors.issue550);
const inputBlur = $(selectors.issue550Blur);
input.click();

expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('0');
browser.keys(['Home', '5']);
expect(browser.getValue(selectors.issue550)).toEqual('-51,357,246.81');
inputBlur.click();
expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('1');

// Modify the input again
input.click();
browser.keys(['Home', '6']);
expect(browser.getValue(selectors.issue550)).toEqual('-651,357,246.81');
inputBlur.click();
expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('2');
input.click();
browser.keys(['Home', '2']);
expect(browser.getValue(selectors.issue550)).toEqual('-2,651,357,246.81');
inputBlur.click();
expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('3');

// Reset the change event counter
$(selectors.issue550Button).click();
expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('0');
});

it(`should send a single 'change' event when modifying the value, then hitting the enter key (and then blurring the input)`, () => {
const input = $(selectors.issue550);
const inputBlur = $(selectors.issue550Blur);
input.click();

expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('0');
browser.keys(['Home', '1']);
expect(browser.getValue(selectors.issue550)).toEqual('-12,651,357,246.81');
browser.keys('Enter');
expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('1');
inputBlur.click();
expect(browser.getValue(selectors.issue550ChangeDetector)).toEqual('1');
});
});

//TODO Add some tests to make sure the correct number of `AutoNumeric.events.formatted` is sent during each keypress

0 comments on commit cc04b41

Please sign in to comment.