malarkey
Version:
Simulate a typewriter effect in vanilla JavaScript.
135 lines (120 loc) • 3.02 kB
JavaScript
var DELETE_ALL_SENTINEL = -1
function noop () {}
function malarkey (callback, options) {
options = options || {}
var text = ''
var functionQueue = []
var functionArguments = []
var functionIndex = -1
var isStopped = true
var stoppedCallback = noop
var methods = {
call: function (fn) {
return enqueue(_call, [fn])
},
clear: function () {
return enqueue(_clear, null)
},
delete: function (characterCount, deleteOptions) {
if (typeof characterCount === 'object') {
deleteOptions = characterCount
characterCount = DELETE_ALL_SENTINEL
}
return enqueue(_delete, [
characterCount || DELETE_ALL_SENTINEL,
(deleteOptions ? deleteOptions.speed : options.deleteSpeed) || 50
])
},
isStopped: function () {
return isStopped
},
pause: function (pauseOptions) {
return enqueue(setTimeout, [
(pauseOptions ? pauseOptions.duration : options.pauseDuration) || 2000
])
},
triggerResume: function () {
if (isStopped) {
isStopped = false
next()
}
return methods
},
triggerStop: function (fn) {
isStopped = true
stoppedCallback = fn || noop
return methods
},
type: function (text, typeOptions) {
return enqueue(_type, [
text,
(typeOptions ? typeOptions.speed : options.typeSpeed) || 50
])
}
}
function next () {
if (isStopped) {
stoppedCallback(text)
stoppedCallback = noop
return
}
functionIndex += 1
if (functionIndex === functionQueue.length) {
if (!options.repeat) {
functionIndex = functionQueue.length - 1
isStopped = true
return
}
functionIndex = 0
}
functionQueue[functionIndex].apply(
null,
[next].concat(functionArguments[functionIndex])
)
}
function enqueue (callback, args) {
functionQueue.push(callback)
functionArguments.push(args)
if (isStopped) {
isStopped = false
setTimeout(next, 0)
}
return methods
}
function _type (next, typeText, typeSpeed) {
var length = typeText.length
var i = 0
setTimeout(function typeCharacter () {
text += typeText[i++]
callback(text)
if (i === length) {
next()
return
}
setTimeout(typeCharacter, typeSpeed)
}, typeSpeed)
}
function _delete (next, characterCount, deleteSpeed) {
var finalLength =
characterCount === DELETE_ALL_SENTINEL ? 0 : text.length - characterCount
setTimeout(function deleteCharacter () {
text = text.substring(0, text.length - 1)
callback(text)
if (text.length === finalLength) {
next()
return
}
setTimeout(deleteCharacter, deleteSpeed)
}, deleteSpeed)
}
function _clear (next) {
text = ''
callback(text)
next()
}
function _call (next, fn) {
fn(next, text)
}
return methods
}
module.exports = malarkey