Skip to content

Commit

Permalink
Merge pull request ichord#301 from XrXr/remoteFilter-callback-timing
Browse files Browse the repository at this point in the history
Make handling of resolution of remoteFilter more robust under various timings
  • Loading branch information
ichord committed Jun 16, 2015
2 parents 29700b6 + 1b3e013 commit e88fa03
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 11 deletions.
20 changes: 16 additions & 4 deletions dist/js/jquery.atwho.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ App = (function() {
return function(e) {
var c;
if (c = _this.controller()) {
c.expectedQueryCBId = null;
return c.view.hide(e, c.getOpt("displayTimeout"));
}
};
Expand Down Expand Up @@ -262,6 +263,7 @@ Controller = (function() {
this.at = at1;
this.$inputor = this.app.$inputor;
this.id = this.$inputor[0].id || this.uid();
this.expectedQueryCBId = null;
this.setting = null;
this.query = null;
this.pos = 0;
Expand Down Expand Up @@ -359,8 +361,10 @@ Controller = (function() {

Controller.prototype.lookUp = function(e) {
var query, wait;
if (!(query = this.catchQuery(e))) {
return;
query = this.catchQuery(e);
if (!query) {
this.expectedQueryCBId = null;
return query;
}
this.app.setContextFor(this.at);
if (wait = this.getOpt('delay')) {
Expand Down Expand Up @@ -402,16 +406,24 @@ Controller = (function() {
}
};

Controller.prototype._generateQueryCBId = function() {
return {};
};

Controller.prototype._lookUp = function(query) {
var _callback;
_callback = function(data) {
_callback = function(queryCBId, data) {
if (queryCBId !== this.expectedQueryCBId) {
return;
}
if (data && data.length > 0) {
return this.renderView(this.constructor.arrayToDefaultHash(data));
} else {
return this.view.hide();
}
};
return this.model.query(query.text, $.proxy(_callback, this));
this.expectedQueryCBId = this._generateQueryCBId();
return this.model.query(query.text, $.proxy(_callback, this, this.expectedQueryCBId));
};

return Controller;
Expand Down
2 changes: 1 addition & 1 deletion dist/js/jquery.atwho.min.js

Large diffs are not rendered by default.

88 changes: 88 additions & 0 deletions spec/javascripts/custom_callbacks.spec.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
describe "custom callbacks", ->
$inputor = null

beforeEach ->
loadFixtures("inputors.html")
afterEach ->
$inputor.atwho 'destroy'

describe "remoteFilter()", ->
it "only renders the view for data from the latest lookup", ->
callbackList = []

remoteFilter = jasmine.createSpy("remoteFilter").and.callFake (_, cb) ->
callbackList.push cb

$inputor = $("#inputor").atwho({
at: "@",
data: [],
callbacks: {
remoteFilter
}
})
$inputor.val('@foo')

app = getAppOf $inputor
controller = app.controller()
spyOn(controller, 'renderView')

simulateTypingIn $inputor
expect(remoteFilter).toHaveBeenCalled()
simulateTypingIn $inputor
expect(callbackList.length).toBeGreaterThan(1)
while callbackList.length > 1
callbackList.shift()(['no renders'])
expect(controller.renderView).not.toHaveBeenCalled()

callbackList.shift()(['render'])
expect(controller.renderView).toHaveBeenCalled()

it "does not attempt to render the view after query has been cleared", ->
remoteFilterCb = null

remoteFilter = jasmine.createSpy("remoteFilter").and.callFake (_, cb) ->
remoteFilterCb = cb

$inputor = $("#inputor").atwho({
at: "@",
data: [],
callbacks: {
remoteFilter
}
})

app = getAppOf $inputor
controller = app.controller()
spyOn controller, 'renderView'

simulateTypingIn $inputor
expect(remoteFilter).toHaveBeenCalled()
$inputor.val ''
simulateTypingIn $inputor
expect(remoteFilter.calls.count()).toEqual(1)
remoteFilterCb ['should not render']
expect(controller.renderView).not.toHaveBeenCalled()

it "does not attempt to render the view after focus has been lost", ->
remoteFilterCb = null

remoteFilter = jasmine.createSpy("remoteFilter").and.callFake (_, cb) ->
remoteFilterCb = cb

$inputor = $("#inputor").atwho({
at: "@",
data: [],
callbacks: {
remoteFilter
}
})

app = getAppOf $inputor
controller = app.controller()
spyOn controller, 'renderView'

simulateTypingIn $inputor
expect(remoteFilter).toHaveBeenCalled()
$inputor.blur();
remoteFilterCb ['should not render']
expect(controller.renderView).not.toHaveBeenCalled()
4 changes: 3 additions & 1 deletion src/app.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ class App
.on 'scroll.atwhoInner', (e) =>
this.controller()?.view.hide(e)
.on 'blur.atwhoInner', (e) =>
c.view.hide(e,c.getOpt("displayTimeout")) if c = this.controller()
if c = this.controller()
c.expectedQueryCBId = null
c.view.hide(e,c.getOpt("displayTimeout"))
.on 'click.atwhoInner', (e) =>
this.dispatch e

Expand Down
21 changes: 16 additions & 5 deletions src/controller.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class Controller
constructor: (@app, @at) ->
@$inputor = @app.$inputor
@id = @$inputor[0].id || this.uid()
@expectedQueryCBId = null

@setting = null
@query = null
Expand Down Expand Up @@ -90,7 +91,10 @@ class Controller

# Searching!
lookUp: (e) ->
return if not query = this.catchQuery e
query = @catchQuery e
if not query
@expectedQueryCBId = null
return query
@app.setContextFor @at
if wait = this.getOpt('delay')
@_delayLookUp query, wait
Expand All @@ -112,18 +116,25 @@ class Controller
, wait)
else
@_stopDelayedCall()
@previousCallTime = 0 if @previousCallTime isnt now
@previousCallTime = 0 if @previousCallTime isnt now
@_lookUp query

_stopDelayedCall: ->
if @delayedCallTimeout
clearTimeout @delayedCallTimeout
@delayedCallTimeout = null
@delayedCallTimeout = null

_generateQueryCBId: ->
return {};

_lookUp: (query) ->
_callback = (data) ->
_callback = (queryCBId, data) ->
# ensure only the latest instance of this function perform actions
if queryCBId isnt @expectedQueryCBId
return
if data and data.length > 0
this.renderView @constructor.arrayToDefaultHash data
else
@view.hide()
@model.query query.text, $.proxy(_callback, this)
@expectedQueryCBId = @_generateQueryCBId()
@model.query query.text, $.proxy(_callback, this, @expectedQueryCBId)

0 comments on commit e88fa03

Please sign in to comment.