Prototyping a code editor with line numbering

advanced-prototyping

#1

Hey folks,

I’ve spent several hours on this and am back to the drawing board, so I’m hoping someone might have an idea that will allow me to move forward. I’m trying to create a prototype of a (VERY) simple code editor, consisting of a text area with a monospace font and a column to the left of it showing line numbers. Nothing more fancy than that.

This is one of those things that sounds straightforward and simple, but since I need to account for text wrapping, it runs up against Axure’s lack of awareness of text sizes at runtime…

Things I’ve tried:

  1. As the user types, copy their text into a repeater the same width as the text field, use another column in the same repeater as the line number column
    -this works for default content loaded when the page loads, but if the user adds text, it breaks.

  2. Copy the user’s input onto a rectangle behind the text field, which is the same width + ~50px for line numbers. Replace all visible characters with spaces. Add numbers to the beginning of each line. (this is a simplified explanation, but hopefully you get the idea). This way, when a line wraps in the text field, it also wraps on the rectangle, so the position of the line numbers is also affected.
    -This was stupidly complicated, and kinda works, but only if a line wraps once. Wrapping more than once causes inaccuracies.

I’m really hoping there’s a native Axure solution that doesn’t rely on plugins. Anyone done this before?


#2

Woa. Not that easy I think.
What about using one of those js code editors (like ACE - ace.c9.io ) - you could set that up, either using a local host webserver or an online one (they might even already exist) and using an inline frame to pull that in ? Provided you don’t need to do anything with the text that could work.


#3

Hi!

This could be done without a plug-in, but it does require some javascript to get the height of the text in your edit area: i.e, the height of the HTML span. (It’s super annoying that Axure doesn’t let you get this natively,.) Note that you can add this javascript directly to the Axure file without a plug-in. (It would probably be 5 or so lines of code.)

The strategy would be this;

  • Create a tall text field with a stack of numbers for your row numbers
  • Put that list of numbers in a dynamic panel whose purpose is to clip the numbers list so you only see the top [n] pixels of it.
  • To the right of this dynamic panel, add in your text field for the code editing.
  • As you type in this text filed, trigger javascript that does the following:
    ** Get the height of the span of the code field
    ** Set the height of the dynamic panel (clipping the number list) to the height of the span.

This post shows how to get the width of a field’s span. You’d be getting the height instead.

This post shows how to use javascript to change the height of an Axure widget, which you will be doing for the DP containing the numbers list. (You can ignore most of the code: just look for the resize command.)

If you are not comfortable with javascript or otherwise have trouble getting it working, let me know. I’m happy to create this example.


#4

Thanks @josephxbrick—I thought the solution might look something like this, but (correct me if I’m wrong) I don’t think a textarea gives you individual spans for lines of text. So this wouldn’t work unless I was creating a new widget for each line of code, which gets into the repeater thing I had been trying to do.

A static column of numbers doesn’t work for me because individual lines of code can wrap, and if that happens, the line numbers will be inaccurate.

@alex.boschmans it may come to using iframes. I just can’t shake the notion that there must be some clever way to do it within Axure…


#5

Hi!

Oh! That is trickier.

This is still something I’d prefer to hand off to js, just because it’s so much easier with access to arrays and looping, plus the speed will be needed. But in theory you could do it in Axure, assuming you can get the line feed character.

Basic strategy, assuming two side-by side fields, one for the numbers, one for the code. On whatever event (say, text changed):

  • Clear the numbers field,
  • Split the text of the code field on the new-line character and place each text line into an array element. (A single javascript command does this.)
  • Loop through the array: you’ll start with an blank variable for your line numbers called, say, lineNumbers, and a variable called currentLineNumber initialized to 0.
    ** divide the number of characters in the current array element by character width to determine number of lines, since you will know the width of the code field. This works with a mono-spaced font.
    ** increment currentLineNumber and tack the current line number onto the end lineNumbers
    ** tack the appropriate number of line feeds onto the end of lineNumbers
  • When the loop completes, set the text widget holding the line numbers to lineNumbers.

#6

Thank you, @josephxbrick.

Oof. This is more than I bargained for (insert my semi-annual lament about not having just become a front-end developer here), but you’re right, the speed of pure JS is definitely a benefit here. I’ll noodle on this a bit and post the widget if I get it working.

It’s a shame there isn’t something similar to a content-editable div within Axure! I often think of text editing, rich or otherwise, as Axure’s final frontier…


#7

BTW, to get it working in straight up Axure, you’d create a loop recursively:

On Text Changed
  v_curChar = [[v_curChar + 1]] 
  -- react here appropriately to the value of that character
  if v_curChar is less then the length of the code field
     Fire event On Text Changed of this

#8

Hi again!

I got it working, at least on my machine. Tested only on Chrome and Safari.

It should adjust automatically to the text-area width, as well as the font size. Requires fixed width font. I didn’t implement scrolling.

The file is in Axure 8, but it works fine when converted to 9.

Preview

File: linenumber_code.rp (46.8 KB)

[edit] It is possible to break it, but you really have to work at it. Should be fine for a prototype.


#9

If you already use javascript, I think embed a code editor will be better than create a new one, I’ve tried to make an example with ax-webview in Axure 9:

【Preview】
http://minicg.com/demo/axure/monaco-code-editor

【RP File】
monaco-code-editor.rp (58.5 KB)

【Monaco Editor】
https://microsoft.github.io/monaco-editor/playground.html


#10

@josephxbrick NICE! Thank you so much. Yeah, this’ll do very nicely for a prototype.


closed #11

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.