├── .gitignore
├── Gemfile
├── Gemfile.lock
├── README.md
├── Rakefile
├── dist
├── css
│ └── jquery.qeditor.css
├── index.html
└── js
│ └── jquery.qeditor.js
└── src
├── css
└── jquery.qeditor.scss
└── js
└── jquery.qeditor.coffee
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | tmp/**/*
3 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gem "rake"
4 | gem "sass"
5 | gem "coffee-script"
6 |
7 | gem "rb-fsevent", "~> 0.9"
8 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | coffee-script (2.2.0)
5 | coffee-script-source
6 | execjs
7 | coffee-script-source (1.6.3)
8 | execjs (1.4.0)
9 | multi_json (~> 1.0)
10 | multi_json (1.7.9)
11 | rake (10.1.0)
12 | rb-fsevent (0.9.3)
13 | sass (3.2.10)
14 |
15 | PLATFORMS
16 | ruby
17 |
18 | DEPENDENCIES
19 | coffee-script
20 | rake
21 | rb-fsevent (~> 0.9)
22 | sass
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | jquery.qeditor
2 | ==============
3 |
4 | This is a simple WYSIWYG editor with jQuery.
5 |
6 | [中文介绍请点这里](http://huacnlee.com/blog/jquery-qeditor-introduction/)
7 |
8 |
9 |
10 | ## Featrues
11 |
12 | - Simple UI, Simple Use;
13 | - Use font-awsome as toolbar icon;
14 | - Remove complex html tag, attributes on paste, this can make you web page clean;
15 | - Less code;
16 | - Use `
` not ` ` on press `Enter`, This can help you make a neat layout;
17 | - PlaceHolder for WYSIWYG editor;
18 | - FullScreen;
19 |
20 | ## Changelogs
21 |
22 | You can see all of the release notes in here: [Release notes](https://github.com/huacnlee/jquery.qeditor/releases)
23 |
24 | ## Browser support
25 |
26 | - Safari
27 | - Chrome
28 | - Firefox
29 | - IE (No test), maybe 8+
30 |
31 | ## Demo
32 |
33 | You can try the [Demo app](http://huacnlee.github.io/jquery.qeditor).
34 |
35 | ## Usage
36 |
37 | ```html
38 |
39 |
42 | ```
43 |
44 | ## How to add custom toolbar icon
45 |
46 | ```js
47 | // Custom a toolbar icon
48 | var toolbar = $("#post_body").parent().find(".qeditor_toolbar");
49 | var link = $(" ");
50 | link.click(function(){
51 | alert("Put you custom toolbar event in here.");
52 | return false;
53 | });
54 | toolbar.append(link);
55 | ```
56 |
57 |
58 | ## Build
59 |
60 | ```
61 | $ bundle install
62 | $ rake watch # or use "rake build" to release
63 | ```
64 |
65 |
66 | ## License
67 |
68 | Apache V2 : http://choosealicense.com/licenses/apache
69 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | task :build do
2 | print "Building Sass files..."
3 | `bundle exec sass --cache-location tmp/cache/sass --update src/css:dist/css -t compressed -f`
4 | puts " [Done]"
5 | print "Building CoffeeScript files..."
6 | `bundle exec coffee -c -b -o dist/js src/js`
7 | puts " [Done]"
8 | end
9 |
10 | task :watch do
11 | Process.fork do
12 | # In child
13 | exec("bundle exec sass --scss --watch src/css:dist/css --cache-location tmp/cache/sass")
14 | end
15 |
16 | Process.fork do
17 | exec("bundle exec coffee -w -b -c -o dist/js src/js")
18 | end
19 | Process.waitall
20 | end
21 |
--------------------------------------------------------------------------------
/dist/css/jquery.qeditor.css:
--------------------------------------------------------------------------------
1 | .qeditor_border {
2 | background: #FFF;
3 | padding-bottom: 20px;
4 | text-align: center;
5 | position: relative; }
6 |
7 | .qeditor_toolbar {
8 | text-align: left;
9 | background: #FFF;
10 | margin: 0 auto 3px auto; }
11 | .qeditor_toolbar span.vline {
12 | border-left: 1px solid #bbb;
13 | padding-right: 10px; }
14 | .qeditor_toolbar a, .qeditor_toolbar .qe-icon {
15 | color: #666;
16 | text-decoration: none;
17 | font-size: 14px;
18 | margin-right: 8px; }
19 | .qeditor_toolbar a:hover, .qeditor_toolbar .qe-icon:hover {
20 | color: #43be4d; }
21 | .qeditor_toolbar a.qe-state-on {
22 | color: #43be4d; }
23 | .qeditor_toolbar .qe-heading {
24 | position: relative; }
25 | .qeditor_toolbar .qe-heading .qe-menu {
26 | width: 120px;
27 | display: none;
28 | position: absolute;
29 | margin: 0;
30 | padding: 0;
31 | left: -25px;
32 | top: 15px;
33 | border: 1px solid #eee;
34 | border-right: 1px solid #ddd;
35 | border-bottom: 1px solid #ddd;
36 | z-index: 9991;
37 | background: #FFF;
38 | list-style: none; }
39 | .qeditor_toolbar .qe-heading .qe-menu li {
40 | display: inline;
41 | padding: 0;
42 | margin: 0; }
43 | .qeditor_toolbar .qe-heading .qe-menu a {
44 | display: block;
45 | margin: 0;
46 | padding: 2px 10px; }
47 | .qeditor_toolbar .qe-heading .qe-menu a:hover {
48 | background: #f0f0f0; }
49 | .qeditor_toolbar .qe-heading .qe-menu .qe-h1 {
50 | font-size: 17px;
51 | font-weight: bold; }
52 | .qeditor_toolbar .qe-heading .qe-menu .qe-h2 {
53 | font-size: 16px;
54 | font-weight: bold; }
55 | .qeditor_toolbar .qe-heading .qe-menu .qe-h3 {
56 | font-size: 15px;
57 | font-weight: bold; }
58 | .qeditor_toolbar .qe-heading .qe-menu .qe-h4 {
59 | font-size: 14px;
60 | font-weight: bold; }
61 | .qeditor_toolbar .qe-heading .qe-menu .qe-h5 {
62 | font-size: 13px;
63 | font-weight: bold; }
64 | .qeditor_toolbar .qe-heading .qe-menu .qe-h6 {
65 | font-size: 12px;
66 | font-weight: bold; }
67 | .qeditor_toolbar .qe-heading .qe-menu .qe-p {
68 | font-size: 12px;
69 | border-top: 1px solid #eee; }
70 | .qeditor_toolbar .qe-heading.hover {
71 | background: #eee; }
72 | .qeditor_toolbar .qe-heading.hover .qe-menu {
73 | background: #fff;
74 | display: block; }
75 |
76 | .qeditor_preview {
77 | text-align: left;
78 | min-height: 80px;
79 | margin: 0 auto;
80 | overflow-y: scroll; }
81 |
82 | .qeditor_placeholder {
83 | color: #999; }
84 |
85 | .qeditor_fullscreen {
86 | position: fixed;
87 | background: #FFF;
88 | top: 0;
89 | left: 0;
90 | bottom: 0;
91 | right: 0;
92 | z-index: 99990;
93 | padding: 30px 0;
94 | overflow: hidden; }
95 | .qeditor_fullscreen .qeditor_preview {
96 | max-width: 900px;
97 | box-sizing: border-box;
98 | width: 100%;
99 | height: 90%;
100 | margin-top: 20px;
101 | border: 0;
102 | -webkit-box-shadow: none;
103 | -moz-box-shadow: none;
104 | box-shadow: none;
105 | -webkit-transition: none;
106 | -moz-transition: none;
107 | -o-transition: none;
108 | transition: none;
109 | padding: 0; }
110 | .qeditor_fullscreen .qeditor_toolbar {
111 | max-width: 900px;
112 | box-sizing: border-box;
113 | width: 100%;
114 | padding-bottom: 10px; }
115 | .qeditor_fullscreen .qeditor_toolbar a, .qeditor_fullscreen .qeditor_toolbar .qe-icon {
116 | font-size: 18px;
117 | margin-right: 8px; }
118 |
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | jquery.qeditor
6 |
7 |
8 |
9 |
32 |
33 |
34 |
35 |
36 |
95 |
96 |
--------------------------------------------------------------------------------
/dist/js/jquery.qeditor.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.6.3
2 | /*
3 | jquery.qeditor
4 | ==============
5 |
6 | This is a simple WYSIWYG editor with jQuery.
7 |
8 | ## Author:
9 |
10 | Jason Lee
11 |
12 | ## Requirements:
13 |
14 | [jQuery](http://jquery.com)
15 | (Font-Awesome)[http://fortawesome.github.io/Font-Awesome/] - Toolbar icons
16 |
17 | ## Usage:
18 |
19 | $("textarea").qeditor();
20 |
21 | and then you need filt the html tags,attributes in you content page.
22 | In Rails application, you can use like this:
23 |
24 | <%= sanitize(@post.body,:tags => %w(strong b i u strike ol ul li address blockquote pre code br div p), :attributes => %w(src)) %>
25 | */
26 |
27 | var QEDITOR_ALLOW_TAGS_ON_PASTE, QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE, QEDITOR_TOOLBAR_HTML;
28 |
29 | QEDITOR_TOOLBAR_HTML = "";
30 |
31 | QEDITOR_ALLOW_TAGS_ON_PASTE = "div,p,ul,ol,li,hr,br,b,strong,i,em,img,h2,h3,h4,h5,h6,h7";
32 |
33 | QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE = ["style", "class", "id", "name", "width", "height"];
34 |
35 | window.QEditor = {
36 | actions: ['bold', 'italic', 'underline', 'strikethrough', 'insertunorderedlist', 'insertorderedlist', 'blockquote', 'pre'],
37 | action: function(el, a, p) {
38 | var editor;
39 | editor = $(".qeditor_preview", $(el).parent().parent());
40 | editor.find(".qeditor_placeholder").remove();
41 | editor.focus();
42 | if (p === null) {
43 | p = false;
44 | }
45 | if (a === "blockquote" || a === "pre") {
46 | p = a;
47 | a = "formatBlock";
48 | }
49 | if (a === "createLink") {
50 | p = prompt("Type URL:");
51 | if (p.trim().length === 0) {
52 | return false;
53 | }
54 | } else if (a === "insertimage") {
55 | p = prompt("Image URL:");
56 | if (p.trim().length === 0) {
57 | return false;
58 | }
59 | }
60 | if (QEditor.state(a)) {
61 | document.execCommand(a, false, null);
62 | } else {
63 | document.execCommand(a, false, p);
64 | }
65 | QEditor.checkSectionState(editor);
66 | editor.change();
67 | return false;
68 | },
69 | state: function(action) {
70 | return document.queryCommandState(action) === true;
71 | },
72 | prompt: function(title) {
73 | var val;
74 | val = prompt(title);
75 | if (val) {
76 | return val;
77 | } else {
78 | return false;
79 | }
80 | },
81 | toggleFullScreen: function(el) {
82 | var border;
83 | border = $(el).parent().parent();
84 | if (border.data("qe-fullscreen") === "1") {
85 | QEditor.exitFullScreen();
86 | } else {
87 | QEditor.enterFullScreen(border);
88 | }
89 | return false;
90 | },
91 | enterFullScreen: function(border) {
92 | border.data("qe-fullscreen", "1").addClass("qeditor_fullscreen");
93 | border.find(".qeditor_preview").focus();
94 | return border.find(".qe-fullscreen span").attr("class", "fa fa-compress");
95 | },
96 | exitFullScreen: function() {
97 | return $(".qeditor_border").removeClass("qeditor_fullscreen").data("qe-fullscreen", "0").find(".qe-fullscreen span").attr("class", "fa fa-arrows-alt");
98 | },
99 | getCurrentContainerNode: function() {
100 | var containerNode, node;
101 | if (window.getSelection) {
102 | node = window.getSelection().anchorNode;
103 | containerNode = node.nodeType === 3 ? node.parentNode : node;
104 | }
105 | return containerNode;
106 | },
107 | checkSectionState: function(editor) {
108 | var a, link, _i, _len, _ref, _results;
109 | _ref = QEditor.actions;
110 | _results = [];
111 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
112 | a = _ref[_i];
113 | link = editor.parent().find(".qeditor_toolbar a[data-action=" + a + "]");
114 | if (QEditor.state(a)) {
115 | _results.push(link.addClass("qe-state-on"));
116 | } else {
117 | _results.push(link.removeClass("qe-state-on"));
118 | }
119 | }
120 | return _results;
121 | },
122 | version: function() {
123 | return "0.2.0";
124 | }
125 | };
126 |
127 | (function($) {
128 | return $.fn.qeditor = function(options) {
129 | return this.each(function() {
130 | var currentVal, editor, obj, placeholder, qe_heading, toolbar;
131 | obj = $(this);
132 | obj.addClass("qeditor");
133 | editor = $('
');
134 | placeholder = $('
');
135 | $(document).keyup(function(e) {
136 | if (e.keyCode === 27) {
137 | return QEditor.exitFullScreen();
138 | }
139 | });
140 | document.execCommand('defaultParagraphSeparator', false, 'p');
141 | currentVal = obj.val();
142 | editor.html(currentVal);
143 | editor.addClass(obj.attr("class"));
144 | obj.after(editor);
145 | placeholder.text(obj.attr("placeholder"));
146 | editor.attr("placeholder", obj.attr("placeholder") || "");
147 | editor.append(placeholder);
148 | editor.focusin(function() {
149 | QEditor.checkSectionState(editor);
150 | return $(this).find(".qeditor_placeholder").remove();
151 | });
152 | editor.blur(function() {
153 | var t;
154 | t = $(this);
155 | QEditor.checkSectionState(editor);
156 | if (t.html().length === 0 || t.html() === " " || t.html() === "
") {
157 | return $(this).html('' + $(this).attr("placeholder") + '
');
158 | }
159 | });
160 | editor.change(function() {
161 | var pobj, t;
162 | pobj = $(this);
163 | t = pobj.parent().find('.qeditor');
164 | return t.val(pobj.html());
165 | });
166 | editor.on("paste", function() {
167 | var txt;
168 | txt = $(this);
169 | return setTimeout(function() {
170 | var attrName, els, _i, _len;
171 | els = txt.find("*");
172 | for (_i = 0, _len = QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE.length; _i < _len; _i++) {
173 | attrName = QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE[_i];
174 | els.removeAttr(attrName);
175 | }
176 | els.find(":not(" + QEDITOR_ALLOW_TAGS_ON_PASTE + ")").contents().unwrap();
177 | txt.change();
178 | return true;
179 | }, 100);
180 | });
181 | editor.keyup(function(e) {
182 | QEditor.checkSectionState(editor);
183 | return $(this).change();
184 | });
185 | editor.on("click", function(e) {
186 | QEditor.checkSectionState(editor);
187 | return e.stopPropagation();
188 | });
189 | editor.keydown(function(e) {
190 | var node, nodeName;
191 | node = QEditor.getCurrentContainerNode();
192 | nodeName = "";
193 | if (node && node.nodeName) {
194 | nodeName = node.nodeName.toLowerCase();
195 | }
196 | if (e.keyCode === 13 && !(e.shiftKey || e.ctrlKey)) {
197 | if (nodeName === "blockquote" || nodeName === "pre") {
198 | e.stopPropagation();
199 | document.execCommand('InsertParagraph', false);
200 | document.execCommand("formatBlock", false, "p");
201 | document.execCommand('outdent', false);
202 | return false;
203 | }
204 | }
205 | });
206 | obj.hide();
207 | obj.wrap('
');
208 | obj.after(editor);
209 | toolbar = $(QEDITOR_TOOLBAR_HTML);
210 | qe_heading = toolbar.find(".qe-heading");
211 | qe_heading.mouseenter(function() {
212 | $(this).addClass("hover");
213 | return $(this).find(".qe-menu").show();
214 | });
215 | qe_heading.mouseleave(function() {
216 | $(this).removeClass("hover");
217 | return $(this).find(".qe-menu").hide();
218 | });
219 | toolbar.find(".qe-heading .qe-menu a").click(function() {
220 | var link;
221 | link = $(this);
222 | link.parent().parent().hide();
223 | QEditor.action(this, "formatBlock", link.data("name"));
224 | return false;
225 | });
226 | toolbar.find("a[data-action]").click(function() {
227 | return QEditor.action(this, $(this).attr("data-action"));
228 | });
229 | return editor.before(toolbar);
230 | });
231 | };
232 | })(jQuery);
233 |
--------------------------------------------------------------------------------
/src/css/jquery.qeditor.scss:
--------------------------------------------------------------------------------
1 | .qeditor_border {
2 | background:#FFF;
3 | padding-bottom:20px;
4 | text-align: center;
5 | position: relative;
6 | }
7 | .qeditor_toolbar {
8 | text-align: left;
9 | background:#FFF;
10 | margin: 0 auto 3px auto;
11 | span.vline { border-left:1px solid #bbb; padding-right:10px; }
12 | a,.qe-icon {
13 | color: #666;
14 | text-decoration: none;
15 | font-size:14px;
16 | margin-right:8px;
17 | &:hover {
18 | color: #43be4d;
19 | }
20 | }
21 | a.qe-state-on {
22 | color:#43be4d;
23 | }
24 |
25 | .qe-heading {
26 | position: relative;
27 | .qe-menu {
28 | width: 120px;
29 | display: none;
30 | position: absolute;
31 | margin:0; padding:0;
32 | left:-25px; top:15px;
33 | border:1px solid #eee;
34 | border-right: 1px solid #ddd;
35 | border-bottom: 1px solid #ddd;
36 | z-index:9991;
37 | background:#FFF;
38 | list-style: none;
39 | li { display:inline; padding:0; margin:0; }
40 | a {
41 | display:block;
42 | margin:0;
43 | padding:2px 10px;
44 | &:hover {
45 | background:#f0f0f0;
46 | }
47 | }
48 | .qe-h1 { font-size:17px; font-weight:bold; }
49 | .qe-h2 { font-size:16px; font-weight:bold; }
50 | .qe-h3 { font-size:15px; font-weight:bold; }
51 | .qe-h4 { font-size:14px; font-weight:bold; }
52 | .qe-h5 { font-size:13px; font-weight:bold; }
53 | .qe-h6 { font-size:12px; font-weight:bold; }
54 | .qe-p { font-size:12px; border-top:1px solid #eee; }
55 | }
56 | &.hover {
57 | background:#eee;
58 | .qe-menu {
59 | background:#fff;
60 | display:block;
61 | }
62 | }
63 | }
64 |
65 | }
66 | .qeditor_preview {
67 | text-align: left;
68 | min-height:80px;
69 | margin:0 auto;
70 | overflow-y:scroll;
71 | }
72 | .qeditor_placeholder { color:#999; }
73 | .qeditor_fullscreen {
74 | position: fixed;
75 | background:#FFF;
76 | top:0; left:0; bottom:0; right:0;
77 | z-index: 99990;
78 | padding:30px 0;
79 | overflow:hidden;
80 |
81 | .qeditor_preview {
82 | max-width: 900px;
83 | box-sizing: border-box;
84 | width: 100%;
85 | height: 90%;
86 | margin-top: 20px;
87 | border:0;
88 | -webkit-box-shadow: none;
89 | -moz-box-shadow: none;
90 | box-shadow: none;
91 | -webkit-transition: none;
92 | -moz-transition: none;
93 | -o-transition: none;
94 | transition: none;
95 | padding:0;
96 | }
97 | .qeditor_toolbar {
98 | max-width: 900px;
99 | box-sizing: border-box;
100 | width: 100%;
101 | padding-bottom:10px;
102 | a,.qe-icon { font-size:18px; margin-right:8px; }
103 | }
104 | }
--------------------------------------------------------------------------------
/src/js/jquery.qeditor.coffee:
--------------------------------------------------------------------------------
1 | ###
2 | jquery.qeditor
3 | ==============
4 |
5 | This is a simple WYSIWYG editor with jQuery.
6 |
7 | ## Author:
8 |
9 | Jason Lee
10 |
11 | ## Requirements:
12 |
13 | [jQuery](http://jquery.com)
14 | (Font-Awesome)[http://fortawesome.github.io/Font-Awesome/] - Toolbar icons
15 |
16 | ## Usage:
17 |
18 | $("textarea").qeditor();
19 |
20 | and then you need filt the html tags,attributes in you content page.
21 | In Rails application, you can use like this:
22 |
23 | <%= sanitize(@post.body,:tags => %w(strong b i u strike ol ul li address blockquote pre code br div p), :attributes => %w(src)) %>
24 | ###
25 |
26 | QEDITOR_TOOLBAR_HTML = """
27 |
59 | """
60 | QEDITOR_ALLOW_TAGS_ON_PASTE = "div,p,ul,ol,li,hr,br,b,strong,i,em,img,h2,h3,h4,h5,h6,h7"
61 | QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE = ["style","class","id","name","width","height"]
62 |
63 | window.QEditor =
64 | actions : ['bold','italic','underline','strikethrough','insertunorderedlist','insertorderedlist','blockquote','pre']
65 |
66 | action : (el,a,p) ->
67 | editor = $(".qeditor_preview",$(el).parent().parent())
68 | editor.find(".qeditor_placeholder").remove()
69 | editor.focus()
70 | p = false if p == null
71 |
72 | # pre, blockquote params fix
73 | if a == "blockquote" or a == "pre"
74 | p = a
75 | a = "formatBlock"
76 |
77 |
78 | if a == "createLink"
79 | p = prompt("Type URL:")
80 | return false if p.trim().length == 0
81 | else if a == "insertimage"
82 | p = prompt("Image URL:")
83 | return false if p.trim().length == 0
84 |
85 | if QEditor.state(a)
86 | # remove style
87 | document.execCommand(a,false,null)
88 | else
89 | # apply style
90 | document.execCommand(a, false, p)
91 | QEditor.checkSectionState(editor)
92 | editor.change()
93 | false
94 |
95 | state: (action) ->
96 | document.queryCommandState(action) == true
97 |
98 | prompt : (title) ->
99 | val = prompt(title)
100 | if val
101 | return val
102 | else
103 | return false
104 |
105 | toggleFullScreen : (el) ->
106 | border = $(el).parent().parent()
107 | if border.data("qe-fullscreen") == "1"
108 | QEditor.exitFullScreen()
109 | else
110 | QEditor.enterFullScreen(border)
111 |
112 | false
113 |
114 | enterFullScreen : (border) ->
115 | border.data("qe-fullscreen","1")
116 | .addClass("qeditor_fullscreen")
117 | border.find(".qeditor_preview").focus()
118 | border.find(".qe-fullscreen span").attr("class","fa fa-compress")
119 |
120 | exitFullScreen : () ->
121 | $(".qeditor_border").removeClass("qeditor_fullscreen")
122 | .data("qe-fullscreen","0")
123 | .find(".qe-fullscreen span").attr("class","fa fa-arrows-alt")
124 |
125 | getCurrentContainerNode : () ->
126 | if window.getSelection
127 | node = window.getSelection().anchorNode
128 | containerNode = if node.nodeType == 3 then node.parentNode else node
129 | return containerNode
130 |
131 | checkSectionState : (editor) ->
132 | for a in QEditor.actions
133 | link = editor.parent().find(".qeditor_toolbar a[data-action=#{a}]")
134 | if QEditor.state(a)
135 | link.addClass("qe-state-on")
136 | else
137 | link.removeClass("qe-state-on")
138 |
139 | version : ->
140 | "0.2.0"
141 |
142 | do ($=jQuery)->
143 | $.fn.qeditor = (options) ->
144 | this.each ->
145 | obj = $(this)
146 | obj.addClass("qeditor")
147 | editor = $('
')
148 | placeholder = $('
')
149 |
150 | $(document).keyup (e) ->
151 | QEditor.exitFullScreen() if e.keyCode == 27
152 |
153 | # use tag on enter by default
154 | document.execCommand('defaultParagraphSeparator', false, 'p')
155 |
156 | currentVal = obj.val()
157 | # if currentVal.trim().lenth == 0
158 | # TODO: default value need in paragraph
159 | # currentVal = "
"
160 |
161 | editor.html(currentVal)
162 | editor.addClass(obj.attr("class"))
163 | obj.after(editor)
164 |
165 | # add place holder
166 | placeholder.text(obj.attr("placeholder"))
167 | editor.attr("placeholder",obj.attr("placeholder") || "")
168 | editor.append(placeholder)
169 | editor.focusin ->
170 | QEditor.checkSectionState(editor)
171 | $(this).find(".qeditor_placeholder").remove()
172 | editor.blur ->
173 | t = $(this)
174 | QEditor.checkSectionState(editor)
175 | if t.html().length == 0 or t.html() == " " or t.html() == "
"
176 | $(this).html('' + $(this).attr("placeholder") + '
' )
177 |
178 | # put value to origin textare when QEditor has changed value
179 | editor.change ->
180 | pobj = $(this);
181 | t = pobj.parent().find('.qeditor')
182 | t.val(pobj.html())
183 |
184 | # watch pasite event, to remove unsafe html tag, attributes
185 | editor.on "paste", ->
186 | txt = $(this)
187 | setTimeout ->
188 | els = txt.find("*")
189 | for attrName in QEDITOR_DISABLE_ATTRIBUTES_ON_PASTE
190 | els.removeAttr(attrName)
191 | els.find(":not(#{QEDITOR_ALLOW_TAGS_ON_PASTE})").contents().unwrap()
192 | txt.change()
193 | true
194 | ,100
195 |
196 | # attach change event on editor keyup
197 | editor.keyup (e) ->
198 | QEditor.checkSectionState(editor)
199 | $(this).change()
200 |
201 | editor.on "click", (e) ->
202 | QEditor.checkSectionState(editor)
203 | e.stopPropagation()
204 |
205 | editor.keydown (e) ->
206 | node = QEditor.getCurrentContainerNode()
207 | nodeName = ""
208 | if node and node.nodeName
209 | nodeName = node.nodeName.toLowerCase()
210 | if e.keyCode == 13 && !(e.shiftKey or e.ctrlKey)
211 | if nodeName == "blockquote" or nodeName == "pre"
212 | e.stopPropagation()
213 | document.execCommand('InsertParagraph',false)
214 | document.execCommand("formatBlock",false,"p")
215 | document.execCommand('outdent',false)
216 | return false
217 |
218 |
219 | obj.hide()
220 | obj.wrap('
')
221 | obj.after(editor)
222 |
223 | # render toolbar & binding events
224 | toolbar = $(QEDITOR_TOOLBAR_HTML)
225 | qe_heading = toolbar.find(".qe-heading")
226 | qe_heading.mouseenter ->
227 | $(this).addClass("hover")
228 | $(this).find(".qe-menu").show()
229 | qe_heading.mouseleave ->
230 | $(this).removeClass("hover")
231 | $(this).find(".qe-menu").hide()
232 | toolbar.find(".qe-heading .qe-menu a").click ->
233 | link = $(this)
234 | link.parent().parent().hide()
235 | QEditor.action(this,"formatBlock",link.data("name"))
236 | return false
237 | toolbar.find("a[data-action]").click ->
238 | QEditor.action(this,$(this).attr("data-action"))
239 | editor.before(toolbar)
--------------------------------------------------------------------------------