radiant-forum-extension 1.2.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +37 -56
- data/VERSION +1 -1
- data/app/controllers/forum_base_controller.rb +78 -0
- data/app/controllers/forums_controller.rb +5 -34
- data/app/controllers/posts_controller.rb +61 -153
- data/app/controllers/topics_controller.rb +6 -63
- data/app/helpers/forum_helper.rb +24 -48
- data/app/models/forum.rb +5 -18
- data/app/models/post.rb +53 -55
- data/app/models/post_attachment.rb +9 -6
- data/app/models/topic.rb +20 -113
- data/app/views/admin/reader_configuration/_edit_forum.html.haml +4 -2
- data/app/views/admin/reader_configuration/_forum.html.haml +6 -2
- data/app/views/forums/_forum.html.haml +14 -20
- data/app/views/forums/_latest.html.haml +12 -0
- data/app/views/forums/_standard_parts.html.haml +49 -0
- data/app/views/forums/index.html.haml +16 -24
- data/app/views/forums/show.html.haml +18 -28
- data/app/views/pages/_comment.html.haml +1 -1
- data/app/views/posts/_attachments.html.haml +13 -0
- data/app/views/posts/_confirm_delete.html.haml +10 -0
- data/app/views/posts/_context.html.haml +16 -0
- data/app/views/posts/_edit_links.html.haml +11 -0
- data/app/views/posts/_form.html.haml +40 -2
- data/app/views/posts/_latest.html.haml +10 -17
- data/app/views/posts/_new_attachment.html.haml +2 -0
- data/app/views/posts/_post.html.haml +25 -60
- data/app/views/posts/{_search.html.haml → _search_form.html.haml} +1 -1
- data/app/views/posts/_uploader.html.haml +2 -2
- data/app/views/posts/edit.html.haml +26 -13
- data/app/views/posts/index.html.haml +19 -27
- data/app/views/posts/new.html.haml +27 -7
- data/app/views/posts/remove.html.haml +27 -0
- data/app/views/posts/show.html.haml +20 -7
- data/app/views/readers/_forum_messages.html.haml +20 -0
- data/app/views/readers/_messages_summary.html.haml +3 -0
- data/app/views/topics/_context.html.haml +12 -0
- data/app/views/topics/_latest.html.haml +14 -16
- data/app/views/topics/_locked.html.haml +1 -1
- data/app/views/topics/_replies.html.haml +6 -0
- data/app/views/topics/_reply.html.haml +23 -0
- data/app/views/topics/_topic.html.haml +14 -43
- data/app/views/topics/_voices.html.haml +5 -0
- data/app/views/topics/index.html.haml +11 -24
- data/app/views/topics/show.html.haml +25 -38
- data/config/initializers/radiant_config.rb +5 -1
- data/config/locales/en.yml +73 -27
- data/config/routes.rb +3 -4
- data/db/migrate/20101222160900_page_posts.rb +21 -0
- data/db/migrate/20101222163605_no_comment_forum.rb +10 -0
- data/db/migrate/20110105103827_topic_merely_associative.rb +23 -0
- data/db/migrate/20110111080550_detach_observer.rb +11 -0
- data/db/migrate/20110127113852_import_attachments.rb +9 -0
- data/forum_extension.rb +12 -13
- data/lib/commentable_model.rb +98 -0
- data/lib/forum_page.rb +2 -22
- data/lib/forum_reader_sessions_controller.rb +14 -0
- data/lib/forum_readers_controller.rb +2 -9
- data/lib/forum_red_cloth3.rb +23 -4
- data/lib/forum_red_cloth4.rb +23 -4
- data/lib/forum_tags.rb +298 -194
- data/lib/sanitize/config/forum.rb +47 -0
- data/public/images/furniture/blank.png +0 -0
- data/public/images/furniture/emoticons.png +0 -0
- data/public/javascripts/forum.js +349 -93
- data/public/javascripts/jquery.tools.min.js +195 -0
- data/public/punymce/blank.htm +1 -0
- data/public/punymce/css/content.css +4 -0
- data/public/punymce/css/editor.css +58 -0
- data/public/punymce/i18n/sv.js +28 -0
- data/public/punymce/img/icons.gif +0 -0
- data/public/punymce/img/icons_uncompressed.png +0 -0
- data/public/punymce/plugins/bbcode.js +1 -0
- data/public/punymce/plugins/bbcode_src.js +50 -0
- data/public/punymce/plugins/editsource/css/editor.css +3 -0
- data/public/punymce/plugins/editsource/editsource.js +1 -0
- data/public/punymce/plugins/editsource/editsource_src.js +81 -0
- data/public/punymce/plugins/editsource/img/icons.gif +0 -0
- data/public/punymce/plugins/emoticons/css/content.css +13 -0
- data/public/punymce/plugins/emoticons/css/editor.css +17 -0
- data/public/punymce/plugins/emoticons/emoticons.js +1 -0
- data/public/punymce/plugins/emoticons/emoticons_src.js +303 -0
- data/public/punymce/plugins/emoticons/img/emoticons.gif +0 -0
- data/public/punymce/plugins/emoticons/img/emoticons.png +0 -0
- data/public/punymce/plugins/emoticons/img/trans.gif +0 -0
- data/public/punymce/plugins/entities.js +1 -0
- data/public/punymce/plugins/entities_src.js +37 -0
- data/public/punymce/plugins/forceblocks.js +1 -0
- data/public/punymce/plugins/forceblocks_src.js +465 -0
- data/public/punymce/plugins/forcenl.js +1 -0
- data/public/punymce/plugins/forcenl_src.js +26 -0
- data/public/punymce/plugins/image/css/editor.css +1 -0
- data/public/punymce/plugins/image/image.js +1 -0
- data/public/punymce/plugins/image/image_src.js +30 -0
- data/public/punymce/plugins/image/img/icons.gif +0 -0
- data/public/punymce/plugins/link/css/editor.css +2 -0
- data/public/punymce/plugins/link/img/icons.gif +0 -0
- data/public/punymce/plugins/link/link.js +1 -0
- data/public/punymce/plugins/link/link_src.js +36 -0
- data/public/punymce/plugins/paste.js +1 -0
- data/public/punymce/plugins/paste_src.js +169 -0
- data/public/punymce/plugins/protect.js +1 -0
- data/public/punymce/plugins/protect_src.js +30 -0
- data/public/punymce/plugins/safari2x.js +1 -0
- data/public/punymce/plugins/safari2x_src.js +284 -0
- data/public/punymce/plugins/tabfocus.js +1 -0
- data/public/punymce/plugins/tabfocus_src.js +45 -0
- data/public/punymce/plugins/textcolor/css/editor.css +7 -0
- data/public/punymce/plugins/textcolor/img/icons.gif +0 -0
- data/public/punymce/plugins/textcolor/textcolor.js +1 -0
- data/public/punymce/plugins/textcolor/textcolor_src.js +73 -0
- data/public/punymce/puny_mce.js +1 -0
- data/public/punymce/puny_mce_full.js +1 -0
- data/public/punymce/puny_mce_src.js +1460 -0
- data/public/stylesheets/sass/forum.sass +175 -169
- data/radiant-forum-extension.gemspec +81 -19
- data/spec/controllers/admin/forums_controller_spec.rb +2 -2
- data/spec/controllers/forums_controller_spec.rb +3 -6
- data/spec/controllers/posts_controller_spec.rb +76 -59
- data/spec/controllers/topics_controller_spec.rb +4 -95
- data/spec/datasets/forum_readers_dataset.rb +1 -0
- data/spec/datasets/forums_dataset.rb +91 -10
- data/spec/lib/commentable_model_spec.rb +88 -0
- data/spec/lib/forum_page_spec.rb +2 -34
- data/spec/lib/forum_site_spec.rb +2 -3
- data/spec/lib/forum_tags_spec.rb +35 -0
- data/spec/models/forum_spec.rb +31 -20
- data/spec/models/post_spec.rb +40 -39
- data/spec/models/topic_spec.rb +29 -71
- data/spec/spec_helper.rb +10 -1
- metadata +84 -22
- data/app/views/posts/_reply.html.haml +0 -35
- data/app/views/posts/_upload.html.haml +0 -2
- data/app/views/posts/preview.html.haml +0 -32
- data/app/views/posts/search.html.haml +0 -63
- data/app/views/posts/search.rss.builder +0 -14
- data/app/views/topics/_form.html.haml +0 -30
- data/app/views/topics/_help.html.haml +0 -8
- data/app/views/topics/comments.html.haml +0 -6
- data/app/views/topics/edit.html.haml +0 -26
- data/app/views/topics/new.html.haml +0 -56
- data/spec/datasets/forum_pages_dataset.rb +0 -11
- data/spec/datasets/posts_dataset.rb +0 -31
- data/spec/datasets/topics_dataset.rb +0 -37
@@ -0,0 +1,17 @@
|
|
1
|
+
.punymce a.emoticons { background: url('../img/emoticons.png') 0 0; }
|
2
|
+
|
3
|
+
/* Menu */
|
4
|
+
div.punymce_emoticons { position: absolute; display: none; background-color: white; border: 1px solid #F0F0EE;}
|
5
|
+
.punymce a.emoticon { display: block; width: 16px; height: 16px; }
|
6
|
+
.punymce a.happy { background: url('../img/emoticons.png') no-repeat 0 0; }
|
7
|
+
.punymce a.unhappy { background: url('../img/emoticons.png') no-repeat -16px 0; }
|
8
|
+
.punymce a.sad { background: url('../img/emoticons.png') no-repeat -32px 0; }
|
9
|
+
.punymce a.grin { background: url('../img/emoticons.png') no-repeat -48px 0; }
|
10
|
+
.punymce a.surprised { background: url('../img/emoticons.png') no-repeat -64px 0; }
|
11
|
+
.punymce a.wink { background: url('../img/emoticons.png') no-repeat -80px 0; }
|
12
|
+
.punymce a.halfhappy { background: url('../img/emoticons.png') no-repeat -96px 0; }
|
13
|
+
.punymce a.tongue { background: url('../img/emoticons.png') no-repeat -112px 0; }
|
14
|
+
.punymce a.lol { background: url('../img/emoticons.png') no-repeat -128px 0; }
|
15
|
+
.punymce a.mad { background: url('../img/emoticons.png') no-repeat -144px 0; }
|
16
|
+
.punymce a.shocked { background: url('../img/emoticons.png') no-repeat -160px 0; }
|
17
|
+
.punymce a.cool { background: url('../img/emoticons.png') no-repeat -176px 0; }
|
@@ -0,0 +1 @@
|
|
1
|
+
(function(a){a.plugins.Emoticons=function(e){var k=a.Event,i,g,c,b,m,j,l,d;i=a.each;g=a.extend;c=a.isIE;b=a.isGecko;l=a.DOM;this.settings=m=g({emoticons:{happy:[":)"],neutral:[":|"],sad:[":("],grin:[":D"],surprised:[":O"],wink:[";)"],devil:["}:)"],tongue:[":P"],lol:[':@'],mad:[':['],shocked:['8|'],cool:['B]']},row_length:4,trans_img:a.baseURL+"plugins/emoticons/img/trans.gif",skip_css:0,auto_convert:1},e.settings.emoticons);if(!m.skip_css){l.loadCSS(a.baseURL+"/plugins/emoticons/css/editor.css")}j="";i(m.emoticons,function(h){i(h,function(n){if(j.length!=0){j+="|"}j+=n.replace(/([^a-zA-Z0-9])/g,"\\$1")})});j=new RegExp(j,"g");g(e.commands,{mceEmoticons:function(B,A,y){var q,C=this,h=e.settings.id,o=l.getPos(y.target),z,w;if(e.hideMenu){return e.hideMenu()}function x(n){e.hideMenu=null;k.remove(document,"click",x);k.remove(e.getDoc(),"click",x);l.get(h+"_memoticons").style.display="none";return 1}q=l.get(h+"_memoticons");if(!q){q=l.get(h+"_t");q=l.add(document.body,"div",{id:h+"_memoticons","class":"punymce_emoticons punymce"});q=l.add(q,"table",{"class":"punymce"});q=l.add(q,"tbody");z=m.row_length;i(m.emoticons,function(p,n){if(z==m.row_length){r=l.add(q,"tr");z=0}z++;k.add(l.add(l.add(r,"td"),"a",{href:"#","class":"emoticon "+n}),"mousedown",function(t){x.call(C);e.selection.setNode(e.dom.create("img",{title:p[0]||n,src:m.trans_img,"class":"emoticon "+n}));return k.cancel(t)})})}k.add(document,"click",x,C);k.add(e.getDoc(),"click",x,C);e.hideMenu=x;s=l.get(h+"_memoticons").style;s.left=o.x+"px";s.top=(o.y+y.target.clientHeight+2)+"px";s.display="block"}});function f(h){var n;i(m.emoticons,function(p,o){i(p,function(q){if(q==h){n=o;return false}});return !n});return n}e.onPreProcess.add(function(p,q){var n=q.node.getElementsByTagName("img"),h=[];i(n,function(o){h.push(o)});i(h,function(t){var o=e.dom.getAttr(t,"class");if(o&&o.indexOf("emoticon")!=-1){t.parentNode.replaceChild(e.getDoc().createTextNode(t.getAttribute("title")),t)}})});e.onSetContent.add(function(n,p){var h=[];d=p.content.replace(/(<\/?[^>]+>|:\/\/)/g,function(o){return o.replace(j,function(q){var t=f(q);if(t){h.push(q);return"�"+h.length+"�"}return q})});d=d.replace(j,function(o){return'<img src="'+m.trans_img+'" title="'+o+'" class="emoticon '+f(o)+'" />'});d=d.replace(/�([^�]+)�/g,function(q,o){return h[parseInt(o)-1]});p.content=d});e.onInit.add(function(){var h=e.dom;if(!m.skip_css){h.loadCSS(a.baseURL+"/plugins/emoticons/css/content.css")}k.add(e.getDoc(),"controlselect",function(n){if(h.getAttr(n.target,"class").indexOf("emoticon")!=-1){return k.cancel(n)}});if(b){k.add(e.getDoc(),"mousedown",function(n){if(h.getAttr(n.target,"class").indexOf("emoticon")!=-1){e.getDoc().execCommand("enableObjectResizing",false,false);return k.cancel(n)}else{e.getDoc().execCommand("enableObjectResizing",false,true)}});k.add(e.getDoc(),"keydown",function(u){var y=e.selection,v=y.getSel(),w=e.getDoc(),o=y.getRng(),x,p,q,t;x=o.startContainer;p=o.startOffset;if(x.nodeType==1){return}if(x){if(u.keyCode==39&&p==x.nodeValue.length){q=x.nextSibling;if(q&&q.nodeName=="IMG"){q=q.nextSibling;o=w.createRange();o.setStart(q,0);o.setEnd(q,0);v.removeAllRanges();v.addRange(o);return k.cancel(u)}}if(u.keyCode==37&&p==0){q=x.previousSibling;if(q&&q.nodeName=="IMG"){q=q.previousSibling;t=q.nodeValue.length;o=w.createRange();o.setStart(q,t);o.setEnd(q,t);v.removeAllRanges();v.addRange(o);return k.cancel(u)}}}})}k.add(e.getDoc(),"keypress",function(t){var p,x,o,w,v=e.getDoc(),u=e.selection,y=u.getSel(),n=u.getRng();function q(C){var B,A,z;if(!c){B=n.startContainer;A=n.startOffset;z=n.endOffset;if(A>0&&B.nodeType==3){return B.nodeValue.substring(Math.max(0,A+C),z)}}else{n=n.duplicate();n.moveStart("character",C);return n.text}}if(a.isOldWebKit||!m.auto_convert){return true}if(/(ttp|ftp):/i.test(q(-4))){return}o=q(-1);p=o+String.fromCharCode(t.charCode||t.keyCode);j.lastIndex=0;if(!o||!j.test(p)||w=="/"){return}if(x=f(p)){if(!c){n.setStart(n.startContainer,n.startOffset-1);y.removeAllRanges();y.addRange(n)}else{n=e.selection.getRng();n.moveStart("character",-1);n.select()}e.selection.setNode(h.create("img",{id:"emoticon",title:p,src:m.trans_img,"class":"emoticon "+x}));p=h.get("emoticon");h.setAttr(p,"id","");e.selection.select(p);e.selection.collapse(0);return k.cancel(t)}})});g(e.tools,{emoticons:{cmd:"mceEmoticons",title:a.I18n.emoticons}})};a.extend(a.I18n,{emoticons:"Insert emoticon"})})(punymce);
|
@@ -0,0 +1,303 @@
|
|
1
|
+
(function(punymce) {
|
2
|
+
punymce.plugins.Emoticons = function(ed) {
|
3
|
+
var Event = punymce.Event, each, extend, isIE, isGecko, st, emoReg, DOM, h;
|
4
|
+
|
5
|
+
each = punymce.each;
|
6
|
+
extend = punymce.extend;
|
7
|
+
isIE = punymce.isIE;
|
8
|
+
isGecko = punymce.isGecko;
|
9
|
+
DOM = punymce.DOM;
|
10
|
+
|
11
|
+
// Default settings
|
12
|
+
this.settings = st = extend({
|
13
|
+
emoticons : {
|
14
|
+
happy : [':)', '=)'],
|
15
|
+
unhappy : [':|', '=|'],
|
16
|
+
sad : [':(','=('],
|
17
|
+
grin : [':D', '=D'],
|
18
|
+
surprised : [':o',':O','=o', '=O'],
|
19
|
+
wink : [';)'],
|
20
|
+
halfhappy : [':/', '=/'],
|
21
|
+
tongue : [':P', ':p', '=P', '=p'],
|
22
|
+
lol : [':0'],
|
23
|
+
mad : [':['],
|
24
|
+
shocked : ['8|'],
|
25
|
+
cool : ['B]']
|
26
|
+
},
|
27
|
+
row_length : 4,
|
28
|
+
trans_img : punymce.baseURL + 'plugins/emoticons/img/trans.gif',
|
29
|
+
skip_css : 0,
|
30
|
+
auto_convert : 1
|
31
|
+
}, ed.settings.emoticons);
|
32
|
+
|
33
|
+
if (!st.skip_css)
|
34
|
+
DOM.loadCSS(punymce.baseURL + '/plugins/emoticons/css/editor.css');
|
35
|
+
|
36
|
+
// Build regexp from emoticons
|
37
|
+
emoReg = '';
|
38
|
+
each(st.emoticons, function(v) {
|
39
|
+
each(v, function(v) {
|
40
|
+
if (emoReg.length != 0)
|
41
|
+
emoReg += '|';
|
42
|
+
|
43
|
+
emoReg += v.replace(/([^a-zA-Z0-9])/g, '\\$1');
|
44
|
+
});
|
45
|
+
});
|
46
|
+
emoReg = new RegExp(emoReg, 'g');
|
47
|
+
|
48
|
+
// Add commands
|
49
|
+
extend(ed.commands, {
|
50
|
+
mceEmoticons : function(u, v, e) {
|
51
|
+
var n, t = this, id = ed.settings.id, p = DOM.getPos(e.target), co, cb;
|
52
|
+
|
53
|
+
if (ed.hideMenu)
|
54
|
+
return ed.hideMenu();
|
55
|
+
|
56
|
+
function hide(e) {
|
57
|
+
ed.hideMenu = null;
|
58
|
+
Event.remove(document, 'click', hide);
|
59
|
+
Event.remove(ed.getDoc(), 'click', hide);
|
60
|
+
DOM.get(id + '_memoticons').style.display = 'none';
|
61
|
+
return 1;
|
62
|
+
};
|
63
|
+
|
64
|
+
n = DOM.get(id + '_memoticons');
|
65
|
+
if (!n) {
|
66
|
+
n = DOM.get(id + '_t');
|
67
|
+
n = DOM.add(document.body, 'div', {id : id + '_memoticons', 'class' : 'punymce_emoticons punymce'});
|
68
|
+
n = DOM.add(n, 'table', {'class' : 'punymce'});
|
69
|
+
n = DOM.add(n, 'tbody');
|
70
|
+
co = st.row_length;
|
71
|
+
each(st.emoticons, function(c, k) {
|
72
|
+
if (co == st.row_length) {
|
73
|
+
r = DOM.add(n, 'tr');
|
74
|
+
co = 0;
|
75
|
+
}
|
76
|
+
|
77
|
+
co++;
|
78
|
+
|
79
|
+
Event.add(DOM.add(DOM.add(r, 'td'), 'a', {href : '#', 'class' : 'emoticon ' + k}), 'mousedown', function(e) {
|
80
|
+
hide.call(t);
|
81
|
+
|
82
|
+
ed.selection.setNode(ed.dom.create('img', { title : c[0] || k, src : st.trans_img, 'class' : 'emoticon ' + k }));
|
83
|
+
|
84
|
+
return Event.cancel(e);
|
85
|
+
});
|
86
|
+
});
|
87
|
+
}
|
88
|
+
|
89
|
+
Event.add(document, 'click', hide, t);
|
90
|
+
Event.add(ed.getDoc(), 'click', hide, t);
|
91
|
+
ed.hideMenu = hide;
|
92
|
+
|
93
|
+
s = DOM.get(id + '_memoticons').style;
|
94
|
+
s.left = p.x + 'px';
|
95
|
+
s.top = (p.y + e.target.clientHeight + 2) + 'px';
|
96
|
+
s.display = 'block';
|
97
|
+
}
|
98
|
+
});
|
99
|
+
|
100
|
+
function find(e) {
|
101
|
+
var c;
|
102
|
+
|
103
|
+
each(st.emoticons, function(v, k) {
|
104
|
+
each(v, function(v) {
|
105
|
+
if (v == e) {
|
106
|
+
c = k;
|
107
|
+
return false;
|
108
|
+
}
|
109
|
+
});
|
110
|
+
|
111
|
+
return !c;
|
112
|
+
});
|
113
|
+
|
114
|
+
return c;
|
115
|
+
};
|
116
|
+
|
117
|
+
ed.onPreProcess.add(function(se, o) {
|
118
|
+
var nl = o.node.getElementsByTagName('img'), a = [];
|
119
|
+
|
120
|
+
each(nl, function(n) {
|
121
|
+
a.push(n);
|
122
|
+
});
|
123
|
+
|
124
|
+
each(a, function(n) {
|
125
|
+
var c = ed.dom.getAttr(n, 'class');
|
126
|
+
|
127
|
+
if (c && c.indexOf('emoticon') != -1) {
|
128
|
+
n.parentNode.replaceChild(ed.getDoc().createTextNode(n.getAttribute('title')), n);
|
129
|
+
}
|
130
|
+
});
|
131
|
+
});
|
132
|
+
|
133
|
+
ed.onSetContent.add(function(ed, o) {
|
134
|
+
var ar = [];
|
135
|
+
|
136
|
+
// Store away all tags and URL parts (://)
|
137
|
+
h = o.content.replace(/(<\/?[^>]+>|:\/\/)/g, function(a) {
|
138
|
+
return a.replace(emoReg, function(a) {
|
139
|
+
var c = find(a);
|
140
|
+
|
141
|
+
if (c) {
|
142
|
+
ar.push(a);
|
143
|
+
return '�' + ar.length + '�';
|
144
|
+
}
|
145
|
+
|
146
|
+
return a;
|
147
|
+
});
|
148
|
+
});
|
149
|
+
|
150
|
+
// Replace emoticons in remaining text nodes
|
151
|
+
h = h.replace(emoReg, function(a) {
|
152
|
+
return '<img src="' + st.trans_img + '" title="' + a + '" class="emoticon ' + find(a) + '" />';
|
153
|
+
});
|
154
|
+
|
155
|
+
// Restore attribs
|
156
|
+
h = h.replace(/�([^�]+)�/g, function(a, b) {
|
157
|
+
return ar[parseInt(b) - 1];
|
158
|
+
});
|
159
|
+
|
160
|
+
o.content = h;
|
161
|
+
});
|
162
|
+
|
163
|
+
ed.onInit.add(function() {
|
164
|
+
var DOM = ed.dom;
|
165
|
+
|
166
|
+
if (!st.skip_css)
|
167
|
+
DOM.loadCSS(punymce.baseURL + '/plugins/emoticons/css/content.css');
|
168
|
+
|
169
|
+
// Disable selection on emoticons in IE
|
170
|
+
Event.add(ed.getDoc(), 'controlselect', function(e) {
|
171
|
+
if (DOM.getAttr(e.target, 'class').indexOf('emoticon') != -1)
|
172
|
+
return Event.cancel(e);
|
173
|
+
});
|
174
|
+
|
175
|
+
if (isGecko) {
|
176
|
+
// Disable selection of emoticons in Gecko
|
177
|
+
Event.add(ed.getDoc(), 'mousedown', function(e) {
|
178
|
+
if (DOM.getAttr(e.target, 'class').indexOf('emoticon') != -1) {
|
179
|
+
ed.getDoc().execCommand('enableObjectResizing', false, false);
|
180
|
+
return Event.cancel(e);
|
181
|
+
} else
|
182
|
+
ed.getDoc().execCommand('enableObjectResizing', false, true);
|
183
|
+
});
|
184
|
+
|
185
|
+
// Fix for bug: https://bugzilla.mozilla.org/show_bug.cgi?id=392569
|
186
|
+
Event.add(ed.getDoc(), 'keydown', function(e) {
|
187
|
+
var s = ed.selection, se = s.getSel(), d = ed.getDoc(), r = s.getRng(), sc, so, n, l;
|
188
|
+
|
189
|
+
sc = r.startContainer;
|
190
|
+
so = r.startOffset;
|
191
|
+
|
192
|
+
// Element instead of text just pass it though
|
193
|
+
if (sc.nodeType == 1)
|
194
|
+
return;
|
195
|
+
|
196
|
+
if (sc) {
|
197
|
+
// Right key
|
198
|
+
if (e.keyCode == 39 && so == sc.nodeValue.length) {
|
199
|
+
n = sc.nextSibling;
|
200
|
+
if (n && n.nodeName == 'IMG') {
|
201
|
+
n = n.nextSibling;
|
202
|
+
|
203
|
+
r = d.createRange();
|
204
|
+
r.setStart(n, 0);
|
205
|
+
r.setEnd(n, 0);
|
206
|
+
|
207
|
+
se.removeAllRanges();
|
208
|
+
se.addRange(r);
|
209
|
+
|
210
|
+
return Event.cancel(e);
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
// Left key
|
215
|
+
if (e.keyCode == 37 && so == 0) {
|
216
|
+
n = sc.previousSibling;
|
217
|
+
if (n && n.nodeName == 'IMG') {
|
218
|
+
n = n.previousSibling;
|
219
|
+
l = n.nodeValue.length;
|
220
|
+
|
221
|
+
r = d.createRange();
|
222
|
+
r.setStart(n, l);
|
223
|
+
r.setEnd(n, l);
|
224
|
+
|
225
|
+
se.removeAllRanges();
|
226
|
+
se.addRange(r);
|
227
|
+
|
228
|
+
return Event.cancel(e);
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
});
|
233
|
+
}
|
234
|
+
|
235
|
+
Event.add(ed.getDoc(), 'keypress', function(e) {
|
236
|
+
var em, cls, lc, lc2, d = ed.getDoc(), se = ed.selection, s = se.getSel(), r = se.getRng();
|
237
|
+
|
238
|
+
function getStr(pos) {
|
239
|
+
var sn, so, eo;
|
240
|
+
|
241
|
+
if (!isIE) {
|
242
|
+
sn = r.startContainer;
|
243
|
+
so = r.startOffset;
|
244
|
+
eo = r.endOffset;
|
245
|
+
|
246
|
+
if (so > 0 && sn.nodeType == 3)
|
247
|
+
return sn.nodeValue.substring(Math.max(0, so + pos), eo);
|
248
|
+
} else {
|
249
|
+
r = r.duplicate();
|
250
|
+
r.moveStart('character', pos);
|
251
|
+
|
252
|
+
return r.text;
|
253
|
+
}
|
254
|
+
};
|
255
|
+
|
256
|
+
// Check if Safari 2.x
|
257
|
+
if (punymce.isOldWebKit || !st.auto_convert)
|
258
|
+
return true;
|
259
|
+
|
260
|
+
// If http/ftp
|
261
|
+
if (/(ttp|ftp):/i.test(getStr(-4)))
|
262
|
+
return;
|
263
|
+
|
264
|
+
lc = getStr(-1);
|
265
|
+
em = lc + String.fromCharCode(e.charCode || e.keyCode);
|
266
|
+
emoReg.lastIndex = 0;
|
267
|
+
|
268
|
+
if (!lc || !emoReg.test(em) || lc2 == '/')
|
269
|
+
return;
|
270
|
+
|
271
|
+
if (cls = find(em)) {
|
272
|
+
if (!isIE) {
|
273
|
+
r.setStart(r.startContainer, r.startOffset - 1);
|
274
|
+
s.removeAllRanges();
|
275
|
+
s.addRange(r);
|
276
|
+
} else {
|
277
|
+
r = ed.selection.getRng();
|
278
|
+
r.moveStart('character', -1);
|
279
|
+
r.select();
|
280
|
+
}
|
281
|
+
|
282
|
+
ed.selection.setNode(DOM.create('img', { id : 'emoticon', title : em, src : st.trans_img, 'class' : 'emoticon ' + cls }));
|
283
|
+
|
284
|
+
em = DOM.get('emoticon');
|
285
|
+
DOM.setAttr(em, 'id', '');
|
286
|
+
ed.selection.select(em);
|
287
|
+
ed.selection.collapse(0);
|
288
|
+
|
289
|
+
return Event.cancel(e);
|
290
|
+
}
|
291
|
+
});
|
292
|
+
});
|
293
|
+
|
294
|
+
extend(ed.tools, {
|
295
|
+
emoticons : {cmd : 'mceEmoticons', title : punymce.I18n.emoticons}
|
296
|
+
});
|
297
|
+
};
|
298
|
+
|
299
|
+
// English i18n strings
|
300
|
+
punymce.extend(punymce.I18n, {
|
301
|
+
emoticons : 'Insert emoticon'
|
302
|
+
});
|
303
|
+
})(punymce);
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
(function(a){a.plugins.Entities=function(e){var j,c,h="",b={},f,d,g;j=e.settings;j.entities="named";g=j.entity_list;if(!g){g="160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro"}c=g.split(",");for(f=0;f<c.length;f+=2){b[String.fromCharCode(c[f])]=c[f+1];d=parseInt(c[f]).toString(16);h+="\\u"+"0000".substring(d.length)+d}h=new RegExp("["+h+"]","g");e.onGetContent.add(function(i,k){if(k.format=="html"){k.content=k.content.replace(h,function(l){var m;if(m=b[l]){l="&"+m+";"}return l})}})}})(punymce);
|
@@ -0,0 +1,37 @@
|
|
1
|
+
(function(punymce) {
|
2
|
+
punymce.plugins.Entities = function(ed) {
|
3
|
+
var s, a, re = '', l = {}, i, v, el;
|
4
|
+
|
5
|
+
s = ed.settings;
|
6
|
+
|
7
|
+
// Force named
|
8
|
+
s.entities = 'named';
|
9
|
+
el = s.entity_list;
|
10
|
+
|
11
|
+
if (!el)
|
12
|
+
el = '160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro';
|
13
|
+
|
14
|
+
// Build regex and lookup array
|
15
|
+
a = el.split(',');
|
16
|
+
for (i=0; i<a.length; i+=2) {
|
17
|
+
l[String.fromCharCode(a[i])] = a[i + 1];
|
18
|
+
|
19
|
+
v = parseInt(a[i]).toString(16);
|
20
|
+
re += '\\u' + '0000'.substring(v.length) + v;
|
21
|
+
}
|
22
|
+
re = new RegExp('[' + re + ']', 'g');
|
23
|
+
|
24
|
+
ed.onGetContent.add(function(ed, o) {
|
25
|
+
if (o.format == 'html') {
|
26
|
+
o.content = o.content.replace(re, function(a) {
|
27
|
+
var v;
|
28
|
+
|
29
|
+
if (v = l[a])
|
30
|
+
a = '&' + v + ';';
|
31
|
+
|
32
|
+
return a;
|
33
|
+
});
|
34
|
+
}
|
35
|
+
});
|
36
|
+
};
|
37
|
+
})(punymce);
|
@@ -0,0 +1 @@
|
|
1
|
+
(function(a){a.plugins.ForceBlocks=function(d){var v=a.Event,s,g=this;var n,k,u,q;var c,r,p;n=a.isIE;k=a.isGecko;u=a.isOpera;q=a.isWebKit;c=a.each;r=a.extend;this.settings=p=r({element:"P"},d.settings.forceblocks);d.onPreInit.add(m,g);if(!n){d.onSetContent.add(function(t,w){if(w.format=="html"){w.content=w.content.replace(/<p>[\s\u00a0]+<\/p>/g,"<p><br /></p>")}})}d.onPostProcess.add(function(t,w){w.content=w.content.replace(/<p><\/p>/g,"<p>\u00a0</p>")});function m(){s=d.dom;v.add(d.getDoc(),"keyup",j);d.onSetContent.add(j);d.onBeforeGetContent.add(j);if(!n){d.onPreProcess.add(function(t,w){c(w.node.getElementsByTagName("br"),function(y){var x=y.parentNode;if(x&&x.nodeName=="p"&&(x.childNodes.length==1||x.lastChild==y)){x.replaceChild(t.getDoc().createTextNode("\u00a0"),y)}})});v.add(d.getDoc(),"keypress",function(t){if(t.keyCode==13&&!t.shiftKey){if(!o(t)){return v.cancel(t)}}});if(k){v.add(d.getDoc(),"keydown",function(t){if((t.keyCode==8||t.keyCode==46)&&!t.shiftKey){h(t,t.keyCode==8)}})}}}function b(x){var y,t;y=x.document;t=y.compatMode=="CSS1Compat"?y.documentElement:y.body;return{x:x.pageXOffset||t.scrollLeft,y:x.pageYOffset||t.scrollTop,w:x.innerWidth||t.clientWidth,h:x.innerHeight||t.clientHeight}}function l(B,y,z){var x=d.getDoc().createTreeWalker(B,4,null,false),B,A=-1;while(B=x.nextNode()){A++;if(y==0&&B==z){return A}if(y==1&&A==z){return B}}return -1}function j(){var C=this,O=d.getBody(),L=d.getDoc(),R=d.selection,D=R.getSel(),E=R.getRng(),P=-2,A,J,w,x,M=-16777215;var N,y,Q,I,F,z=O.childNodes,H,G,B;for(H=z.length-1;H>=0;H--){N=z[H];if(N.nodeType==3||(!f(N)&&N.nodeType!=8)){if(!y){if(N.nodeType!=3||/[^\s]/g.test(N.nodeValue)){if(P==-2&&E){if(!n){if(E.startContainer.nodeType==1&&(G=E.startContainer.childNodes[E.startOffset])&&G.nodeType==1){B=G.getAttribute("id");G.setAttribute("id","__mce")}else{if(d.dom.getParent(E.startContainer,function(t){return t===O})){J=E.startOffset;w=E.endOffset;P=l(O,0,E.startContainer);A=l(O,0,E.endContainer)}}}else{x=L.body.createTextRange();x.moveToElementText(O);x.collapse(1);Q=x.move("character",M)*-1;x=E.duplicate();x.collapse(1);I=x.move("character",M)*-1;x=E.duplicate();x.collapse(0);F=(x.move("character",M)*-1)-I;P=I-Q;A=F}}y=d.dom.create(p.element);y.appendChild(N.cloneNode(1));N.parentNode.replaceChild(y,N)}}else{if(y.hasChildNodes()){y.insertBefore(N,y.firstChild)}else{y.appendChild(N)}}}else{y=null}}if(P!=-2){if(!n){y=O.getElementsByTagName(p.element)[0];E=L.createRange();if(P!=-1){E.setStart(l(O,1,P),J)}else{E.setStart(y,0)}if(A!=-1){E.setEnd(l(O,1,A),w)}else{E.setEnd(y,0)}if(D){D.removeAllRanges();D.addRange(E)}}else{try{E=D.createRange();E.moveToElementText(O);E.collapse(1);E.moveStart("character",P);E.moveEnd("character",A);E.select()}catch(K){}}}else{if(!n&&(G=d.dom.get("__mce"))){if(B){G.setAttribute("id",B)}else{G.removeAttribute("id")}E=L.createRange();E.setStartBefore(G);E.setEndBefore(G);R.setRng(E)}}}function f(t){return t.nodeType==1&&/^(H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CODE|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(t.nodeName)}function e(t){return s.getParent(t,function(w){return f(w)})}function i(t){t=t.innerHTML;t=t.replace(/<img|hr|table/g,"d");t=t.replace(/<[^>]+>/g,"");return t.replace(/[ \t\r\n]+/g,"")==""}function o(O){var P=d.getDoc(),G=d.selection.getSel(),H=d.selection.getRng(),Q=P.body;var K,L,I,N,M,z,w,A,C,t,E,R,x,B,J,D,F;if(a.isOldWebKit){return true}K=P.createRange();K.setStart(G.anchorNode,G.anchorOffset);K.collapse(true);L=P.createRange();L.setStart(G.focusNode,G.focusOffset);L.collapse(true);I=K.compareBoundaryPoints(K.START_TO_END,L)<0;N=I?G.anchorNode:G.focusNode;M=I?G.anchorOffset:G.focusOffset;z=I?G.focusNode:G.anchorNode;w=I?G.focusOffset:G.anchorOffset;N=N.nodeName=="BODY"?N.firstChild:N;z=z.nodeName=="BODY"?z.firstChild:z;A=e(N);C=e(z);t=A?A.nodeName:p.element;if(s.getParent(A,function(y){return/OL|UL/.test(y.nodeName)})){return true}if(A&&(A.nodeName=="CAPTION"||/absolute|relative|static/gi.test(A.style.position))){t=p.element;A=null}if(C&&(C.nodeName=="CAPTION"||/absolute|relative|static/gi.test(C.style.position))){t=p.element;C=null}if(/(TD|TABLE|TH|CAPTION)/.test(t)||(A&&t=="DIV"&&/left|right/gi.test(A.style.cssFloat))){t=p.element;A=C=null}E=(A&&A.nodeName==t)?A.cloneNode(0):P.createElement(t);R=(C&&C.nodeName==t)?C.cloneNode(0):P.createElement(t);R.id="";if(/^(H[1-6])$/.test(t)&&N.nodeValue&&M==N.nodeValue.length){R=P.createElement(p.element)}J=x=N;do{if(J==Q||J.nodeType==9||f(J)||/(TD|TABLE|TH|CAPTION)/.test(J.nodeName)){break}x=J}while((J=J.previousSibling?J.previousSibling:J.parentNode));J=B=z;do{if(J==Q||J.nodeType==9||f(J)||/(TD|TABLE|TH|CAPTION)/.test(J.nodeName)){break}B=J}while((J=J.nextSibling?J.nextSibling:J.parentNode));if(x.nodeName==t){K.setStart(x,0)}else{K.setStartBefore(x)}K.setEnd(N,M);E.appendChild(K.cloneContents());L.setEndAfter(B);L.setStart(z,w);R.appendChild(L.cloneContents());H=P.createRange();if(!x.previousSibling&&x.parentNode.nodeName==t){H.setStartBefore(x.parentNode)}else{if(K.startContainer.nodeName==t&&K.startOffset==0){H.setStartBefore(K.startContainer)}else{H.setStart(K.startContainer,K.startOffset)}}if(!B.nextSibling&&B.parentNode.nodeName==t){H.setEndAfter(B.parentNode)}else{H.setEnd(L.endContainer,L.endOffset)}H.deleteContents();if(E.firstChild&&E.firstChild.nodeName==t){E.innerHTML=E.firstChild.innerHTML}if(R.firstChild&&R.firstChild.nodeName==t){R.innerHTML=R.firstChild.innerHTML}if(i(E)){E.innerHTML=u?" <br />":"<br />"}if(i(R)){R.innerHTML=u?" <br />":"<br />"}if(u){H.insertNode(E);H.insertNode(R)}else{H.insertNode(R);H.insertNode(E)}R.normalize();E.normalize();H=P.createRange();H.selectNodeContents(R);H.collapse(1);G.removeAllRanges();G.addRange(H);vp=b(d.getWin());D=d.dom.getPos(R).y;F=R.clientHeight;if(D<vp.y||D+F>vp.y+vp.h){d.getWin().scrollTo(0,D<vp.y?D:D-vp.h+25)}return false}function h(y,E){var B=d.getBody(),x,z=d.selection,t=z.getRng(),A=t.startContainer,x,C,D;if(A&&f(A)&&!/^(TD|TH)$/.test(A.nodeName)&&E){if(A.childNodes.length==0||(A.childNodes.length==1&&A.firstChild.nodeName=="BR")){x=A;while((x=x.previousSibling)&&!f(x)){}if(x){if(A!=B.firstChild){C=d.getDoc().createTreeWalker(x,NodeFilter.SHOW_TEXT,null,false);while(D=C.nextNode()){x=D}t=d.getDoc().createRange();t.setStart(x,x.nodeValue?x.nodeValue.length:0);t.setEnd(x,x.nodeValue?x.nodeValue.length:0);z.getSel().removeAllRanges();z.getSel().addRange(t);A.parentNode.removeChild(A)}return v.cancel(y)}}}function F(w){var G;w=w.target;if(w&&w.parentNode&&w.nodeName=="BR"&&(x=e(w))){G=w.previousSibling;v.remove(B,"DOMNodeInserted",F);if(G&&G.nodeType==3&&/\s+$/.test(G.nodeValue)){return}if(w.previousSibling||w.nextSibling){w.parentNode.removeChild(w)}}}v._add(B,"DOMNodeInserted",F);window.setTimeout(function(){v._remove(B,"DOMNodeInserted",F)},1)}}})(punymce);
|
@@ -0,0 +1,465 @@
|
|
1
|
+
(function(punymce) {
|
2
|
+
punymce.plugins.ForceBlocks = function(ed) {
|
3
|
+
var Event = punymce.Event, DOM, t = this;
|
4
|
+
var isIE, isGecko, isOpera, isWebKit;
|
5
|
+
var each, extend, st;
|
6
|
+
|
7
|
+
isIE = punymce.isIE;
|
8
|
+
isGecko = punymce.isGecko;
|
9
|
+
isOpera = punymce.isOpera;
|
10
|
+
isWebKit = punymce.isWebKit;
|
11
|
+
each = punymce.each;
|
12
|
+
extend = punymce.extend;
|
13
|
+
|
14
|
+
// Default settings
|
15
|
+
this.settings = st = extend({
|
16
|
+
element : 'P'
|
17
|
+
}, ed.settings.forceblocks);
|
18
|
+
|
19
|
+
ed.onPreInit.add(setup, t);
|
20
|
+
|
21
|
+
if (!isIE) {
|
22
|
+
ed.onSetContent.add(function(ed, o) {
|
23
|
+
if (o.format == 'html')
|
24
|
+
o.content = o.content.replace(/<p>[\s\u00a0]+<\/p>/g, '<p><br /></p>');
|
25
|
+
});
|
26
|
+
}
|
27
|
+
|
28
|
+
ed.onPostProcess.add(function(ed, o) {
|
29
|
+
o.content = o.content.replace(/<p><\/p>/g, '<p>\u00a0</p>');
|
30
|
+
});
|
31
|
+
|
32
|
+
function setup() {
|
33
|
+
DOM = ed.dom;
|
34
|
+
|
35
|
+
// Force root blocks when typing and when getting output
|
36
|
+
Event.add(ed.getDoc(), 'keyup', forceRoots);
|
37
|
+
ed.onSetContent.add(forceRoots);
|
38
|
+
ed.onBeforeGetContent.add(forceRoots);
|
39
|
+
|
40
|
+
if (!isIE) {
|
41
|
+
ed.onPreProcess.add(function(ed, o) {
|
42
|
+
each(o.node.getElementsByTagName('br'), function(n) {
|
43
|
+
var p = n.parentNode;
|
44
|
+
|
45
|
+
if (p && p.nodeName == 'p' && (p.childNodes.length == 1 || p.lastChild == n)) {
|
46
|
+
p.replaceChild(ed.getDoc().createTextNode('\u00a0'), n);
|
47
|
+
}
|
48
|
+
});
|
49
|
+
});
|
50
|
+
|
51
|
+
Event.add(ed.getDoc(), 'keypress', function(e) {
|
52
|
+
if (e.keyCode == 13 && !e.shiftKey) {
|
53
|
+
if (!insertPara(e))
|
54
|
+
return Event.cancel(e);
|
55
|
+
}
|
56
|
+
});
|
57
|
+
|
58
|
+
if (isGecko) {
|
59
|
+
Event.add(ed.getDoc(), 'keydown', function(e) {
|
60
|
+
if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey)
|
61
|
+
backspaceDelete(e, e.keyCode == 8);
|
62
|
+
});
|
63
|
+
}
|
64
|
+
}
|
65
|
+
};
|
66
|
+
|
67
|
+
function getViewPort(w) {
|
68
|
+
var d, b;
|
69
|
+
|
70
|
+
d = w.document;
|
71
|
+
b = d.compatMode == "CSS1Compat" ? d.documentElement : d.body;
|
72
|
+
|
73
|
+
// Returns viewport size excluding scrollbars
|
74
|
+
return {
|
75
|
+
x : w.pageXOffset || b.scrollLeft,
|
76
|
+
y : w.pageYOffset || b.scrollTop,
|
77
|
+
w : w.innerWidth || b.clientWidth,
|
78
|
+
h : w.innerHeight || b.clientHeight
|
79
|
+
};
|
80
|
+
};
|
81
|
+
|
82
|
+
function find(n, t, s) {
|
83
|
+
var w = ed.getDoc().createTreeWalker(n, 4, null, false), n, c = -1;
|
84
|
+
|
85
|
+
while (n = w.nextNode()) {
|
86
|
+
c++;
|
87
|
+
|
88
|
+
// Index by node
|
89
|
+
if (t == 0 && n == s)
|
90
|
+
return c;
|
91
|
+
|
92
|
+
// Node by index
|
93
|
+
if (t == 1 && c == s)
|
94
|
+
return n;
|
95
|
+
}
|
96
|
+
|
97
|
+
return -1;
|
98
|
+
};
|
99
|
+
|
100
|
+
function forceRoots() {
|
101
|
+
var t = this, b = ed.getBody(), d = ed.getDoc(), se = ed.selection, s = se.getSel(), r = se.getRng(), si = -2, ei, so, eo, tr, c = -0xFFFFFF;
|
102
|
+
var nx, bl, bp, sp, le, nl = b.childNodes, i, n, eid;
|
103
|
+
|
104
|
+
// Fix for bug #1863847
|
105
|
+
//if (e && e.keyCode == 13)
|
106
|
+
// return true;
|
107
|
+
|
108
|
+
// Wrap non blocks into blocks
|
109
|
+
for (i = nl.length - 1; i >= 0; i--) {
|
110
|
+
nx = nl[i];
|
111
|
+
|
112
|
+
// Is text or non block element
|
113
|
+
if (nx.nodeType == 3 || (!isBlock(nx) && nx.nodeType != 8)) {
|
114
|
+
if (!bl) {
|
115
|
+
// Create new block but ignore whitespace
|
116
|
+
if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {
|
117
|
+
// Store selection
|
118
|
+
if (si == -2 && r) {
|
119
|
+
if (!isIE) {
|
120
|
+
// If selection is element then mark it
|
121
|
+
if (r.startContainer.nodeType == 1 && (n = r.startContainer.childNodes[r.startOffset]) && n.nodeType == 1) {
|
122
|
+
// Save the id of the selected element
|
123
|
+
eid = n.getAttribute("id");
|
124
|
+
n.setAttribute("id", "__mce");
|
125
|
+
} else {
|
126
|
+
// If element is inside body, might not be the case in contentEdiable mode
|
127
|
+
if (ed.dom.getParent(r.startContainer, function(e) {return e === b;})) {
|
128
|
+
so = r.startOffset;
|
129
|
+
eo = r.endOffset;
|
130
|
+
si = find(b, 0, r.startContainer);
|
131
|
+
ei = find(b, 0, r.endContainer);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
} else {
|
135
|
+
tr = d.body.createTextRange();
|
136
|
+
tr.moveToElementText(b);
|
137
|
+
tr.collapse(1);
|
138
|
+
bp = tr.move('character', c) * -1;
|
139
|
+
|
140
|
+
tr = r.duplicate();
|
141
|
+
tr.collapse(1);
|
142
|
+
sp = tr.move('character', c) * -1;
|
143
|
+
|
144
|
+
tr = r.duplicate();
|
145
|
+
tr.collapse(0);
|
146
|
+
le = (tr.move('character', c) * -1) - sp;
|
147
|
+
|
148
|
+
si = sp - bp;
|
149
|
+
ei = le;
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
bl = ed.dom.create(st.element);
|
154
|
+
bl.appendChild(nx.cloneNode(1));
|
155
|
+
nx.parentNode.replaceChild(bl, nx);
|
156
|
+
}
|
157
|
+
} else {
|
158
|
+
if (bl.hasChildNodes())
|
159
|
+
bl.insertBefore(nx, bl.firstChild);
|
160
|
+
else
|
161
|
+
bl.appendChild(nx);
|
162
|
+
}
|
163
|
+
} else
|
164
|
+
bl = null; // Time to create new block
|
165
|
+
}
|
166
|
+
|
167
|
+
// Restore selection
|
168
|
+
if (si != -2) {
|
169
|
+
if (!isIE) {
|
170
|
+
bl = b.getElementsByTagName(st.element)[0];
|
171
|
+
r = d.createRange();
|
172
|
+
|
173
|
+
// Select last location or generated block
|
174
|
+
if (si != -1)
|
175
|
+
r.setStart(find(b, 1, si), so);
|
176
|
+
else
|
177
|
+
r.setStart(bl, 0);
|
178
|
+
|
179
|
+
// Select last location or generated block
|
180
|
+
if (ei != -1)
|
181
|
+
r.setEnd(find(b, 1, ei), eo);
|
182
|
+
else
|
183
|
+
r.setEnd(bl, 0);
|
184
|
+
|
185
|
+
if (s) {
|
186
|
+
s.removeAllRanges();
|
187
|
+
s.addRange(r);
|
188
|
+
}
|
189
|
+
} else {
|
190
|
+
try {
|
191
|
+
r = s.createRange();
|
192
|
+
r.moveToElementText(b);
|
193
|
+
r.collapse(1);
|
194
|
+
r.moveStart('character', si);
|
195
|
+
r.moveEnd('character', ei);
|
196
|
+
r.select();
|
197
|
+
} catch (ex) {
|
198
|
+
// Ignore
|
199
|
+
}
|
200
|
+
}
|
201
|
+
} else if (!isIE && (n = ed.dom.get('__mce'))) {
|
202
|
+
// Restore the id of the selected element
|
203
|
+
if (eid)
|
204
|
+
n.setAttribute('id', eid);
|
205
|
+
else
|
206
|
+
n.removeAttribute('id');
|
207
|
+
|
208
|
+
// Move caret before selected element
|
209
|
+
r = d.createRange();
|
210
|
+
r.setStartBefore(n);
|
211
|
+
r.setEndBefore(n);
|
212
|
+
se.setRng(r);
|
213
|
+
}
|
214
|
+
};
|
215
|
+
|
216
|
+
function isBlock(n) {
|
217
|
+
return n.nodeType == 1 && /^(H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CODE|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n.nodeName);
|
218
|
+
};
|
219
|
+
|
220
|
+
function getParentBlock(n) {
|
221
|
+
return DOM.getParent(n, function(n) {
|
222
|
+
return isBlock(n);
|
223
|
+
});
|
224
|
+
};
|
225
|
+
|
226
|
+
function isEmpty(n) {
|
227
|
+
n = n.innerHTML;
|
228
|
+
n = n.replace(/<img|hr|table/g, 'd'); // Keep these
|
229
|
+
n = n.replace(/<[^>]+>/g, ''); // Remove all tags
|
230
|
+
|
231
|
+
return n.replace(/[ \t\r\n]+/g, '') == '';
|
232
|
+
};
|
233
|
+
|
234
|
+
function insertPara(e) {
|
235
|
+
var d = ed.getDoc(), s = ed.selection.getSel(), r = ed.selection.getRng(), b = d.body;
|
236
|
+
var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, y, ch;
|
237
|
+
|
238
|
+
// Check if Safari 2.x
|
239
|
+
if (punymce.isOldWebKit)
|
240
|
+
return true;
|
241
|
+
|
242
|
+
// Setup before range
|
243
|
+
rb = d.createRange();
|
244
|
+
rb.setStart(s.anchorNode, s.anchorOffset);
|
245
|
+
rb.collapse(true);
|
246
|
+
|
247
|
+
// Setup after range
|
248
|
+
ra = d.createRange();
|
249
|
+
ra.setStart(s.focusNode, s.focusOffset);
|
250
|
+
ra.collapse(true);
|
251
|
+
|
252
|
+
// Setup start/end points
|
253
|
+
dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;
|
254
|
+
sn = dir ? s.anchorNode : s.focusNode;
|
255
|
+
so = dir ? s.anchorOffset : s.focusOffset;
|
256
|
+
en = dir ? s.focusNode : s.anchorNode;
|
257
|
+
eo = dir ? s.focusOffset : s.anchorOffset;
|
258
|
+
|
259
|
+
// Never use body as start or end node
|
260
|
+
sn = sn.nodeName == "BODY" ? sn.firstChild : sn;
|
261
|
+
en = en.nodeName == "BODY" ? en.firstChild : en;
|
262
|
+
|
263
|
+
// Get start and end blocks
|
264
|
+
sb = getParentBlock(sn);
|
265
|
+
eb = getParentBlock(en);
|
266
|
+
bn = sb ? sb.nodeName : st.element; // Get block name to create
|
267
|
+
|
268
|
+
// Return inside list use default browser behavior
|
269
|
+
if (DOM.getParent(sb, function(n) { return /OL|UL/.test(n.nodeName); }))
|
270
|
+
return true;
|
271
|
+
|
272
|
+
// If caption or absolute layers then always generate new blocks within
|
273
|
+
if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(sb.style.position))) {
|
274
|
+
bn = st.element;
|
275
|
+
sb = null;
|
276
|
+
}
|
277
|
+
|
278
|
+
// If caption or absolute layers then always generate new blocks within
|
279
|
+
if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(eb.style.position))) {
|
280
|
+
bn = st.element;
|
281
|
+
eb = null;
|
282
|
+
}
|
283
|
+
|
284
|
+
// Use P instead
|
285
|
+
if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(sb.style.cssFloat))) {
|
286
|
+
bn = st.element;
|
287
|
+
sb = eb = null;
|
288
|
+
}
|
289
|
+
|
290
|
+
// Setup new before and after blocks
|
291
|
+
bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : d.createElement(bn);
|
292
|
+
aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : d.createElement(bn);
|
293
|
+
|
294
|
+
// Remove id from after clone
|
295
|
+
aft.id = '';
|
296
|
+
|
297
|
+
// Is header and cursor is at the end, then force paragraph under
|
298
|
+
if (/^(H[1-6])$/.test(bn) && sn.nodeValue && so == sn.nodeValue.length)
|
299
|
+
aft = d.createElement(st.element);
|
300
|
+
|
301
|
+
// Find start chop node
|
302
|
+
n = sc = sn;
|
303
|
+
do {
|
304
|
+
if (n == b || n.nodeType == 9 || isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
|
305
|
+
break;
|
306
|
+
|
307
|
+
sc = n;
|
308
|
+
} while ((n = n.previousSibling ? n.previousSibling : n.parentNode));
|
309
|
+
|
310
|
+
// Find end chop node
|
311
|
+
n = ec = en;
|
312
|
+
do {
|
313
|
+
if (n == b || n.nodeType == 9 || isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
|
314
|
+
break;
|
315
|
+
|
316
|
+
ec = n;
|
317
|
+
} while ((n = n.nextSibling ? n.nextSibling : n.parentNode));
|
318
|
+
|
319
|
+
// Place first chop part into before block element
|
320
|
+
if (sc.nodeName == bn)
|
321
|
+
rb.setStart(sc, 0);
|
322
|
+
else
|
323
|
+
rb.setStartBefore(sc);
|
324
|
+
|
325
|
+
rb.setEnd(sn, so);
|
326
|
+
bef.appendChild(rb.cloneContents());
|
327
|
+
|
328
|
+
// Place secnd chop part within new block element
|
329
|
+
ra.setEndAfter(ec);
|
330
|
+
ra.setStart(en, eo);
|
331
|
+
aft.appendChild(ra.cloneContents());
|
332
|
+
|
333
|
+
// Create range around everything
|
334
|
+
r = d.createRange();
|
335
|
+
if (!sc.previousSibling && sc.parentNode.nodeName == bn) {
|
336
|
+
r.setStartBefore(sc.parentNode);
|
337
|
+
} else {
|
338
|
+
if (rb.startContainer.nodeName == bn && rb.startOffset == 0)
|
339
|
+
r.setStartBefore(rb.startContainer);
|
340
|
+
else
|
341
|
+
r.setStart(rb.startContainer, rb.startOffset);
|
342
|
+
}
|
343
|
+
|
344
|
+
if (!ec.nextSibling && ec.parentNode.nodeName == bn)
|
345
|
+
r.setEndAfter(ec.parentNode);
|
346
|
+
else
|
347
|
+
r.setEnd(ra.endContainer, ra.endOffset);
|
348
|
+
|
349
|
+
// Delete and replace it with new block elements
|
350
|
+
r.deleteContents();
|
351
|
+
|
352
|
+
// Never wrap blocks in blocks
|
353
|
+
if (bef.firstChild && bef.firstChild.nodeName == bn)
|
354
|
+
bef.innerHTML = bef.firstChild.innerHTML;
|
355
|
+
|
356
|
+
if (aft.firstChild && aft.firstChild.nodeName == bn)
|
357
|
+
aft.innerHTML = aft.firstChild.innerHTML;
|
358
|
+
|
359
|
+
// Padd empty blocks
|
360
|
+
if (isEmpty(bef))
|
361
|
+
bef.innerHTML = isOpera ? ' <br />' : '<br />'; // Extra space for Opera
|
362
|
+
|
363
|
+
if (isEmpty(aft))
|
364
|
+
aft.innerHTML = isOpera ? ' <br />' : '<br />'; // Extra space for Opera
|
365
|
+
|
366
|
+
// Opera needs this one backwards
|
367
|
+
if (isOpera) {
|
368
|
+
r.insertNode(bef);
|
369
|
+
r.insertNode(aft);
|
370
|
+
} else {
|
371
|
+
r.insertNode(aft);
|
372
|
+
r.insertNode(bef);
|
373
|
+
}
|
374
|
+
|
375
|
+
// Normalize
|
376
|
+
aft.normalize();
|
377
|
+
bef.normalize();
|
378
|
+
|
379
|
+
// Move cursor and scroll into view
|
380
|
+
r = d.createRange();
|
381
|
+
r.selectNodeContents(aft);
|
382
|
+
r.collapse(1);
|
383
|
+
s.removeAllRanges();
|
384
|
+
s.addRange(r);
|
385
|
+
//aft.scrollIntoView(0);
|
386
|
+
|
387
|
+
// scrollIntoView seems to scroll the parent window in most browsers now including FF 3.0b4 so it's time to stop using it and do it our selfs
|
388
|
+
vp = getViewPort(ed.getWin());
|
389
|
+
y = ed.dom.getPos(aft).y;
|
390
|
+
ch = aft.clientHeight;
|
391
|
+
|
392
|
+
// Is element within viewport
|
393
|
+
if (y < vp.y || y + ch > vp.y + vp.h)
|
394
|
+
ed.getWin().scrollTo(0, y < vp.y ? y : y - vp.h + 25); // Needs to be hardcoded to roughly one line of text if a huge text block is broken into two blocks
|
395
|
+
|
396
|
+
return false;
|
397
|
+
};
|
398
|
+
|
399
|
+
function backspaceDelete(e, bs) {
|
400
|
+
var b = ed.getBody(), n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn;
|
401
|
+
|
402
|
+
// The caret sometimes gets stuck in Gecko if you delete empty paragraphs
|
403
|
+
// This workaround removes the element by hand and moves the caret to the previous element
|
404
|
+
if (sc && isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) {
|
405
|
+
if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) {
|
406
|
+
// Find previous block element
|
407
|
+
n = sc;
|
408
|
+
while ((n = n.previousSibling) && !isBlock(n)) ;
|
409
|
+
|
410
|
+
if (n) {
|
411
|
+
if (sc != b.firstChild) {
|
412
|
+
// Find last text node
|
413
|
+
w = ed.getDoc().createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
|
414
|
+
while (tn = w.nextNode())
|
415
|
+
n = tn;
|
416
|
+
|
417
|
+
// Place caret at the end of last text node
|
418
|
+
r = ed.getDoc().createRange();
|
419
|
+
r.setStart(n, n.nodeValue ? n.nodeValue.length : 0);
|
420
|
+
r.setEnd(n, n.nodeValue ? n.nodeValue.length : 0);
|
421
|
+
se.getSel().removeAllRanges();
|
422
|
+
se.getSel().addRange(r);
|
423
|
+
|
424
|
+
// Remove the target container
|
425
|
+
sc.parentNode.removeChild(sc);
|
426
|
+
}
|
427
|
+
|
428
|
+
return Event.cancel(e);
|
429
|
+
}
|
430
|
+
}
|
431
|
+
}
|
432
|
+
|
433
|
+
// Gecko generates BR elements here and there, we don't like those so lets remove them
|
434
|
+
function handler(e) {
|
435
|
+
var pr;
|
436
|
+
|
437
|
+
e = e.target;
|
438
|
+
|
439
|
+
// A new BR was created in a block element, remove it
|
440
|
+
if (e && e.parentNode && e.nodeName == 'BR' && (n = getParentBlock(e))) {
|
441
|
+
pr = e.previousSibling;
|
442
|
+
|
443
|
+
Event.remove(b, 'DOMNodeInserted', handler);
|
444
|
+
|
445
|
+
// Is there whitespace at the end of the node before then we might need the pesky BR
|
446
|
+
// to place the caret at a correct location see bug: #2013943
|
447
|
+
if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue))
|
448
|
+
return;
|
449
|
+
|
450
|
+
// Only remove BR elements that got inserted in the middle of the text
|
451
|
+
if (e.previousSibling || e.nextSibling)
|
452
|
+
e.parentNode.removeChild(e);
|
453
|
+
}
|
454
|
+
};
|
455
|
+
|
456
|
+
// Listen for new nodes
|
457
|
+
Event._add(b, 'DOMNodeInserted', handler);
|
458
|
+
|
459
|
+
// Remove listener
|
460
|
+
window.setTimeout(function() {
|
461
|
+
Event._remove(b, 'DOMNodeInserted', handler);
|
462
|
+
}, 1);
|
463
|
+
};
|
464
|
+
};
|
465
|
+
})(punymce);
|