refinerycms-wymeditor 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/.gitignore +88 -0
  2. data/app/assets/images/wymeditor/skins/refinery/arrow_redo.png +0 -0
  3. data/app/assets/images/wymeditor/skins/refinery/arrow_undo.png +0 -0
  4. data/app/assets/images/wymeditor/skins/refinery/eye.png +0 -0
  5. data/app/assets/images/wymeditor/skins/refinery/html5/article.png +0 -0
  6. data/app/assets/images/wymeditor/skins/refinery/html5/aside.png +0 -0
  7. data/app/assets/images/wymeditor/skins/refinery/html5/blockquote.png +0 -0
  8. data/app/assets/images/wymeditor/skins/refinery/html5/command.png +0 -0
  9. data/app/assets/images/wymeditor/skins/refinery/html5/details.png +0 -0
  10. data/app/assets/images/wymeditor/skins/refinery/html5/figcaption.png +0 -0
  11. data/app/assets/images/wymeditor/skins/refinery/html5/figure.png +0 -0
  12. data/app/assets/images/wymeditor/skins/refinery/html5/footer.png +0 -0
  13. data/app/assets/images/wymeditor/skins/refinery/html5/h1.png +0 -0
  14. data/app/assets/images/wymeditor/skins/refinery/html5/h2.png +0 -0
  15. data/app/assets/images/wymeditor/skins/refinery/html5/h3.png +0 -0
  16. data/app/assets/images/wymeditor/skins/refinery/html5/h4.png +0 -0
  17. data/app/assets/images/wymeditor/skins/refinery/html5/h5.png +0 -0
  18. data/app/assets/images/wymeditor/skins/refinery/html5/h6.png +0 -0
  19. data/app/assets/images/wymeditor/skins/refinery/html5/header.png +0 -0
  20. data/app/assets/images/wymeditor/skins/refinery/html5/hgroup.png +0 -0
  21. data/app/assets/images/wymeditor/skins/refinery/html5/mark.png +0 -0
  22. data/app/assets/images/wymeditor/skins/refinery/html5/meter.png +0 -0
  23. data/app/assets/images/wymeditor/skins/refinery/html5/nav.png +0 -0
  24. data/app/assets/images/wymeditor/skins/refinery/html5/p.png +0 -0
  25. data/app/assets/images/wymeditor/skins/refinery/html5/pre.png +0 -0
  26. data/app/assets/images/wymeditor/skins/refinery/html5/progress.png +0 -0
  27. data/app/assets/images/wymeditor/skins/refinery/html5/readme.md +1 -0
  28. data/app/assets/images/wymeditor/skins/refinery/html5/rp.png +0 -0
  29. data/app/assets/images/wymeditor/skins/refinery/html5/rt.png +0 -0
  30. data/app/assets/images/wymeditor/skins/refinery/html5/ruby.png +0 -0
  31. data/app/assets/images/wymeditor/skins/refinery/html5/section.png +0 -0
  32. data/app/assets/images/wymeditor/skins/refinery/html5/summary.png +0 -0
  33. data/app/assets/images/wymeditor/skins/refinery/html5/time.png +0 -0
  34. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-blockquote.png +0 -0
  35. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-h1.png +0 -0
  36. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-h2.png +0 -0
  37. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-h3.png +0 -0
  38. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-h4.png +0 -0
  39. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-h5.png +0 -0
  40. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-h6.png +0 -0
  41. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-p.png +0 -0
  42. data/app/assets/images/wymeditor/skins/refinery/iframe/lbl-pre.png +0 -0
  43. data/app/assets/images/wymeditor/skins/refinery/link_add.png +0 -0
  44. data/app/assets/images/wymeditor/skins/refinery/link_break.png +0 -0
  45. data/app/assets/images/wymeditor/skins/refinery/page_code.png +0 -0
  46. data/app/assets/images/wymeditor/skins/refinery/page_paste.png +0 -0
  47. data/app/assets/images/wymeditor/skins/refinery/photo_add.png +0 -0
  48. data/app/assets/images/wymeditor/skins/refinery/right.png +0 -0
  49. data/app/assets/images/wymeditor/skins/refinery/style.png +0 -0
  50. data/app/assets/images/wymeditor/skins/refinery/table_add.png +0 -0
  51. data/app/assets/images/wymeditor/skins/refinery/text_align_center.png +0 -0
  52. data/app/assets/images/wymeditor/skins/refinery/text_align_justify.png +0 -0
  53. data/app/assets/images/wymeditor/skins/refinery/text_align_left.png +0 -0
  54. data/app/assets/images/wymeditor/skins/refinery/text_align_right.png +0 -0
  55. data/app/assets/images/wymeditor/skins/refinery/text_bold.png +0 -0
  56. data/app/assets/images/wymeditor/skins/refinery/text_heading_1.png +0 -0
  57. data/app/assets/images/wymeditor/skins/refinery/text_heading_2.png +0 -0
  58. data/app/assets/images/wymeditor/skins/refinery/text_heading_3.png +0 -0
  59. data/app/assets/images/wymeditor/skins/refinery/text_heading_4.png +0 -0
  60. data/app/assets/images/wymeditor/skins/refinery/text_heading_5.png +0 -0
  61. data/app/assets/images/wymeditor/skins/refinery/text_heading_6.png +0 -0
  62. data/app/assets/images/wymeditor/skins/refinery/text_indent.png +0 -0
  63. data/app/assets/images/wymeditor/skins/refinery/text_indent_remove.png +0 -0
  64. data/app/assets/images/wymeditor/skins/refinery/text_italic.png +0 -0
  65. data/app/assets/images/wymeditor/skins/refinery/text_list_bullets.png +0 -0
  66. data/app/assets/images/wymeditor/skins/refinery/text_list_numbers.png +0 -0
  67. data/app/assets/images/wymeditor/skins/refinery/text_paragraph.png +0 -0
  68. data/app/assets/images/wymeditor/skins/refinery/text_strikethrough.png +0 -0
  69. data/app/assets/images/wymeditor/skins/refinery/text_subscript.png +0 -0
  70. data/app/assets/images/wymeditor/skins/refinery/text_superscript.png +0 -0
  71. data/app/assets/images/wymeditor/skins/refinery/text_underline.png +0 -0
  72. data/app/assets/images/wymeditor/skins/wymeditor_icon.png +0 -0
  73. data/app/assets/javascripts/refinery/boot_wym.js.erb +289 -0
  74. data/app/assets/javascripts/refinery/wymeditor.js +37 -0
  75. data/app/assets/javascripts/wymeditor/browsers/ie.js.erb +224 -0
  76. data/app/assets/javascripts/wymeditor/browsers/mozilla.js.erb +293 -0
  77. data/app/assets/javascripts/wymeditor/browsers/opera.js.erb +123 -0
  78. data/app/assets/javascripts/wymeditor/browsers/webkit.js.erb +284 -0
  79. data/app/assets/javascripts/wymeditor/classes.js.erb +1577 -0
  80. data/app/assets/javascripts/wymeditor/functions.js.erb +218 -0
  81. data/app/assets/javascripts/wymeditor/lang/bg.js +57 -0
  82. data/app/assets/javascripts/wymeditor/lang/ca.js +45 -0
  83. data/app/assets/javascripts/wymeditor/lang/cs.js +58 -0
  84. data/app/assets/javascripts/wymeditor/lang/da.js +48 -0
  85. data/app/assets/javascripts/wymeditor/lang/de.js +45 -0
  86. data/app/assets/javascripts/wymeditor/lang/en.js +57 -0
  87. data/app/assets/javascripts/wymeditor/lang/es.js +58 -0
  88. data/app/assets/javascripts/wymeditor/lang/fa.js +46 -0
  89. data/app/assets/javascripts/wymeditor/lang/fi.js +57 -0
  90. data/app/assets/javascripts/wymeditor/lang/fr.js +57 -0
  91. data/app/assets/javascripts/wymeditor/lang/he.js +45 -0
  92. data/app/assets/javascripts/wymeditor/lang/hu.js +45 -0
  93. data/app/assets/javascripts/wymeditor/lang/it.js +48 -0
  94. data/app/assets/javascripts/wymeditor/lang/ja.js +47 -0
  95. data/app/assets/javascripts/wymeditor/lang/lv.js +47 -0
  96. data/app/assets/javascripts/wymeditor/lang/nb.js +48 -0
  97. data/app/assets/javascripts/wymeditor/lang/nl.js +47 -0
  98. data/app/assets/javascripts/wymeditor/lang/nn.js +45 -0
  99. data/app/assets/javascripts/wymeditor/lang/pl.js +45 -0
  100. data/app/assets/javascripts/wymeditor/lang/pt-BR.js +58 -0
  101. data/app/assets/javascripts/wymeditor/lang/pt.js +45 -0
  102. data/app/assets/javascripts/wymeditor/lang/rs.js +47 -0
  103. data/app/assets/javascripts/wymeditor/lang/ru.js +56 -0
  104. data/app/assets/javascripts/wymeditor/lang/sk.js +56 -0
  105. data/app/assets/javascripts/wymeditor/lang/sl.js +47 -0
  106. data/app/assets/javascripts/wymeditor/lang/sv.js +45 -0
  107. data/app/assets/javascripts/wymeditor/lang/tr.js +45 -0
  108. data/app/assets/javascripts/wymeditor/lang/vi.js +47 -0
  109. data/app/assets/javascripts/wymeditor/lang/zh_cn.js +47 -0
  110. data/app/assets/javascripts/wymeditor/prototypes.js.erb +1106 -0
  111. data/app/assets/javascripts/wymeditor/setup.js.erb +622 -0
  112. data/app/assets/javascripts/wymeditor/skins/refinery/skin.js +48 -0
  113. data/app/assets/javascripts/wymeditor/validators.js.erb +776 -0
  114. data/app/assets/stylesheets/theme.css.scss +36 -0
  115. data/app/assets/stylesheets/wymeditor/skins/refinery/skin.css.scss +530 -0
  116. data/app/assets/stylesheets/wymeditor/skins/refinery/wymiframe.css.scss +156 -0
  117. data/app/assets/stylesheets/wymeditor.css.scss +0 -0
  118. data/app/controllers/refinery/wymeditor_controller.rb +9 -0
  119. data/app/views/refinery/wymiframe.html.erb +14 -0
  120. data/config/initializers/refinery/wymeditor.rb.erb +4 -0
  121. data/lib/refinery/wymeditor/configuration.rb +10 -0
  122. data/lib/refinery/wymeditor/engine.rb +30 -0
  123. data/lib/refinery/wymeditor.rb +12 -0
  124. data/public/wymeditor/GPL-license.txt +278 -0
  125. data/public/wymeditor/MIT-license.txt +20 -0
  126. data/public/wymeditor/README +35 -0
  127. data/readme.md +96 -0
  128. data/refinerycms-wymeditor.gemspec +17 -0
  129. metadata +173 -0
@@ -0,0 +1,1106 @@
1
+ /********** WYMeditor **********/
2
+
3
+ /* @name Wymeditor
4
+ * @description WYMeditor class
5
+ */
6
+
7
+ /* @name init
8
+ * @description Initializes a WYMeditor instance
9
+ */
10
+ WYMeditor.editor.prototype.init = function() {
11
+
12
+ //load subclass - browser specific
13
+ //unsupported browsers: do nothing
14
+
15
+ if ($.browser.msie) {
16
+ var WymClass = new WYMeditor.WymClassExplorer(this);
17
+ }
18
+ else if ($.browser.mozilla) {
19
+ var WymClass = new WYMeditor.WymClassMozilla(this);
20
+ }
21
+ else if ($.browser.opera) {
22
+ var WymClass = new WYMeditor.WymClassOpera(this);
23
+ }
24
+ else if ($.browser.webkit) {
25
+ var WymClass = new WYMeditor.WymClassSafari(this);
26
+ }
27
+
28
+ if(WymClass) {
29
+
30
+ if($.isFunction(this._options.preInit)) { this._options.preInit(this); }
31
+
32
+ var SaxListener = new WYMeditor.XhtmlSaxListener();
33
+ $.extend(SaxListener, WymClass);
34
+ this.parser = new WYMeditor.XhtmlParser(SaxListener);
35
+
36
+ if(this._options.styles || this._options.stylesheet){
37
+ this.configureEditorUsingRawCss();
38
+ }
39
+
40
+ this.helper = new WYMeditor.XmlHelper();
41
+
42
+ //extend the Wymeditor object
43
+ //don't use $.extend since 1.1.4
44
+ //$.extend(this, WymClass);
45
+ for (var prop in WymClass) { this[prop] = WymClass[prop]; }
46
+
47
+ //load wymbox
48
+ this._box = $(this._element).hide().after(this._options.boxHtml).next().addClass('wym_box_' + this._index);
49
+
50
+ //store the instance index in wymbox and element replaced by editor instance
51
+ //but keep it compatible with jQuery < 1.2.3, see #122
52
+ if( $.isFunction( $.fn.data ) ) {
53
+ $.data(this._box.get(0), WYMeditor.WYM_INDEX, this._index);
54
+ $.data(this._element.get(0), WYMeditor.WYM_INDEX, this._index);
55
+ }
56
+
57
+ var h = WYMeditor.Helper;
58
+
59
+ //construct the iframe
60
+ var iframeHtml = this._options.iframeHtml;
61
+
62
+ iframeHtml = h.replaceAll(iframeHtml, WYMeditor.INDEX, this._index);
63
+ iframeHtml = h.replaceAll(iframeHtml, WYMeditor.IFRAME_BASE_PATH, this._options.iframeBasePath);
64
+
65
+ //construct wymbox
66
+ var boxHtml = $(this._box).html();
67
+
68
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.LOGO, this._options.logoHtml);
69
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.TOOLS, this._options.toolsHtml);
70
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.CONTAINERS,this._options.containersHtml);
71
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.CLASSES, this._options.classesHtml);
72
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.HTML, this._options.htmlHtml);
73
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.IFRAME, iframeHtml);
74
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.STATUS, this._options.statusHtml);
75
+
76
+ //construct tools list
77
+ var aTools = eval(this._options.toolsItems);
78
+ var sTools = "";
79
+
80
+ for(var i = 0; i < aTools.length; i++) {
81
+ var oTool = aTools[i];
82
+ if(oTool.name && oTool.title) {
83
+ var sTool = this._options.toolsItemHtml;
84
+ var sTool = h.replaceAll(sTool, WYMeditor.TOOL_NAME, oTool.name);
85
+ sTool = h.replaceAll(sTool, WYMeditor.TOOL_TITLE, this._options.stringDelimiterLeft
86
+ + oTool.title
87
+ + this._options.stringDelimiterRight);
88
+ sTool = h.replaceAll(sTool, WYMeditor.TOOL_CLASS, oTool.css);
89
+ sTools += sTool;
90
+ }
91
+ }
92
+
93
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.TOOLS_ITEMS, sTools);
94
+
95
+ //construct classes list
96
+ var aClasses = eval(this._options.classesItems);
97
+ var sClasses = "";
98
+
99
+ for(var i = 0; i < aClasses.length; i++) {
100
+ var oClass = aClasses[i];
101
+ if(oClass.name) {
102
+ if (oClass.rules && oClass.rules.length > 0) {
103
+ var sRules = "";
104
+ var wym = this;
105
+ $.each(oClass.rules, function(index, rule) {
106
+ sClass = wym._options.classesItemHtml;
107
+ sClass = h.replaceAll(sClass, WYMeditor.CLASS_NAME, oClass.name + (oClass.join || "") + (rule.name || rule));
108
+ sClass = h.replaceAll(sClass, WYMeditor.CLASS_TITLE, rule.title || titleize(rule.name || rule));
109
+ sRules += sClass;
110
+ });
111
+
112
+ var sClassMultiple = this._options.classesItemHtmlMultiple;
113
+ sClassMultiple = h.replaceAll(sClassMultiple, WYMeditor.CLASS_TITLE, oClass.title || titleize(oClass.name));
114
+ sClassMultiple = h.replaceAll(sClassMultiple, '{classesItemHtml}', sRules);
115
+ sClasses += sClassMultiple;
116
+ }
117
+ else {
118
+ sClass = this._options.classesItemHtml;
119
+ sClass = h.replaceAll(sClass, WYMeditor.CLASS_NAME, oClass.name);
120
+ sClass = h.replaceAll(sClass, WYMeditor.CLASS_TITLE, oClass.title || titleize(oClass.name));
121
+ sClasses += sClass;
122
+ }
123
+ }
124
+ }
125
+
126
+ boxHtml = h.replaceAll(boxHtml, ">"+WYMeditor.APPLY_CLASS+"<",
127
+ ">" + this._options.stringDelimiterLeft
128
+ + WYMeditor.APPLY_CLASS
129
+ + this._options.stringDelimiterRight + "<");
130
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.CLASSES_ITEMS, sClasses);
131
+
132
+ //construct containers list
133
+ var aContainers = eval(this._options.containersItems);
134
+ var sContainers = "";
135
+
136
+ for(var i = 0; i < aContainers.length; i++) {
137
+ var oContainer = aContainers[i];
138
+ if(oContainer.name && oContainer.title) {
139
+ var sContainer = this._options.containersItemHtml;
140
+ sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_NAME, oContainer.name);
141
+ sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_TITLE,
142
+ this._options.stringDelimiterLeft
143
+ + oContainer.title
144
+ + this._options.stringDelimiterRight);
145
+ sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_CLASS, oContainer.css);
146
+ sContainers += sContainer;
147
+ }
148
+ }
149
+
150
+ boxHtml = h.replaceAll(boxHtml, WYMeditor.CONTAINERS_ITEMS, sContainers);
151
+
152
+ //l18n
153
+ boxHtml = this.replaceStrings(boxHtml);
154
+
155
+ //load html in wymbox
156
+ $(this._box).html(boxHtml);
157
+
158
+ //hide the html value
159
+ $(this._box).find(this._options.htmlSelector).hide();
160
+
161
+ //enable the skin
162
+ this.loadSkin();
163
+
164
+ // store which WYMeditor instance the element owns on the element.
165
+ $(this._element).data('wymeditor', this);
166
+ }
167
+ };
168
+
169
+ WYMeditor.editor.prototype.bindEvents = function() {
170
+
171
+ //copy the instance
172
+ var wym = this;
173
+
174
+ //handle click event on tools buttons
175
+ $(this._box).find(this._options.toolSelector).click(function() {
176
+ wym._iframe.contentWindow.focus(); //See #154
177
+ wym.exec($(this).attr(WYMeditor.NAME));
178
+ return(false);
179
+ });
180
+
181
+ //handle click event on containers buttons
182
+ $(this._box).find(this._options.containerSelector).click(function() {
183
+ wym.container($(this).attr(WYMeditor.NAME));
184
+ return(false);
185
+ });
186
+
187
+ //handle keyup event on html value: set the editor value
188
+ //handle focus/blur events to check if the element has focus, see #147
189
+ $(this._box).find(this._options.htmlValSelector)
190
+ .keyup(function() { $(wym._doc.body).html($(this).val());})
191
+ .focus(function() { $(this).toggleClass('hasfocus'); })
192
+ .blur(function() { $(this).toggleClass('hasfocus'); });
193
+
194
+ //handle click event on classes buttons
195
+ $(this._box).find(this._options.classSelector).bind('click', function(e) {
196
+
197
+ var aClasses = eval(wym._options.classesItems);
198
+ var sName = $(this).attr(WYMeditor.NAME);
199
+ var oClass = WYMeditor.Helper.findByName(aClasses, sName);
200
+ var replacers = $([]);
201
+ if (oClass == null) {
202
+ $.each(aClasses, function(index, classRule){
203
+ if (oClass == null && classRule.rules && classRule.rules.length > 0){
204
+ var ruleName = sName.replace(classRule.name + (classRule.join || ""), "");
205
+ var indexOf = null;
206
+ $.each(classRule.rules, function(i, rule) {
207
+ if (ruleName == (rule.name || rule)) {
208
+ indexOf = i;
209
+ } else {
210
+ replacers.push(classRule.name + (classRule.join || "") + (rule.name || rule));
211
+ }
212
+ });
213
+
214
+ if (indexOf != null) oClass = {expr: (classRule.rules[indexOf].expr || null)};
215
+ }
216
+ });
217
+ }
218
+
219
+ if(oClass) {
220
+ // remove all related classes.
221
+ replacers.each(function(index, removable_class){
222
+ wym.removeClass(removable_class, oClass.expr);
223
+ });
224
+
225
+ wym.toggleClass(sName, oClass.expr);
226
+ }
227
+
228
+ // now hide the menu
229
+ wym.exec(WYMeditor.APPLY_CLASS);
230
+
231
+ wym._iframe.contentWindow.focus(); //See #154
232
+ e.preventDefault();
233
+ });
234
+
235
+ //handle event on update element
236
+ $(this._options.updateSelector).bind(this._options.updateEvent, function() {
237
+ wym.update();
238
+ });
239
+ };
240
+
241
+ WYMeditor.editor.prototype.ready = function() {
242
+ return(this._doc != null);
243
+ };
244
+
245
+
246
+ /********** METHODS **********/
247
+
248
+ /* @name box
249
+ * @description Returns the WYMeditor container
250
+ */
251
+ WYMeditor.editor.prototype.box = function() {
252
+ return(this._box);
253
+ };
254
+
255
+ /* @name html
256
+ * @description Get/Set the html value
257
+ */
258
+ WYMeditor.editor.prototype.html = function(html) {
259
+
260
+ if(typeof html === 'string') {
261
+ $(this._doc.body).html(html);
262
+ } else {
263
+ return($(this._doc.body).html());
264
+ }
265
+ };
266
+
267
+ /* @name intercept_paste
268
+ * @description Catch the browser paste action and open the appropriate dialog instead
269
+ */
270
+ WYMeditor.editor.prototype.intercept_paste = function(e) {
271
+ var wym = WYMeditor.INSTANCES[this.title];
272
+ wym.format_block();
273
+ wym.exec(WYMeditor.PASTE);
274
+ if (e) {
275
+ e.preventDefault();
276
+ }
277
+ };
278
+
279
+ /* @name xhtml
280
+ * @description Cleans up the HTML
281
+ */
282
+ WYMeditor.editor.prototype.xhtml = function() {
283
+ return this.parser.parse(this.html());
284
+ };
285
+
286
+ /* @name exec
287
+ * @description Executes a button command
288
+ */
289
+ WYMeditor.editor.prototype.exec = function(cmd) {
290
+
291
+ //base function for execCommand
292
+ //open a dialog or exec
293
+ switch(cmd) {
294
+ case WYMeditor.CREATE_LINK:
295
+ if((container = this.container()) || this._selected_image) {
296
+ this.dialog(WYMeditor.DIALOG_LINK);
297
+ }
298
+ break;
299
+
300
+ case WYMeditor.INSERT_IMAGE:
301
+ this.dialog(WYMeditor.DIALOG_IMAGE);
302
+ break;
303
+
304
+ case WYMeditor.INSERT_TABLE:
305
+ this.dialog(WYMeditor.DIALOG_TABLE);
306
+ break;
307
+
308
+ case WYMeditor.PASTE:
309
+ this.dialog(WYMeditor.DIALOG_PASTE);
310
+ break;
311
+
312
+ case WYMeditor.TOGGLE_HTML:
313
+ this.update();
314
+ this.toggleHtml();
315
+
316
+ //partially fixes #121 when the user manually inserts an image
317
+ //if(!$(this._box).find(this._options.htmlSelector).is(':visible')) {
318
+ // this.listen();
319
+ //}
320
+ break;
321
+
322
+ case WYMeditor.PREVIEW:
323
+ this.dialog(WYMeditor.PREVIEW);
324
+ break;
325
+
326
+ case WYMeditor.APPLY_CLASS:
327
+ wym = this;
328
+ // determine whether any classes are already selected and add the enabled class to them.
329
+ $(wym._box).find(this._options.classUnhiddenSelector).find("a[name]").each(function(index, rule){
330
+ if ($(wym.selected()).hasClass($(rule).attr('name'))) {
331
+ $(rule).parent().addClass('enabled');
332
+ } else {
333
+ $(rule).parent().removeClass('enabled');
334
+ }
335
+ });
336
+ break;
337
+
338
+ default:
339
+ this._exec(cmd);
340
+ break;
341
+ }
342
+ };
343
+
344
+ /* @name container
345
+ * @description Get/Set the selected container
346
+ */
347
+ WYMeditor.editor.prototype.container = function(sType) {
348
+
349
+ if(sType) {
350
+
351
+ var container = null;
352
+
353
+ if(sType.toLowerCase() == WYMeditor.TH) {
354
+
355
+ container = this.container();
356
+
357
+ //find the TD or TH container
358
+ switch(container.tagName.toLowerCase()) {
359
+
360
+ case WYMeditor.TD: case WYMeditor.TH:
361
+ break;
362
+ default:
363
+ var aTypes = new Array(WYMeditor.TD,WYMeditor.TH);
364
+ container = this.findUp(this.container(), aTypes);
365
+ break;
366
+ }
367
+
368
+ //if it exists, switch
369
+ if(container!=null) {
370
+
371
+ sType = (container.tagName.toLowerCase() == WYMeditor.TD)? WYMeditor.TH: WYMeditor.TD;
372
+ this.switchTo(container,sType);
373
+ this.update();
374
+ }
375
+ } else {
376
+
377
+ //set the container type
378
+ var aTypes=new Array(WYMeditor.P,WYMeditor.H1,WYMeditor.H2,WYMeditor.H3,WYMeditor.H4,WYMeditor.H5,
379
+ WYMeditor.H6,WYMeditor.PRE,WYMeditor.BLOCKQUOTE);
380
+
381
+ container = this.findUp(this.container(), aTypes);
382
+
383
+ if(container) {
384
+
385
+ var newNode = null;
386
+
387
+ //blockquotes must contain a block level element
388
+ if(sType.toLowerCase() == WYMeditor.BLOCKQUOTE) {
389
+
390
+ var blockquote = this.findUp(this.container(), WYMeditor.BLOCKQUOTE);
391
+
392
+ if(blockquote == null) {
393
+
394
+ newNode = this._doc.createElement(sType);
395
+ container.parentNode.insertBefore(newNode,container);
396
+ newNode.appendChild(container);
397
+ this.setFocusToNode(newNode.firstChild);
398
+
399
+ } else {
400
+
401
+ var nodes = blockquote.childNodes;
402
+ var lgt = nodes.length;
403
+ var firstNode = null;
404
+
405
+ if(lgt > 0) { firstNode = nodes.item(0); }
406
+ for(var x=0; x<lgt; x++) {
407
+ blockquote.parentNode.insertBefore(nodes.item(0),blockquote);
408
+ }
409
+ blockquote.parentNode.removeChild(blockquote);
410
+ if(firstNode) { this.setFocusToNode(firstNode); }
411
+ }
412
+ }
413
+
414
+ else
415
+ {
416
+ this.setFocusToNode(this.switchTo(container,sType));
417
+ }
418
+
419
+ this.update();
420
+ }
421
+ }
422
+ }
423
+ else { return(this.selected()); }
424
+ };
425
+
426
+ /* @name toggleClass
427
+ * @description Toggles class on selected element, or one of its parents
428
+ */
429
+ WYMeditor.editor.prototype.toggleClass = function(sClass, jqexpr) {
430
+
431
+ var container = $((this._selected_image ? this._selected_image : this.selected(true)));
432
+ if (jqexpr != null) { container = $(container.parentsOrSelf(jqexpr)); }
433
+ container.toggleClass(sClass);
434
+ if(!container.attr(WYMeditor.CLASS)) { container.removeAttr(this._class); }
435
+
436
+ };
437
+
438
+ WYMeditor.editor.prototype.toggleClassSelector = function() {
439
+ // substring(1) to remove the . at the start
440
+ var wym = this;
441
+ var disabled = $(wym._box).find(wym._options.classUnhiddenSelector)
442
+ .hasClass(wym._options.classHiddenSelector.substring(1));
443
+ if (disabled) {
444
+ $(wym._box).find(wym._options.classUnhiddenSelector)
445
+ .removeClass(wym._options.classHiddenSelector.substring(1));
446
+
447
+ $(wym._box).find("a[name=" + WYMeditor.APPLY_CLASS +"]")
448
+ .addClass('selected').parent().addClass('activated');
449
+ } else {
450
+ $(wym._box).find(wym._options.classUnhiddenSelector)
451
+ .addClass(wym._options.classHiddenSelector.substring(1));
452
+
453
+ $(wym._box).find("a[name=" + WYMeditor.APPLY_CLASS +"]")
454
+ .removeClass('selected').parent().removeClass('activated');
455
+ }
456
+
457
+ wym.exec(WYMeditor.APPLY_CLASS);
458
+ }
459
+
460
+ /* @name removeClass
461
+ * @description Removes class on selected element, or one of its parents
462
+ */
463
+ WYMeditor.editor.prototype.removeClass = function(sClass, jqexpr) {
464
+
465
+ var container = $((this._selected_image ? this._selected_image : $(this.selected(true))));
466
+ if (jqexpr != null) { container = $(container.parentsOrSelf(jqexpr)); }
467
+ container.removeClass(sClass);
468
+
469
+ if(!container.attr(WYMeditor.CLASS)) { container.removeAttr(this._class); }
470
+
471
+ };
472
+
473
+ /* @name findUp
474
+ * @description Returns the first parent or self container, based on its type
475
+ */
476
+ WYMeditor.editor.prototype.findUp = function(node, filter) {
477
+
478
+ //filter is a string or an array of strings
479
+
480
+ if(node) {
481
+
482
+ var tagname = node.tagName.toLowerCase();
483
+
484
+ if(typeof(filter) == WYMeditor.STRING) {
485
+
486
+ while(tagname != filter && tagname != WYMeditor.BODY) {
487
+
488
+ node = node.parentNode;
489
+ tagname = node.tagName.toLowerCase();
490
+ }
491
+
492
+ } else {
493
+
494
+ var bFound = false;
495
+
496
+ while(!bFound && tagname != WYMeditor.BODY) {
497
+ for(var i = 0; i < filter.length; i++) {
498
+ if(tagname == filter[i]) {
499
+ bFound = true;
500
+ break;
501
+ }
502
+ }
503
+ if(!bFound) {
504
+ node = node.parentNode;
505
+ tagname = node.tagName.toLowerCase();
506
+ }
507
+ }
508
+ }
509
+
510
+ if(tagname != WYMeditor.BODY) {
511
+ return(node);
512
+ } else {
513
+ return(null);
514
+ }
515
+ } else {
516
+ return(null);
517
+ }
518
+ };
519
+
520
+ /* @name switchTo
521
+ * @description Switch the node's type
522
+ */
523
+ WYMeditor.editor.prototype.switchTo = function(selectionOrNode,sType) {
524
+
525
+ if (selectionOrNode.getRangeAt) {
526
+ // We have a selection object so we need to create a temporary node around it (bold is easy). This node will be replaced anyway.
527
+ this.exec(WYMeditor.BOLD);
528
+ selectionOrNode = selectionOrNode.focusNode.parentNode;
529
+ }
530
+
531
+ // we have a node.
532
+ var html = $(selectionOrNode).html();
533
+ var newNode = this._doc.createElement(sType);
534
+ var klass = $(selectionOrNode).attr('class');
535
+
536
+ // copy across the css class names.
537
+ if(typeof klass !== 'undefined'){
538
+ $.each($(selectionOrNode).attr('class').split(" "), function(index, className) {
539
+ $(newNode).addClass(className);
540
+ });
541
+ }
542
+
543
+ selectionOrNode.parentNode.replaceChild(newNode,selectionOrNode);
544
+
545
+ $(newNode).html(html);
546
+ this.setFocusToNode(newNode);
547
+
548
+ return newNode;
549
+ };
550
+
551
+ WYMeditor.editor.prototype.replaceStrings = function(sVal) {
552
+ //check if the language file has already been loaded
553
+ //if not, get it via a synchronous ajax call
554
+ var wym = this;
555
+ if(!WYMeditor.STRINGS[wym._options.lang]) {
556
+ try {
557
+ eval($.ajax({url:wym._options.langPath + wym._options.lang + '.js', async:false}).responseText);
558
+ } catch(e) {
559
+ if (WYMeditor.console) {
560
+ WYMeditor.console.error("WYMeditor: error while parsing language file.");
561
+ }
562
+ return sVal;
563
+ }
564
+ }
565
+
566
+ //replace all the strings in sVal and return it
567
+ $.each(WYMeditor.STRINGS[wym._options.lang], function(key, value) {
568
+ sVal = WYMeditor.Helper.replaceAll(sVal, wym.encloseString(key), value);
569
+ });
570
+
571
+ return(sVal);
572
+ };
573
+
574
+ WYMeditor.editor.prototype.encloseString = function(sVal) {
575
+ return(this._options.stringDelimiterLeft + sVal + this._options.stringDelimiterRight);
576
+ };
577
+
578
+ /* @name status
579
+ * @description Prints a status message
580
+ */
581
+ WYMeditor.editor.prototype.status = function(sMessage) {
582
+
583
+ //print status message
584
+ $(this._box).find(this._options.statusSelector).html(sMessage);
585
+ };
586
+
587
+ /* @name update
588
+ * @description Updates the element and textarea values
589
+ */
590
+ WYMeditor.editor.prototype.update = function() {
591
+ var wym = this;
592
+
593
+ // the replace function below makes the HTML source code easier to read when end users need to use this view.
594
+ var html = wym.xhtml().replace(/<\/([A-Za-z0-9]*)></g, function(m){
595
+ return m.split(">").join(">\n");
596
+ });
597
+
598
+ // ensure system/images calls become /system/images.
599
+ html = html.replace(/src=\"system\/images/g, 'src="/system/images');
600
+
601
+ // get rid of wym id tags that were forgotten about by replacing them with their content.
602
+ $(html).find(bad_spans='span[id|=wym], span[id=undefined]').add($(html).filter(bad_spans)).each(function(i, span) {
603
+ html_to_replace_with = wym.parser.parse($(span).html());
604
+ html_to_replace = wym.parser.parse($(span).wrap('<div />').parent().html());
605
+ if($.browser.msie) {
606
+ // converts <SPAN id=wym-1231231>foo</SPAN> to <SPAN id="wym-1231231">foo</SPAN> (note the quotes)
607
+ html_to_replace = new RegExp(html_to_replace.replace(/(\ [^\=]+\=)([^\ >]+)/, '$1"$2"'), "ig");
608
+ }
609
+ html = html.replace(html_to_replace, html_to_replace_with);
610
+ });
611
+
612
+ // get rid of id='last_paste' tags that were forgotten about.
613
+ html = html.replace(/(\ ?id=(\"|\')last\_paste(\"|\'))/igm, '');
614
+
615
+ // get rid of any temporary text-only interpolation tags we have inserted for cursor position.
616
+ html = html.replace(/[%$]+wym-[^%$]*[%$]+/igm, '');
617
+
618
+ // get rid of <br /> tag that appears when empty.
619
+ html = html.replace(/^<br\ ?\/?>$/, '')
620
+
621
+ // apply changes/
622
+ $(wym._element).val(html);
623
+ $(wym._box).find(wym._options.htmlValSelector).not('.hasfocus').val(html); //#147
624
+ };
625
+
626
+ /* @name dialog
627
+ * @description Opens a dialog box
628
+ */
629
+ WYMeditor.editor.prototype.dialog = function( dialogType ) {
630
+ var wym = this;
631
+
632
+ wym.update();
633
+ var path = this._wym._options.dialogPath + dialogType + '?wymeditor=true&' + window.location.href.match(/switch_locale=[a-z]{2}/);
634
+
635
+ wym._current_unique_stamp = wym.uniqueStamp();
636
+ // change undo or redo on cancel to true to have this happen when a user closes (cancels) a dialogue
637
+ wym._undo_on_cancel = false;
638
+ wym._redo_on_cancel = false;
639
+
640
+ var selected = this.selected();
641
+ //set to P if parent = BODY unless it's a table going in there.
642
+ if (dialogType != WYMeditor.DIALOG_TABLE) {
643
+ wym.format_block();
644
+ }
645
+
646
+ if (dialogType == WYMeditor.DIALOG_LINK && $.browser.mozilla) {
647
+ selection = wym._iframe.contentWindow.getSelection();
648
+ matches = $($(selected).html().match(new RegExp(RegExp.escape(selection.anchorNode.textContent) + "(.*)" + RegExp.escape(selection.focusNode.textContent))));
649
+ if (matches != null && matches.length > 0 && (possible_anchor_tag = matches.last()).length > 0)
650
+ {
651
+ if (((href_matches = possible_anchor_tag.get(0).match(/href="([^"]*)"/)) != null) && (href = $(href_matches).last().get(0)) != null)
652
+ {
653
+ $(wym._doc).find('a').each(function(index, possible_match)
654
+ {
655
+ if ($(possible_match).html() == selection)
656
+ {
657
+ selected = possible_match;
658
+ }
659
+ });
660
+ }
661
+ }
662
+ }
663
+
664
+ ajax_loaded_callback = function(){wym.dialog_ajax_callback(selected);};
665
+
666
+ var parent_node = wym._selected_image ? wym._selected_image.parentNode : selected;
667
+ if (typeof(parent_node) != 'undefined' && parent_node !== null) {
668
+ if (parent_node.tagName.toLowerCase() != WYMeditor.A) {
669
+ // wrap the current selection with a funky span.
670
+ if (wym._selected_image == null)
671
+ {
672
+ if (selected != null && selected.tagName.toLowerCase() != WYMeditor.A && wym._iframe.contentWindow.getSelection) {
673
+ // Fixes webkit issue where it would not paste at cursor.
674
+ selection = wym._iframe.contentWindow.getSelection();
675
+ if (selection.focusNode.insertData) {
676
+ // if you highlight backwards, it reverses the order of the anchorNode and focusNode / anchorOffset and focusOffset.
677
+ // anchorOffset is where you started the selection, focusOffset is where you ended the selection.
678
+ // So, if you highlight forwards then {anchorOffset}some text{focusOffset}
679
+ // But, if you highlight backwards then {focusOffset}some text{anchorOffset}
680
+ if (selection.anchorOffset > selection.focusOffset) {
681
+ start_node = selection.focusNode;
682
+ start = selection.focusOffset;
683
+
684
+ end_node = selection.anchorNode;
685
+ end = selection.anchorOffset;
686
+ } else {
687
+ start_node = selection.anchorNode;
688
+ start = selection.anchorOffset;
689
+
690
+ end_node = selection.focusNode;
691
+ end = selection.focusOffset;
692
+ }
693
+
694
+ // for https://github.com/resolve/refinerycms/issues/581
695
+ if (typeof (start_node.insertData) === 'undefined') {
696
+ var j = start_node.childNodes.length - 1,
697
+ tmp_start_node = start_node;
698
+
699
+ // @todo what then if function insertData is not found?
700
+ while (typeof(end_node.insertData) !== 'function' || !j) {
701
+ start_node = tmp_start_node.childNodes[j--];
702
+ }
703
+
704
+ start = 0;
705
+ }
706
+
707
+ if (typeof (end_node.insertData) === 'undefined') {
708
+ var i = end_node.childNodes.length - 1,
709
+ tmp_end_node = end_node;
710
+ while (typeof(end_node.insertData) !== 'function' || !i) {
711
+ end_node = tmp_end_node.childNodes[i--];
712
+ }
713
+
714
+ end = end_node.length;
715
+ }
716
+
717
+ // because .insertData only inserts text, we have to insert some 'meaningful' *text* only interpolation tags (no html).
718
+ start_tag = '%%' + wym._current_unique_stamp + '%%';
719
+ end_tag = '$$' + wym._current_unique_stamp + '$$';
720
+
721
+ // sometimes we may be crossing multiple "nodes" so a simple test for whether this is the case.
722
+ // this is important, see this example:
723
+ // some text <a href='/'>with some link</a> and then more text
724
+ // {start_node}some text {end_start_node}{anotherNode}<a href='/'>with some link</a>{end_anotherNode}{end_node} and then more text{end_end_node}
725
+ // the "start_node" is a separate node to the end node and therefore we can't treat them as one long node anymore.
726
+ if (start_node === end_node) {
727
+ end = end + start_tag.length;
728
+ }
729
+
730
+ // Insert the 'meaningful' text interpolation tags.
731
+ start_node.insertData(start, start_tag);
732
+ end_node.insertData(end, end_tag);
733
+
734
+ // Now that we can use HTML again, replace the simple text with a span tag.
735
+ $(selected).html($(selected).html().replace(start_tag, "<span id='" + wym._current_unique_stamp + "'>")
736
+ .replace(end_tag, "</span>"));
737
+ } else {
738
+ wym.wrap("<span id='" + wym._current_unique_stamp + "'>", "</span>");
739
+ }
740
+ } else {
741
+ wym.wrap("<span id='" + wym._current_unique_stamp + "'>", "</span>");
742
+ }
743
+ }
744
+ }
745
+ else {
746
+ if (!wym._selected_image) {
747
+ parent_node._id_before_replaceable = parent_node.id;
748
+ parent_node.id = '' + this._current_unique_stamp;
749
+ $(parent_node).attr("_id_before_replaceable", parent_node._id_before_replaceable);
750
+ }
751
+
752
+ if (dialogType != WYMeditor.DIALOG_PASTE && dialogType != WYMeditor.DIALOG_TABLE) {
753
+ path += path.indexOf("?") == -1 ? "?" : "&";
754
+ port = (window.location.port.length > 0 ? (":" + window.location.port) : "");
755
+ path += "current_link=" + parent_node.href.replace(window.location.protocol + "//" + window.location.hostname + port, "");
756
+ path += "&target_blank=" + (parent_node.target == "_blank" ? "true" : "false");
757
+ }
758
+ }
759
+ }
760
+
761
+ // launch dialog
762
+ dialog_title = wym.replaceStrings(wym.encloseString( dialogType ));
763
+ dialog_container = $("<div id='" + wym._options.dialogId + "' class='editor_dialog'></div>");
764
+ switch(dialogType) {
765
+ case WYMeditor.DIALOG_TABLE:
766
+ // create and open dialog
767
+ dialog_container.html(wym.replaceStrings(wym._options.dialogTableHtml))
768
+ .dialog($.extend(wym._options.dialogInlineFeatures, {
769
+ title: dialog_title
770
+ }));
771
+
772
+ ajax_loaded_callback();
773
+ break;
774
+ case WYMeditor.DIALOG_PASTE:
775
+ dialog_container.html(wym.replaceStrings(wym._options.dialogPasteHtml))
776
+ .dialog($.extend(wym._options.dialogInlineFeatures, {
777
+ title: dialog_title
778
+ }));
779
+
780
+ ajax_loaded_callback();
781
+ break;
782
+ default:
783
+ $("<img id='dialog_loading' src='/assets/refinery/dialogLoadingAnimation.gif' width='208' height='13' />").appendTo(dialog_container);
784
+ dialog_container.dialog($.extend(wym._options.dialogFeatures, {
785
+ title: dialog_title
786
+ })).load(path, ajax_loaded_callback);
787
+ break;
788
+ }
789
+
790
+ };
791
+
792
+ WYMeditor.editor.prototype.dialog_ajax_callback = function(selected) {
793
+
794
+ // set variables
795
+ wym = this; _selected = selected;
796
+ // now fix the height;
797
+ $("#" + wym._options.dialogId + ".editor_dialog").css('height', 'auto');
798
+
799
+ // add corners to the buttons.
800
+ $('#' + wym._options.dialogId + " .button").corner('6px');
801
+
802
+ // look for iframes
803
+ (iframes = $("#" + this._options.dialogId).find('iframe')).load(function() {
804
+ WYMeditor.INIT_DIALOG(wym, _selected, true);
805
+ $(this).unbind('load');
806
+ });
807
+
808
+ if (iframes.length == 0) {
809
+ WYMeditor.INIT_DIALOG(this, selected);
810
+ }
811
+ };
812
+
813
+ /* @name toggleHtml
814
+ * @description Shows/Hides the HTML
815
+ */
816
+ WYMeditor.editor.prototype.toggleHtml = function() {
817
+ $(this._box).find(this._options.htmlSelector).toggle();
818
+ };
819
+
820
+ WYMeditor.editor.prototype.uniqueStamp = function() {
821
+ return("wym-" + new Date().getTime());
822
+ };
823
+
824
+ WYMeditor.editor.prototype.paste = function(sData) {
825
+ wym = this;
826
+
827
+ wym.format_block();
828
+
829
+ var sTmp;
830
+ replaceable = $(wym._doc.body).find('#' + wym._current_unique_stamp);
831
+
832
+ // replaceable doesn't actually get replaced here, it's just used as a marker for where the cursor was.
833
+ container = replaceable.get(0) || this.selected();
834
+
835
+ //split the data, using double newlines as the separator
836
+ var aP = sData.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").split(wym._newLine + wym._newLine);
837
+ var rExp = new RegExp(wym._newLine, "g");
838
+
839
+ //add a P for each item
840
+ if(container && container.tagName.toLowerCase() != WYMeditor.BODY) {
841
+ contentAfterBreak = "";
842
+ insertedContentAfterBreak = "";
843
+ for(x = aP.length - 1; x >= 0; x--) {
844
+ //simple newlines are replaced by a break
845
+ sTmp = aP[x].replace(rExp, "<br />");
846
+ if (x == 0) {
847
+ // if we're inside a p tag but the container is not a p tag
848
+ // then we need to close the p tag first before starting a new one.
849
+ // Only if we placed more items after it (aP.length)
850
+ if (aP.length > 1
851
+ && $(container).get(0).tagName.toLowerCase() == "span"
852
+ && $(container).attr('id') == ('' + wym._current_unique_stamp)
853
+ && $(container).parent().get(0).tagName.toLowerCase() == "p")
854
+ {
855
+ p = $(container).parent();
856
+ matches = p.html().match(new RegExp("([\\s\\S]*)\<span id=[\'|\"]" + wym._current_unique_stamp + "[\'|\"]\>.*\<\/span\>"));
857
+ sTmp = matches[1] + sTmp + $(container).html();
858
+ p.html(sTmp);
859
+ if (insertedContentAfterBreak != null && insertedContentAfterBreak.length > 0) {
860
+ p.after(insertedContentAfterBreak);
861
+ }
862
+ if (contentAfterBreak != null && contentAfterBreak.length > 0) {
863
+ if ((last_paste = p.parent().find('p#last_paste')).length == 1) {
864
+ last_paste.attr('id', null).html(last_paste.html() + contentAfterBreak);
865
+ } else {
866
+ p.next().after("<p>" + contentAfterBreak + "</p>");
867
+ }
868
+ }
869
+
870
+ } else {
871
+ $(container).html($(container).html().replace(/^<br\/?>$/, '') + sTmp);
872
+ }
873
+ } else {
874
+ if ((aP.length -1) == x) {
875
+ var rgx = $(container).parent().html().match(new RegExp("\<span id=[\'|\"]" + wym._current_unique_stamp + "[\'|\"]\>.*\<\/span\>([\\s\\S]*)"));
876
+ if(rgx && rgx[1]){
877
+ contentAfterBreak = rgx[1].split('</p>')[0];
878
+ }
879
+ sTmp = "<p id='last_paste'>" + sTmp + "</p>";
880
+ } else {
881
+ sTmp = "<p>" + sTmp + "</p>";
882
+ }
883
+
884
+ if (insertedContentAfterBreak == "") {
885
+ insertedContentAfterBreak = insertedContentAfterBreak + sTmp;
886
+ } else {
887
+ insertedContentAfterBreak = sTmp + insertedContentAfterBreak;
888
+ }
889
+ }
890
+ }
891
+ } else {
892
+ for(x = 0; x < aP.length; x++) {
893
+ sTmp = aP[x];
894
+ //simple newlines are replaced by a break
895
+ sTmp = sTmp.replace(rExp, "<br />");
896
+ if (x == 0 && $(container).html().replace(/<br\ ?\/?>/, "").length == 0) {
897
+ $(container).html(sTmp);
898
+ } else {
899
+ $(wym._doc.body).append("<p>" + sTmp + "</p>");
900
+ }
901
+ }
902
+ }
903
+
904
+ if (replaceable.get(0) != null) {
905
+ // set the id of the container back.
906
+ if (replaceable.get(0).tagName.toLowerCase() == 'span') {
907
+ replaceable.replaceWith(replaceable.html());
908
+ }
909
+ replaceable.attr('id', replaceable.get(0)._id_before_replaceable || null);
910
+ }
911
+ };
912
+
913
+ WYMeditor.editor.prototype.insert = function(html) {
914
+ // Do we have a selection?
915
+ if (this._iframe.contentWindow.getSelection().focusNode != null) {
916
+ // Overwrite selection with provided html
917
+ this._exec(WYMeditor.INSERT_HTML, html);
918
+ } else {
919
+ // Fall back to the internal paste function if there's no selection
920
+ this.paste(html);
921
+ }
922
+ };
923
+
924
+ WYMeditor.editor.prototype.wrap = function(left, right, selection) {
925
+ left = (typeof(left) != 'undefined' ? left : '');
926
+ right = (typeof(right) != 'undefined' ? right : '');
927
+
928
+ // Do we have a selection?
929
+ if (selection == null) { selection = this._iframe.contentWindow.getSelection();}
930
+ if (selection.focusNode != null) {
931
+ // Wrap selection with provided html
932
+ this._exec( WYMeditor.INSERT_HTML, left + selection.toString() + right);
933
+ }
934
+ };
935
+
936
+ WYMeditor.editor.prototype.unwrap = function(selection) {
937
+ // Do we have a selection?
938
+ if (selection == null) { selection = this._iframe.contentWindow.getSelection();}
939
+ if (selection.focusNode != null) {
940
+ // Unwrap selection
941
+ this._exec( WYMeditor.INSERT_HTML, selection.toString() );
942
+ }
943
+ };
944
+
945
+ WYMeditor.editor.prototype.setFocusToNode = function(node, toStart) {
946
+ var range = this._doc.createRange(),
947
+ selection = this._iframe.contentWindow.getSelection();
948
+ toStart = toStart ? 0 : 1;
949
+
950
+ range.selectNodeContents(node);
951
+ selection.addRange(range);
952
+ selection.collapse(node, toStart);
953
+ this._iframe.contentWindow.focus();
954
+ };
955
+
956
+ WYMeditor.editor.prototype.addCssRules = function(doc, aCss) {
957
+ var styles = doc.styleSheets[0];
958
+ if(styles) {
959
+ for(var i = 0; i < aCss.length; i++) {
960
+ var oCss = aCss[i];
961
+ if(oCss.name && oCss.css) { this.addCssRule(styles, oCss); }
962
+ }
963
+ }
964
+ };
965
+
966
+ WYMeditor.editor.prototype.format_block = function(selected) {
967
+
968
+ //'this' should be the wymeditor instance.
969
+ var wym = this;
970
+ var container = selected || wym.selected() || $(wym._iframe).contents().find('body').get(0);
971
+ var name = container.tagName.toLowerCase();
972
+
973
+ //fix forbidden main containers
974
+ if($.inArray(name, ['strong', 'b', 'em', 'i', 'sub', 'sup', 'a']) > -1) {
975
+ name = container.parentNode.tagName.toLowerCase();
976
+ }
977
+
978
+ if(name == WYMeditor.BODY) {
979
+ wym._selected_image = null;
980
+ $(wym._iframe).contents().find('.selected_by_wym').removeClass('selected_by_wym');
981
+ wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P);
982
+ }
983
+ };
984
+
985
+ /********** CONFIGURATION **********/
986
+
987
+ WYMeditor.editor.prototype.computeBasePath = function() {
988
+ if ((script_path = this.computeWymPath()) != null) {
989
+ if ((src_parts = script_path.split('/')).length > 1) { src_parts.pop(); }
990
+ return src_parts.join('/') + "/";
991
+ }
992
+ else {
993
+ return null;
994
+ }
995
+ };
996
+
997
+ WYMeditor.editor.prototype.computeWymPath = function() {
998
+ return $('script[src*=jquery.refinery.wymeditor]').attr('src');
999
+ };
1000
+
1001
+ WYMeditor.editor.prototype.computeJqueryPath = function() {
1002
+ return $($.grep($('script'), function(s){
1003
+ return (s.src && s.src.match(/jquery(-(.*)){0,1}(\.pack|\.min|\.packed)?\.js(\?.*)?$/ ))
1004
+ })).attr('src');
1005
+ };
1006
+
1007
+ WYMeditor.editor.prototype.computeCssPath = function() {
1008
+ return $($.grep($('link'), function(s){
1009
+ return (s.href && s.href.match(/wymeditor\/skins\/(.*)screen\.css(\?.*)?$/ ))
1010
+ })).attr('href');
1011
+ };
1012
+
1013
+ WYMeditor.editor.prototype.configureEditorUsingRawCss = function() {
1014
+
1015
+ var CssParser = new WYMeditor.WymCssParser();
1016
+ if(this._options.stylesheet){
1017
+ CssParser.parse($.ajax({url: this._options.stylesheet,async:false}).responseText);
1018
+ }else{
1019
+ CssParser.parse(this._options.styles, false);
1020
+ }
1021
+
1022
+ if(this._options.classesItems.length == 0) {
1023
+ this._options.classesItems = CssParser.css_settings.classesItems;
1024
+ }
1025
+ if(this._options.editorStyles.length == 0) {
1026
+ this._options.editorStyles = CssParser.css_settings.editorStyles;
1027
+ }
1028
+ if(this._options.dialogStyles.length == 0) {
1029
+ this._options.dialogStyles = CssParser.css_settings.dialogStyles;
1030
+ }
1031
+ };
1032
+
1033
+ /********** EVENTS **********/
1034
+
1035
+ WYMeditor.editor.prototype.listen = function() {
1036
+
1037
+ //don't use $.find() on the iframe body
1038
+ //because of MSIE + jQuery + expando issue (#JQ1143)
1039
+ //$(this._doc.body).find("*").bind("mouseup", this.mouseup);
1040
+
1041
+ $(this._doc.body).bind("mousedown", this.mousedown);
1042
+ var images = this._doc.body.getElementsByTagName("img");
1043
+ for(var i=0; i < images.length; i++) {
1044
+ $(images[i]).bind("mousedown", this.mousedown);
1045
+ }
1046
+
1047
+ // ensure links can't be navigated to.
1048
+ $(this._doc).find('a[href]').click(function(e){
1049
+ e.preventDefault();
1050
+ });
1051
+ };
1052
+
1053
+ WYMeditor.editor.prototype.mousedown = function(e) {
1054
+
1055
+ var wym = WYMeditor.INSTANCES[this.ownerDocument.title];
1056
+
1057
+ wym._selected_image = (e.target.tagName.toLowerCase() == WYMeditor.IMG) ? e.target : null;
1058
+ $(wym._iframe).contents().find('.selected_by_wym').removeClass('selected_by_wym');
1059
+ if (!$.browser.mozilla) { $(wym._selected_image).addClass('selected_by_wym'); }
1060
+ if (!$.browser.webkit) { e.stopPropagation(); }
1061
+ };
1062
+
1063
+ /********** SKINS **********/
1064
+
1065
+ /*
1066
+ * Function: WYMeditor.editor.loadSkin
1067
+ * Loads the skin CSS and initialization script (if needed).
1068
+ */
1069
+ WYMeditor.editor.prototype.loadSkin = function() {
1070
+
1071
+ //does the user want to automatically load the CSS (default: yes)?
1072
+ //we also test if it hasn't been already loaded by another instance
1073
+ //see below for a better (second) test
1074
+ if(this._options.loadSkin && !WYMeditor.SKINS[this._options.skin]) {
1075
+ //check if it hasn't been already loaded
1076
+ //so we don't load it more than once
1077
+ //(we check the existing <link> elements)
1078
+
1079
+ var found = false;
1080
+ var rExp = new RegExp(this._options.skin + '\/' + WYMeditor.SKINS_DEFAULT_CSS + '([\?].+?)?$');
1081
+
1082
+ $('link').each( function() {
1083
+ if(this.href.match(rExp)) found = true;
1084
+ });
1085
+
1086
+ // if not found, load it, using the skin path
1087
+ if(!found) {
1088
+ WYMeditor.loadCss( this._options.cssCompiledSkinPath + WYMeditor.SKINS_DEFAULT_CSS );
1089
+ }
1090
+ }
1091
+
1092
+ //put the classname (ex. wym_skin_default) on wym_box
1093
+ $(this._box).addClass( "wym_skin_" + this._options.skin );
1094
+
1095
+ //does the user want to use some JS to initialize the skin (default: yes)?
1096
+ //also check if it hasn't already been loaded by another instance
1097
+ if(this._options.initSkin && !WYMeditor.SKINS[this._options.skin]) {
1098
+ eval($.ajax({url:this._options.jsCompiledSkinPath + WYMeditor.SKINS_DEFAULT_JS, async:false}).responseText);
1099
+ }
1100
+
1101
+ //init the skin, if needed
1102
+ if(WYMeditor.SKINS[this._options.skin] && WYMeditor.SKINS[this._options.skin].init) {
1103
+ WYMeditor.SKINS[this._options.skin].init(this);
1104
+ }
1105
+
1106
+ };