There's a subtlety in using Promises with event handlers or any code that's executed asynchronously.

Promises are supposed to be used for future values, with the reject handler acting like an exception handler, so that the Promise constructor actually catches real exceptions and turns them into rejects (from the polyfill; I assume the browser-implemented code works similarly):

try {
  resolver(resolvePromise, rejectPromise);
} catch(e) {
  rejectPromise(e);
}

But asynchronous code runs outside the execution unit that runs resolver(), so any exceptions there have to be caught explicitly:

<button id=one>Click Me</button>
<button id=two>Don't Click Me</button>
<script>
var promise = new Promise(function(resolve, reject){
	document.querySelector('#one').onclick = function(){
		resolve ('You Clicked!');
	};
	document.querySelector('#two').onclick = function(){
		throw new Error ('You Clicked!');
	};
});

promise.then(function(msg){
	alert('Button clicked: '+msg);
}, function(err){
	alert('Error caught:'+err.message);
});
</script>

Clicking button two gives an uncaught exception error, not the alert from the then(). You have to catch the exceptions:

	document.querySelector('#two').onclick = function(){
		try {
			throw new Error ('You Clicked!');
		} catch (e) {
			reject(e);
		}
	};

or resolve to a new promise that can catch the error:

	document.querySelector('#two').onclick = function(){
		resolve(new Promise(function (){
			throw new Error ('You Clicked!');
		}));
	};

The other subtlety (which is obvious from the definition of a Promise) is that Promises are once-only; in the above code, clicking either button settles the Promise and further clicking does nothing. Event handlers can be called multiple times, so you have to think about what you intend.

Just in time for me to start thinking about Javascript Promises, comes along an official API, along with a polyfill that basically re-implements rsvp.js with the "official" terminology.

Now for some experimenting (and rewriting jquery.status.js to use real Promises).

It seems from all the discussion that jQuery $.Deferred are not and will not be real Promises, but they can be Promise.cast($.Deferred()) into one. Note that to use that, you need to $.Deferred().resolve() on the jQuery object, but attach Promise.then()'s to the Promise.

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've been looking at Promise/A+ as a way to abstract future values, or values that depend on something the user will do later, specifically Yehuda Katz's rsvp.js, and came across Domenic Denicola's You're Missing the Point of Promises, which got me looking at Oliver Steele's Minimizing Code Paths in Asychronous Code. Now I have another consideration in my code that I never thought about before.

Continue reading ‘Thinking about synchonicity’ »

This plugin is obsolete. See the new status at github.bililite.com/status.

Updated 2015-01-19 to allow $(console).status(). Now at version 1.4.

Updated 2013-12-18 to use Promises. This necessitated removing the result option and adding the returnPromise.

Updated 2014-01-09 to add initialText option and to document the markup used.

For the Kavanot editor I wanted to have a way to display messages (like "Text saved successfully") that would show up on screen then fade out, and a way to enter text (like the title, or editing commands if I ever get that working). I packaged that all together into a plugin could handle both, with an anticipated use like:

<textarea id=editor></textarea>
<div id=notifications></div>

And then do something like $('#notifications').status('Text saved'); and that briefly shows the message in the <div> and then gradually fade out.

And for user input,

$('#notifications').status({
  prompt: 'File Name:',
  run: function (text) { 
    /* do something with text */
    if (successful) return 'success message';
    if (! successful) throw {message: 'failure message'};
  }
});

displays the prompt and an input box then runs the function and displays the result (it automatically catches the thrown exception).

See the code on github.

See a demo.

Continue reading ‘New jQuery plugin, status’ »

Looking back at my line numbering plugin for Prism, I realized that it's working too hard by manipulating the DOM. Prism works by string manipulation anyway, so there's no harm in using that to wrap the lines rather than searching through elements. The code is now only 6 lines long. It still uses CSS and ::before pseudoelements to show the line numbers.

Just upgraded the server to Apache 2.4, and started getting 500 errors on everything. Turns out the access control was completely changed; instead of Order deny,allow and Deny from all you use Require all denied. That change fixed everything. Hope this helps someone.

The Torah as traditionally written has two kinds of paragraph breaks: "open" and "closed". Open paragraphs are the same as in English typography: the next paragraph starts on the next line. Closed paragraphs start the next paragraph on the same line, after a 9-em gap. In the image on the page linked to above, there are 3 closed paragraph breaks, 2 open, then 1 closed.

I was thinking about representing this in CSS, with semantic HTML; something like <p class=open>First Paragraph</p><p class=closed>Second paragraph</p>. The Mechon Mamre tikkun uses a single <p> for the entire portion, then has <br>'s and &nbsp;'s hard-coded into the text. But there ought to be a better way.

See the final formatting.

Continue reading ‘Formatting the Torah’ »

I never really liked how my hotkeys plugin (that allows things like $('body').on('keydown', {keys: '^A'}, function() {alert ('Control-A!'); })) worked internally, and it didn't allow multiple handlers on a single element for a given key combination, and required initialization. I went back and looked at it some more, and studied John Resig's hotkeys, and came up with a simpler, better version. Use is largely the same, but there's no $.keymap.hotkeys('keydown') to initialize, and you have to explicitly remove handlers with $().off() rather than replacing with a new handler.

See the code.

This is obsolete. The documentation is now on github.bililite.com/timerevents.

Code and demo are on github.

I wanted to have a simple word count on the Kavanot editor, and this:

$('span.wordcount').text($('#editor').val().split(/\s+/).length+' words');

is enough for me. Keeping it live is straightforward:

$('#editor').on('input', function(){
  $('span.wordcount').text(this.value.split(/\s+/).length+' words');
});

But that won't show the word count when the page is first loaded. The ready event only works on document, and there isn't any event that just fires immediately (as far as I can see). So I created one.

$(selector).on('immediate', function() {...}); just calls the function with the relevant element as this. That's pretty much worthless, but you can combine the events:

$('#editor').on('immediate input', function(){
  $('span.wordcount').text(this.value.split(/\s+/).length+' words');
});

And now the word count shows immediately and is live, and remains DRY.

Continue reading ‘Timer events for jQuery’ »