<!doctype html>
<html>
<head>
<title>Test Page</title>
body { font: normal 87%/1.4 Arial, sans-serif; }
input { width: 35em; }
div input { width: auto; }
xp { margin: 1.4em 0 1ex; }
</style>
</head>
<body class="yui-skin-sam">
<h1>The typing-pause special event</h1>
<p>
<label for="in">Type here and look for responses in the console</label>
</p>
<input id="in">
<div>
<p>
<input type="radio" name="mode" id="mode1" value="1" checked="checked">
<label for="mode1">Simple default subscription</label>
</p>
<p>
<input type="radio" name="mode" id="mode2" value="2">
<label for="mode2">Non-adaptive subscription (400ms delay)</label>
</p>
<p>
<input type="radio" name="mode" id="mode3" value="3">
<label for="mode3">Configured sub, fires after mention of "dog"</label>
</p>
<button type="button" id="attach">attach</button>
<button type="button" id="attach_handle">attach + handle</button>
<button type="button" id="attach_cat">attach + category</button>
<button type="button" id="detach">detach by signature</button>
<button type="button" id="detach_handle">detach by handle</button>
<button type="button" id="detach_cat">detach by category</button>
<button type="button" id="detach_nofn">detach without fn</button>
<button type="button" id="remove">remove buttons</button>
</div>
<script>
YUI({
lazyEventFacade: true
}).use('node-base', 'event-synthetic', function (Y) {
function asIs(x) { return x; }
Y.Event.define('typing-pause', {
processArgs: function (args) {
// Extract configuration from third position in the args
// Apply defaults to the returned config object.
return Y.mix({
adaptive: true,
minLength: 1,
minWait: 400,
maxWait: 3000,
waitMultiplier: 4,
filter: asIs,
}, (args.splice(3,1)[0] || {}), true);
},
on: function (node, sub, ce) {
sub._cat = Y.guid();
sub._strokes = 0;
sub._first = 0;
sub._args = Y.Array(arguments, 4, true);
node.on(sub._cat+'|keyup', this._handleKey, null, sub, ce);
node.on(sub._cat+'|blur', this._handleBlur, null, sub, ce);
},
detach: function (node, sub, ce) {
node.detach(sub._cat + '|*');
clearTimeout(sub._timer);
},
// Support functions
_handleKey: function (e, sub, ce) {
// Allow delete and backspace, but not shift, alt, ctrl, etc
return;
}
config = sub._extra,
minLength = config.minLength,
minWait = config.minWait,
maxWait = config.maxWait,
delay, now;
if (sub._timer) {
delete sub._timer;
}
if (config.adaptive) {
now = new Date();
++sub._strokes;
// On first key stroke, use maxWait because we don't
// have enough data to calculate a reasonable delay
if (sub._strokes === 1) {
sub._first = now;
delay = maxWait;
} else {
// @TODO: intentional pauses should not affect
// the average (e.g. fast typist that pauses
// enough to trigger the event, then leaves
// focus in the input. The avg is then
// skewed.)
delay = (now - sub._first) / sub._strokes;
delay = Math.round(delay) * config.waitMultiplier;
if (delay > maxWait) {
delay = maxWait;
}
}
if (delay < minWait) {
delay = minWait;
}
} else {
delay = minWait;
}
// Schedule firing according to the appropriate delay
ce.fire({
inputValue: raw,
value: value,
lastKeyEvent: e,
target: this,
currentTarget: this
});
});
}
},
_handleBlur: function (e, sub, ce) {
sub._strokes = 0;
if (sub._timer) {
delete sub._timer;
}
}
});
/****************************************************************/
/********************** Test implementation *********************/
/****************************************************************/
var handle, last;
function notify(e) {
}
last = new Date();
});
switch (mode) {
adaptive: false
}); break;
//adaptive: true,
minLength: 8,
minWait: 1000,
maxWait: 5000,
waitMultiplier: 2,
filter: function (v) {
}
});
}
});
switch(mode) {
adaptive: false
}); break;
minLength: 8,
minWait: 1000,
maxWait: 5000,
waitMultiplier: 2,
filter: function (v) {
}
});
}
});
switch (mode) {
adaptive: false
}); break;
minLength: 8,
minWait: 1000,
maxWait: 5000,
waitMultiplier: 2,
filter: function (v) {
}
});
}
});
switch (mode) {
}
});
});
switch (mode) {
}
});
switch (mode) {
case 2: all('#in').detach('typing-pause'); break;
}
});
inner.remove(true);
Y.log('Detached');
});
});
</script>
</body>
</html>