rolando.cl

Better text areas in enki (or any other rails app for that matter)

When creating my site, I realized that I might be typing a lot of code snippets into this blog, and since usually pressing “tab” changes focus on input fields and not actually inserts a tab in the text I’m editing, I realized I had to “fix” that, here’s my solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# context: enki blog (http://www.enkiblog.com/)
# file: app/views/admin/posts/_form.html.erb

<% content_for(:head) do -%>
  <%= javascript_include_tag 'admin/edit-preview' %>
<% end -%>

<%= form.inputs do -%>
  <%= form.input :title -%>
  <%= form.input :body,
                 :hint => "<a href='http://textile.thresholdstate.com/'>Textile enabled</a>. Use Ctrl+E to switch between preview and edit mode.".html_safe -%>
  <%= form.input :tag_list, :as => 'string', :required => false, :hint => 'Comma separated: ruby, rails&hellip;'.html_safe -%>
<% end -%>
<%= form.inputs do -%>
  <%= form.input :published_at_natural, :label => 'Published at', :as => 'string', :hint => 'Example: now, yesterday, 1 hour from now, '.html_safe + link_to("more&hellip;".html_safe, "http://chronic.rubyforge.org/") -%>
  <%= form.input :slug, :hint => "Leave blank for an auto-generated slug based on the title." -%>
  <%= form.input :minor_edit, :as => 'boolean', :hint => 'Minor edits will not show up as refreshed in feed readers. Use this to fix spelling mistakes and the like.' unless @post.new_record? -%>
<% end -%>

<script type="text/javascript">
$(document).ready(function () {
        $("#post_body").css("font-family", "Menlo").css("font-size", "8pt");
        
        var has_focus = false;
        var lastKey = 0;
        $("#post_body").bind('blur', function () {
                if (lastKey == 9) {
                        // if selection is nothing, then insert a "tab"
                        if (this.selectionStart - this.selectionEnd == 0) {
                                var val = $(this).val();
                                var a = val.substring(0, this.selectionStart);
                                var b = val.substring(this.selectionStart, val.length);
                                $(this).val(a + "\t" + b);
                                // now set the selection
                                this.selectionStart += 1;
                        }
                
                        $(this).focus();
                        return false;
                }
                return true;
        }, true);

        $("#post_body").keydown(function (event) {
                lastKey = event.keyCode;
        });
});
</script>

It goes like this:

when post_body looses focus (the body text area for the post) and if last key pressed was actually a tab (you can loose focus by clicking somewhere else), then insert a tab where the selection pointer was, and move the selection pointer.

Oh, I also added some nice css styles for the textarea, like the lovely Menlo font and a specific font size.

It’s not the best solution, but it works.

Some wild ideas to implement:

  • context-aware tab (like if you’re inside a ruby snippet, then insert two blanks instead of a “\t”
  • be able to shift-up/down indentation levels

But… if you start doing all that, you end up with something more like a text editor than just a simple post creator in your blog app. So… this small change is what will work best for me now.

Post a comment


(lesstile enabled - surround code blocks with ---)