Updating progress using the promise notify feature

This commit is contained in:
Jeff Avallone 2014-12-29 17:34:44 -05:00
parent 99c4c078fb
commit e890fe7d2c
4 changed files with 51 additions and 75 deletions

View File

@ -131,6 +131,18 @@ describe('parser/javascript/node.js', function() {
.done(); .done();
}); });
it('notifies of the progress when the render is not canceled', function(done) {
this.node.state.renderCounter = 116;
this.node.state.maxCounter = 200;
this.node.deferredStep('result')
.then(null, null, progress => {
expect(Math.round(100 * progress)).toEqual(42);
})
.finally(done)
.done();
});
it('rejects the returned promise when the render is canceled', function(done) { it('rejects the returned promise when the render is canceled', function(done) {
var resolve = jasmine.createSpy('resolve'), var resolve = jasmine.createSpy('resolve'),
reject = jasmine.createSpy('reject'); reject = jasmine.createSpy('reject');
@ -231,45 +243,26 @@ describe('parser/javascript/node.js', function() {
expect(this.node.state.renderCounter).toEqual(1); expect(this.node.state.renderCounter).toEqual(1);
}); });
it('sets the maxCounter', function() {
this.node.state.renderCounter = 42;
this.node.state.maxCounter = 0;
this.node.startRender();
expect(this.node.state.maxCounter).toEqual(43);
this.node.state.maxCounter = 50;
this.node.startRender();
expect(this.node.state.maxCounter).toEqual(50);
});
}); });
describe('#doneRender', function() { describe('#doneRender', function() {
it('sets the maxCounter when the maxCounter is initially 0', function() {
this.node.state.renderCounter = 42;
this.node.state.maxCounter = 0;
this.node.doneRender();
expect(this.node.state.maxCounter).toEqual(42);
this.node.state.renderCounter = 24;
this.node.doneRender();
expect(this.node.state.maxCounter).toEqual(42);
});
it('decrements the renderCounter', function() { it('decrements the renderCounter', function() {
this.node.state.renderCounter = 42; this.node.state.renderCounter = 42;
this.node.doneRender(); this.node.doneRender();
expect(this.node.state.renderCounter).toEqual(41); expect(this.node.state.renderCounter).toEqual(41);
}); });
it('triggers an updateStatus event', function() {
var evt;
this.node.state.renderCounter = 117;
this.node.state.maxCounter = 200;
spyOn(document.body, 'dispatchEvent');
this.node.doneRender();
expect(document.body.dispatchEvent).toHaveBeenCalled();
evt = document.body.dispatchEvent.calls.mostRecent().args[0];
expect(evt.type).toEqual('updateStatus');
expect(evt.detail).toEqual({ percentage: 0.42 });
});
it('returns a deferredStep', function() {
spyOn(this.node, 'deferredStep').and.returnValue('example deferred');
expect(this.node.doneRender()).toEqual('example deferred');
});
}); });
describe('#render', function() { describe('#render', function() {

View File

@ -190,25 +190,11 @@ describe('regexper.js', function() {
}); });
describe('#updatePercentage', function() {
beforeEach(function() {
this.event = util.customEvent('updateStatus', { percentage: 0.42 });
});
it('sets the width of the progress bar', function() {
this.regexper.updatePercentage(this.event);
expect(this.regexper.percentage.style.width).toEqual('42%');
});
});
describe('#bindListeners', function() { describe('#bindListeners', function() {
beforeEach(function() { beforeEach(function() {
spyOn(this.regexper, 'keypressListener'); spyOn(this.regexper, 'keypressListener');
spyOn(this.regexper, 'submitListener'); spyOn(this.regexper, 'submitListener');
spyOn(this.regexper, 'updatePercentage');
spyOn(this.regexper, 'documentKeypressListener'); spyOn(this.regexper, 'documentKeypressListener');
spyOn(this.regexper, 'hashchangeListener'); spyOn(this.regexper, 'hashchangeListener');
}); });
@ -231,15 +217,6 @@ describe('regexper.js', function() {
expect(this.regexper.submitListener).toHaveBeenCalled(); expect(this.regexper.submitListener).toHaveBeenCalled();
}); });
it('binds #updatePercentage to updateStatus on the root', function() {
spyOn(this.regexper.root, 'addEventListener');
this.regexper.bindListeners();
expect(this.regexper.root.addEventListener).toHaveBeenCalledWith('updateStatus', jasmine.any(Function));
this.regexper.root.addEventListener.calls.first().args[1]();
expect(this.regexper.updatePercentage).toHaveBeenCalled();
});
it('binds #documentKeypressListener to keyup on the root', function() { it('binds #documentKeypressListener to keyup on the root', function() {
spyOn(this.regexper.root, 'addEventListener'); spyOn(this.regexper.root, 'addEventListener');
this.regexper.bindListeners(); this.regexper.bindListeners();

View File

@ -66,6 +66,7 @@ export default class Node {
if (this.state.cancelRender) { if (this.state.cancelRender) {
deferred.reject('Render cancelled'); deferred.reject('Render cancelled');
} else { } else {
deferred.notify(1 - this.state.renderCounter / this.state.maxCounter);
deferred.resolve.apply(this, result); deferred.resolve.apply(this, result);
} }
}, 1); }, 1);
@ -98,20 +99,12 @@ export default class Node {
startRender() { startRender() {
this.state.renderCounter++; this.state.renderCounter++;
this.state.maxCounter = Math.max(this.state.maxCounter, this.state.renderCounter);
} }
doneRender() { doneRender() {
if (this.state.maxCounter === 0) {
this.state.maxCounter = this.state.renderCounter;
}
this.state.renderCounter--; this.state.renderCounter--;
document.body.dispatchEvent(util.customEvent('updateStatus', {
percentage: (this.state.maxCounter - this.state.renderCounter) / this.state.maxCounter
}));
return this.deferredStep();
} }
render(container) { render(container) {
@ -124,8 +117,20 @@ export default class Node {
} else { } else {
this.startRender(); this.startRender();
return this._render() return this._render()
.then(this.doneRender.bind(this)) .then(
.then(_.constant(this)); () => {
this.doneRender();
return this;
},
null,
progress => {
if (typeof progress.value !== 'undefined') {
return progress.value;
} else {
return progress;
}
}
);
} }
} }

View File

@ -56,14 +56,9 @@ export default class Regexper {
this.showExpression(this._getHash()); this.showExpression(this._getHash());
} }
updatePercentage(event) {
this.percentage.style.width = event.detail.percentage * 100 + '%';
}
bindListeners() { bindListeners() {
this.field.addEventListener('keypress', this.keypressListener.bind(this)); this.field.addEventListener('keypress', this.keypressListener.bind(this));
this.form.addEventListener('submit', this.submitListener.bind(this)); this.form.addEventListener('submit', this.submitListener.bind(this));
this.root.addEventListener('updateStatus', this.updatePercentage.bind(this));
this.root.addEventListener('keyup', this.documentKeypressListener.bind(this)); this.root.addEventListener('keyup', this.documentKeypressListener.bind(this));
window.addEventListener('hashchange', this.hashchangeListener.bind(this)); window.addEventListener('hashchange', this.hashchangeListener.bind(this));
} }
@ -157,12 +152,18 @@ export default class Regexper {
throw message; throw message;
}) })
.invoke('render', this.svgContainer, this.svgBase) .invoke('render', this.svgContainer, this.svgBase)
.then(() => { .then(
this.state = 'has-results'; () => {
this.updateLinks(); this.state = 'has-results';
this.displayWarnings(this.runningParser.warnings); this.updateLinks();
this._trackEvent('visualization', 'complete'); this.displayWarnings(this.runningParser.warnings);
}) this._trackEvent('visualization', 'complete');
},
null,
percentage => {
this.percentage.style.width = percentage * 100 + '%';
}
)
.then(null, message => { .then(null, message => {
if (message === 'Render cancelled') { if (message === 'Render cancelled') {
this._trackEvent('visualization', 'cancelled'); this._trackEvent('visualization', 'cancelled');