radiant-forum-extension 2.1.6 → 3.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. data/README.md +20 -16
  2. data/Rakefile +0 -16
  3. data/app/controllers/forum_base_controller.rb +32 -10
  4. data/app/controllers/posts_controller.rb +37 -14
  5. data/app/helpers/forum_helper.rb +23 -16
  6. data/app/models/forum.rb +11 -7
  7. data/app/models/post.rb +53 -14
  8. data/app/models/post_attachment.rb +1 -1
  9. data/app/models/topic.rb +21 -8
  10. data/app/views/admin/dashboard/_forum_dashboard.html.haml +51 -0
  11. data/app/views/admin/forums/_form.html.haml +12 -0
  12. data/app/views/admin/forums/edit.html.haml +1 -1
  13. data/app/views/admin/forums/index.html.haml +16 -20
  14. data/app/views/admin/posts/_form.html.haml +2 -2
  15. data/app/views/admin/posts/edit.html.haml +1 -1
  16. data/app/views/admin/posts/index.html.haml +5 -5
  17. data/app/views/admin/reader_configuration/_edit_forum.html.haml +6 -0
  18. data/app/views/admin/reader_configuration/_forum.html.haml +5 -1
  19. data/app/views/admin/topics/_form.html.haml +3 -5
  20. data/app/views/admin/topics/edit.html.haml +1 -1
  21. data/app/views/admin/topics/index.html.haml +5 -5
  22. data/app/views/forums/_forum.html.haml +6 -5
  23. data/app/views/forums/_latest.html.haml +14 -12
  24. data/app/views/forums/_statistics.html.haml +4 -4
  25. data/app/views/forums/index.html.haml +8 -10
  26. data/app/views/forums/index.rss.builder +2 -2
  27. data/app/views/forums/show.html.haml +12 -15
  28. data/app/views/pages/_add_comment.html.haml +9 -8
  29. data/app/views/pages/_comments.html.haml +3 -3
  30. data/app/views/posts/_attachments.html.haml +1 -1
  31. data/app/views/posts/_confirm_delete.html.haml +7 -2
  32. data/app/views/posts/_context.html.haml +5 -5
  33. data/app/views/posts/_edit_links.html.haml +4 -4
  34. data/app/views/posts/_form.html.haml +15 -12
  35. data/app/views/posts/_ineditable.html.haml +7 -0
  36. data/app/views/posts/_latest.html.haml +3 -8
  37. data/app/views/posts/_minimal.html.haml +7 -0
  38. data/app/views/posts/_post.html.haml +20 -17
  39. data/app/views/posts/_post.rss.builder +2 -2
  40. data/app/views/posts/_search_form.html.haml +13 -13
  41. data/app/views/posts/_search_results.html.haml +15 -0
  42. data/app/views/posts/_search_summary.html.haml +13 -0
  43. data/app/views/posts/_uploader.html.haml +1 -1
  44. data/app/views/posts/edit.html.haml +22 -21
  45. data/app/views/posts/index.html.haml +12 -19
  46. data/app/views/posts/index.rss.builder +6 -6
  47. data/app/views/posts/new.html.haml +19 -22
  48. data/app/views/posts/remove.html.haml +15 -15
  49. data/app/views/posts/show.html.haml +16 -10
  50. data/app/views/readers/_forum_messages.html.haml +9 -6
  51. data/app/views/readers/_messages_summary.html.haml +1 -1
  52. data/app/views/shared/_standard_forum_parts.html.haml +41 -0
  53. data/app/views/topics/_busiest.html.haml +9 -8
  54. data/app/views/topics/_context.html.haml +11 -8
  55. data/app/views/topics/_latest.html.haml +2 -2
  56. data/app/views/topics/_locked.html.haml +1 -1
  57. data/app/views/topics/_minimal.html.haml +2 -2
  58. data/app/views/topics/_replies.html.haml +4 -3
  59. data/app/views/topics/_reply.html.haml +13 -8
  60. data/app/views/topics/_topic.html.haml +5 -9
  61. data/app/views/topics/_topic.rss.builder +1 -1
  62. data/app/views/topics/index.html.haml +14 -10
  63. data/app/views/topics/index.rss.builder +2 -2
  64. data/app/views/topics/show.html.haml +20 -19
  65. data/app/views/topics/show.rss.builder +3 -3
  66. data/config/initializers/radiant_config.rb +4 -1
  67. data/config/locales/en.yml +202 -178
  68. data/db/migrate/002_pages_commentable.rb +1 -2
  69. data/db/migrate/004_sample_layout.rb +38 -15
  70. data/db/migrate/20110111080550_detach_observer.rb +4 -4
  71. data/db/migrate/20110613112823_search_text.rb +9 -0
  72. data/db/migrate/20110613130230_tidy_up.rb +27 -0
  73. data/db/migrate/20110630083446_page_replied_at.rb +11 -0
  74. data/forum_extension.rb +13 -11
  75. data/lib/commentable_model.rb +13 -9
  76. data/lib/forum_admin_ui.rb +6 -6
  77. data/lib/forum_page.rb +5 -3
  78. data/lib/forum_reader.rb +7 -1
  79. data/lib/forum_reader_sessions_controller.rb +2 -3
  80. data/lib/forum_tags.rb +126 -11
  81. data/lib/radiant-forum-extension.rb +8 -0
  82. data/public/cleditor/images/buttons.gif +0 -0
  83. data/public/cleditor/images/icons/1.gif +0 -0
  84. data/public/cleditor/images/icons/10.gif +0 -0
  85. data/public/cleditor/images/icons/11.gif +0 -0
  86. data/public/cleditor/images/icons/12.gif +0 -0
  87. data/public/cleditor/images/icons/2.gif +0 -0
  88. data/public/cleditor/images/icons/3.gif +0 -0
  89. data/public/cleditor/images/icons/4.gif +0 -0
  90. data/public/cleditor/images/icons/5.gif +0 -0
  91. data/public/cleditor/images/icons/6.gif +0 -0
  92. data/public/cleditor/images/icons/7.gif +0 -0
  93. data/public/cleditor/images/icons/8.gif +0 -0
  94. data/public/cleditor/images/icons/9.gif +0 -0
  95. data/public/cleditor/images/icons/icons.gif +0 -0
  96. data/public/cleditor/images/toolbar.gif +0 -0
  97. data/public/cleditor/jquery.cleditor.css +24 -0
  98. data/public/cleditor/jquery.cleditor.icon.js +65 -0
  99. data/public/cleditor/jquery.cleditor.js +1132 -0
  100. data/public/cleditor/jquery.cleditor.xhtml.js +230 -0
  101. data/public/javascripts/forum.js +146 -107
  102. data/public/stylesheets/sass/forum.sass +94 -58
  103. data/radiant-forum-extension.gemspec +25 -276
  104. data/spec/controllers/forums_controller_spec.rb +0 -7
  105. data/spec/controllers/posts_controller_spec.rb +20 -37
  106. data/spec/controllers/topics_controller_spec.rb +1 -7
  107. data/spec/datasets/forums_dataset.rb +38 -40
  108. data/spec/lib/commentable_model_spec.rb +26 -38
  109. data/spec/lib/forum_reader_spec.rb +0 -4
  110. data/spec/models/forum_spec.rb +46 -16
  111. data/spec/models/post_spec.rb +10 -6
  112. data/spec/models/topic_spec.rb +26 -17
  113. data/spec/spec_helper.rb +1 -0
  114. metadata +66 -99
  115. data/VERSION +0 -1
  116. data/app/views/forums/_standard_parts.html.haml +0 -59
  117. data/lib/sanitize/config/forum.rb +0 -49
  118. data/public/javascripts/gallery.js +0 -275
  119. data/public/punymce/blank.htm +0 -1
  120. data/public/punymce/css/content.css +0 -4
  121. data/public/punymce/css/editor.css +0 -58
  122. data/public/punymce/i18n/sv.js +0 -28
  123. data/public/punymce/img/icons.gif +0 -0
  124. data/public/punymce/img/icons_uncompressed.png +0 -0
  125. data/public/punymce/plugins/bbcode.js +0 -1
  126. data/public/punymce/plugins/bbcode_src.js +0 -50
  127. data/public/punymce/plugins/editsource/css/editor.css +0 -3
  128. data/public/punymce/plugins/editsource/editsource.js +0 -1
  129. data/public/punymce/plugins/editsource/editsource_src.js +0 -81
  130. data/public/punymce/plugins/editsource/img/icons.gif +0 -0
  131. data/public/punymce/plugins/emoticons/css/content.css +0 -13
  132. data/public/punymce/plugins/emoticons/css/editor.css +0 -17
  133. data/public/punymce/plugins/emoticons/emoticons.js +0 -1
  134. data/public/punymce/plugins/emoticons/emoticons_src.js +0 -303
  135. data/public/punymce/plugins/emoticons/img/emoticons.gif +0 -0
  136. data/public/punymce/plugins/emoticons/img/emoticons.png +0 -0
  137. data/public/punymce/plugins/emoticons/img/trans.gif +0 -0
  138. data/public/punymce/plugins/entities.js +0 -1
  139. data/public/punymce/plugins/entities_src.js +0 -37
  140. data/public/punymce/plugins/forceblocks.js +0 -1
  141. data/public/punymce/plugins/forceblocks_src.js +0 -465
  142. data/public/punymce/plugins/forcenl.js +0 -1
  143. data/public/punymce/plugins/forcenl_src.js +0 -26
  144. data/public/punymce/plugins/image/css/editor.css +0 -1
  145. data/public/punymce/plugins/image/image.js +0 -1
  146. data/public/punymce/plugins/image/image_src.js +0 -30
  147. data/public/punymce/plugins/image/img/icons.gif +0 -0
  148. data/public/punymce/plugins/link/css/editor.css +0 -2
  149. data/public/punymce/plugins/link/img/icons.gif +0 -0
  150. data/public/punymce/plugins/link/link.js +0 -1
  151. data/public/punymce/plugins/link/link_src.js +0 -36
  152. data/public/punymce/plugins/paste.js +0 -1
  153. data/public/punymce/plugins/paste_src.js +0 -169
  154. data/public/punymce/plugins/protect.js +0 -1
  155. data/public/punymce/plugins/protect_src.js +0 -30
  156. data/public/punymce/plugins/safari2x.js +0 -1
  157. data/public/punymce/plugins/safari2x_src.js +0 -284
  158. data/public/punymce/plugins/tabfocus.js +0 -1
  159. data/public/punymce/plugins/tabfocus_src.js +0 -45
  160. data/public/punymce/plugins/textcolor/css/editor.css +0 -7
  161. data/public/punymce/plugins/textcolor/img/icons.gif +0 -0
  162. data/public/punymce/plugins/textcolor/textcolor.js +0 -1
  163. data/public/punymce/plugins/textcolor/textcolor_src.js +0 -73
  164. data/public/punymce/puny_mce.js +0 -1
  165. data/public/punymce/puny_mce_full.js +0 -1
  166. data/public/punymce/puny_mce_src.js +0 -1460
@@ -1,1460 +0,0 @@
1
- (function(punymce) {
2
- var DOMUtils, Engine, Control, Editor, Selection, Dispatcher, Event, Serializer, I18n; // Shorten class names
3
- var pageDOM, isIE, isGecko, isOpera, isWebKit, isOldWebKit, ua; // Global objects
4
-
5
- // Browser checks
6
- ua = navigator.userAgent;
7
- punymce.isOpera = isOpera = window['opera'] && opera.buildNumber;
8
- punymce.isWebKit = isWebKit = /WebKit/.test(ua);
9
- punymce.isOldWebKit = isOldWebKit = isWebKit && !window.getSelection().getRangeAt;
10
- punymce.isIE = isIE = !isWebKit && !isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(navigator.appName);
11
- punymce.isGecko = isGecko = !isWebKit && /Gecko/.test(ua);
12
-
13
- // Plugins namespace
14
- punymce.plugins = {};
15
-
16
- // Global functions
17
-
18
- function is(o, t) {
19
- o = typeof(o);
20
-
21
- if (!t)
22
- return o != 'undefined';
23
-
24
- return o == t;
25
- };
26
-
27
- function each(o, cb, s) {
28
- var n;
29
-
30
- if (!o)
31
- return 0;
32
-
33
- s = !s ? o : s;
34
-
35
- if (is(o.length)) {
36
- // Indexed arrays, needed for Safari
37
- for (n=0; n<o.length; n++) {
38
- if (cb.call(s, o[n], n, o) === false)
39
- return 0;
40
- }
41
- } else {
42
- // Hashtables
43
- for (n in o) {
44
- if (o.hasOwnProperty(n)) {
45
- if (cb.call(s, o[n], n, o) === false)
46
- return 0;
47
- }
48
- }
49
- }
50
-
51
- return 1;
52
- };
53
-
54
- function extend(o, e) {
55
- each(e, function(v, n) {
56
- o[n] = v;
57
- });
58
-
59
- return o;
60
- };
61
-
62
- // Store them in API as well for plugin use
63
- extend(punymce, {
64
- is : is,
65
- each : each,
66
- extend : extend
67
- });
68
-
69
- // English language pack
70
- punymce.I18n = I18n = {
71
- bold : 'Bold (Ctrl+B)',
72
- italic : 'Italic (Ctrl+I)',
73
- underline : 'Underline (Ctrl+U)',
74
- strike : 'Striketrough',
75
- ul : 'Insert unordered list',
76
- ol : 'Insert ordered list',
77
- indent : 'Indent',
78
- outdent : 'Outdent',
79
- left : 'Align left',
80
- center : 'Align center',
81
- right : 'Align right',
82
- style : 'Font style',
83
- removeformat : 'Remove format',
84
- increasefontsize : 'Increase text size',
85
- decreasefontsize : 'Decrease text size'
86
- };
87
-
88
- // Static DOM class
89
- punymce.DOMUtils = DOMUtils = function(d) {
90
- this.files = [];
91
-
92
- // Fix IE6SP2 flicker
93
- try {d.execCommand('BackgroundImageCache', 0, 1);} catch (e) {}
94
-
95
- // Public methods
96
- extend(this, {
97
- get : function(e) {
98
- return e && (!e.nodeType && !e.location ? d.getElementById(e) : e);
99
- },
100
-
101
- add : function(p, n, a, h) {
102
- var t = this, e;
103
-
104
- e = d.createElement(n);
105
-
106
- each(a, function(v, n) {
107
- t.setAttr(e, n, v);
108
- });
109
-
110
- if (h) {
111
- if (h.nodeType)
112
- e.appendChild(h);
113
- else
114
- e.innerHTML = h;
115
- }
116
-
117
- return p ? p.appendChild(e) : e;
118
- },
119
-
120
- create : function(n, a, h) {
121
- return this.add(0, n, a, h);
122
- },
123
-
124
- setAttr : function(e, n, v) {
125
- e = this.get(e);
126
-
127
- if (!e)
128
- return 0;
129
-
130
- if (n == "style") {
131
- e.setAttribute('mce_style', v);
132
- e.style.cssText = v;
133
- }
134
-
135
- if (n == "class")
136
- e.className = v;
137
-
138
- if (v != null && v != "")
139
- e.setAttribute(n, '' + v);
140
- else
141
- e.removeAttribute(n);
142
-
143
- return 1;
144
- },
145
-
146
- getAttr : function(e, n, dv) {
147
- var v;
148
-
149
- e = this.get(e);
150
-
151
- if (!e)
152
- return false;
153
-
154
- if (!is(dv))
155
- dv = "";
156
-
157
- // Try the mce variant for these
158
- if (/^(src|href|style)$/.test(n)) {
159
- v = this.getAttr(e, "mce_" + n);
160
-
161
- if (v)
162
- return v;
163
- }
164
-
165
- v = e.getAttribute(n, 2);
166
-
167
- if (n == "class" && !v)
168
- v = e.className;
169
-
170
- if (n == "style" && !v)
171
- v = e.style.cssText;
172
- else if (!v) {
173
- v = e.attributes[n];
174
- v = v && is(v.nodeValue) ? v.nodeValue : v;
175
- }
176
-
177
- // Remove Apple and WebKit stuff
178
- if (isWebKit && n == "class" && v)
179
- v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');
180
-
181
- return (v && v != "") ? '' + v : dv;
182
- },
183
-
184
- select : function(k, n, f) {
185
- var o = [];
186
-
187
- n = this.get(n);
188
- n = !n ? d : n;
189
-
190
- each(k.split(','), function(v) {
191
- each(n.getElementsByTagName(v), function(v) {
192
- if (!f || f(v))
193
- o.push(v);
194
- });
195
- });
196
-
197
- return o;
198
- },
199
-
200
- getPos : function(n, cn) {
201
- var l = 0, t = 0, p, r, d;
202
-
203
- n = this.get(n);
204
-
205
- // IE specific method (less quirks in IE6)
206
- if (punymce.isIE && n) {
207
- r = n.getBoundingClientRect();
208
- d = document;
209
- n = d.compatMode == 'CSS1Compat' ? d.documentElement : d.body;
210
-
211
- return { x : r.left + (n.scrollLeft || 0), y : r.top + (n.scrollTop || 0) };
212
- }
213
-
214
- while (n && n != cn) {
215
- l += n.offsetLeft || 0;
216
- t += n.offsetTop || 0;
217
- n = n.offsetParent;
218
- }
219
-
220
- return {x : l, y : t};
221
- },
222
-
223
- loadCSS : function(u) {
224
- var t = this;
225
-
226
- if (u) {
227
- each(u.split(','), function(u) {
228
- var l = -1;
229
-
230
- each(t.files, function(c, i) {
231
- if (c == u) {
232
- l = i;
233
- return false;
234
- }
235
- });
236
-
237
- if (l != -1)
238
- return;
239
-
240
- t.files.push(u);
241
-
242
- if (!d.createStyleSheet)
243
- t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : u});
244
- else
245
- d.createStyleSheet(u);
246
- });
247
- }
248
- },
249
-
250
- addClass : function(e, c, b) {
251
- var o;
252
-
253
- e = this.get(e);
254
-
255
- if (!e)
256
- return 0;
257
-
258
- o = this.removeClass(e, c);
259
-
260
- return e.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c;
261
- },
262
-
263
- removeClass : function(e, c) {
264
- e = this.get(e);
265
-
266
- if (!e)
267
- return 0;
268
-
269
- c = e.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g"), ' ');
270
-
271
- return e.className = c != ' ' ? c : '';
272
- },
273
-
274
- hasClass : function(n, c) {
275
- n = this.get(n);
276
-
277
- return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
278
- },
279
-
280
- getParent : function(n, f, r) {
281
- while (n) {
282
- if (n == r)
283
- return null;
284
-
285
- if (f(n))
286
- return n;
287
-
288
- n = n.parentNode;
289
- }
290
-
291
- return null;
292
- },
293
-
294
- keep : function(h) {
295
- // Convert strong and em to b and i in FF since it can't handle them
296
- if (isGecko) {
297
- h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');
298
- h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');
299
- h = h.replace(/<(\/?)del|<del( [^>]+)>/gi, '<$1strike$2>');
300
- }
301
-
302
- // Store away src and href in mce_src and mce_href since browsers mess them up
303
- h = h.replace(/ (src|href|style)=\"([^\"]+)\"/gi, ' $1="$2" mce_$1="$2"');
304
-
305
- return h;
306
- }
307
- });
308
- };
309
-
310
- // Global DOM instance
311
- punymce.DOM = pageDOM = new DOMUtils(document);
312
-
313
- // Static Event class
314
- punymce.Event = Event = {
315
- events : [],
316
- inits : [],
317
- unloads : [],
318
-
319
- add : function(o, n, f, s) {
320
- var cb, t = this, el = t.events;
321
-
322
- o = pageDOM.get(o);
323
-
324
- // Setup event callback
325
- cb = function(e) {
326
- e = e || window.event;
327
-
328
- // Patch in target in IE it's W3C valid
329
- if (e && !e.target && isIE)
330
- e.target = e.srcElement;
331
-
332
- if (!s)
333
- return f(e);
334
-
335
- return f.call(s, e);
336
- };
337
-
338
- if (n == 'unload') {
339
- t.unloads.push(cb);
340
- return cb;
341
- }
342
-
343
- if (n == 'init') {
344
- if (t._init)
345
- cb();
346
- else
347
- t.inits.push(cb);
348
-
349
- return cb;
350
- }
351
-
352
- // Store away listener reference
353
- el.push({
354
- obj : o,
355
- name : n,
356
- func : f,
357
- cfunc : cb,
358
- scope : s
359
- });
360
-
361
- t._add(o, n, cb);
362
-
363
- // Cleanup memory leaks in IE
364
- if (isIE && el.length == 1)
365
- Event._add(window, 'unload', t._unload, Event);
366
-
367
- return cb;
368
- },
369
-
370
- remove : function(o, n, f) {
371
- var t = this, a = t.events;
372
-
373
- o = pageDOM.get(o);
374
-
375
- each(a, function(e, i) {
376
- if (e.obj == o && e.name == n && (!f || e.func == f)) {
377
- a.splice(i, 1);
378
- t._remove(o, n, e.cfunc);
379
- return false;
380
- }
381
- });
382
- },
383
-
384
- cancel : function(e) {
385
- this.stop(e);
386
- return this.prevent(e);
387
- },
388
-
389
- stop : function(e) {
390
- if (e.stopPropagation)
391
- e.stopPropagation();
392
- else
393
- e.cancelBubble = true;
394
-
395
- return false;
396
- },
397
-
398
- prevent : function(e) {
399
- if (e.preventDefault)
400
- e.preventDefault();
401
- else
402
- e.returnValue = false;
403
-
404
- return false;
405
- },
406
-
407
- _unload : function() {
408
- var t = Event;
409
-
410
- each(t.events, function(e) {
411
- t._remove(e.obj, e.name, e.cfunc);
412
- });
413
-
414
- t._remove(window, 'unload', t._unload);
415
- t.events = [];
416
-
417
- each(t.unloads, function(e) {
418
- e();
419
- });
420
- },
421
-
422
- _add : function(o, n, f) {
423
- if (o.attachEvent)
424
- o.attachEvent('on' + n, f);
425
- else if (o.addEventListener)
426
- o.addEventListener(n, f, false);
427
- else
428
- o['on' + n] = f;
429
- },
430
-
431
- _remove : function(o, n, f) {
432
- if (o.detachEvent)
433
- o.detachEvent('on' + n, f);
434
- else if (o.removeEventListener)
435
- o.removeEventListener(n, f, false);
436
- else
437
- o['on' + n] = null;
438
- },
439
-
440
- _pageInit : function() {
441
- var e = Event;
442
-
443
- e._remove(window, 'DOMContentLoaded', e._pageInit);
444
- e._init = true;
445
-
446
- each(e.inits, function(c) {
447
- c();
448
- });
449
-
450
- e.inits = [];
451
- },
452
-
453
- _wait : function() {
454
- var t;
455
-
456
- if (isIE && document.location.protocol != 'https:') {
457
- // Fake DOMContentLoaded on IE when not running under HTTPs
458
- document.write('<script id=__ie_onload defer src=javascript:void(0)><\/script>');
459
- pageDOM.get("__ie_onload").onreadystatechange = function() {
460
- if (this.readyState == "complete") {
461
- Event._pageInit();
462
- pageDOM.get("__ie_onload").onreadystatechange = null; // Prevent leak
463
- }
464
- };
465
- } else {
466
- Event._add(window, 'DOMContentLoaded', Event._pageInit, Event);
467
-
468
- if (isIE || isWebKit) {
469
- t = setInterval(function() {
470
- if (/loaded|complete/.test(document.readyState)) {
471
- clearInterval(t);
472
- Event._pageInit();
473
- }
474
- }, 10);
475
- }
476
- }
477
- }
478
- };
479
-
480
- punymce.Dispatcher = Dispatcher = function(ds) {
481
- var cbl = [];
482
-
483
- if (!ds)
484
- ds = this;
485
-
486
- // Public methods
487
- extend(this, {
488
- add : function(cb, s) {
489
- cbl.push({cb : cb, scope : !s ? ds : s});
490
-
491
- return cb;
492
- },
493
-
494
- remove : function(cb) {
495
- each(cbl, function(c, i) {
496
- if (cb == c.cb)
497
- cbl.splice(i, 1);
498
-
499
- return false;
500
- });
501
-
502
- return cb;
503
- },
504
-
505
- dispatch : function() {
506
- var s, a = arguments;
507
-
508
- each(cbl, function(c) {
509
- return s = c.cb.apply(c.scope, a);
510
- });
511
-
512
- return s;
513
- }
514
- });
515
- };
516
-
517
- punymce.Editor = Editor = function(e) {
518
- var s, DOM, t = this;
519
-
520
- // Setup baseURL
521
- if (!punymce.baseURL) {
522
- each(pageDOM.select('script'), function(n) {
523
- if (/puny_mce/g.test('' + n.src))
524
- punymce.baseURL = n.src.replace(/^(.+)\/puny_mce.+$/, '$1/');
525
- });
526
- }
527
-
528
- // Default settings
529
- this.settings = s = extend({
530
- content_css : punymce.baseURL + '/css/content.css',
531
- editor_css : punymce.baseURL + '/css/editor.css',
532
- width : 0,
533
- height : 0,
534
- min_width : 260,
535
- min_height : 50,
536
- max_width : 800,
537
- max_height : 600,
538
- entities : 'raw',
539
- spellcheck : 0,
540
- resize : true,
541
- plugins : '',
542
-
543
- styles : [
544
- { title : 'H1', cls : 'h1', cmd : 'FormatBlock', val : '<h1>' },
545
- { title : 'H2', cls : 'h2', cmd : 'FormatBlock', val : '<h2>' },
546
- { title : 'H3', cls : 'h3', cmd : 'FormatBlock', val : '<h3>' },
547
- { title : 'Pre', cls : 'pre', cmd : 'FormatBlock', val : '<pre>' },
548
- { title : 'Times', cls : 'times', cmd : 'FontName', val : 'Times'},
549
- { title : 'Arial', cls : 'arial', cmd : 'FontName', val : 'Arial'},
550
- { title : 'Courier', cls : 'courier', cmd : 'FontName', val : 'Courier'}
551
- ],
552
-
553
- toolbar : 'bold,italic,underline,strike,increasefontsize,decreasefontsize,ul,ol,indent,outdent,left,center,right,style,removeformat'
554
- }, e);
555
-
556
- // Default tools
557
- t.tools = {
558
- bold : {cmd : 'Bold', title : I18n.bold},
559
- italic : {cmd : 'Italic', title : I18n.italic},
560
- underline : {cmd : 'Underline', title : I18n.underline},
561
- strike : {cmd : 'Strikethrough', title : I18n.strike},
562
- ul : {cmd : 'InsertUnorderedList', title : I18n.ul},
563
- ol : {cmd : 'InsertOrderedList', title : I18n.ol},
564
- indent : {cmd : 'Indent', title : I18n.indent},
565
- outdent : {cmd : 'Outdent', title : I18n.outdent},
566
- left : {cmd : 'JustifyLeft', title : I18n.left},
567
- center : {cmd : 'JustifyCenter', title : I18n.center},
568
- right : {cmd : 'JustifyRight', title : I18n.right},
569
- style : {cmd : 'mceStyle', title : I18n.style},
570
- removeformat : {cmd : 'RemoveFormat', title : I18n.removeformat},
571
- increasefontsize : {cmd : 'IncreaseFontSize', title : I18n.increasefontsize},
572
- decreasefontsize : {cmd : 'DecreaseFontSize', title : I18n.decreasefontsize}
573
- };
574
-
575
- pageDOM.loadCSS(s.editor_css);
576
-
577
- // Default commands
578
- this.commands = {
579
- mceStyle : function(u, v, e) {
580
- var n, t = this, s = t.settings, id = s.id, p = pageDOM.getPos(e.target), cb;
581
-
582
- if (t.hideMenu)
583
- return t.hideMenu();
584
-
585
- function hide(e) {
586
- t.hideMenu = null;
587
- Event.remove(document, 'click', hide);
588
- Event.remove(t.getDoc(), 'click', hide);
589
- pageDOM.get(id + '_mstyle').style.display = 'none';
590
- };
591
-
592
- n = pageDOM.get(id + '_mstyle');
593
- if (!n) {
594
- n = pageDOM.get(id + '_t');
595
- n = pageDOM.add(document.body, 'div', {id : id + '_mstyle', 'class' : 'punymce_style punymce'});
596
- each(s.styles, function(r) {
597
- Event.add(pageDOM.add(n, 'a', {href : '#', 'class' : r.cls}, r.title), 'mousedown', function(e) {
598
- hide.call(t);
599
-
600
- t.execCommand(r.cmd, r.ui, r.val);
601
-
602
- // Opera looses focus (could not be placed in execCommand)
603
- if (isOpera)
604
- t.getIfr().focus();
605
-
606
- return Event.cancel(e);
607
- });
608
- });
609
- }
610
-
611
- t.hideMenu = hide;
612
- Event.add(document, 'click', hide, t);
613
- Event.add(t.getDoc(), 'click', hide, t);
614
-
615
- s = n.style;
616
- s.left = p.x + 'px';
617
- s.top = (p.y + e.target.clientHeight + 2) + 'px';
618
- s.display = 'block';
619
- },
620
-
621
- FormatBlock : function(u, v, e) {
622
- // Gecko can't handle <> correctly on some elements
623
- if (isGecko && /<(div|blockquote|code|dt|dd|dl|samp)>/gi.test(v))
624
- v = v.replace(/[^a-z]/gi, '');
625
-
626
- t.getDoc().execCommand("FormatBlock", 0, v);
627
- },
628
-
629
- CreateLink : function(u, v) {
630
- var dom = t.dom, k = 'javascript:mox();';
631
-
632
- t.getDoc().execCommand("CreateLink", 0, k);
633
- each(dom.select('A'), function(n) {
634
- if (dom.getAttr(n, 'href') == k) {
635
- dom.setAttr(n, 'href', v);
636
- dom.setAttr(n, 'mce_href', v);
637
- }
638
- });
639
- },
640
-
641
- mceFontSizeDelta : function(u, v) {
642
- var d = t.getDoc(), cv, sp, fo, s = t.selection;
643
-
644
- cv = parseInt(d.queryCommandValue('FontSize') || 3);
645
-
646
- // WebKit returns pixel value, convert it to a size value
647
- if (isWebKit) {
648
- each([10, 13, 16, 18, 24, 32, 48], function(c, i) {
649
- if (cv == c) {
650
- cv = i + 1;
651
- return false;
652
- }
653
- });
654
- }
655
-
656
- if (cv + v <= 1)
657
- return;
658
-
659
- d.execCommand('FontSize', false, cv + v);
660
- },
661
-
662
- IncreaseFontSize : function() {
663
- t.execCommand('mceFontSizeDelta', 0, 1);
664
- },
665
-
666
- DecreaseFontSize : function() {
667
- t.execCommand('mceFontSizeDelta', 0, -1);
668
- },
669
-
670
- Indent : function(u, v, e) {
671
- t.getDoc().execCommand("Indent", 0, 0);
672
-
673
- if (isIE) {
674
- // IE adds strange ltr and margin right when making a blockquote
675
- t.dom.getParent(t.selection.getNode(), function(n) {
676
- if (n.nodeName == 'BLOCKQUOTE')
677
- n.dir = n.style.marginRight = '';
678
- });
679
- }
680
- },
681
-
682
- mceSetClass : function(u, v, e) {
683
- var s = t.selection;
684
-
685
- // Wrap it
686
- if (is(v, 'string')) {
687
- v = {
688
- element : 'span',
689
- 'class' : v
690
- };
691
- }
692
-
693
- if (s.isCollapsed())
694
- t.dom.setAttr(s.getNode(), 'class', v['class']);
695
- else
696
- s.setContent('<' + v.element + ' class="' + v['class'] + '">' + s.getContent() + '</' + v.element + '>');
697
- },
698
-
699
- RemoveFormat : function(u, v, e) {
700
- var s = t.selection;
701
-
702
- t.getDoc().execCommand('RemoveFormat', u, v);
703
-
704
- // Extra format removal for IE 6
705
- if (isIE) {
706
- v = s.getContent();
707
-
708
- v = v.replace(/ (class|style)=\"[^\"]+\"/g, '');
709
- v = v.replace(/<\/?(font|strong|em|b|i|u|strike)>/g, '');
710
- v = v.replace(/<(font|strong|em|b|i|u|strike) [^>]+>/g, '');
711
-
712
- s.setContent(v);
713
- }
714
- }
715
- };
716
-
717
- // Private methods
718
-
719
- function startResize(e) {
720
- var c, p, w, h;
721
-
722
- // Measure container
723
- c = pageDOM.get(s.id + '_c');
724
- w = c.clientWidth - 2;
725
- h = c.clientHeight - 2;
726
-
727
- // Setup placeholder
728
- p = pageDOM.get(s.id + '_p');
729
- p.style.width = w + 'px';
730
- p.style.height = h + 'px';
731
-
732
- // Replace with placeholder
733
- c.style.display = 'none';
734
- p.style.display = 'block';
735
-
736
- // Create internal resize obj
737
- t.resize = {
738
- x : e.screenX,
739
- y : e.screenY,
740
- w : w,
741
- h : h
742
- };
743
-
744
- // Start listening
745
- Event.add(document, 'mousemove', resizeMove, this);
746
- Event.add(document, 'mouseup', endResize, this);
747
-
748
- t.onResizeStart.dispatch(t, e, w, h);
749
- };
750
-
751
- function resizeMove(e) {
752
- var r = t.resize, p, w, h;
753
-
754
- // Calc delta values
755
- r.dx = e.screenX - r.x;
756
- r.dy = e.screenY - r.y;
757
-
758
- // Boundery fix box
759
- w = Math.max(s.min_width, r.w + r.dx);
760
- h = Math.max(s.min_height, r.h + r.dy);
761
- w = Math.min(s.max_width, w);
762
- h = Math.min(s.max_height, h);
763
-
764
- // Resize placeholder
765
- p = pageDOM.get(s.id + '_p');
766
- p.style.width = w + 'px';
767
- p.style.height = h + 'px';
768
-
769
- return Event.cancel(e);
770
- };
771
-
772
- function endResize(e) {
773
- var r = t.resize;
774
-
775
- // Stop listening
776
- Event.remove(document, 'mousemove', resizeMove, this);
777
- Event.remove(document, 'mouseup', endResize, this);
778
-
779
- // Replace with editor
780
- pageDOM.get(s.id + '_c').style.display = '';
781
- pageDOM.get(s.id + '_p').style.display = 'none';
782
-
783
- // Resize it to new size
784
- t.resizeBy(r.dx, r.dy);
785
-
786
- t.onResizeEnd.dispatch(t, e, r.dx, r.dy);
787
- };
788
-
789
- function setup() {
790
- var e = pageDOM.get(s.id), d = t.getDoc();
791
-
792
- // Design mode needs to be added here Ctrl+A will fail otherwise
793
- if (isGecko)
794
- t.getDoc().designMode = 'On';
795
-
796
- // Setup body
797
- d.open();
798
- d.write('<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body id="punymce"></body></html>');
799
- d.close();
800
-
801
- t.dom = DOM = new DOMUtils(t.getDoc());
802
- DOM.loadCSS(s.content_css);
803
-
804
- t.onPreInit.dispatch(t);
805
-
806
- if (!s.spellcheck)
807
- t.getBody().spellcheck = 0;
808
-
809
- // Add node change handlers
810
- Event.add(t.getDoc(), 'mouseup', t.nodeChanged, t);
811
- Event.add(t.getDoc(), 'keyup', t.nodeChanged, t );
812
-
813
- // Add focus event
814
- Event.add(isGecko ? t.getDoc() : t.getWin(), 'focus', function(e) {
815
- var ed;
816
-
817
- if ((ed = punymce.focusEditor) != null)
818
- ed.onBlur.dispatch(ed, t);
819
-
820
- t.onFocus.dispatch(t, ed);
821
- punymce.focusEditor = t;
822
- }, this);
823
-
824
- // IE fired load event twice if designMode is set
825
- if (!isIE)
826
- t.getDoc().designMode = 'On';
827
- else
828
- t.getBody().contentEditable = true;
829
-
830
- t.setContent(is(e.value) ? e.value : e.innerHTML, {load : true});
831
-
832
- pageDOM.get(s.id + '_c').style.display = t.orgDisplay;
833
- pageDOM.get(s.id).style.display = 'none';
834
-
835
- t.onInit.dispatch(t);
836
- };
837
-
838
- // Public fields
839
- extend(this, {
840
- serializer : new Serializer(t),
841
- selection : new Selection(t),
842
- plugins : []
843
- });
844
-
845
- // Add events
846
- each(['onPreInit', 'onInit', 'onFocus', 'onBlur', 'onResizeStart', 'onResizeEnd', 'onPreProcess', 'onPostProcess', 'onSetContent', 'onBeforeGetContent', 'onGetContent', 'onNodeChange'], function(e) {
847
- t[e] = new Dispatcher(t);
848
- });
849
-
850
- // Public methods
851
- extend(this, {
852
- init : function() {
853
- var e = pageDOM.get(s.id), pe = e.parentNode, w, h, ht, ul, n, r, f, sta = ['bold', 'italic', 'underline', 'left', 'center', 'right'];
854
-
855
- // Create plugins
856
- each(s.plugins.split(','), function(p) {
857
- if (p)
858
- t.plugins.push(new punymce.plugins[p](t));
859
- });
860
-
861
- // Handle common states
862
- t.onNodeChange.add(function() {
863
- each(sta, function(n) {
864
- var f;
865
-
866
- try {
867
- f = t.getDoc().queryCommandState(t.tools[n].cmd) ? pageDOM.addClass : pageDOM.removeClass;
868
- f.call(pageDOM, s.id + '_' + n, 'active');
869
- } catch (ex) {
870
- // Might fail
871
- }
872
- });
873
- });
874
-
875
- // Setup numeric entities
876
- if (s.entities == 'numeric') {
877
- t.onGetContent.add(function(ed, o) {
878
- if (o.format == 'html') {
879
- o.content = o.content.replace(/[\u007E-\uFFFF]/g, function(a) {
880
- return '&#' + a.charCodeAt(0) + ';';
881
- });
882
- }
883
- });
884
- }
885
-
886
- w = !s.width ? e.offsetWidth : s.width;
887
- h = !s.height ? e.offsetHeight : s.height;
888
- t.orgDisplay = e.style.display;
889
- e.style.display = 'none';
890
-
891
- // Add submit handlers
892
- if (e.form) {
893
- f = e.form;
894
-
895
- // Piggy back
896
- t._submit = f.submit;
897
- f.submit = function() {
898
- var e = pageDOM.get(s.id), f = e.form;
899
- t.save();
900
- f.submit = t._submit;
901
- f.submit();
902
- };
903
-
904
- // Prevent IE from memory leaking
905
- Event.add(0, 'unload', function() {
906
- var f = pageDOM.get(s.id).form;
907
- t._submit = t.submit = null;
908
- });
909
-
910
- // Submit event
911
- Event.add(f, 'submit', t.save, t);
912
- }
913
-
914
- // Setup UI table, could not use DOM since IE couldn't add the table this method is smaller in size anyway
915
- ht = '<div id="' + s.id + '_w" class="punymce"><table id="' + s.id + '_c" class="punymce"><tr class="mceToolbar">';
916
- ht += '<td id="' + s.id + '_t"></td></tr><tr class="mceBody"><td></div><div id="' + s.id + '_b" class="mceBody">';
917
-
918
- if (s.resize)
919
- ht += '<div id="' + s.id + '_r" class="mceResize"></div>';
920
-
921
- ht += '</td></tr></table>';
922
- ht += '<div id="' + s.id + '_p" class="mcePlaceholder"></div></div>';
923
-
924
- if (!e.insertAdjacentHTML) {
925
- r = e.ownerDocument.createRange();
926
- r.setStartBefore(e);
927
- pe.insertBefore(r.createContextualFragment(ht), e);
928
- } else
929
- e.insertAdjacentHTML("beforeBegin", ht);
930
-
931
- // Add tools to toolbar
932
- n = pageDOM.get(s.id + '_t');
933
- ul = pageDOM.add(n, 'ul', {id : s.id + '_tb', 'class' : 'punymce'});
934
-
935
- each(s.toolbar.split(','), function(v) {
936
- var to = t.tools[v];
937
-
938
- n = pageDOM.add(pageDOM.add(ul, 'li', {id : s.id + '_' + v, 'class' : v}), 'a', {'href' : 'javascript:void(0);', 'class' : v, title : to.title, tabIndex : -1, onmousedown : 'return false;'});
939
-
940
- Event.add(n, 'click', function(e) {
941
- if (!pageDOM.hasClass(e.target.parentNode, 'disabled'))
942
- t.execCommand(to.cmd, 0, 0, e);
943
-
944
- return Event.cancel(e);
945
- });
946
- });
947
-
948
- // Add iframe to body
949
- n = pageDOM.get(s.id + '_b');
950
-
951
- // Create iframe
952
- n = pageDOM.add(n, 'iframe', {
953
- id : s.id + "_f",
954
- src : 'javascript:""', // Workaround for HTTPs warning in IE6/7
955
- frameBorder : '0',
956
- 'class' : 'punymce',
957
- style : 'width:' + w + 'px;height:' + h + 'px'
958
- });
959
-
960
- t.resizeTo(w, h);
961
-
962
- // WebKit needs to be loaded this way to force it in to quirksmode to get <b> instead of <span>
963
- if (isWebKit) {
964
- Event.add(n, 'load', setup, t);
965
- n.src = punymce.baseURL + 'blank.htm';
966
- } else
967
- setup();
968
-
969
- // Add resize event
970
- if (s.resize) {
971
- Event.add(s.id + '_r', 'mousedown', function(e) {
972
- return startResize(e, s.id);
973
- }, this);
974
- }
975
-
976
- ul = f = e = n = null; // Prevent IE memory leak
977
- },
978
-
979
- getSize : function() {
980
- var e = pageDOM.get(s.id + '_f');
981
-
982
- return {
983
- w : e.clientWidth,
984
- h : e.clientHeight
985
- };
986
- },
987
-
988
- resizeTo : function(w, h) {
989
- var st = pageDOM.get(s.id + '_f').style;
990
-
991
- // Fix size
992
- w = Math.max(s.min_width, w);
993
- h = Math.max(s.min_height, h);
994
- w = Math.min(s.max_width, w);
995
- h = Math.min(s.max_height, h);
996
-
997
- // Store away size
998
- t.width = w;
999
- t.height = h;
1000
-
1001
- // Resize container
1002
- st.width = w + 'px';
1003
- st.height = h + 'px';
1004
- },
1005
-
1006
- resizeBy : function(w, h) {
1007
- var r = t.getSize();
1008
-
1009
- t.resizeTo(r.w + w, r.h + h);
1010
- },
1011
-
1012
- show : function() {
1013
- pageDOM.get(s.id + '_w').style.display = 'block';
1014
- pageDOM.get(s.id).style.display = 'none';
1015
- t.load();
1016
- },
1017
-
1018
- hide : function() {
1019
- // Fixed bug where IE has a blinking cursor left from the editor
1020
- if (isIE)
1021
- t.execCommand('SelectAll');
1022
-
1023
- pageDOM.get(s.id + '_w').style.display = 'none';
1024
- pageDOM.get(s.id).style.display = t.orgDisplay;
1025
- t.save();
1026
- },
1027
-
1028
- load : function() {
1029
- var e = pageDOM.get(s.id);
1030
-
1031
- t.setContent(is(e.value) ? e.value : e.innerHTML, {load : true});
1032
- },
1033
-
1034
- save : function() {
1035
- var e = pageDOM.get(s.id), h = t.getContent({save : true});
1036
- // Fixed bug where empty boxes return '<html/>' as content
1037
- h = h.replace(/<(\/?)html(\/?)>/gi, "");
1038
- if (/TEXTAREA|INPUT/.test(e.nodeName))
1039
- e.value = h;
1040
- else
1041
- e.innerHTML = h;
1042
- },
1043
-
1044
- setUseCSS : function(s) {
1045
- var d = t.getDoc(), e;
1046
-
1047
- try {
1048
- // Try new Gecko method
1049
- d.execCommand("styleWithCSS", 0, false);
1050
- } catch (e) {
1051
- try {
1052
- // Use old
1053
- d.execCommand("useCSS", 0, true);
1054
- } catch (e) {
1055
- // Ignore
1056
- }
1057
- }
1058
- },
1059
-
1060
- execCommand : function(c, u, v, e) {
1061
- var cl = t.commands, s;
1062
-
1063
- t.getWin().focus();
1064
- t.setUseCSS(0);
1065
-
1066
- if (cl[c])
1067
- s = cl[c].call(t, u, v, e);
1068
- else
1069
- s = t.getDoc().execCommand(c, u, v);
1070
-
1071
- if (s !== false)
1072
- t.nodeChanged();
1073
- },
1074
-
1075
- getContent : function(o) {
1076
- var h;
1077
-
1078
- o = o || {};
1079
- o.format = o.format || 'html';
1080
- t.onBeforeGetContent.dispatch(this, o);
1081
- h = t.serializer.serialize(t.getBody(), o);
1082
- h = h.replace(/^\s*|\s*$/g, '');
1083
- o.content = h;
1084
- t.onGetContent.dispatch(this, o);
1085
-
1086
- return o.content;
1087
- },
1088
-
1089
- setContent : function(h, o) {
1090
- o = o || {};
1091
- o.content = h;
1092
- t.onSetContent.dispatch(this, o);
1093
- h = o.content;
1094
- h = pageDOM.keep(h);
1095
-
1096
- t.getBody().innerHTML = h;
1097
-
1098
- if (o.format != "raw") {
1099
- t.setContent(h = t.getContent(o), {format : 'raw'});
1100
- } else
1101
- t.getBody().innerHTML = h;
1102
-
1103
- return h;
1104
- },
1105
-
1106
- getIfr : function() {
1107
- return pageDOM.get(s.id + "_f");
1108
- },
1109
-
1110
- getWin : function() {
1111
- return t.getIfr().contentWindow;
1112
- },
1113
-
1114
- getDoc : function() {
1115
- return t.getWin().document;
1116
- },
1117
-
1118
- getBody : function() {
1119
- return t.getDoc().body;
1120
- },
1121
-
1122
- nodeChanged : function() {
1123
- t.setUseCSS(0);
1124
- t.onNodeChange.dispatch(t, t.selection.getNode());
1125
- }
1126
- });
1127
-
1128
- // Call init when page loads
1129
- Event.add(window, 'init', t.init, this);
1130
- };
1131
-
1132
- punymce.Selection = Selection = function(ed) {
1133
- var t = this;
1134
-
1135
- // Public methods
1136
- extend(t, {
1137
- getContent : function(o) {
1138
- var h, r = t.getRng(), e = document.createElement("body");
1139
-
1140
- o = o || {};
1141
-
1142
- if (t.isCollapsed())
1143
- return '';
1144
-
1145
- if (r.cloneContents)
1146
- e.appendChild(r.cloneContents());
1147
- else if (is(r.item) || is(r.htmlText))
1148
- e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
1149
- else
1150
- e.innerHTML = r.toString();
1151
-
1152
- if (o.format != "raw") {
1153
- o.content = h;
1154
- ed.serializer.serialize(e, o);
1155
- o.content = o.content.replace(/^\s*|\s*$/g, '');
1156
- ed.onGetContent.dispatch(h, o);
1157
- h = o.content;
1158
- } else
1159
- h = e.innerHTML;
1160
-
1161
- return h;
1162
- },
1163
-
1164
- getText : function() {
1165
- var r = t.getRng(), s = t.getSel();
1166
-
1167
- if (isOldWebKit)
1168
- return s;
1169
-
1170
- return t.isCollapsed() ? '' : r.text || s.toString();
1171
- },
1172
-
1173
- setContent : function(h, o) {
1174
- var r = t.getRng(), b, c, r, s;
1175
-
1176
- o = o || {format : 'raw'};
1177
- h = pageDOM.keep(h);
1178
-
1179
- if (o.format != "raw") {
1180
- o.content = h;
1181
- h = ed.onSetContent.dispatch(this, o);
1182
- h = o.content;
1183
- b = ed.dom.create('body');
1184
- b.innerHTML = h;
1185
- }
1186
-
1187
- if (r.insertNode) {
1188
- r.deleteContents();
1189
- r.insertNode(r.createContextualFragment(h + '<span id="__caret">_</span>'));
1190
-
1191
- // Move to caret marker
1192
- c = ed.dom.get('__caret');
1193
-
1194
- // Make sure we wrap it compleatly, Opera fails with a simple select call
1195
- r = ed.getDoc().createRange();
1196
- r.setStartBefore(c);
1197
- r.setEndBefore(c);
1198
- s = t.getSel();
1199
- s.removeAllRanges();
1200
- s.addRange(r);
1201
-
1202
- // Remove the caret
1203
- c.parentNode.removeChild(c);
1204
- } else {
1205
- // Handle text and control range
1206
- if (r.pasteHTML)
1207
- r.pasteHTML(h);
1208
- else
1209
- r.item(0).outerHTML = h;
1210
- }
1211
- },
1212
-
1213
- select : function(n, c) {
1214
- var r = t.getRng(), s = t.getSel();
1215
-
1216
- if (r.moveToElementText) {
1217
- try {
1218
- r.moveToElementText(n);
1219
- r.select();
1220
- } catch (ex) {
1221
- // Throws illigal agrument in IE some times
1222
- }
1223
- } else if (s.addRange) {
1224
- c ? r.selectNodeContents(n) : r.selectNode(n);
1225
- s.removeAllRanges();
1226
- s.addRange(r);
1227
- } else
1228
- s.setBaseAndExtent(n, 0, n, 1);
1229
-
1230
- return n;
1231
- },
1232
-
1233
- isCollapsed : function() {
1234
- var r = t.getRng();
1235
-
1236
- if (r.item)
1237
- return false;
1238
-
1239
- return r.boundingWidth == 0 || t.getSel().isCollapsed;
1240
- },
1241
-
1242
- collapse : function(b) {
1243
- var r = t.getRng(), s = t.getSel();
1244
-
1245
- if (r.select) {
1246
- r.collapse(b);
1247
- r.select();
1248
- } else {
1249
- if (b)
1250
- s.collapseToStart();
1251
- else
1252
- s.collapseToEnd();
1253
- }
1254
- },
1255
-
1256
- getSel : function() {
1257
- var w = ed.getWin();
1258
-
1259
- return w.getSelection ? w.getSelection() : ed.getDoc().selection;
1260
- },
1261
-
1262
- getRng : function() {
1263
- var s = t.getSel(), d = ed.getDoc(), r, rb, ra, di;
1264
-
1265
- if (!s)
1266
- return null;
1267
-
1268
- try {
1269
- return s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : null);
1270
- } catch (e) {
1271
- // IE bug when used in frameset
1272
- return d.body.createTextRange();
1273
- }
1274
- },
1275
-
1276
- setRng : function(r) {
1277
- var s = t.getSel();
1278
-
1279
- s.removeAllRanges();
1280
- s.addRange(r);
1281
- },
1282
-
1283
- setNode : function(n) {
1284
- t.setContent(ed.dom.create('div', null, n).innerHTML);
1285
- },
1286
-
1287
- getNode : function() {
1288
- var r = t.getRng(), s = t.getSel(), e;
1289
-
1290
- if (!isIE) {
1291
- if (r) {
1292
- e = r.commonAncestorContainer;
1293
-
1294
- // Handle selection a image or other control like element such as anchors
1295
- if (!r.collapsed) {
1296
- if (r.startContainer == r.endContainer) {
1297
- if (r.startOffset - r.endOffset < 2) {
1298
- if (r.startContainer.hasChildNodes())
1299
- e = r.startContainer.childNodes[r.startOffset];
1300
- }
1301
- }
1302
- }
1303
- }
1304
-
1305
- return pageDOM.getParent(e, function(n) {
1306
- return n.nodeType == 1;
1307
- });
1308
- }
1309
-
1310
- return r.item ? r.item(0) : r.parentElement();
1311
- }
1312
- });
1313
- };
1314
-
1315
- punymce.Serializer = Serializer = function(ed) {
1316
- var xml, key = 0, s;
1317
-
1318
- // Get XML document
1319
- function getXML() {
1320
- var i = document.implementation;
1321
-
1322
- if (!i || !i.createDocument) {
1323
- // Try IE objects
1324
- try {return new ActiveXObject('MSXML2.DOMDocument');} catch (ex) {}
1325
- try {return new ActiveXObject('Microsoft.XmlDom');} catch (ex) {}
1326
- } else
1327
- return i.createDocument('', '', null);
1328
- };
1329
-
1330
- xml = getXML();
1331
-
1332
- // Default settings
1333
- this.settings = s = extend({
1334
- valid_nodes : 0,
1335
- invalid_nodes : /(BODY)/,
1336
- valid_attrs : 0,
1337
- node_filter : 0,
1338
- root_node : 0,
1339
- pi : 0,
1340
- invalid_attrs : /(^mce_|^_moz_|^contenteditable$)/,
1341
- closed : /(BR|HR|INPUT|META|IMG)/
1342
- }, ed.settings.serializer);
1343
-
1344
- // Returns only attribites that have values not all attributes in IE
1345
- function getIEAtts(n) {
1346
- var o = [];
1347
-
1348
- n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {
1349
- o.push({specified : 1, nodeName : b});
1350
- });
1351
-
1352
- return o;
1353
- };
1354
-
1355
- // Private methods
1356
- function serializeNode(n, xn) {
1357
- var hc, el, cn, i, l, a, at, no, v;
1358
-
1359
- if ((!s.valid_nodes || s.valid_nodes.test(n.nodeName)) && (!s.invalid_nodes || !s.invalid_nodes.test(n.nodeName)) && (!s.node_filter || s.node_filter(n, xn))) {
1360
- switch (n.nodeType) {
1361
- case 1: // Element
1362
- // Fix IE content duplication (DOM can have multiple copies of the same node)
1363
- if (isIE) {
1364
- if (n.mce_serialized == key)
1365
- return;
1366
-
1367
- n.mce_serialized = key;
1368
- }
1369
-
1370
- hc = n.hasChildNodes();
1371
- el = xml.createElement(n.nodeName.toLowerCase());
1372
-
1373
- // Add attributes
1374
- at = isIE ? getIEAtts(n) : n.attributes;
1375
- for (i=at.length-1; i>-1; i--) {
1376
- no = at[i];
1377
-
1378
- if (no.specified) {
1379
- a = no.nodeName.toLowerCase();
1380
-
1381
- if (s.invalid_attrs && s.invalid_attrs.test(a))
1382
- continue;
1383
-
1384
- if (s.valid_attrs && !s.valid_attrs.test(a))
1385
- continue;
1386
-
1387
- v = pageDOM.getAttr(n, a);
1388
-
1389
- if (v !== '')
1390
- el.setAttribute(a, v);
1391
- }
1392
- }
1393
-
1394
- if (!hc && !s.closed.test(n.nodeName))
1395
- el.appendChild(xml.createTextNode(""));
1396
-
1397
- xn = xn.appendChild(el);
1398
- break;
1399
-
1400
- case 3: // Text
1401
- return xn.appendChild(xml.createTextNode(n.nodeValue));
1402
-
1403
- case 8: // Comment
1404
- return xn.appendChild(xml.createComment(n.nodeValue));
1405
- }
1406
- } else if (n.nodeType == 1)
1407
- hc = n.hasChildNodes();
1408
-
1409
- if (hc) {
1410
- cn = n.firstChild;
1411
-
1412
- while (cn) {
1413
- serializeNode(cn, xn);
1414
- cn = cn.nextSibling;
1415
- }
1416
- }
1417
- };
1418
-
1419
- // Public methods
1420
- extend(this, {
1421
- serialize : function(n, o) {
1422
- var h;
1423
-
1424
- key = '' + (parseInt(key) + 1);
1425
-
1426
- if (xml.firstChild)
1427
- xml.removeChild(xml.firstChild);
1428
-
1429
- n = o.node = n.cloneNode(1);
1430
-
1431
- // Call preprocess
1432
- ed.onPreProcess.dispatch(this, o);
1433
-
1434
- // Serialize HTML DOM into XML DOM
1435
- serializeNode(n, xml.appendChild(xml.createElement("html")));
1436
- h = xml.xml || new XMLSerializer().serializeToString(xml);
1437
-
1438
- // Remove PI
1439
- if (!s.pi)
1440
- h = h.replace(/<\?[^?]+\?>/g, '');
1441
-
1442
- // Remove root element
1443
- if (!s.root_node)
1444
- h = h.replace(/<html>|<\/html>/g, '');
1445
-
1446
- // Call post process
1447
- o.content = h;
1448
- ed.onPostProcess.dispatch(this, o);
1449
-
1450
- return o.content;
1451
- }
1452
- });
1453
- };
1454
-
1455
- // Wait for DOM loaded
1456
- Event._wait();
1457
-
1458
- // Expose punymce
1459
- window.punymce = punymce;
1460
- })({});