Skip to content

Commit a0174a5

Browse files
Implemented ACE for markdown editing replacing the generic textarea
1 parent 7f239ba commit a0174a5

File tree

7 files changed

+216
-19
lines changed

7 files changed

+216
-19
lines changed

code/forms/MarkdownEditor.php

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ public function FieldHolder($properties=array()) {
1010
$this->extraClasses['stacked']='stacked';
1111

1212

13+
14+
Requirements::css(MARKDOWN_MODULE_BASE.'/css/MarkdownEditor.css');
15+
16+
Requirements::javascript(MARKDOWN_MODULE_BASE.'/javascript/external/ace/ace.js');
17+
Requirements::javascript(MARKDOWN_MODULE_BASE.'/javascript/external/ace/mode-markdown.js');
18+
Requirements::javascript(MARKDOWN_MODULE_BASE.'/javascript/external/ace/theme-textmate.js');
19+
Requirements::javascript(MARKDOWN_MODULE_BASE.'/javascript/external/ace/theme-twilight.js');
1320
Requirements::javascript(MARKDOWN_MODULE_BASE.'/javascript/MarkdownEditor.js');
1421
return parent::FieldHolder($properties);
1522
}

css/MarkdownEditor.css

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
.markdowneditor .middleColumn {
2+
border: 1px solid #CCCCCC;
3+
}
4+
5+
.markdowneditor .markdowneditor_editor {
6+
position: relative;
7+
font-family: Monaco, "Liberation Mono", Courier, monospace;
8+
9+
z-index: 0;
10+
}
11+
12+
.markdowneditor .markdowneditor_editor .ace_content {
13+
line-height: normal;
14+
}
15+
16+
.markdowneditor .ace-twilight .ace_editor {
17+
border: 2px solid #9f9f9f;
18+
}
19+
20+
.markdowneditor .ace-twilight .ace_editor.ace_focus {
21+
border: 2px solid #327fbd;
22+
}
23+
24+
.markdowneditor .ace-twilight .ace_gutter {
25+
width: 50px;
26+
background: #ECECEC;
27+
color: #AAA;
28+
overflow: hidden;
29+
border-right: 1px solid #DDD;
30+
font-family: Consolas, "Liberation Mono", Courier, monospace;
31+
}
32+
33+
.markdowneditor .ace-twilight .ace_gutter-layer {
34+
width: 100%;
35+
text-align: right;
36+
}
37+
38+
.markdowneditor .ace-twilight .ace_gutter-layer .ace_gutter-cell {
39+
padding-right: 12px;
40+
}
41+
42+
.markdowneditor .ace-twilight .ace_print_margin {
43+
width: 1px;
44+
background: #e8e8e8;
45+
}
46+
47+
.markdowneditor .ace-twilight .ace_scroller {
48+
background-color: #141414;
49+
}
50+
51+
.markdowneditor .ace-twilight .ace_text-layer {
52+
cursor: text;
53+
color: #F8F8F8;
54+
}
55+
56+
.markdowneditor .ace-twilight .ace_cursor {
57+
border-left: 2px solid #F8F8F8;
58+
}
59+
60+
.markdowneditor .ace-twilight .ace_cursor.ace_overwrite {
61+
border-left: 0px;
62+
border-bottom: 1px solid #A7A7A7;
63+
}
64+
65+
.markdowneditor .ace-twilight .ace_marker-layer .ace_selection {
66+
background: rgba(221,240,255,0.2);
67+
}
68+
69+
.markdowneditor .ace-twilight .ace_marker-layer .ace_step {
70+
background: #c6dbae;
71+
}
72+
73+
.markdowneditor .ace-twilight .ace_marker-layer .ace_bracket {
74+
margin: -1px 0 0 -1px;
75+
border: 1px solid rgba(255,255,255,0.25);
76+
}
77+
78+
.markdowneditor .ace-twilight .ace_marker-layer .ace_active_line {
79+
background: rgba(255,255,255,0.12);
80+
}
81+
82+
.markdowneditor .ace-twilight .ace_invisible {
83+
color: rgba(255,255,255,0.25);
84+
}
85+
86+
.markdowneditor .ace-twilight .ace_keyword {
87+
color: #CDA869;
88+
}
89+
90+
.markdowneditor .ace-twilight .ace_constant {
91+
color: #CF6A4C;
92+
}
93+
94+
.markdowneditor .ace-twilight .ace_invalid.ace_illegal {
95+
color: #F8F8F8;
96+
background-color: rgba(86,45,86,0.75);
97+
}
98+
99+
.markdowneditor .ace-twilight .ace_invalid.ace_deprecated {
100+
text-decoration: underline;
101+
font-style: italic;
102+
color: #D2A8A1;
103+
}
104+
105+
.markdowneditor .ace-twilight .ace_support {
106+
color: #9B859D;
107+
}
108+
109+
.markdowneditor .ace-twilight .ace_support.ace_function {
110+
color: #DAD085;
111+
}
112+
113+
.markdowneditor .ace-twilight .ace_string {
114+
color: #8F9D6A;
115+
}
116+
117+
.markdowneditor .ace-twilight .ace_string.ace_regexp {
118+
color: #E9C062;
119+
}
120+
121+
.markdowneditor .ace-twilight .ace_comment {
122+
font-style: italic;
123+
color: #5F5A60;
124+
}
125+
126+
.markdowneditor .ace-twilight .ace_variable {
127+
color: #7587A6;
128+
}
129+
130+
.markdowneditor .ace-twilight .ace_xml_pe {
131+
color: #494949;
132+
}

javascript/MarkdownEditor.js

+63-19
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,69 @@
11
(function($) {
22
$.entwine('ss', function($) {
33
$('textarea.markdowneditor').entwine({
4-
onkeydown: function(e) {
5-
if(e.keyCode===9) { // tab was pressed
6-
var domElm=$(this).get(0);
7-
8-
// get caret position/selection
9-
var start=domElm.selectionStart;
10-
var end=domElm.selectionEnd;
11-
console.log(start, end);
12-
13-
// set textarea value to: text before caret + tab + text after caret
14-
$(this).val($(this).val().substring(0, start)+"\t"+$(this).val().substring(end));
15-
16-
// put caret at right position again
17-
domElm.selectionStart=domElm.selectionEnd=start+1;
18-
19-
// prevent the focus lose
20-
return false;
21-
}
4+
TextArea: null,
5+
Div: null,
6+
Editor: null,
7+
Frame: null,
8+
WrapMode: false,
9+
SoftTabs: true,
10+
onmatch: function() {
11+
$(this).setFrame({
12+
width: '100%',
13+
height: $(this).height()
14+
});
15+
16+
$(this).setTextArea($(this));
17+
$(this).hide();
18+
19+
var div=$('<div id="'+$(this).attr('ID')+'_Editor" class="markdowneditor_editor"/>').css('height', $(this).getFrame().height).css('width', $(this).getFrame().width).text($(this).val());
20+
div.insertAfter($(this));
21+
$(this).setDiv(div);
22+
23+
var editor=ace.edit(div.get(0));
24+
editor.getSession().setMode('ace/mode/markdown');
25+
editor.setShowPrintMargin(false);
26+
editor.setTheme('ace/theme/twilight');
27+
editor.resize();
28+
div.removeClass('ace_dark');
29+
$(this).setEditor(editor);
30+
31+
var code=$(this).val();
32+
$(this).setUseSoftTabs($(this).usesSoftTabs(code));
33+
$(this).setTabSize($(this).getSoftTabs() ? $(this).guessTabSize(code):8);
34+
$(this).setUseWrapMode($(this).getWrapMode());
35+
$(this).setupFormBindings();
36+
$(this).setupHacks();
37+
},
38+
code: function() {
39+
return $(this).getEditor().getSession().getValue();
40+
},
41+
setupFormBindings: function() {
42+
var self=$(this);
43+
$(this).getEditor().getSession().on("change", function() {
44+
self.getTextArea().val(self.code()).change();
45+
});
46+
},
47+
setupHacks: function() {
48+
$(this).getDiv().find('.ace_gutter').css("height", $(this).getFrame().height);
49+
},
50+
setUseSoftTabs: function(val) {
51+
$(this).setSoftTabs(val);
52+
$(this).getEditor().getSession().setUseSoftTabs(val);
53+
},
54+
setTabSize: function(val) {
55+
$(this).getEditor().getSession().setTabSize(val);
56+
},
57+
setUseWrapMode: function(val) {
58+
$(this).getEditor().getSession().setUseWrapMode(val);
59+
},
60+
guessTabSize: function(val) {
61+
var result=/^( +)[^*]/im.exec(val || $(this).code());
62+
return (result ? result[1].length:2);
63+
},
64+
usesSoftTabs: function(val) {
65+
return !/^\t/m.test(val || $(this).code());
2266
}
2367
});
2468
});
25-
})(jQuery);
69+
})(jQuery);

javascript/external/ace/ace.js

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

javascript/external/ace/mode-markdown.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

javascript/external/ace/theme-textmate.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

javascript/external/ace/theme-twilight.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)