Wijmo 5 - Event Debouncing
Shows how to debounce Wijmo events so they don't fire too often.
HTML
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="http://cdn.wijmo.com/5.latest/styles/wijmo.min.css">
<script src="http://cdn.wijmo.com/5.latest/controls/wijmo.min.js"></script>
<script src="http://cdn.wijmo.com/5.latest/controls/wijmo.input.min.js"></script>
<script src="http://cdn.wijmo.com/5.latest/controls/wijmo.grid.min.js"></script>
<script src="http://cdn.wijmo.com/5.latest/controls/wijmo.chart.min.js"></script>
<script src="http://cdn.wijmo.com/5.latest/controls/wijmo.gauge.min.js"></script>
<script src="http://cdn.wijmo.com/5.latest/interop/angular/wijmo.angular.min.js"></script>
<div class="container" ng-app="app" ng-controller="appCtrl">
<h1>Event Debouncing</h1>
<p>
When handling events that fire in bursts, like mouse moves,
key presses, or selection changes, you may be able to improve application
performance by "debouncing" the event (handing it only a little while after
it stops firing).</p>
<p>
For example, this <b>FlexGrid</b> control handles the <b>selectionChanging</b>
and <b>mousemove</b> events synchronously (without debouncing). The event
handler calls a "sleep" method to simulate a lengthy operation.</p>
<wj-flex-grid style="max-height:150px" items-source="data" initialized="initRegular(s,e)">
</wj-flex-grid>
<p>
And this <b>FlexGrid</b> control handles the <b>selectionChanging</b> and <b>mousemove</b>
events using the same handlers, but this time with a 500ms debounce.</p>
<wj-flex-grid
items-source="data"
initialized="initDebounced(s,e)">
</wj-flex-grid>
<p>
The log elements below show how the <b>selectionChanging</b> and <b>mousemove</b> events
get handled. For the top grid, the logs are updated immediately after each selection change
and mouse move. For the bottom grid, they are updated 500ms after the events stop firing.</p>
<div id="logsel" class="log">
selection...
CSS
.wj-flexgrid {
max-height: 150px;
}
.wj-radialgauge {
width: 300px;
margin: auto auto;
}
.log {
font-size: 150%;
color: #800000;
text-align: center;
}
p {
margin-top: 12px;
}
JavaScript
var app = angular.module('app', ['wj']);
app.controller('appCtrl', function($scope) {
// attach Wijmo and DOM event handlers without debouncing
$scope.initRegular = function(s, e) {
s.selectionChanging.addHandler(selectionChanging, this); // Wijmo event
s.addEventListener(s.hostElement, 'mousemove', mouseMove); // DOM event
};
// attach Wijmo and DOM event handlers with debouncing
$scope.initDebounced = function(s, e) {
s.selectionChanging.addHandler(debounce(selectionChanging, 500), this); // Wijmo event
s.addEventListener(s.hostElement, 'mousemove', debounce(mouseMove, 500)); // DOM event
};
// handle gauge's valuechanged event
$scope.valueChangedDebounced = debounce(function(s, e) {
$scope.theGaugeValue = s.value;
$scope.$apply();
}, 300);
// Wijmo event handler
function selectionChanging(s, e) {
var sel = e.range;
log('logsel', 'Selection Changing to (' + sel.row + ', ' + sel.col + ')');
sleep(100); // simulate an expensive handler
}
// DOM event handler
function mouseMove(e) {
log('logmove', 'Mouse Moved to (' + Math.round(e.pageX) + ', ' + Math.round(e.pageY) + ')');
sleep(100); // simulate an expensive handler
}
// log events
function log(id, msg) {
document.getElementById(id).textContent = msg;
}
// simulate expensive event handling
function sleep(milliseconds) {
var start = Date.now();
for (;;) {
if (Date.now() - start > milliseconds) {
break;
}
}
}
// create some data
var items = 'Apple,Apricot,Banana,Blueberry,Cherry,Coconut,Grape'.split(',');
$scope.data = [];
for (var i = 0; i < 100; i++) {
$scope.data.push({
id: i,
fruit: items[i % items.length],
qty: i % 12,
check: (i % 3 == 0)
});
}
});
/**
* Returns a function that calls another function after being
* called at least once and then not called again for a specified
* interval.
*
* This can be used when implementing some...