CodeMirror, a very impressive in-browser code editor for Javascript, XML/HTML or CSS (or any language, you just have to plug in a your own parser) made some nice progress in the last months. CodeMirror has no dependency on other frameworks or libraries. If you want to use it in a dojo environment as a dojo compatible widget, here I am gonna share here a little tutorial how to write such a thing:
First download CodeMirror and transform CodeMirror.js (the main file which loads the other files into an iframe), into something like this:
dojo.provide("mystuff.widget.CodeMirror");
dojo.require("dijit._Widget");
dojo.declare("mystuff.widget.CodeMirror", dijit._Widget, {
initialized: false,
// currently supported: 'xml' (HTML), 'js' or 'css'
type: 'xml',
options: {
stylesheet: "",
path: "/static/codemirror/js/",
parserfiles: [],
basefiles: ["codemirror_iframe.js"],
linesPerPass: 15,
passDelay: 200,
continuousScanning: false,
saveFunction: function() {
console.log('save');
},
content: " ",
undoDepth: 20,
undoDelay: 800,
disableSpellcheck: true,
textWrapping: true,
readOnly: false,
width: "100%",
height: "100%",
parserConfig: null
},
postMixInProperties: function() {
this.options.stylesheet = "/static/codemirror/css/" + this.type + "colors.css";
this.options.parserfiles = ["parse" + this.type + ".js"];
},
postCreate: function() {
this.inherited(arguments);
},
startup: function() {
if (dijit._isElementShown(this.domNode.parentNode))
this.initialize();
},
initialize: function() {
if (this.initialized)
return;
frame = document.createElement("IFRAME");
frame.style.border = "0";
frame.style.width = this.options.width;
frame.style.height = this.options.height;
// display: block occasionally suppresses some Firefox bugs, so we
// always add it, redundant as it sounds.
frame.style.display = "block";
this.domNode.appendChild(frame);
// Link back to this object, so that the editor can fetch options
// and add a reference to itself.
frame.CodeMirror = this;
this.win = frame.contentWindow;
var _this = this;
var html = ["<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"" + this.options.stylesheet + "\"/>"];
dojo.forEach(this.options.basefiles.concat(this.options.parserfiles), function(file) {
html.push("<script type=\"text/javascript\" src=\"" + _this.options.path + file + "\"></script>");
});
html.push("</head><body style=\"border-width: 0;\" class=\"editbox\" spellcheck=\"" +
(this.options.disableSpellcheck ? "false" : "true") + "\"></body></html>");
var doc = this.win.document;
doc.open();
doc.write(html.join(""));
doc.close();
this.initialized = true;
},
getCode: function() {
return this.editor.getCode();
},
setCode: function(code) {
this.editor.importCode(code);
},
focus: function() {
this.win.focus();
},
jumpToChar: function(start, end) {
this.editor.jumpToChar(start, end);
this.focus();
},
jumpToLine: function(line) {
this.editor.jumpToLine(line);
this.focus();
},
currentLine: function() {
return this.editor.currentLine();
},
selection: function() {
return this.editor.selectedText();
},
reindent: function() {
this.editor.reindent();
},
replaceSelection: function(text, focus) {
this.editor.replaceSelection(text);
if (focus) this.focus();
},
replaceChars: function(text, start, end) {
this.editor.replaceChars(text, start, end);
},
getSearchCursor: function(string, fromCursor) {
return this.editor.getSearchCursor(string, fromCursor);
}
});