var snippets = [{ name: "years", body: "Year is [[%d(YYYY)]]", timestamp: "March 03, 2015" }, { name: "hours", body: "Hour is [[%d(hh)]]", timestamp: "March 03, 2015" }]; var macros = { "\\bhh\\b": function(date){ // 24h return date.getHours(); }, "\\bYYYY\\b": function(date){ // year return date.getFullYear(); } }; function formatMacros(snipBody) { // find the %d macro text and call replace function on it snipBody = snipBody.replace(/\[\[\%d\((.*?)\)\]\]/g, function(wholeMatch, text) { var date = new Date(); // operate on text (it is the one inside parentheses of %d) for (var regex in macros) { // macros object has regex-function pairs var reg = new RegExp(regex); // regex was a string; construct primitive regex object from it text = text.replace(reg, function() { return macros[regex](date); }); } return text; }); return snipBody; } function formatSnippets(node) { /*assumes node is a textarea element*/ var selection = window.getSelection(), range = selection.rangeCount ? selection.getRangeAt(0) : null, offset = range ? range.endOffset : node.selectionStart, // the caret position in the node snip, // holds current snippet length, // holds current snippet name’s length valueND = node.value; // holds value of node // loop through Snippets arrray for (var i = 0, len = snippets.length; i < len; i++) { snip = snippets[i]; length = snip.name.length; // the key part // gets the text immediately behind the user’s cursor (caret) // checks if it corresponds with the current snippet name var textBehind = valueND.substring(offset - length, offset); if (textBehind === snip.name) { // performs snippet replacement var snipBody = snip.body, // take value before snip name beginValue = valueND.substring(0, offset - length), // take value after snip name end endValue = valueND.substring(offset), // length where snip body starts beginLength = beginValue.length, // length where snip body ends endLength = (beginValue + snipBody).length; snipBody = formatMacros(snipBody); // covered in 3rd blog post // concatenate everything together! node.value = beginValue + snipBody + endValue; // set caret position (at end of snippet body) node.selectionEnd = node.selectionStart = endLength; // snippet replacement done; move out of loop break; } } } // formatSnippets function ends function handleKeyDown(event) { var keyCode = event.keyCode; // [Shift] + [Space] = formatting snippets if (event.shiftKey && keyCode === 32 && !event.ctrlKey) { event.preventDefault(); // do not insert space (default event) formatSnippets(this); // format snippets in `this` (node) } } document.onkeydown = function (event) { var node = event.target; // run only if the node is a <textarea> if (node.tagName === "TEXTAREA") handleKeyDown.call(node, event); };
Try typing "years" or "hours" and pressing Shift+Space: <br> <br> <textarea></textarea>