This post is more of a discussion about how I've setup CodeMirror in my project rather than a specific support request, but there may be some questions as I go through this
When displaying text, TWebMemo works pretty well, but not very fancy when it comes to things like syntax highlighting. Ace Editor also works pretty well. With a bit of effort, I was able to bend it to my will for the most part. Nothing here is intended as criticism of either component. Just that in the world of web development, if things aren't to your liking for any reason at all, there are likely alternatives.
For me there were three with Ace Editor. (1) The horizontal scrollbar would show up even when the text was barely half the width of the control. (2) The scrollbar would disappear entirely on iOS. (3) While many themes are available, adjusting the theme specifically to match my website themes seemed to be more difficult than changing my themes to match Ace Editor - not really how it should be. I don't particularly want to dwell on these as they may have solutions or may be non-issues for most people, just that I spent time trying to resolve them and it was easier to switch to something else.
So. CodeMirror is a project similar to Ace Editor in that it provides syntax highlighting for a number of languages, themes and the rest of it. I'm not affiliated with them in any way, but I've used it before on a project as the HTML editor behind a Drupal website. Seemed to work well in that environment.
To get this working in Web Core was pretty straight forward. Starting as usual with the CDN links to get it loaded up. In this case I've included bits for a custom scrollbar and the syntaxes that I'm interested in. Could probably pare this down a bit. There are themes that can also be added in this way, so check out the Code Mirror site if that is of interest.
<!-- CodeMirror -->
<script src="https://cdn.jsdelivr.net/npm/codemirror@latest/lib/codemirror.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@latest/addon/scroll/simplescrollbars.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@latest/addon/scroll/annotatescrollbar.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@latest/addon/scroll/scrollpastend.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@latest/mode/htmlmixed/htmlmixed.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@latest/mode/sql/sql.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@latest/mode/xml/xml.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@latest/mode/css/css.js"></script>
<link href="https://cdn.jsdelivr.net/npm/codemirror@latest/lib/codemirror.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/codemirror@latest/addon/scroll/simplescrollbars.min.css" rel="stylesheet"/>
To create the control on the page, I added a TWebHTMLDiv component to a form and set its ElementID to cmMemo. In the interface for the form, I added a variable to reference the javascript object:
var
cmMemoObject: JSValue;
And then in the form's WebFormCreate
procedure I create the CodeMirror object. In this case, it starts out as an empty, read-only variant, with SQL-style syntax highlighting and my own theme and fancier scrollbars - all customizable to other things of course:
asm
this.cmMemoObject = CodeMirror(document.getElementById("cmMemo"), {
value: "",
mode: "sql",
readOnly: true,
theme: "custom",
scrollbarStyle: "overlay"
});
end;
In this example, I'm using the memo to display log entries, so adding text and scrolling to the bottom of that text is the objective. Seems to work well:
procedure TfrmWhatever.LogThis(LogData: String);
var
LogString: String;
begin
LogString := chr(10)+LogData;
asm
this.cmMemoObject.replaceRange(LogString, {line: Infinity});
this.cmMemoObject.execCommand("goDocEnd");
end;
PreventCompilerHint(LogString);
end;
Some additional notes about this.
- When passing data to/from JS, it seems easier to create a new local variable rather than trying to mess about with JS syntax. Here it would probably be easy enough to add the chr(10) directly in JS but in other cases it may involve adding strings together or using variables from other forms, where the extra period or whatever is enough of an obstacle that this approach has become a habit.
- When declaring a variable in this way and only using it in the JS block, a compiler hint is generated. This happens often enough that I've added functions that do nothing (and hopefully the compiler optimizes them out completely) but they help suppress the unwanted hints. Not sure if there is a better way?
Now one of the benefits of CodeMirror is also that the entire control is drawn with HTML and CSS (and no sign of a canvas element anywhere ). So adjusting to fit into a theme becomes entirely possible. In my case I was interested in replacing the scollbars and having the theme mesh with the theme of my website. Rather than having to adjust my website to fit the themes available. CodeMirror has many themes as well (just like Ace) so this can be skipped.
But to give a bit of an idea of the end result, I've attached a video clip showing what this looks like. CodeMirror Example screencap.