Summary Using jquery.blockUI seems to hide / swallow / mask button click event.
Tech Stach
- backbone and marionette
- backbone.radio
- underscore
- jquery
- jquery.blockUI
(all latest version)
The App
The app consists of a text input and a button.
In terms of backbone/marionette terminology, there is
- a top view which has 2 regions
- container view which as the text input
- footer view which has the button
- The container view is backed by a model.
- The footer has a button, Clicking the button sends a backbone.radio event.
- This event is picked up in the top view.
When the user leaves the text input, an API (server / backend) is called. In the example a Promise / setTimeout is used to simulate the call.
In the example the button calls console.log.
Code
Here is the JSFiddle Example on JSFiddle and below the Javascript code
// ------------------------------------------------------------------
var Model = Backbone.Model.extend({
defaults: {
"SearchCriteria": {
"Min": { "value": "abc123", "ReadOnly": true }
}
},
async callBackend() {
//$.blockUI(); //<----- uncomment this and the button click is swallowed
await new Promise(resolve => setTimeout(resolve, 3000));
$.unblockUI();
}
});
// ------------------------------------------------------------------
// ------------------------------------------------------------------
var ContainerView = Marionette.View.extend({
template: _.template('<div><label>Container</label></div><div><input id = "min" name = "min" type = "text"/></div>'),
events: {
'change': 'onChangeData',
},
async onChangeData(data) {
console.log('start onChangeData');
await this.model.callBackend();
this.render();
console.log('end onChangeData');
}
});
// ------------------------------------------------------------------
// ------------------------------------------------------------------
var FooterView = Marionette.View.extend({
template: _.template('<div><button class="btn-footer-test">Footer</button></div>'),
events: {
"click .btn-footer-test": () => {
console.log('click test ...');
Backbone.Radio.channel("maske").trigger("select:test");
}
},
});
// ------------------------------------------------------------------
// ------------------------------------------------------------------
var TopView = Marionette.View.extend({
template: _.template("<div id='container'></div><div id='footer'></div>"),
regions: {
container: '#container',
footer: '#footer'
},
events: {
'change': 'onChangeData',
},
initialize() {
this.listenTo(Backbone.Radio.channel("maske"), "select:test", this.onTest, this);
},
onRender() {
this.showChildView('container', new ContainerView({
model: new Model()
}));
this.showChildView('footer', new FooterView());
},
onChangeData(data) {
},
onTest() {
//NOT called if jquery.blockUI present ******
console.log('onTest');
}
});
// ------------------------------------------------------------------
$(document).ready(function () {
console.log('Start');
const topView = new TopView();
topView.render();
$('body').append(topView.$el);
});
Use
The user uses the app like so. The user
- changes the text input
- and directly clicks the button (without tabbing out of the field first!)
Expected Behavior
- the change to the text input triggers a change event.
- jquery.blockUI
- async call
- jquery unblockUI
- the click event to the button is executed
Actual Behavior
When the jquery.blockUI function is present the click event to the button is not executed. Commenting jquery.blockUI the button click event occurs, however before the await returns.
Questions
- What am I doing wrong?
- Why is the click event swallowed?

