______
/\__ _\ __
\/_/\ \/ __ __ _____ __ _ __ /\_\ ____
\ \ \ /\ \/\ \ /\ '__`\ /'__`\/\`'__\ \/\ \ /',__\
\ \ \\ \ \_\ \\ \ \L\ \/\ __/\ \ \/ __ \ \ \ /\__, `\
\ \_\\/`____ \\ \ ,__/\ \____\\ \_\/\_\ _\ \ \\/\____/
\/_/ `/___/> \\ \ \/ \/____/ \/_/\/_//\ \_\ \\/___/
/\___/ \ \_\ \ \____/
\/__/ \/_/ By: The Qodesmith \/___/
Typer.js ·
Typer.js is an easy to use, choc-full-of-options, robust automated typing library. There are a number of methods with various options for you to impress your friends, have a parade thrown in your name, and officially obtain "that guy" status ("that gal" for the ladies).
Typer.js has no library dependencies so just slap it on your page and go. We still love you, jQuery. And the minified file is only 4k gzipped!
In short... Typer.js can type regular characters, unicode characters, whole words, half words, HTML elements, erase stuff, go fast, go slow, make new lines, fire events, listen to events, run functions, and make julienne fries in minutes.
Quick Links - API Methods
- Cursor
- Line
- Back
- Continue
- Pause
- Emit
- Listen
- Empty
- Run
- End
- Kill
- Halt
- Resume
- Repeat
- Kill Switch (non-api feature)
Installation
Manually
Simply include typer.css
in the <head>
...
<head>
...
<link rel="stylesheet" href="typer.css" />
<!-- Via Unpkg CDN -->
<!-- <link rel="stylesheet" href="https://unpkg.com/typer-js/dist/typer.min.css"> -->
</head>
and include typer.min.js
just above your closing </body>
tag...
<body>
...
<script src="typer.min.js"></script>
<!-- Via Unpkg CDN -->
<!-- <script src="https://unpkg.com/typer-js"></script> -->
</body>
Via NPM
From the CLI run:
npm install typer-js
In your project require
this library:
const typer = require('typer-js')
Use fancy import
for inclusion:
import typer from 'typer-js'
Files & locations:
File | Location | Description |
---|---|---|
typer.min.js | node_modules/typer-js/ | minified main file (4k gzipped!) |
typer.css | node_modules/typer-js/ | stylesheet necessary for the cursor |
typer.less | node_modules/typer-js/less | less: use it for your own builds |
Usage
typer(target, speed)
The Typer function itself takes two arguments:
-
target
- two possibilities:-
string
- a valid CSS selector, such as'.some-class'
,'#some-id'
, or'.a-class .in-a-class'
, for Typer to grab (withdocument.querySelector
) and type in. -
element
- a single DOM element, such asdocument.body
ordocument.querySelector('div')
.
-
-
speed
- (optional) two possibilities:-
number
- a number (milliseconds) representing how fast each character should be typed out. -
object
- an object specifying the speed. When you want to "humanize" the speed, supply numbers formin
andmax
properties. This will indicate to Typer that you want to "humanize" the speed for all lines (per-line speeds, if provided, override this speed).
-
* Note: Typer will default to a speed of 70 if nothing is provided.
Now you can begin calling Typer's various methods via simple & sexy dot-notation...
Simple Code Examples
Type a single line:
// Type in the body element.
typer('body').line('Typer.js is awesome!')
// Same example with a DOM element and humanized speed.
typer(document.body, {min: 20, max: 350}).line(
'Humanizing the speed will look more, uh, human.',
)
// Providing a DOM element and speed.
const element = document.querySelector('#some-id')
typer(element, 100).line('Using a DOM element as the 1st argument works!')
Type a single line, correct mispelling with back:
typer('.some-class').line('This function roolz.').back(5).continue('ules!')
Type a list of frameworks with the help of pause & back:
typer('#some-id')
.line('Backbone')
.pause(1000)
.back('all')
.continue('Angular')
.pause(1000)
.back('all')
.continue('React!!')
Multi-line typing:
const element = document.querySelector('.my-element')
typer(element).line('How cool is this?').line('So very cool.').line('Agreed!')
Repeat automatically:
// Repeat something forever.
typer('.some-class')
.line('I love JavaScript.')
.pause(1000)
.back('all')
.repeat(Infinity)
Methods
CURSOR
The .cursor
method takes a single argument: false
or {an: object}
. You can specify the 3 options below within the object. .cursor
can be omitted altogether which will result in the default styles mentioned below. Default options need not be given as they will take effect unless otherwise specified.
No cursor
.cursor(false)
Options
block
.cursor({ block: true })
-
false
- (default) The cursor will be a standard vertical line. -
true
- The cursor will be a block, inspired from older style terminals.
blink
.cursor({ blink: 'hard' });
-
'soft'
- (default) Smooth blinking animation. -
'hard'
- Binary (on / off) blinking animation.
color
// Examples.
.cursor({ color: 'red' })
.cursor({ color: '#ff0000' })
.cursor({ color: 'rgb(255,0,0)' })
.cursor({ color: 'rgba(255,0,0,0.7)' })
- You can specify any css color you want via any method (i.e. name, rgb, hsla, etc.).
- As a default, Typer will grab the color attribute of the parent element and use that for the cursor color to match the text with the cursor.
all options at once
.cursor({ block: true, blink: 'hard', color: 'red' })
LINE
// Examples.
.line() // Creates a blank line.
.line('Typer.js is visual awesomeness!')
.line('Typer.js is visual <em>awesomeness!</em>', 100)
.line(['Type. ', 'Whole. ', '<span style="color: yellow;">Words.</span>'], 200)
.line('Typer can "humanize" the speed with min & max values.', {
min: 30,
max: 350,
element: 'p',
html: false
})
.line('Typer.js is <span style="color: red">visual</span> awesomeness!', {
speed: 150,
element: 'span'
})
.line({ // Grab content from a hidden div & type it. #SEO!!!
container: '.hidden-content',
element: 'span',
totalTime: 3500 // Take 3.5 seconds to type it all out.
})
.line('MISSION ACCOMPLISHED', { // Military typing!
military: {
chars: 5,
speed: 50
}
})
The .line
method is at the heart of Typer. As the name suggests, it types out a single line.
You can feed it a 'single string'
, an ['array', 'of', 'strings']
, or an options object containing at least a container
property. .line
defaults to parsing HTML, so you must explicitly tell it not to within the options object.
Arguments
- Argument 1 - three possibilities:
-
string
- The message you want typed out, character by character (normal typing). -
array
- The message you want typed out, item by item (word by word). -
object
- An options object. If this is the only argument passed to.line
, it must have thecontainer
property.
-
- Argument 2 (optional) - two possibilities:
-
number
- A speed in milliseconds. Each line can optionally have its own typing speed. If no speed is given, it defaults to the number given to thetyper
function itself or Typer's internal default of 70. -
object
- An options object. This object will be ignored if you provided an options object to argument 1. This object takes all the same options as the object used in argument 1 minus thecontainer
property. Don't providecontainer
with this object, it will be ignored.
-
* TIP: If you supply no arguments, you will create a blank line.
Options
* NOTE: If you're passing in an options object to argument 1, argument 2 will be ignored.
container
Values:
-
string
- any valid CSS selector -
element
- a DOM element
.line({ container: '.hidden-content' }) // Valid CSS selector.
.line({ container: document.body }) // Valid DOM element.
SEO in the house! You can tell .line
to use the contents of a pre-existing element on the page. So, for instance, you can hide a paragraph of text with CSS (display: none
) which will still be indexed by search engines and use it to feed Typer! Amazing.
min / max
Value: number
.line({ container: '.hidden-content', min: 30, max: 350 })
.line('Humanize the speed of typing stuff', { min: 30, max: 350 })
We all want our robot overlord's to be more, uh, human. And so Typer delivers! Typer has the ability to "humanize" the typing speed. Provide min
and max
properties which define a range within which Typer will pick a random number for each character's typing speed. Voila. It's like a real person typing. Only not.
speed
Value: number
.line({ container: '.hidden-content', speed: 50 })
.line('The speed property is usually specified with other options.', { speed: 100, html: false })
.line("Just use a plain number if you're only specififying speed.", 100)
.line('However, this will work just fine.', { speed: 100 })
When using an options object as the 2nd argument to .line
, the speed property is usually accompanied by other options, such as html
or element
.
NOTE: the speed
option will take priority over min
and max
if they are all provided. For example, if your options look like {speed: 50, min: 10, max: 300}
, Typer will only process speed
.
totalTime
Value: number
.line({ container: '.hidden-content', totalTime: 4500 })
.line('This should take 3 seconds to type', { totalTime: 3000 })
.line('This line is much longer but will also only take 3 seconds to type.', { totalTime: 3000 })
.line(['Works', ' with', ' arrays.'], { totalTime: 2000 })
.line('And <strong>HTML</strong> too!', { totalTime: 1500 })
Instead of specifying how fast you want things to type, with the totalTime
option you specifiy how long you want it to take.
NOTE: the totalTime
option will take priority over all other speed-related options. For example, if your options look like {speed: 50, min: 10, max: 300, totalTime: 3000}
, all the other speed-related options will be ignored and Typer will only process totalTime
.
military
Values:
number
object
.line('A number representing speed of change', { military: 50 })
.line('Speed of change <strong>and</strong> # of characters:', { military: { speed: 50, chars: 5 } })
.line(["Doesn't", ' work', ' with', ' arrays.'], { military: 25 }) // No effect.
Atteeeeeeeen-tion! I geek out about this one. What the military option does is for each character that needs to be typed it first scrolls through typing out a handful of random characters in its place.
Passing a number represents the scrolling speed - how fast the random characters will change.
Passing an object let's you specify the scrolling speed
and how many random characters (chars
) will be scrolled before typing the actual content you supplied and moving on.
NOTE: When supplying an array to be typed, the military
option will be ignored.
NOTE: Because it takes time to scroll through random characters before something is typed out, timing options such as totalTime
will be affected.
html
Values:
-
true
(default) false
.line({ container: '.hidden-content', html: false })
.line('Do <em>not</em> process this as html.', { html: false })
.line("No need to tell <strong>Typer</strong> to process html since that's the default.")
Typer can handle html, unicode, and all sorts of craziness (see below). It defaults to processing contents as html so you need to explicitly tell it not to.
HTML / Unicode
Go nuts. You can include <div>
's, <span>
's, elements with styles (i.e. <span style="color: red;">I'm red!</span>
), <em>
's, <strong>
's, etc. You can also include HTML void elements (self-closing tags) such as <br>
, <img>
, and <hr>
. If you're really feeling brave, start including <textarea>
's and <input>
's!.
Valid unicode characters begin with &
and end with ;
. Some examples:
Character | Code | Character | Code | Character | Code |
---|---|---|---|---|---|
🐇 |
→ | → |
☎ |
||
® | ® |
↘ |
♪ | ♪ |
|
¼ | ¼ |
↓ | ↓ |
♥ |
HTML / Unicode examples:
The following code...
typer('body')
.line('<em>How will I look?</em>')
.line('<em>How will I look?</em>', {html: false})
.line('Cookies & milk')
.line('Cookies & milk')
.line('Cookies & milk', {html: false})
.line('The ✈ flies ↑ in the sky.')
will result in this output on the screen:
How will I look?
> <em>How will I look?</em>
Cookies & milk
Cookies & milk
Cookies & milk
The✈ flies ↑ in the sky.
BACK
Arguments
The 1st argument is mandatory and has three options. The 2nd argument is optional and has a different effect based upon the 1st argument (O.o). These arguments are order sensative. Now, stop arguing and .continue
reading...
- Argument 1 - three possibilities:
-
number
- number of characters to be erased / how many times you want to "hit" the "backspace button".- Positive #'s erase that many characters.
- Negative #'s keep that many characters. For example, a value of -2 will erase all but two characters.
-
string
('all'
) - this will "backspace" the entire line, character by character, without you having to give a number. Useful for longer lines and those wanting to avoid math. -
string
('empty'
) - this will empty the entire line at once. The 2nd argument can have effects on this behavior (see below).
-
- Argument 2 - one type, two possibilities:
-
number
(when arg 1 is not'empty'
) - the speed at which the backspace will perform. If no number is specified, it will default to the user-supplied Typer speed or Typer's internal default of 70. -
number
(when arg 1 is'empty'
) - if positive (i.e.15
), the number of character to erase at once, else if negative (i.e.-15
), the number of characters to leave remaining.
-
Some examples to dispel confusion (hopefully):
.back(10) // Erase 10 characters at the default speed.
.back(-10) // Erase *all-but* 10 characters at the default speed.
.back(10, 5) // Erase 10 characters at a speed of 5 milliseconds per character.
.back(-10, 5) // Erase *all-but* 10 characters at a speed of 5 milliseconds per character.
.back('all') // Erase all characters at the default speed.
.back('all', 5) // Erase all characters at a speed of 5 milliseconds per character.
.back('empty') // Erase all the character *at once*.
.back('empty', 15) // Erase 15 characters *at once*.
.back('empty', -15) // Erase *all-but* 15 characters *at once*.
CONTINUE
// Examples.
.continue("I'm on the same line!")
.continue(' Same line, emphasis on <em>sloooow</em>.', 500)
.continue(" Now let's <strong>ignore</strong> <em>html</em>", { html: false })
.continue(' Type more like a human would!', { min: 30, max: 350 })
.continue([' Whole sentence at once.'])
.continue({
container: '.hidden-div', // This property is mandatory when using a single options object.
speed: 500,
html: false
})
.continue({
container: document.querySelector('.hidden-div'),
min: 30,
max: 350
})
The .continue
method works just like .line
in that it accepts all the same arguments & options but it continues typing on the same line, whereas .line
creates new lines. In conjunction with the .pause
and .line
methods, you can create eloborate schemes. You can feed .continue
the same content (HTML, unicode, etc.) as .line
.
Arguments
Same as those for .line
(above).
* NOTE: unlike .line
, calling .continue
with no arguments will produce no effect.
* NOTE: .continue
will ignore the container
property.
PAUSE
// Examples.
.pause() // 500ms default time.
.pause(1000)
The .pause
method takes a single argument, a number in milliseconds. Typer will wait that long before proceeding to the next called method. If no argument is provided, the default is 500.
EMIT
// Examples.
let element = document
.querySelector('#some-id')
.emit('boom') // Fires off the body.
.emit('boom', '.some-class') // Fires off a specific element (string selector).
.emit('boom', element) // Fires off a specific element (element provided).
Emits an event on a specified DOM element or defaults to the body
. This is useful for setting up complex automation scenarios where multiple Typer functions (or other functions on your page) are time-dependant on eachother. DOM event explosions causing mass automated awesomeness. What could be better?
Arguments
- Argument 1:
string
- the event name; Omitting a 2nd argument will default to the event firing from thebody
. - Argument 2:
string
orelement
- (optional) target a DOM element that the event will be fired from. Provide a string CSS selector or an HTML element.
LISTEN
// Examples.
let element = document
.querySelector('#some-id')
.listen('boom') // Listens on the body.
.listen('boom', '.some-class') // Listens on a specific element (string selector).
.listen('boom', element) // Listens on a specific element (element provided).
Typer has the ability (read: super-power) to listen for events as well. The .listen
method will stop Typer in its tracks until the specified event is fired. Once fired, Typer will proceed from where it last left off. More automation goodness.
Arguments
- Argument 1:
string
- the event name; Omitting a 2nd argument will default to the listener listening from thebody
. - Argument 2:
string
orelement
- (optional) target a DOM element that the listener will be placed on. Provide a string CSS selector or an HTML element.
* NOTE: Typer uses one-time event listeners. Once the event is fired the listener is triggered and then immediately removed. See how tidy we are?
EMPTY
.empty()
The .empty
method empties the parent element (specified as the 1st argument to typer
) and starts over with a fresh line.
The parent element could contain multiple lines and HTML elements, the likes of which cannot be undone with a simple .back('all')
. Also, .empty
will instantaneously empty the parent element as opposed to backspacing it into oblivion. Have fun.
RUN
.run(function() { /* do stuff */ })
.run(function(el) { /* do stuff with access to parent element */ })
To round out our automation tools, the .run
method will do just that: run a function before proceeding with any additional methods. Feed it a function and let it fly.
Access to the parent element
The .run
method exposes the parent element that Typer is currently typing in through an argument in the function you pass to .run
(el
in the example above).
END
.end()
.end(true) // Fire off the `typerFinished` event.
.end(true, function() { /* do stuff */ }) // Event fired.
.end(function() { /* do stuff */ })
.end(function() { /* do stuff */ }, true) // Event fired.
.end(function(el) { /* do stuff with access to parent element */ }, true) // Event fired.
Arguments
The .end
method always removes the cursor, can optionally execute a callback function, and optionally fire off the typerFinished
event. The event can be used to trigger other things in your application. These arguments are completely optional. The order of the arguments is not strict but the callback will always be executed before firing the typerFinished
event.
- callback - A function you want executed when
typer
is finished. -
true
- Indicates you want thetyperFinished
event fired once Typer is finished. This event is fired from the<body>
. The default (if left unspecified) is false.
Access to the parent element
As with the .run
method above, .end
exposes the parent element that Typer is currently typing in through an argument in the function you pass to to .end
.
KILL
.kill()
The .kill
method will terminate an individual Typer instance. It takes no arguments. This feature is useful when you want to ensure a Typer instance is no longer running, perhaps in a single-page application when the view changes. You can also use the Kill Switch (below) to terminate all instances at once. This method also cleans up any and all event listeners that the instance produced.
* NOTE: Chaining any other methods after .kill
will produce no effect.
const t1 = typer('#some-id-1').line('This is the first instance of Typer.')
const t2 = typer('#some-id-2').line(
'This is the second instance of Typer that we want to kill.',
)
// after some time...
t2.kill() // <-- This instance will stop while 't1' remains unaffected.
HALT
.halt()
This method is like having a remote control that can stop Typer whenever you want. It's different than the pause method because pause
needs to be declared at runtime. Once you've started the Typer process you can't "pause" it again with the pause
method at will - it would have to have already been declared.
With halt
, you can stop Typer at will. The only catch is that if Typer is in a "pause" or "listen" state, halt
will do nothing. Other than that, feel free to have at it!
const t1 = typer('.some-class').line(aReallyLongString)
// Wait 1 second and halt Typer in the middle of typing:
setTimeout(() => t1.halt(), 1000)
RESUME
.resume()
This method - wait for it - resumes Typer from where halt
left off! It's easy peezy. Here's an example:
const t1 = typer('.some-class').line(aReallyLongString)
// Wait 1 second and halt Typer in the middle of typing:
setTimeout(() => t1.halt(), 1000)
// Go get a sandwich, stretch, come back...
setTimeout(() => t1.resume(), 5000)
Here's an example of using a button to toggle between halting & resuming Typer:
let halted = false
document.querySelector('.my-button').addEventListener('click', () => {
halted ? t1.resume() : t1.halt()
halted = !halted
})
REPEAT
.repeat(Infinity) // Repeat forever.
.repeat(3) // Repeat 3 times.
.repeat(3, true) // Repeat 3 times, clearing the contents each time.
There are times where you want to continuously repeat a set of instructions. While you could achieve this on your own, Typer includes the .repeat
method to allow you to do this programmatically.
* NOTE: Repeat is really meant to be called last. If you call it more than once in your setup, each repeat will start repeating instructions from the last repeat or the beginning - whichever comes first.
Arguments
- Argument 1:
number
- how many times you want to repeat the prior commands. - Argument 2:
boolean
- (optional) indicates wether to clear the contents before repeating or not.
END OF METHODS
Kill Switch
Typer's kill switch feature let's you annihilate all Typer instances no matter what they're currently doing. This is particularly useful for single-page applications to prevent Typer from continuing in the background even after a view has been removed from the DOM. The kill switch will also remove any current listener any Typer instance has on a DOM element.
* NOTE: If you have multiple instances of Typer running on the page, this will kill them all.
How to use:
This is an example function you can use to flip the kill switch:
function killTyper() {
const kill = new Event('killTyper')
document.body.dispatchEvent(kill)
}
To activate Typer's kill switch, a killTyper
event must be dispatched from the <body>
. That's it.
Showcase
Have you done something cool with Typer.js? Have an awesome site / use-case you'd like to share? Contact me! I'd love to show off your awesomeness with a link here.
- http://aaroncordova.xyz/this-isnt-real - awesome 404 pages (random page each time)
- http://mihaeltomic.com/ - cool introduction
Feature Requests
I think I thought of everything, but I thought wrong once, even though I think I'm right.
O.o If you think of a feature you feel would be an awesome addition to Typer, raise an issue or create a pull request. I'm all ears.