Archive for the ‘bililiteRange’ Category

This is a plugin for bililiteRange that implements a simple undo/redo stack. It listens for input events (so to use it in IE<10 you need some kind of polyfill) and records the old text each time, so it's pretty memory-inefficient, but it works for what I want to do.

See the code on github.

See a demo with the Prism editor (control-z to undo, control-y to redo).

Usage is simple:

bililiteRange(element).undo(0); // initializes the event listener without trying to undo anything; safe to call multiple times
bililiteRange(element).undo(); // restores the text from the last undo point
bililiteRange(element).undo(-1); // redo--undoes the last undo

bililiteRange(element).undo(n) for any n works and will undo (for positive n) or redo (for negative n) that many times, though I'm not sure how useful that would be.

There are convenience methods to be used as event handlers:


So a simple keyboard shortcut handler would be:

		bililiteRange(editor).undo(0); // initialize
		editor.addEventListener ('keydown', function(evt){
			// control z
			if (evt.ctrlKey && evt.which == 90) bililiteRange.undo(evt);
			// control y
			if (evt.ctrlKey && evt.which == 89) bililiteRange.redo(evt);

or, if you use my hotkeys jQuery plugin,

$(editor).on('keydown', {keys: '^z'}, bililiteRange.undo);
$(editor).on('keydown', {keys: '^y'}, bililiteRange.redo);

Hope that this is useful to someone.

It tries to be sophisticated about typing, and bunches all typing done in a row into one, so that undo undoes the entire line. Backspacing, moving the insertion point, or typing a newline starts a new undo point.

Restoring the insertion point isn't as sophisticated as in a real word processor yet; moving the insertion point then typing then undoing moves the insertion point back to where is was originally, not to the start of typing.

Prism is a great Javascript syntax highlighter, and it's fast enough to be used on the fly for active editing; Lea Verou (the author) does this with Dabblet. Combined with bililiteRange to handle some of the subtleties of dealing with contenteditable elements, a syntax-highlighting editor is relatively easy.

Simplest usage: bililiteRange.fancyText(element, Prism.highlightelement);.

See the demo.

See the code on github.

There's a fair amount of flakiness; contenteditable elements are still handled inconsistently. Newlines are changed into actual elements (Firefox adds <br>s; Chrome adds a whole new <div>), even though a <pre> doesn't need that; it would interpret newlines the way we want. So we have to intercept those and just insert the newline. Firefox insists on changing newlines into <br>'s even in pasted text, and Chrome's clipboard implementation includes the carriage return character, so we have to intercept paste events and insert the text appropriately mangled.

Continue reading ‘Simple syntax-highlighting editor with Prism’ »

I wanted to be able to wrap arbitrary text with HTML elements, so I added a wrap method to my bililiteRange routines. Now I can do something like bililiteRange(el).find(/foo/).wrap(document.createElement('strong')) and I have instant highlighting!

It obviously can only work if the range is defined on an actual HTML element, not on the text of a <input> or <text> element (it throws an error if you try).

For standards-based browsers, there is a simple surroundContents method that does it in one step. Note that it uses the actual node passed in, so if you need to reuse it, remember to clone it.

IE < 10 doesn't have anything so nice, so I have to hack it by extracting and re-inserting the HTML with htmltext and pasteHTML.

It is possible to attempt to create invalid HTML; for instance wrap a range containing a <p> with a <span> element. Depending on the browser, this may throw an error or create undefined results.

Edited 2014-02-27 to add the indentation code.

I created a collection of useful plugins for my bililiteRange, for more sophisticated manipulations. Now you can search the element with a regular expression, and you can keep the range "live", adjusting it when the text is edited.

Download the code.

See the demo. (The dynamic highlighting is off by a few pixels in iOS Safari. I'm still working on that)

Continue reading ‘bililiteRange Plugins’ »

I've been working on a project that uses bililiteRange a lot, so I added two improvements: plugins and events.

bililiteRange.fn.myplugin = function() {}; or bililiteRange.extend({ myplugin1: function() {}, myplugin2: function(){} }); creates new functions for a bililiteRange (just like with jQuery).

Also, the text method now triggers an input event on the element. Only works on browsers that implement CustomEvent.

Updated to version 2.3 on 2014-02-26 for data routines.

I was trying to update my sendkeys plugin to use contentEditable, and realized that it was getting harder and harder to do without some selection/text replacement library. Each browser is different and even different elements are treated differently. There are a few libraries out there, but none handled both input and textarea elements and regular elements, and would constrain the selections to a given element (critical if I want to edit only part of a document) and none made it easy to simulate arrow keys, moving the selection left or right. So I figured I would make my own.

See the code on Github.

See the demo (try it in different browsers!).

Continue reading ‘Cross-Browser Text Ranges and Selections’ »