README
Zen Area — textarea with inner power
This is a work in progress. Stay tuned for 1.x.x releases!
This tiny (~15Kb minified) framework-agnostic library provides an extensible set of commands along with some fluent API.
Use them to train your textarea into powerful text processing warrior.
Add a few lines of code:
new ZenArea(document.querySelector('textarea'))
.bind('Tab', 'indent')
.bind('Shift + Tab', 'outdent');
Congrats, you've just trained your textarea to indent selected lines with Tab and remove indentation with Shift+Tab.
You can also bind commands to UI (buttons, menus, etc.) and easily create your own commands.
Key Features
- Vanilla JavaScript, no dependencies
- Supports modern browsers and IE9
- Designed with/for Browserify
- Compatible with RequireJS/AMD
- No custom/shadow elements — only textarea and you
- Undo/redo friendly (well, mostly, see below)
Install
Browserify
We highly recommend building front-end with npm and Browserify. Installation is trivial:
npm i zenarea
var ZenArea = require('zenarea');
AMD/RequireJS
Grab latest build
into your project and require it (ZenArea
class is exposed).
Script tag
Grab latest build and include it to your page:
<script src="/js/zenarea.js"></script>
The ZenArea
class is now bound to window
.
Usage
This library exposes ZenArea
constructor which accepts a single textarea Element:
var z = new ZenArea(document.querySelector('textarea'));
This instance holds all API methods described below.
Binding commands to keyboard
Commands are simply API methods defined on ZenArea.prototype
.
You can bind any command to your keyboard like this:
z.bind('Ctrl + B', 'surround', ['*', '*', true]);
Pressing Ctrl+B is now equivalent to
z.surround('*', '*', true)
See? It's also pretty easy to add your own command.
By default ZenArea does not bind any command, it's up to you to teach your textarea your favorite kung fu style.
Init / destroy
ZenArea attaches certain events listeners to textarea (e.g. keydown).
Use z.destroy()
to remove them — this is especially useful in
Single Page Applications to prevent memory leaks.
Once ZenArea has been destroyed it is possible to return it back to its former
glory with z.init()
.
Custom commands
Commands are simply methods defined on ZenArea.prototype
.
You can add new command to all ZenArea instances like this:
ZenArea.prototype.sayHello = function(name) {
return this.insetText('Hello, ' + name);
}
Here's how you bind this command to Ctrl+H:
z.bind('Ctrl + H', 'sayHello', ['World']);
API
Selection
selection
property returns current user selection like this:{ start: 10, end: 15, length: 5, value: 'World' }
select(start[, end])
sets user selection range to specified indices (e.g.z.select(0, z.value.length)
selects everything in textarea)selectAll()
— select everythingselectLines(start[, end])
— select lines between specified indicesselectCurrentLines()
— expand selection in both directions up to line boundariesselectLeft(predicateFn)
— expand selection to the left untilpredicateFn(sel)
returnstrue
selectRight(predicateFn)
expandSelection()
— expand selection: from caret to word, from word to line, from line to everything
Manipulation
insertText(text[, preserveSelection])
— replace selected text with specified one; passingtrue
as second argument will also select this textindent([indentation])
— prepends each current line with specified indentation chars (two spaces by default), preserving original selection; if nothing is selected, just inserts indentation chars at caret positionoutdent([indentation])
— removes specified indentation chars from current lines, preserving original selectionsurround(prefix, suffix[, toggle])
— surrounds selected text withprefix
andsuffix
; when the third argument is truthy it will detect already surrounded text and de-surround it (e.g. strip prefix and suffix instead)
Search & Replace
search(regex[, startIndex])
— selects first match ofregex
starting at specifiedstartIndex
searchNext(regex)
- likesearch
, but starts at the end of current selectionreplace(regex, replacement[, startIndex])
— replaces first match ofregex
replaceNext(regex, replacement)
— likereplace
, but starts at the end of current selectionreplaceAll(regex, replacement)
— replaces all matches ofregex
withreplacement
(theg
flag on regex is mandatory, otherwise just replaces first occurrence)
Getters
Getters return selection objects without modifying actual user selection in textarea:
z.get(0, 5)
// { start: 0, end: 5, length: 5, value: 'Hello' }
// current user selection not modified
Selection API delegates to getters to evaluate start/end indices of selection. Therefore getters are essentially non-mutating helpers for their selection counterparts.
get(start, end)
returns a selection object for a substring between specified indicesgetLines(start, end)
getCurrentLines()
getExpandedLeft(predicate)
getExpandedRight(predicate)
getExpanded()
Known issues
Undo/redo is known to be broken in IE after manipulation commands.
This is due to the fact that
initTextEvent
does not remove text when an empty string is passed as andata
, causing some commands likedeleteText
,deleteCurrentLines
, etc. to fail silently.
License
ISC / Boris Okunskiy