spree_static_content 0.30.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. data/README.rdoc +2 -1
  2. data/Rakefile +2 -1
  3. data/VERSION +1 -1
  4. data/app/views/admin/pages/_form.html.erb +5 -29
  5. data/app/views/admin/pages/edit.html.erb +1 -1
  6. data/app/views/admin/pages/new.html.erb +1 -1
  7. data/config/locales/{ru-RU.yml → ru.yml} +2 -1
  8. data/spree_static_content.gemspec +9 -68
  9. metadata +17 -68
  10. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-blockquote.png +0 -0
  11. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-h1.png +0 -0
  12. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-h2.png +0 -0
  13. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-h3.png +0 -0
  14. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-h4.png +0 -0
  15. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-h5.png +0 -0
  16. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-h6.png +0 -0
  17. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-p.png +0 -0
  18. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/lbl-pre.png +0 -0
  19. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/wymiframe.css +0 -90
  20. data/lib/generators/templates/public/javascripts/wymeditor/iframe/default/wymiframe.html +0 -25
  21. data/lib/generators/templates/public/javascripts/wymeditor/jquery.wymeditor.js +0 -4676
  22. data/lib/generators/templates/public/javascripts/wymeditor/jquery.wymeditor.pack.js +0 -1
  23. data/lib/generators/templates/public/javascripts/wymeditor/lang/ca.js +0 -45
  24. data/lib/generators/templates/public/javascripts/wymeditor/lang/cs.js +0 -45
  25. data/lib/generators/templates/public/javascripts/wymeditor/lang/de.js +0 -45
  26. data/lib/generators/templates/public/javascripts/wymeditor/lang/en.js +0 -45
  27. data/lib/generators/templates/public/javascripts/wymeditor/lang/es.js +0 -45
  28. data/lib/generators/templates/public/javascripts/wymeditor/lang/fa.js +0 -46
  29. data/lib/generators/templates/public/javascripts/wymeditor/lang/fr.js +0 -45
  30. data/lib/generators/templates/public/javascripts/wymeditor/lang/he.js +0 -45
  31. data/lib/generators/templates/public/javascripts/wymeditor/lang/hu.js +0 -45
  32. data/lib/generators/templates/public/javascripts/wymeditor/lang/it.js +0 -45
  33. data/lib/generators/templates/public/javascripts/wymeditor/lang/nb.js +0 -45
  34. data/lib/generators/templates/public/javascripts/wymeditor/lang/nl.js +0 -45
  35. data/lib/generators/templates/public/javascripts/wymeditor/lang/nn.js +0 -45
  36. data/lib/generators/templates/public/javascripts/wymeditor/lang/pl.js +0 -45
  37. data/lib/generators/templates/public/javascripts/wymeditor/lang/pt-br.js +0 -45
  38. data/lib/generators/templates/public/javascripts/wymeditor/lang/pt.js +0 -45
  39. data/lib/generators/templates/public/javascripts/wymeditor/lang/ru.js +0 -45
  40. data/lib/generators/templates/public/javascripts/wymeditor/lang/sv.js +0 -45
  41. data/lib/generators/templates/public/javascripts/wymeditor/lang/tr.js +0 -45
  42. data/lib/generators/templates/public/javascripts/wymeditor/lang/zh_cn.js +0 -47
  43. data/lib/generators/templates/public/javascripts/wymeditor/plugins/hovertools/jquery.wymeditor.hovertools.js +0 -57
  44. data/lib/generators/templates/public/javascripts/wymeditor/plugins/resizable/jquery.wymeditor.resizable.js +0 -102
  45. data/lib/generators/templates/public/javascripts/wymeditor/plugins/resizable/readme.txt +0 -124
  46. data/lib/generators/templates/public/javascripts/wymeditor/plugins/tidy/README +0 -19
  47. data/lib/generators/templates/public/javascripts/wymeditor/plugins/tidy/jquery.wymeditor.tidy.js +0 -82
  48. data/lib/generators/templates/public/javascripts/wymeditor/plugins/tidy/tidy.php +0 -36
  49. data/lib/generators/templates/public/javascripts/wymeditor/plugins/tidy/wand.png +0 -0
  50. data/lib/generators/templates/public/javascripts/wymeditor/skins/default/icons.png +0 -0
  51. data/lib/generators/templates/public/javascripts/wymeditor/skins/default/skin.css +0 -133
  52. data/lib/generators/templates/public/javascripts/wymeditor/skins/default/skin.js +0 -40
  53. data/lib/generators/templates/public/javascripts/wymeditor/skins/minimal/images/bg.header.gif +0 -0
  54. data/lib/generators/templates/public/javascripts/wymeditor/skins/minimal/images/bg.selector.silver.gif +0 -0
  55. data/lib/generators/templates/public/javascripts/wymeditor/skins/minimal/images/bg.wymeditor.png +0 -0
  56. data/lib/generators/templates/public/javascripts/wymeditor/skins/minimal/images/icons.silver.gif +0 -0
  57. data/lib/generators/templates/public/javascripts/wymeditor/skins/minimal/skin.css +0 -131
  58. data/lib/generators/templates/public/javascripts/wymeditor/skins/minimal/skin.js +0 -30
  59. data/lib/generators/templates/public/javascripts/wymeditor/skins/silver/COPYING +0 -674
  60. data/lib/generators/templates/public/javascripts/wymeditor/skins/silver/README +0 -27
  61. data/lib/generators/templates/public/javascripts/wymeditor/skins/silver/images/bg.header.gif +0 -0
  62. data/lib/generators/templates/public/javascripts/wymeditor/skins/silver/images/bg.selector.silver.gif +0 -0
  63. data/lib/generators/templates/public/javascripts/wymeditor/skins/silver/images/bg.wymeditor.png +0 -0
  64. data/lib/generators/templates/public/javascripts/wymeditor/skins/silver/images/icons.silver.gif +0 -0
  65. data/lib/generators/templates/public/javascripts/wymeditor/skins/silver/skin.css +0 -297
  66. data/lib/generators/templates/public/javascripts/wymeditor/skins/silver/skin.js +0 -61
  67. data/lib/generators/templates/public/javascripts/wymeditor/skins/twopanels/icons.png +0 -0
  68. data/lib/generators/templates/public/javascripts/wymeditor/skins/twopanels/skin.css +0 -134
  69. data/lib/generators/templates/public/javascripts/wymeditor/skins/twopanels/skin.js +0 -39
  70. data/lib/generators/templates/public/javascripts/wymeditor/skins/wymeditor_icon.png +0 -0
  71. data/lib/generators/templates/public/stylesheets/static.css +0 -42
@@ -1,4676 +0,0 @@
1
- /*
2
- * WYMeditor : what you see is What You Mean web-based editor
3
- * Copyright (c) 2008 Jean-Francois Hovinne, http://www.wymeditor.org/
4
- * Dual licensed under the MIT (MIT-license.txt)
5
- * and GPL (GPL-license.txt) licenses.
6
- *
7
- * For further information visit:
8
- * http://www.wymeditor.org/
9
- *
10
- * File: jquery.wymeditor.js
11
- *
12
- * Main JS file with core classes and functions.
13
- * See the documentation for more info.
14
- *
15
- * About: authors
16
- *
17
- * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg)
18
- * Volker Mische (vmx a-t gmx dotde)
19
- * Scott Lewis (lewiscot a-t gmail dotcom)
20
- * Bermi Ferrer (wymeditor a-t bermi dotorg)
21
- * Daniel Reszka (d.reszka a-t wymeditor dotorg)
22
- * Jonatan Lundin (jonatan.lundin _at_ gmail.com)
23
- */
24
-
25
- /*
26
- Namespace: WYMeditor
27
- Global WYMeditor namespace.
28
- */
29
- if(!WYMeditor) var WYMeditor = {};
30
-
31
- //Wrap the Firebug console in WYMeditor.console
32
- (function() {
33
- if ( !window.console || !console.firebug ) {
34
- var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
35
- "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
36
-
37
- WYMeditor.console = {};
38
- for (var i = 0; i < names.length; ++i)
39
- WYMeditor.console[names[i]] = function() {}
40
-
41
- } else WYMeditor.console = window.console;
42
- })();
43
-
44
- jQuery.extend(WYMeditor, {
45
-
46
- /*
47
- Constants: Global WYMeditor constants.
48
-
49
- VERSION - Defines WYMeditor version.
50
- INSTANCES - An array of loaded WYMeditor.editor instances.
51
- STRINGS - An array of loaded WYMeditor language pairs/values.
52
- SKINS - An array of loaded WYMeditor skins.
53
- NAME - The "name" attribute.
54
- INDEX - A string replaced by the instance index.
55
- WYM_INDEX - A string used to get/set the instance index.
56
- BASE_PATH - A string replaced by WYMeditor's base path.
57
- SKIN_PATH - A string replaced by WYMeditor's skin path.
58
- WYM_PATH - A string replaced by WYMeditor's main JS file path.
59
- SKINS_DEFAULT_PATH - The skins default base path.
60
- SKINS_DEFAULT_CSS - The skins default CSS file.
61
- LANG_DEFAULT_PATH - The language files default path.
62
- IFRAME_BASE_PATH - A string replaced by the designmode iframe's base path.
63
- IFRAME_DEFAULT - The iframe's default base path.
64
- JQUERY_PATH - A string replaced by the computed jQuery path.
65
- DIRECTION - A string replaced by the text direction (rtl or ltr).
66
- LOGO - A string replaced by WYMeditor logo.
67
- TOOLS - A string replaced by the toolbar's HTML.
68
- TOOLS_ITEMS - A string replaced by the toolbar items.
69
- TOOL_NAME - A string replaced by a toolbar item's name.
70
- TOOL_TITLE - A string replaced by a toolbar item's title.
71
- TOOL_CLASS - A string replaced by a toolbar item's class.
72
- CLASSES - A string replaced by the classes panel's HTML.
73
- CLASSES_ITEMS - A string replaced by the classes items.
74
- CLASS_NAME - A string replaced by a class item's name.
75
- CLASS_TITLE - A string replaced by a class item's title.
76
- CONTAINERS - A string replaced by the containers panel's HTML.
77
- CONTAINERS_ITEMS - A string replaced by the containers items.
78
- CONTAINER_NAME - A string replaced by a container item's name.
79
- CONTAINER_TITLE - A string replaced by a container item's title.
80
- CONTAINER_CLASS - A string replaced by a container item's class.
81
- HTML - A string replaced by the HTML view panel's HTML.
82
- IFRAME - A string replaced by the designmode iframe.
83
- STATUS - A string replaced by the status panel's HTML.
84
- DIALOG_TITLE - A string replaced by a dialog's title.
85
- DIALOG_BODY - A string replaced by a dialog's HTML body.
86
- BODY - The BODY element.
87
- STRING - The "string" type.
88
- BODY,DIV,P,
89
- H1,H2,H3,H4,H5,H6,
90
- PRE,BLOCKQUOTE,
91
- A,BR,IMG,
92
- TABLE,TD,TH,
93
- UL,OL,LI - HTML elements string representation.
94
- CLASS,HREF,SRC,
95
- TITLE,ALT - HTML attributes string representation.
96
- DIALOG_LINK - A link dialog type.
97
- DIALOG_IMAGE - An image dialog type.
98
- DIALOG_TABLE - A table dialog type.
99
- DIALOG_PASTE - A 'Paste from Word' dialog type.
100
- BOLD - Command: (un)set selection to <strong>.
101
- ITALIC - Command: (un)set selection to <em>.
102
- CREATE_LINK - Command: open the link dialog or (un)set link.
103
- INSERT_IMAGE - Command: open the image dialog or insert an image.
104
- INSERT_TABLE - Command: open the table dialog.
105
- PASTE - Command: open the paste dialog.
106
- INDENT - Command: nest a list item.
107
- OUTDENT - Command: unnest a list item.
108
- TOGGLE_HTML - Command: display/hide the HTML view.
109
- FORMAT_BLOCK - Command: set a block element to another type.
110
- PREVIEW - Command: open the preview dialog.
111
- UNLINK - Command: unset a link.
112
- INSERT_UNORDEREDLIST- Command: insert an unordered list.
113
- INSERT_ORDEREDLIST - Command: insert an ordered list.
114
- MAIN_CONTAINERS - An array of the main HTML containers used in WYMeditor.
115
- BLOCKS - An array of the HTML block elements.
116
- KEY - Standard key codes.
117
- NODE - Node types.
118
-
119
- */
120
-
121
- VERSION : "0.5-b2",
122
- INSTANCES : [],
123
- STRINGS : [],
124
- SKINS : [],
125
- NAME : "name",
126
- INDEX : "{Wym_Index}",
127
- WYM_INDEX : "wym_index",
128
- BASE_PATH : "{Wym_Base_Path}",
129
- CSS_PATH : "{Wym_Css_Path}",
130
- WYM_PATH : "{Wym_Wym_Path}",
131
- SKINS_DEFAULT_PATH : "skins/",
132
- SKINS_DEFAULT_CSS : "skin.css",
133
- SKINS_DEFAULT_JS : "skin.js",
134
- LANG_DEFAULT_PATH : "lang/",
135
- IFRAME_BASE_PATH : "{Wym_Iframe_Base_Path}",
136
- IFRAME_DEFAULT : "iframe/default/",
137
- JQUERY_PATH : "{Wym_Jquery_Path}",
138
- DIRECTION : "{Wym_Direction}",
139
- LOGO : "{Wym_Logo}",
140
- TOOLS : "{Wym_Tools}",
141
- TOOLS_ITEMS : "{Wym_Tools_Items}",
142
- TOOL_NAME : "{Wym_Tool_Name}",
143
- TOOL_TITLE : "{Wym_Tool_Title}",
144
- TOOL_CLASS : "{Wym_Tool_Class}",
145
- CLASSES : "{Wym_Classes}",
146
- CLASSES_ITEMS : "{Wym_Classes_Items}",
147
- CLASS_NAME : "{Wym_Class_Name}",
148
- CLASS_TITLE : "{Wym_Class_Title}",
149
- CONTAINERS : "{Wym_Containers}",
150
- CONTAINERS_ITEMS : "{Wym_Containers_Items}",
151
- CONTAINER_NAME : "{Wym_Container_Name}",
152
- CONTAINER_TITLE : "{Wym_Containers_Title}",
153
- CONTAINER_CLASS : "{Wym_Container_Class}",
154
- HTML : "{Wym_Html}",
155
- IFRAME : "{Wym_Iframe}",
156
- STATUS : "{Wym_Status}",
157
- DIALOG_TITLE : "{Wym_Dialog_Title}",
158
- DIALOG_BODY : "{Wym_Dialog_Body}",
159
- STRING : "string",
160
- BODY : "body",
161
- DIV : "div",
162
- P : "p",
163
- H1 : "h1",
164
- H2 : "h2",
165
- H3 : "h3",
166
- H4 : "h4",
167
- H5 : "h5",
168
- H6 : "h6",
169
- PRE : "pre",
170
- BLOCKQUOTE : "blockquote",
171
- A : "a",
172
- BR : "br",
173
- IMG : "img",
174
- TABLE : "table",
175
- TD : "td",
176
- TH : "th",
177
- UL : "ul",
178
- OL : "ol",
179
- LI : "li",
180
- CLASS : "class",
181
- HREF : "href",
182
- SRC : "src",
183
- TITLE : "title",
184
- ALT : "alt",
185
- DIALOG_LINK : "Link",
186
- DIALOG_IMAGE : "Image",
187
- DIALOG_TABLE : "Table",
188
- DIALOG_PASTE : "Paste_From_Word",
189
- BOLD : "Bold",
190
- ITALIC : "Italic",
191
- CREATE_LINK : "CreateLink",
192
- INSERT_IMAGE : "InsertImage",
193
- INSERT_TABLE : "InsertTable",
194
- INSERT_HTML : "InsertHTML",
195
- PASTE : "Paste",
196
- INDENT : "Indent",
197
- OUTDENT : "Outdent",
198
- TOGGLE_HTML : "ToggleHtml",
199
- FORMAT_BLOCK : "FormatBlock",
200
- PREVIEW : "Preview",
201
-
202
- UNLINK : "Unlink",
203
- INSERT_UNORDEREDLIST : "InsertUnorderedList",
204
- INSERT_ORDEREDLIST : "InsertOrderedList",
205
-
206
- MAIN_CONTAINERS : new Array("p","h1","h2","h3","h4","h5","h6","pre","blockquote"),
207
-
208
- BLOCKS : new Array("address", "blockquote", "div", "dl",
209
- "fieldset", "form", "h1", "h2", "h3", "h4", "h5", "h6", "hr",
210
- "noscript", "ol", "p", "pre", "table", "ul", "dd", "dt",
211
- "li", "tbody", "td", "tfoot", "th", "thead", "tr"),
212
-
213
- KEY : {
214
- BACKSPACE: 8,
215
- ENTER: 13,
216
- END: 35,
217
- HOME: 36,
218
- LEFT: 37,
219
- UP: 38,
220
- RIGHT: 39,
221
- DOWN: 40,
222
- CURSOR: new Array(37, 38, 39, 40),
223
- DELETE: 46
224
- },
225
-
226
- NODE : {
227
- ELEMENT: 1,
228
- ATTRIBUTE: 2,
229
- TEXT: 3
230
- },
231
-
232
- /*
233
- Class: WYMeditor.editor
234
- WYMeditor editor main class, instanciated for each editor occurrence.
235
- */
236
-
237
- editor : function(elem, options) {
238
-
239
- /*
240
- Constructor: WYMeditor.editor
241
-
242
- Initializes main values (index, elements, paths, ...)
243
- and call WYMeditor.editor.init which initializes the editor.
244
-
245
- Parameters:
246
-
247
- elem - The HTML element to be replaced by the editor.
248
- options - The hash of options.
249
-
250
- Returns:
251
-
252
- Nothing.
253
-
254
- See Also:
255
-
256
- <WYMeditor.editor.init>
257
- */
258
-
259
- //store the instance in the INSTANCES array and store the index
260
- this._index = WYMeditor.INSTANCES.push(this) - 1;
261
- //store the element replaced by the editor
262
- this._element = elem;
263
- //store the options
264
- this._options = options;
265
- //store the element's inner value
266
- this._html = jQuery(elem).val();
267
-
268
- //store the HTML option, if any
269
- if(this._options.html) this._html = this._options.html;
270
- //get or compute the base path (where the main JS file is located)
271
- this._options.basePath = this._options.basePath
272
- || this.computeBasePath();
273
- //get or set the skin path (where the skin files are located)
274
- this._options.skinPath = this._options.skinPath
275
- || this._options.basePath + WYMeditor.SKINS_DEFAULT_PATH
276
- + this._options.skin + '/';
277
- //get or compute the main JS file location
278
- this._options.wymPath = this._options.wymPath
279
- || this.computeWymPath();
280
- //get or set the language files path
281
- this._options.langPath = this._options.langPath
282
- || this._options.basePath + WYMeditor.LANG_DEFAULT_PATH;
283
- //get or set the designmode iframe's base path
284
- this._options.iframeBasePath = this._options.iframeBasePath
285
- || this._options.basePath + WYMeditor.IFRAME_DEFAULT;
286
- //get or compute the jQuery JS file location
287
- this._options.jQueryPath = this._options.jQueryPath
288
- || this.computeJqueryPath();
289
-
290
- //initialize the editor instance
291
- this.init();
292
-
293
- }
294
-
295
- });
296
-
297
-
298
- /********** JQUERY **********/
299
-
300
- /**
301
- * Replace an HTML element by WYMeditor
302
- *
303
- * @example jQuery(".wymeditor").wymeditor(
304
- * {
305
- *
306
- * }
307
- * );
308
- * @desc Example description here
309
- *
310
- * @name WYMeditor
311
- * @description WYMeditor is a web-based WYSIWYM XHTML editor
312
- * @param Hash hash A hash of parameters
313
- * @option Integer iExample Description here
314
- * @option String sExample Description here
315
- *
316
- * @type jQuery
317
- * @cat Plugins/WYMeditor
318
- * @author Jean-Francois Hovinne
319
- */
320
- jQuery.fn.wymeditor = function(options) {
321
-
322
- options = jQuery.extend({
323
-
324
- html: "",
325
-
326
- basePath: false,
327
-
328
- skinPath: false,
329
-
330
- wymPath: false,
331
-
332
- iframeBasePath: false,
333
-
334
- jQueryPath: false,
335
-
336
- styles: false,
337
-
338
- stylesheet: false,
339
-
340
- skin: "default",
341
- initSkin: true,
342
- loadSkin: true,
343
-
344
- lang: "en",
345
-
346
- direction: "ltr",
347
-
348
- boxHtml: "<div class='wym_box'>"
349
- + "<div class='wym_area_top'>"
350
- + WYMeditor.TOOLS
351
- + "</div>"
352
- + "<div class='wym_area_left'></div>"
353
- + "<div class='wym_area_right'>"
354
- + WYMeditor.CONTAINERS
355
- + WYMeditor.CLASSES
356
- + "</div>"
357
- + "<div class='wym_area_main'>"
358
- + WYMeditor.HTML
359
- + WYMeditor.IFRAME
360
- + WYMeditor.STATUS
361
- + "</div>"
362
- + "<div class='wym_area_bottom'>"
363
- + WYMeditor.LOGO
364
- + "</div>"
365
- + "</div>",
366
-
367
- logoHtml: "<a class='wym_wymeditor_link' "
368
- + "href='http://www.wymeditor.org/'>WYMeditor</a>",
369
-
370
- iframeHtml:"<div class='wym_iframe wym_section'>"
371
- + "<iframe "
372
- + "src='"
373
- + WYMeditor.IFRAME_BASE_PATH
374
- + "wymiframe.html' "
375
- + "onload='this.contentWindow.parent.WYMeditor.INSTANCES["
376
- + WYMeditor.INDEX + "].initIframe(this)'"
377
- + "></iframe>"
378
- + "</div>",
379
-
380
- editorStyles: [],
381
-
382
- toolsHtml: "<div class='wym_tools wym_section'>"
383
- + "<h2>{Tools}</h2>"
384
- + "<ul>"
385
- + WYMeditor.TOOLS_ITEMS
386
- + "</ul>"
387
- + "</div>",
388
-
389
- toolsItemHtml: "<li class='"
390
- + WYMeditor.TOOL_CLASS
391
- + "'><a href='#' name='"
392
- + WYMeditor.TOOL_NAME
393
- + "' title='"
394
- + WYMeditor.TOOL_TITLE
395
- + "'>"
396
- + WYMeditor.TOOL_TITLE
397
- + "</a></li>",
398
-
399
- toolsItems: [
400
- {'name': 'Bold', 'title': 'Strong', 'css': 'wym_tools_strong'},
401
- {'name': 'Italic', 'title': 'Emphasis', 'css': 'wym_tools_emphasis'},
402
- {'name': 'Superscript', 'title': 'Superscript',
403
- 'css': 'wym_tools_superscript'},
404
- {'name': 'Subscript', 'title': 'Subscript',
405
- 'css': 'wym_tools_subscript'},
406
- {'name': 'InsertOrderedList', 'title': 'Ordered_List',
407
- 'css': 'wym_tools_ordered_list'},
408
- {'name': 'InsertUnorderedList', 'title': 'Unordered_List',
409
- 'css': 'wym_tools_unordered_list'},
410
- {'name': 'Indent', 'title': 'Indent', 'css': 'wym_tools_indent'},
411
- {'name': 'Outdent', 'title': 'Outdent', 'css': 'wym_tools_outdent'},
412
- {'name': 'Undo', 'title': 'Undo', 'css': 'wym_tools_undo'},
413
- {'name': 'Redo', 'title': 'Redo', 'css': 'wym_tools_redo'},
414
- {'name': 'CreateLink', 'title': 'Link', 'css': 'wym_tools_link'},
415
- {'name': 'Unlink', 'title': 'Unlink', 'css': 'wym_tools_unlink'},
416
- {'name': 'InsertImage', 'title': 'Image', 'css': 'wym_tools_image'},
417
- {'name': 'InsertTable', 'title': 'Table', 'css': 'wym_tools_table'},
418
- {'name': 'Paste', 'title': 'Paste_From_Word',
419
- 'css': 'wym_tools_paste'},
420
- {'name': 'ToggleHtml', 'title': 'HTML', 'css': 'wym_tools_html'},
421
- {'name': 'Preview', 'title': 'Preview', 'css': 'wym_tools_preview'}
422
- ],
423
-
424
- containersHtml: "<div class='wym_containers wym_section'>"
425
- + "<h2>{Containers}</h2>"
426
- + "<ul>"
427
- + WYMeditor.CONTAINERS_ITEMS
428
- + "</ul>"
429
- + "</div>",
430
-
431
- containersItemHtml:"<li class='"
432
- + WYMeditor.CONTAINER_CLASS
433
- + "'>"
434
- + "<a href='#' name='"
435
- + WYMeditor.CONTAINER_NAME
436
- + "'>"
437
- + WYMeditor.CONTAINER_TITLE
438
- + "</a></li>",
439
-
440
- containersItems: [
441
- {'name': 'P', 'title': 'Paragraph', 'css': 'wym_containers_p'},
442
- {'name': 'H1', 'title': 'Heading_1', 'css': 'wym_containers_h1'},
443
- {'name': 'H2', 'title': 'Heading_2', 'css': 'wym_containers_h2'},
444
- {'name': 'H3', 'title': 'Heading_3', 'css': 'wym_containers_h3'},
445
- {'name': 'H4', 'title': 'Heading_4', 'css': 'wym_containers_h4'},
446
- {'name': 'H5', 'title': 'Heading_5', 'css': 'wym_containers_h5'},
447
- {'name': 'H6', 'title': 'Heading_6', 'css': 'wym_containers_h6'},
448
- {'name': 'PRE', 'title': 'Preformatted', 'css': 'wym_containers_pre'},
449
- {'name': 'BLOCKQUOTE', 'title': 'Blockquote',
450
- 'css': 'wym_containers_blockquote'},
451
- {'name': 'TH', 'title': 'Table_Header', 'css': 'wym_containers_th'}
452
- ],
453
-
454
- classesHtml: "<div class='wym_classes wym_section'>"
455
- + "<h2>{Classes}</h2><ul>"
456
- + WYMeditor.CLASSES_ITEMS
457
- + "</ul></div>",
458
-
459
- classesItemHtml: "<li><a href='#' name='"
460
- + WYMeditor.CLASS_NAME
461
- + "'>"
462
- + WYMeditor.CLASS_TITLE
463
- + "</a></li>",
464
-
465
- classesItems: [],
466
-
467
- statusHtml: "<div class='wym_status wym_section'>"
468
- + "<h2>{Status}</h2>"
469
- + "</div>",
470
-
471
- htmlHtml: "<div class='wym_html wym_section'>"
472
- + "<h2>{Source_Code}</h2>"
473
- + "<textarea class='wym_html_val'></textarea>"
474
- + "</div>",
475
-
476
- boxSelector: ".wym_box",
477
- toolsSelector: ".wym_tools",
478
- toolsListSelector: " ul",
479
- containersSelector:".wym_containers",
480
- classesSelector: ".wym_classes",
481
- htmlSelector: ".wym_html",
482
- iframeSelector: ".wym_iframe iframe",
483
- iframeBodySelector:".wym_iframe",
484
- statusSelector: ".wym_status",
485
- toolSelector: ".wym_tools a",
486
- containerSelector: ".wym_containers a",
487
- classSelector: ".wym_classes a",
488
- htmlValSelector: ".wym_html_val",
489
-
490
- hrefSelector: ".wym_href",
491
- srcSelector: ".wym_src",
492
- titleSelector: ".wym_title",
493
- altSelector: ".wym_alt",
494
- textSelector: ".wym_text",
495
-
496
- rowsSelector: ".wym_rows",
497
- colsSelector: ".wym_cols",
498
- captionSelector: ".wym_caption",
499
- summarySelector: ".wym_summary",
500
-
501
- submitSelector: ".wym_submit",
502
- cancelSelector: ".wym_cancel",
503
- previewSelector: "",
504
-
505
- dialogTypeSelector: ".wym_dialog_type",
506
- dialogLinkSelector: ".wym_dialog_link",
507
- dialogImageSelector: ".wym_dialog_image",
508
- dialogTableSelector: ".wym_dialog_table",
509
- dialogPasteSelector: ".wym_dialog_paste",
510
- dialogPreviewSelector: ".wym_dialog_preview",
511
-
512
- updateSelector: ".wymupdate",
513
- updateEvent: "click",
514
-
515
- dialogFeatures: "menubar=no,titlebar=no,toolbar=no,resizable=no"
516
- + ",width=560,height=300,top=0,left=0",
517
-
518
- dialogHtml: "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'"
519
- + " 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>"
520
- + "<html dir='"
521
- + WYMeditor.DIRECTION
522
- + "'><head>"
523
- + "<link rel='stylesheet' type='text/css' media='screen'"
524
- + " href='"
525
- + WYMeditor.CSS_PATH
526
- + "' />"
527
- + "<title>"
528
- + WYMeditor.DIALOG_TITLE
529
- + "</title>"
530
- + "<script type='text/javascript'"
531
- + " src='"
532
- + WYMeditor.JQUERY_PATH
533
- + "'></script>"
534
- + "<script type='text/javascript'"
535
- + " src='"
536
- + WYMeditor.WYM_PATH
537
- + "'></script>"
538
- + "</head>"
539
- + WYMeditor.DIALOG_BODY
540
- + "</html>",
541
-
542
- dialogLinkHtml: "<body class='wym_dialog wym_dialog_link'"
543
- + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
544
- + ">"
545
- + "<form>"
546
- + "<fieldset>"
547
- + "<input type='hidden' class='wym_dialog_type' value='"
548
- + WYMeditor.DIALOG_LINK
549
- + "' />"
550
- + "<legend>{Link}</legend>"
551
- + "<div class='row'>"
552
- + "<label>{URL}</label>"
553
- + "<input type='text' class='wym_href' value='' size='40' />"
554
- + "</div>"
555
- + "<div class='row'>"
556
- + "<label>{Title}</label>"
557
- + "<input type='text' class='wym_title' value='' size='40' />"
558
- + "</div>"
559
- + "<div class='row row-indent'>"
560
- + "<input class='wym_submit' type='button'"
561
- + " value='{Submit}' />"
562
- + "<input class='wym_cancel' type='button'"
563
- + "value='{Cancel}' />"
564
- + "</div>"
565
- + "</fieldset>"
566
- + "</form>"
567
- + "</body>",
568
-
569
- dialogImageHtml: "<body class='wym_dialog wym_dialog_image'"
570
- + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
571
- + ">"
572
- + "<form>"
573
- + "<fieldset>"
574
- + "<input type='hidden' class='wym_dialog_type' value='"
575
- + WYMeditor.DIALOG_IMAGE
576
- + "' />"
577
- + "<legend>{Image}</legend>"
578
- + "<div class='row'>"
579
- + "<label>{URL}</label>"
580
- + "<input type='text' class='wym_src' value='' size='40' />"
581
- + "</div>"
582
- + "<div class='row'>"
583
- + "<label>{Alternative_Text}</label>"
584
- + "<input type='text' class='wym_alt' value='' size='40' />"
585
- + "</div>"
586
- + "<div class='row'>"
587
- + "<label>{Title}</label>"
588
- + "<input type='text' class='wym_title' value='' size='40' />"
589
- + "</div>"
590
- + "<div class='row row-indent'>"
591
- + "<input class='wym_submit' type='button'"
592
- + " value='{Submit}' />"
593
- + "<input class='wym_cancel' type='button'"
594
- + "value='{Cancel}' />"
595
- + "</div>"
596
- + "</fieldset>"
597
- + "</form>"
598
- + "</body>",
599
-
600
- dialogTableHtml: "<body class='wym_dialog wym_dialog_table'"
601
- + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
602
- + ">"
603
- + "<form>"
604
- + "<fieldset>"
605
- + "<input type='hidden' class='wym_dialog_type' value='"
606
- + WYMeditor.DIALOG_TABLE
607
- + "' />"
608
- + "<legend>{Table}</legend>"
609
- + "<div class='row'>"
610
- + "<label>{Caption}</label>"
611
- + "<input type='text' class='wym_caption' value='' size='40' />"
612
- + "</div>"
613
- + "<div class='row'>"
614
- + "<label>{Summary}</label>"
615
- + "<input type='text' class='wym_summary' value='' size='40' />"
616
- + "</div>"
617
- + "<div class='row'>"
618
- + "<label>{Number_Of_Rows}</label>"
619
- + "<input type='text' class='wym_rows' value='3' size='3' />"
620
- + "</div>"
621
- + "<div class='row'>"
622
- + "<label>{Number_Of_Cols}</label>"
623
- + "<input type='text' class='wym_cols' value='2' size='3' />"
624
- + "</div>"
625
- + "<div class='row row-indent'>"
626
- + "<input class='wym_submit' type='button'"
627
- + " value='{Submit}' />"
628
- + "<input class='wym_cancel' type='button'"
629
- + "value='{Cancel}' />"
630
- + "</div>"
631
- + "</fieldset>"
632
- + "</form>"
633
- + "</body>",
634
-
635
- dialogPasteHtml: "<body class='wym_dialog wym_dialog_paste'"
636
- + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
637
- + ">"
638
- + "<form>"
639
- + "<input type='hidden' class='wym_dialog_type' value='"
640
- + WYMeditor.DIALOG_PASTE
641
- + "' />"
642
- + "<fieldset>"
643
- + "<legend>{Paste_From_Word}</legend>"
644
- + "<div class='row'>"
645
- + "<textarea class='wym_text' rows='10' cols='50'></textarea>"
646
- + "</div>"
647
- + "<div class='row'>"
648
- + "<input class='wym_submit' type='button'"
649
- + " value='{Submit}' />"
650
- + "<input class='wym_cancel' type='button'"
651
- + "value='{Cancel}' />"
652
- + "</div>"
653
- + "</fieldset>"
654
- + "</form>"
655
- + "</body>",
656
-
657
- dialogPreviewHtml: "<body class='wym_dialog wym_dialog_preview'"
658
- + " onload='WYMeditor.INIT_DIALOG(" + WYMeditor.INDEX + ")'"
659
- + "></body>",
660
-
661
- dialogStyles: [],
662
-
663
- stringDelimiterLeft: "{",
664
- stringDelimiterRight:"}",
665
-
666
- preInit: null,
667
- preBind: null,
668
- postInit: null,
669
-
670
- preInitDialog: null,
671
- postInitDialog: null
672
-
673
- }, options);
674
-
675
- return this.each(function() {
676
-
677
- new WYMeditor.editor(jQuery(this),options);
678
- });
679
- };
680
-
681
- /* @name extend
682
- * @description Returns the WYMeditor instance based on its index
683
- */
684
- jQuery.extend({
685
- wymeditors: function(i) {
686
- return (WYMeditor.INSTANCES[i]);
687
- }
688
- });
689
-
690
-
691
- /********** WYMeditor **********/
692
-
693
- /* @name Wymeditor
694
- * @description WYMeditor class
695
- */
696
-
697
- /* @name init
698
- * @description Initializes a WYMeditor instance
699
- */
700
- WYMeditor.editor.prototype.init = function() {
701
-
702
- //load subclass - browser specific
703
- //unsupported browsers: do nothing
704
- if (jQuery.browser.msie) {
705
- var WymClass = new WYMeditor.WymClassExplorer(this);
706
- }
707
- else if (jQuery.browser.mozilla) {
708
- var WymClass = new WYMeditor.WymClassMozilla(this);
709
- }
710
- else if (jQuery.browser.opera) {
711
- var WymClass = new WYMeditor.WymClassOpera(this);
712
- }
713
- else if (jQuery.browser.safari) {
714
- var WymClass = new WYMeditor.WymClassSafari(this);
715
- }
716
-
717
- if(WymClass) {
718
-
719
- if(jQuery.isFunction(this._options.preInit)) this._options.preInit(this);
720
-
721
- var SaxListener = new WYMeditor.XhtmlSaxListener();
722
- jQuery.extend(SaxListener, WymClass);
723
- this.parser = new WYMeditor.XhtmlParser(SaxListener);
724
-
725
- if(this._options.styles || this._options.stylesheet){
726
- this.configureEditorUsingRawCss();
727
- }
728
-
729
- this.helper = new WYMeditor.XmlHelper();
730
-
731
- //extend the Wymeditor object
732
- //don't use jQuery.extend since 1.1.4
733
- //jQuery.extend(this, WymClass);
734
- for (var prop in WymClass) { this[prop] = WymClass[prop]; }
735
-
736
- //load wymbox
737
- this._box = jQuery(this._element).hide().after(this._options.boxHtml).next();
738
-
739
- //store the instance index in the wymbox element
740
- //but keep it compatible with jQuery < 1.2.3, see #122
741
- if( jQuery.isFunction( jQuery.fn.data ) )
742
- jQuery.data(this._box.get(0), WYMeditor.WYM_INDEX, this._index);
743
-
744
- var h = WYMeditor.Helper;
745
-
746
- //construct the iframe
747
- var iframeHtml = this._options.iframeHtml;
748
- iframeHtml = h.replaceAll(iframeHtml, WYMeditor.INDEX, this._index);
749
- iframeHtml = h.replaceAll(iframeHtml, WYMeditor.IFRAME_BASE_PATH, this._options.iframeBasePath);
750
-
751
- //construct wymbox
752
- var boxHtml = jQuery(this._box).html();
753
-
754
- boxHtml = h.replaceAll(boxHtml, WYMeditor.LOGO, this._options.logoHtml);
755
- boxHtml = h.replaceAll(boxHtml, WYMeditor.TOOLS, this._options.toolsHtml);
756
- boxHtml = h.replaceAll(boxHtml, WYMeditor.CONTAINERS,this._options.containersHtml);
757
- boxHtml = h.replaceAll(boxHtml, WYMeditor.CLASSES, this._options.classesHtml);
758
- boxHtml = h.replaceAll(boxHtml, WYMeditor.HTML, this._options.htmlHtml);
759
- boxHtml = h.replaceAll(boxHtml, WYMeditor.IFRAME, iframeHtml);
760
- boxHtml = h.replaceAll(boxHtml, WYMeditor.STATUS, this._options.statusHtml);
761
-
762
- //construct tools list
763
- var aTools = eval(this._options.toolsItems);
764
- var sTools = "";
765
-
766
- for(var i = 0; i < aTools.length; i++) {
767
- var oTool = aTools[i];
768
- if(oTool.name && oTool.title)
769
- var sTool = this._options.toolsItemHtml;
770
- var sTool = h.replaceAll(sTool, WYMeditor.TOOL_NAME, oTool.name);
771
- sTool = h.replaceAll(sTool, WYMeditor.TOOL_TITLE, this._options.stringDelimiterLeft
772
- + oTool.title
773
- + this._options.stringDelimiterRight);
774
- sTool = h.replaceAll(sTool, WYMeditor.TOOL_CLASS, oTool.css);
775
- sTools += sTool;
776
- }
777
-
778
- boxHtml = h.replaceAll(boxHtml, WYMeditor.TOOLS_ITEMS, sTools);
779
-
780
- //construct classes list
781
- var aClasses = eval(this._options.classesItems);
782
- var sClasses = "";
783
-
784
- for(var i = 0; i < aClasses.length; i++) {
785
- var oClass = aClasses[i];
786
- if(oClass.name && oClass.title)
787
- var sClass = this._options.classesItemHtml;
788
- sClass = h.replaceAll(sClass, WYMeditor.CLASS_NAME, oClass.name);
789
- sClass = h.replaceAll(sClass, WYMeditor.CLASS_TITLE, oClass.title);
790
- sClasses += sClass;
791
- }
792
-
793
- boxHtml = h.replaceAll(boxHtml, WYMeditor.CLASSES_ITEMS, sClasses);
794
-
795
- //construct containers list
796
- var aContainers = eval(this._options.containersItems);
797
- var sContainers = "";
798
-
799
- for(var i = 0; i < aContainers.length; i++) {
800
- var oContainer = aContainers[i];
801
- if(oContainer.name && oContainer.title)
802
- var sContainer = this._options.containersItemHtml;
803
- sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_NAME, oContainer.name);
804
- sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_TITLE,
805
- this._options.stringDelimiterLeft
806
- + oContainer.title
807
- + this._options.stringDelimiterRight);
808
- sContainer = h.replaceAll(sContainer, WYMeditor.CONTAINER_CLASS, oContainer.css);
809
- sContainers += sContainer;
810
- }
811
-
812
- boxHtml = h.replaceAll(boxHtml, WYMeditor.CONTAINERS_ITEMS, sContainers);
813
-
814
- //l10n
815
- boxHtml = this.replaceStrings(boxHtml);
816
-
817
- //load html in wymbox
818
- jQuery(this._box).html(boxHtml);
819
-
820
- //hide the html value
821
- jQuery(this._box).find(this._options.htmlSelector).hide();
822
-
823
- //enable the skin
824
- this.loadSkin();
825
-
826
- }
827
- };
828
-
829
- WYMeditor.editor.prototype.bindEvents = function() {
830
-
831
- //copy the instance
832
- var wym = this;
833
-
834
- //handle click event on tools buttons
835
- jQuery(this._box).find(this._options.toolSelector).click(function() {
836
- wym.exec(jQuery(this).attr(WYMeditor.NAME));
837
- return(false);
838
- });
839
-
840
- //handle click event on containers buttons
841
- jQuery(this._box).find(this._options.containerSelector).click(function() {
842
- wym.container(jQuery(this).attr(WYMeditor.NAME));
843
- return(false);
844
- });
845
-
846
- //handle keyup event on html value: set the editor value
847
- jQuery(this._box).find(this._options.htmlValSelector).keyup(function() {
848
- jQuery(wym._doc.body).html(jQuery(this).val());
849
- });
850
-
851
- //handle click event on classes buttons
852
- jQuery(this._box).find(this._options.classSelector).click(function() {
853
-
854
- var aClasses = eval(wym._options.classesItems);
855
- var sName = jQuery(this).attr(WYMeditor.NAME);
856
-
857
- var oClass = WYMeditor.Helper.findByName(aClasses, sName);
858
-
859
- if(oClass) {
860
- var jqexpr = oClass.expr;
861
- wym.toggleClass(sName, jqexpr);
862
- }
863
- return(false);
864
- });
865
-
866
- //handle event on update element
867
- jQuery(this._options.updateSelector)
868
- .bind(this._options.updateEvent, function() {
869
- wym.update();
870
- });
871
- };
872
-
873
- WYMeditor.editor.prototype.ready = function() {
874
- return(this._doc != null);
875
- };
876
-
877
-
878
- /********** METHODS **********/
879
-
880
- /* @name box
881
- * @description Returns the WYMeditor container
882
- */
883
- WYMeditor.editor.prototype.box = function() {
884
- return(this._box);
885
- };
886
-
887
- /* @name html
888
- * @description Get/Set the html value
889
- */
890
- WYMeditor.editor.prototype.html = function(html) {
891
-
892
- if(typeof html === 'string') jQuery(this._doc.body).html(html);
893
- else return(jQuery(this._doc.body).html());
894
- };
895
-
896
- /* @name xhtml
897
- * @description Cleans up the HTML
898
- */
899
- WYMeditor.editor.prototype.xhtml = function() {
900
- return this.parser.parse(this.html());
901
- };
902
-
903
- /* @name exec
904
- * @description Executes a button command
905
- */
906
- WYMeditor.editor.prototype.exec = function(cmd) {
907
-
908
- //base function for execCommand
909
- //open a dialog or exec
910
- switch(cmd) {
911
- case WYMeditor.CREATE_LINK:
912
- var container = this.container();
913
- if(container || this._selected_image) this.dialog(WYMeditor.DIALOG_LINK);
914
- break;
915
-
916
- case WYMeditor.INSERT_IMAGE:
917
- this.dialog(WYMeditor.DIALOG_IMAGE);
918
- break;
919
-
920
- case WYMeditor.INSERT_TABLE:
921
- this.dialog(WYMeditor.DIALOG_TABLE);
922
- break;
923
-
924
- case WYMeditor.PASTE:
925
- this.dialog(WYMeditor.DIALOG_PASTE);
926
- break;
927
-
928
- case WYMeditor.TOGGLE_HTML:
929
- this.update();
930
- this.toggleHtml();
931
-
932
- //partially fixes #121 when the user manually inserts an image
933
- if(!jQuery(this._box).find(this._options.htmlSelector).is(':visible'))
934
- this.listen();
935
- break;
936
-
937
- case WYMeditor.PREVIEW:
938
- this.dialog(WYMeditor.PREVIEW);
939
- break;
940
-
941
- default:
942
- this._exec(cmd);
943
- break;
944
- }
945
- };
946
-
947
- /* @name container
948
- * @description Get/Set the selected container
949
- */
950
- WYMeditor.editor.prototype.container = function(sType) {
951
-
952
- if(sType) {
953
-
954
- var container = null;
955
-
956
- if(sType.toLowerCase() == WYMeditor.TH) {
957
-
958
- container = this.container();
959
-
960
- //find the TD or TH container
961
- switch(container.tagName.toLowerCase()) {
962
-
963
- case WYMeditor.TD: case WYMeditor.TH:
964
- break;
965
- default:
966
- var aTypes = new Array(WYMeditor.TD,WYMeditor.TH);
967
- container = this.findUp(this.container(), aTypes);
968
- break;
969
- }
970
-
971
- //if it exists, switch
972
- if(container!=null) {
973
-
974
- sType = (container.tagName.toLowerCase() == WYMeditor.TD)? WYMeditor.TH: WYMeditor.TD;
975
- this.switchTo(container,sType);
976
- this.update();
977
- }
978
- } else {
979
-
980
- //set the container type
981
- var aTypes=new Array(WYMeditor.P,WYMeditor.H1,WYMeditor.H2,WYMeditor.H3,WYMeditor.H4,WYMeditor.H5,
982
- WYMeditor.H6,WYMeditor.PRE,WYMeditor.BLOCKQUOTE);
983
- container = this.findUp(this.container(), aTypes);
984
-
985
- if(container) {
986
-
987
- var newNode = null;
988
-
989
- //blockquotes must contain a block level element
990
- if(sType.toLowerCase() == WYMeditor.BLOCKQUOTE) {
991
-
992
- var blockquote = this.findUp(this.container(), WYMeditor.BLOCKQUOTE);
993
-
994
- if(blockquote == null) {
995
-
996
- newNode = this._doc.createElement(sType);
997
- container.parentNode.insertBefore(newNode,container);
998
- newNode.appendChild(container);
999
- this.setFocusToNode(newNode.firstChild);
1000
-
1001
- } else {
1002
-
1003
- var nodes = blockquote.childNodes;
1004
- var lgt = nodes.length;
1005
- var firstNode = null;
1006
-
1007
- if(lgt > 0) firstNode = nodes.item(0);
1008
- for(var x=0; x<lgt; x++) {
1009
- blockquote.parentNode.insertBefore(nodes.item(0),blockquote);
1010
- }
1011
- blockquote.parentNode.removeChild(blockquote);
1012
- if(firstNode) this.setFocusToNode(firstNode);
1013
- }
1014
- }
1015
-
1016
- else this.switchTo(container,sType);
1017
-
1018
- this.update();
1019
- }
1020
- }
1021
- }
1022
- else return(this.selected());
1023
- };
1024
-
1025
- /* @name toggleClass
1026
- * @description Toggles class on selected element, or one of its parents
1027
- */
1028
- WYMeditor.editor.prototype.toggleClass = function(sClass, jqexpr) {
1029
-
1030
- var container = (this._selected_image
1031
- ? this._selected_image
1032
- : jQuery(this.selected()));
1033
- container = jQuery(container).parentsOrSelf(jqexpr);
1034
- jQuery(container).toggleClass(sClass);
1035
-
1036
- if(!jQuery(container).attr(WYMeditor.CLASS)) jQuery(container).removeAttr(this._class);
1037
-
1038
- };
1039
-
1040
- /* @name findUp
1041
- * @description Returns the first parent or self container, based on its type
1042
- */
1043
- WYMeditor.editor.prototype.findUp = function(node, filter) {
1044
-
1045
- //filter is a string or an array of strings
1046
-
1047
- if(node) {
1048
-
1049
- var tagname = node.tagName.toLowerCase();
1050
-
1051
- if(typeof(filter) == WYMeditor.STRING) {
1052
-
1053
- while(tagname != filter && tagname != WYMeditor.BODY) {
1054
-
1055
- node = node.parentNode;
1056
- tagname = node.tagName.toLowerCase();
1057
- }
1058
-
1059
- } else {
1060
-
1061
- var bFound = false;
1062
-
1063
- while(!bFound && tagname != WYMeditor.BODY) {
1064
- for(var i = 0; i < filter.length; i++) {
1065
- if(tagname == filter[i]) {
1066
- bFound = true;
1067
- break;
1068
- }
1069
- }
1070
- if(!bFound) {
1071
- node = node.parentNode;
1072
- tagname = node.tagName.toLowerCase();
1073
- }
1074
- }
1075
- }
1076
-
1077
- if(tagname != WYMeditor.BODY) return(node);
1078
- else return(null);
1079
-
1080
- } else return(null);
1081
- };
1082
-
1083
- /* @name switchTo
1084
- * @description Switch the node's type
1085
- */
1086
- WYMeditor.editor.prototype.switchTo = function(node,sType) {
1087
-
1088
- var newNode = this._doc.createElement(sType);
1089
- var html = jQuery(node).html();
1090
- node.parentNode.replaceChild(newNode,node);
1091
- jQuery(newNode).html(html);
1092
- this.setFocusToNode(newNode);
1093
- };
1094
-
1095
- WYMeditor.editor.prototype.replaceStrings = function(sVal) {
1096
- //check if the language file has already been loaded
1097
- //if not, get it via a synchronous ajax call
1098
- if(!WYMeditor.STRINGS[this._options.lang]) {
1099
- try {
1100
- eval(jQuery.ajax({url:this._options.langPath
1101
- + this._options.lang + '.js', async:false}).responseText);
1102
- } catch(e) {
1103
- WYMeditor.console.error("WYMeditor: error while parsing language file.");
1104
- return sVal;
1105
- }
1106
- }
1107
-
1108
- //replace all the strings in sVal and return it
1109
- for (var key in WYMeditor.STRINGS[this._options.lang]) {
1110
- sVal = WYMeditor.Helper.replaceAll(sVal, this._options.stringDelimiterLeft + key
1111
- + this._options.stringDelimiterRight,
1112
- WYMeditor.STRINGS[this._options.lang][key]);
1113
- };
1114
- return(sVal);
1115
- };
1116
-
1117
- WYMeditor.editor.prototype.encloseString = function(sVal) {
1118
-
1119
- return(this._options.stringDelimiterLeft
1120
- + sVal
1121
- + this._options.stringDelimiterRight);
1122
- };
1123
-
1124
- /* @name status
1125
- * @description Prints a status message
1126
- */
1127
- WYMeditor.editor.prototype.status = function(sMessage) {
1128
-
1129
- //print status message
1130
- jQuery(this._box).find(this._options.statusSelector).html(sMessage);
1131
- };
1132
-
1133
- /* @name update
1134
- * @description Updates the element and textarea values
1135
- */
1136
- WYMeditor.editor.prototype.update = function() {
1137
-
1138
- var html = this.xhtml();
1139
- jQuery(this._element).val(html);
1140
- jQuery(this._box).find(this._options.htmlValSelector).val(html);
1141
- };
1142
-
1143
- /* @name dialog
1144
- * @description Opens a dialog box
1145
- */
1146
- WYMeditor.editor.prototype.dialog = function( dialogType, bodyHtml ) {
1147
-
1148
- var wDialog = window.open(
1149
- '',
1150
- 'dialog',
1151
- this._wym._options.dialogFeatures);
1152
-
1153
- if(wDialog) {
1154
-
1155
- var sBodyHtml = "";
1156
-
1157
- switch( dialogType ) {
1158
-
1159
- case(WYMeditor.DIALOG_LINK):
1160
- sBodyHtml = this._options.dialogLinkHtml;
1161
- break;
1162
- case(WYMeditor.DIALOG_IMAGE):
1163
- sBodyHtml = this._options.dialogImageHtml;
1164
- break;
1165
- case(WYMeditor.DIALOG_TABLE):
1166
- sBodyHtml = this._options.dialogTableHtml;
1167
- break;
1168
- case(WYMeditor.DIALOG_PASTE):
1169
- sBodyHtml = this._options.dialogPasteHtml;
1170
- break;
1171
- case(WYMeditor.PREVIEW):
1172
- sBodyHtml = this._options.dialogPreviewHtml;
1173
- break;
1174
-
1175
- default:
1176
- sBodyHtml = bodyHtml;
1177
- }
1178
-
1179
- var h = WYMeditor.Helper;
1180
-
1181
- //construct the dialog
1182
- var dialogHtml = this._options.dialogHtml;
1183
- dialogHtml = h.replaceAll(dialogHtml, WYMeditor.BASE_PATH, this._options.basePath);
1184
- dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIRECTION, this._options.direction);
1185
- dialogHtml = h.replaceAll(dialogHtml, WYMeditor.CSS_PATH, this._options.skinPath + WYMeditor.SKINS_DEFAULT_CSS);
1186
- dialogHtml = h.replaceAll(dialogHtml, WYMeditor.WYM_PATH, this._options.wymPath);
1187
- dialogHtml = h.replaceAll(dialogHtml, WYMeditor.JQUERY_PATH, this._options.jQueryPath);
1188
- dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIALOG_TITLE, this.encloseString( dialogType ));
1189
- dialogHtml = h.replaceAll(dialogHtml, WYMeditor.DIALOG_BODY, sBodyHtml);
1190
- dialogHtml = h.replaceAll(dialogHtml, WYMeditor.INDEX, this._index);
1191
-
1192
- dialogHtml = this.replaceStrings(dialogHtml);
1193
-
1194
- var doc = wDialog.document;
1195
- doc.write(dialogHtml);
1196
- doc.close();
1197
- }
1198
- };
1199
-
1200
- /* @name toggleHtml
1201
- * @description Shows/Hides the HTML
1202
- */
1203
- WYMeditor.editor.prototype.toggleHtml = function() {
1204
- jQuery(this._box).find(this._options.htmlSelector).toggle();
1205
- };
1206
-
1207
- WYMeditor.editor.prototype.uniqueStamp = function() {
1208
- var now = new Date();
1209
- return("wym-" + now.getTime());
1210
- };
1211
-
1212
- WYMeditor.editor.prototype.paste = function(sData) {
1213
-
1214
- var sTmp;
1215
- var container = this.selected();
1216
-
1217
- //split the data, using double newlines as the separator
1218
- var aP = sData.split(this._newLine + this._newLine);
1219
- var rExp = new RegExp(this._newLine, "g");
1220
-
1221
- //add a P for each item
1222
- if(container && container.tagName.toLowerCase() != WYMeditor.BODY) {
1223
- for(x = aP.length - 1; x >= 0; x--) {
1224
- sTmp = aP[x];
1225
- //simple newlines are replaced by a break
1226
- sTmp = sTmp.replace(rExp, "<br />");
1227
- jQuery(container).after("<p>" + sTmp + "</p>");
1228
- }
1229
- } else {
1230
- for(x = 0; x < aP.length; x++) {
1231
- sTmp = aP[x];
1232
- //simple newlines are replaced by a break
1233
- sTmp = sTmp.replace(rExp, "<br />");
1234
- jQuery(this._doc.body).append("<p>" + sTmp + "</p>");
1235
- }
1236
-
1237
- }
1238
- };
1239
-
1240
- WYMeditor.editor.prototype.insert = function(html) {
1241
- // Do we have a selection?
1242
- if (this._iframe.contentWindow.getSelection().focusNode != null) {
1243
- // Overwrite selection with provided html
1244
- this._exec( WYMeditor.INSERT_HTML, html);
1245
- } else {
1246
- // Fall back to the internal paste function if there's no selection
1247
- this.paste(html)
1248
- }
1249
- };
1250
-
1251
- WYMeditor.editor.prototype.wrap = function(left, right) {
1252
- // Do we have a selection?
1253
- if (this._iframe.contentWindow.getSelection().focusNode != null) {
1254
- // Wrap selection with provided html
1255
- this._exec( WYMeditor.INSERT_HTML, left + this._iframe.contentWindow.getSelection().toString() + right);
1256
- }
1257
- };
1258
-
1259
- WYMeditor.editor.prototype.unwrap = function() {
1260
- // Do we have a selection?
1261
- if (this._iframe.contentWindow.getSelection().focusNode != null) {
1262
- // Unwrap selection
1263
- this._exec( WYMeditor.INSERT_HTML, this._iframe.contentWindow.getSelection().toString() );
1264
- }
1265
- };
1266
-
1267
- WYMeditor.editor.prototype.addCssRules = function(doc, aCss) {
1268
- var styles = doc.styleSheets[0];
1269
- if(styles) {
1270
- for(var i = 0; i < aCss.length; i++) {
1271
- var oCss = aCss[i];
1272
- if(oCss.name && oCss.css) this.addCssRule(styles, oCss);
1273
- }
1274
- }
1275
- };
1276
-
1277
- /********** CONFIGURATION **********/
1278
-
1279
- WYMeditor.editor.prototype.computeBasePath = function() {
1280
- return jQuery(jQuery.grep(jQuery('script'), function(s){
1281
- return (s.src && s.src.match(/jquery\.wymeditor(\.pack){0,1}\.js(\?.*)?$/ ))
1282
- })).attr('src').replace(/jquery\.wymeditor(\.pack){0,1}\.js(\?.*)?$/, '');
1283
- };
1284
-
1285
- WYMeditor.editor.prototype.computeWymPath = function() {
1286
- return jQuery(jQuery.grep(jQuery('script'), function(s){
1287
- return (s.src && s.src.match(/jquery\.wymeditor(\.pack){0,1}\.js(\?.*)?$/ ))
1288
- })).attr('src');
1289
- };
1290
-
1291
- WYMeditor.editor.prototype.computeJqueryPath = function() {
1292
- return jQuery(jQuery.grep(jQuery('script'), function(s){
1293
- return (s.src && s.src.match(/jquery(-(.*)){0,1}(\.pack){0,1}\.js(\?.*)?$/ ))
1294
- })).attr('src');
1295
- };
1296
-
1297
- WYMeditor.editor.prototype.computeCssPath = function() {
1298
- return jQuery(jQuery.grep(jQuery('link'), function(s){
1299
- return (s.href && s.href.match(/wymeditor\/skins\/(.*)screen\.css(\?.*)?$/ ))
1300
- })).attr('href');
1301
- };
1302
-
1303
- WYMeditor.editor.prototype.configureEditorUsingRawCss = function() {
1304
-
1305
- var CssParser = new WYMeditor.WymCssParser();
1306
- if(this._options.stylesheet){
1307
- CssParser.parse(jQuery.ajax({url: this._options.stylesheet,async:false}).responseText);
1308
- }else{
1309
- CssParser.parse(this._options.styles, false);
1310
- }
1311
-
1312
- if(this._options.classesItems.length == 0) {
1313
- this._options.classesItems = CssParser.css_settings.classesItems;
1314
- }
1315
- if(this._options.editorStyles.length == 0) {
1316
- this._options.editorStyles = CssParser.css_settings.editorStyles;
1317
- }
1318
- if(this._options.dialogStyles.length == 0) {
1319
- this._options.dialogStyles = CssParser.css_settings.dialogStyles;
1320
- }
1321
- };
1322
-
1323
- /********** EVENTS **********/
1324
-
1325
- WYMeditor.editor.prototype.listen = function() {
1326
-
1327
- //don't use jQuery.find() on the iframe body
1328
- //because of MSIE + jQuery + expando issue (#JQ1143)
1329
- //jQuery(this._doc.body).find("*").bind("mouseup", this.mouseup);
1330
-
1331
- jQuery(this._doc.body).bind("mousedown", this.mousedown);
1332
- var images = this._doc.body.getElementsByTagName("img");
1333
- for(var i=0; i < images.length; i++) {
1334
- jQuery(images[i]).bind("mousedown", this.mousedown);
1335
- }
1336
- };
1337
-
1338
- WYMeditor.editor.prototype.mousedown = function(evt) {
1339
-
1340
- var wym = WYMeditor.INSTANCES[this.ownerDocument.title];
1341
- wym._selected_image = (this.tagName.toLowerCase() == WYMeditor.IMG) ? this : null;
1342
- evt.stopPropagation();
1343
- };
1344
-
1345
- /********** SKINS **********/
1346
-
1347
- /*
1348
- * Function: WYMeditor.loadCss
1349
- * Loads a stylesheet in the document.
1350
- *
1351
- * Parameters:
1352
- * href - The CSS path.
1353
- */
1354
- WYMeditor.loadCss = function(href) {
1355
-
1356
- var link = document.createElement('link');
1357
- link.rel = 'stylesheet';
1358
- link.href = href;
1359
-
1360
- var head = jQuery('head').get(0);
1361
- head.appendChild(link);
1362
- };
1363
-
1364
- /*
1365
- * Function: WYMeditor.editor.loadSkin
1366
- * Loads the skin CSS and initialization script (if needed).
1367
- */
1368
- WYMeditor.editor.prototype.loadSkin = function() {
1369
-
1370
- //does the user want to automatically load the CSS (default: yes)?
1371
- //we also test if it hasn't been already loaded by another instance
1372
- //see below for a better (second) test
1373
- if(this._options.loadSkin && !WYMeditor.SKINS[this._options.skin]) {
1374
-
1375
- //check if it hasn't been already loaded
1376
- //so we don't load it more than once
1377
- //(we check the existing <link> elements)
1378
-
1379
- var found = false;
1380
- var rExp = new RegExp(this._options.skin
1381
- + '\/' + WYMeditor.SKINS_DEFAULT_CSS + '$');
1382
-
1383
- jQuery('link').each( function() {
1384
- if(this.href.match(rExp)) found = true;
1385
- });
1386
-
1387
- //load it, using the skin path
1388
- if(!found) WYMeditor.loadCss( this._options.skinPath
1389
- + WYMeditor.SKINS_DEFAULT_CSS );
1390
- }
1391
-
1392
- //put the classname (ex. wym_skin_default) on wym_box
1393
- jQuery(this._box).addClass( "wym_skin_" + this._options.skin );
1394
-
1395
- //does the user want to use some JS to initialize the skin (default: yes)?
1396
- //also check if it hasn't already been loaded by another instance
1397
- if(this._options.initSkin && !WYMeditor.SKINS[this._options.skin]) {
1398
-
1399
- eval(jQuery.ajax({url:this._options.skinPath
1400
- + WYMeditor.SKINS_DEFAULT_JS, async:false}).responseText);
1401
- }
1402
-
1403
- //init the skin, if needed
1404
- if(WYMeditor.SKINS[this._options.skin]
1405
- && WYMeditor.SKINS[this._options.skin].init)
1406
- WYMeditor.SKINS[this._options.skin].init(this);
1407
-
1408
- };
1409
-
1410
-
1411
- /********** DIALOGS **********/
1412
-
1413
- WYMeditor.INIT_DIALOG = function(index) {
1414
-
1415
- var wym = window.opener.WYMeditor.INSTANCES[index];
1416
- var doc = window.document;
1417
- var selected = wym.selected();
1418
- var dialogType = jQuery(wym._options.dialogTypeSelector).val();
1419
- var sStamp = wym.uniqueStamp();
1420
-
1421
- switch(dialogType) {
1422
-
1423
- case WYMeditor.DIALOG_LINK:
1424
- //ensure that we select the link to populate the fields
1425
- if(selected && selected.tagName && selected.tagName.toLowerCase != WYMeditor.A)
1426
- selected = jQuery(selected).parentsOrSelf(WYMeditor.A);
1427
-
1428
- //fix MSIE selection if link image has been clicked
1429
- if(!selected && wym._selected_image)
1430
- selected = jQuery(wym._selected_image).parentsOrSelf(WYMeditor.A);
1431
- break;
1432
-
1433
- }
1434
-
1435
- //pre-init functions
1436
- if(jQuery.isFunction(wym._options.preInitDialog))
1437
- wym._options.preInitDialog(wym,window);
1438
-
1439
- //add css rules from options
1440
- var styles = doc.styleSheets[0];
1441
- var aCss = eval(wym._options.dialogStyles);
1442
-
1443
- wym.addCssRules(doc, aCss);
1444
-
1445
- //auto populate fields if selected container (e.g. A)
1446
- if(selected) {
1447
- jQuery(wym._options.hrefSelector).val(jQuery(selected).attr(WYMeditor.HREF));
1448
- jQuery(wym._options.srcSelector).val(jQuery(selected).attr(WYMeditor.SRC));
1449
- jQuery(wym._options.titleSelector).val(jQuery(selected).attr(WYMeditor.TITLE));
1450
- jQuery(wym._options.altSelector).val(jQuery(selected).attr(WYMeditor.ALT));
1451
- }
1452
-
1453
- //auto populate image fields if selected image
1454
- if(wym._selected_image) {
1455
- jQuery(wym._options.dialogImageSelector + " " + wym._options.srcSelector)
1456
- .val(jQuery(wym._selected_image).attr(WYMeditor.SRC));
1457
- jQuery(wym._options.dialogImageSelector + " " + wym._options.titleSelector)
1458
- .val(jQuery(wym._selected_image).attr(WYMeditor.TITLE));
1459
- jQuery(wym._options.dialogImageSelector + " " + wym._options.altSelector)
1460
- .val(jQuery(wym._selected_image).attr(WYMeditor.ALT));
1461
- }
1462
-
1463
- jQuery(wym._options.dialogLinkSelector + " "
1464
- + wym._options.submitSelector).click(function() {
1465
-
1466
- var sUrl = jQuery(wym._options.hrefSelector).val();
1467
- if(sUrl.length > 0) {
1468
-
1469
- wym._exec(WYMeditor.CREATE_LINK, sStamp);
1470
-
1471
- jQuery("a[@href=" + sStamp + "]", wym._doc.body)
1472
- .attr(WYMeditor.HREF, sUrl)
1473
- .attr(WYMeditor.TITLE, jQuery(wym._options.titleSelector).val());
1474
-
1475
- }
1476
- window.close();
1477
- });
1478
-
1479
- jQuery(wym._options.dialogImageSelector + " "
1480
- + wym._options.submitSelector).click(function() {
1481
-
1482
- var sUrl = jQuery(wym._options.srcSelector).val();
1483
- if(sUrl.length > 0) {
1484
-
1485
- wym._exec(WYMeditor.INSERT_IMAGE, sStamp);
1486
-
1487
- jQuery("img[@src=" + sStamp + "]", wym._doc.body)
1488
- .attr(WYMeditor.SRC, sUrl)
1489
- .attr(WYMeditor.TITLE, jQuery(wym._options.titleSelector).val())
1490
- .attr(WYMeditor.ALT, jQuery(wym._options.altSelector).val());
1491
- }
1492
- window.close();
1493
- });
1494
-
1495
- jQuery(wym._options.dialogTableSelector + " "
1496
- + wym._options.submitSelector).click(function() {
1497
-
1498
- var iRows = jQuery(wym._options.rowsSelector).val();
1499
- var iCols = jQuery(wym._options.colsSelector).val();
1500
-
1501
- if(iRows > 0 && iCols > 0) {
1502
-
1503
- var table = wym._doc.createElement(WYMeditor.TABLE);
1504
- var newRow = null;
1505
- var newCol = null;
1506
-
1507
- var sCaption = jQuery(wym._options.captionSelector).val();
1508
-
1509
- //we create the caption
1510
- var newCaption = table.createCaption();
1511
- newCaption.innerHTML = sCaption;
1512
-
1513
- //we create the rows and cells
1514
- for(x=0; x<iRows; x++) {
1515
- newRow = table.insertRow(x);
1516
- for(y=0; y<iCols; y++) {newRow.insertCell(y);}
1517
- }
1518
-
1519
- //set the summary attr
1520
- jQuery(table).attr('summary',
1521
- jQuery(wym._options.summarySelector).val());
1522
-
1523
- //append the table after the selected container
1524
- var node = jQuery(wym.findUp(wym.container(),
1525
- WYMeditor.MAIN_CONTAINERS)).get(0);
1526
- if(!node || !node.parentNode) jQuery(wym._doc.body).append(table);
1527
- else jQuery(node).after(table);
1528
- }
1529
- window.close();
1530
- });
1531
-
1532
- jQuery(wym._options.dialogPasteSelector + " "
1533
- + wym._options.submitSelector).click(function() {
1534
-
1535
- var sText = jQuery(wym._options.textSelector).val();
1536
- wym.paste(sText);
1537
- window.close();
1538
- });
1539
-
1540
- jQuery(wym._options.dialogPreviewSelector + " "
1541
- + wym._options.previewSelector)
1542
- .html(wym.xhtml());
1543
-
1544
- //cancel button
1545
- jQuery(wym._options.cancelSelector).mousedown(function() {
1546
- window.close();
1547
- });
1548
-
1549
- //pre-init functions
1550
- if(jQuery.isFunction(wym._options.postInitDialog))
1551
- wym._options.postInitDialog(wym,window);
1552
-
1553
- };
1554
-
1555
- /********** XHTML LEXER/PARSER **********/
1556
-
1557
- /*
1558
- * @name xml
1559
- * @description Use these methods to generate XML and XHTML compliant tags and
1560
- * escape tag attributes correctly
1561
- * @author Bermi Ferrer - http://bermi.org
1562
- * @author David Heinemeier Hansson http://loudthinking.com
1563
- */
1564
- WYMeditor.XmlHelper = function()
1565
- {
1566
- this._entitiesDiv = document.createElement('div');
1567
- return this;
1568
- };
1569
-
1570
-
1571
- /*
1572
- * @name tag
1573
- * @description
1574
- * Returns an empty HTML tag of type *name* which by default is XHTML
1575
- * compliant. Setting *open* to true will create an open tag compatible
1576
- * with HTML 4.0 and below. Add HTML attributes by passing an attributes
1577
- * array to *options*. For attributes with no value like (disabled and
1578
- * readonly), give it a value of true in the *options* array.
1579
- *
1580
- * Examples:
1581
- *
1582
- * this.tag('br')
1583
- * # => <br />
1584
- * this.tag ('br', false, true)
1585
- * # => <br>
1586
- * this.tag ('input', jQuery({type:'text',disabled:true }) )
1587
- * # => <input type="text" disabled="disabled" />
1588
- */
1589
- WYMeditor.XmlHelper.prototype.tag = function(name, options, open)
1590
- {
1591
- options = options || false;
1592
- open = open || false;
1593
- return '<'+name+(options ? this.tagOptions(options) : '')+(open ? '>' : ' />');
1594
- };
1595
-
1596
- /*
1597
- * @name contentTag
1598
- * @description
1599
- * Returns a XML block tag of type *name* surrounding the *content*. Add
1600
- * XML attributes by passing an attributes array to *options*. For attributes
1601
- * with no value like (disabled and readonly), give it a value of true in
1602
- * the *options* array. You can use symbols or strings for the attribute names.
1603
- *
1604
- * this.contentTag ('p', 'Hello world!' )
1605
- * # => <p>Hello world!</p>
1606
- * this.contentTag('div', this.contentTag('p', "Hello world!"), jQuery({class : "strong"}))
1607
- * # => <div class="strong"><p>Hello world!</p></div>
1608
- * this.contentTag("select", options, jQuery({multiple : true}))
1609
- * # => <select multiple="multiple">...options...</select>
1610
- */
1611
- WYMeditor.XmlHelper.prototype.contentTag = function(name, content, options)
1612
- {
1613
- options = options || false;
1614
- return '<'+name+(options ? this.tagOptions(options) : '')+'>'+content+'</'+name+'>';
1615
- };
1616
-
1617
- /*
1618
- * @name cdataSection
1619
- * @description
1620
- * Returns a CDATA section for the given +content+. CDATA sections
1621
- * are used to escape blocks of text containing characters which would
1622
- * otherwise be recognized as markup. CDATA sections begin with the string
1623
- * <tt>&lt;![CDATA[</tt> and } with (and may not contain) the string
1624
- * <tt>]]></tt>.
1625
- */
1626
- WYMeditor.XmlHelper.prototype.cdataSection = function(content)
1627
- {
1628
- return '<![CDATA['+content+']]>';
1629
- };
1630
-
1631
-
1632
- /*
1633
- * @name escapeOnce
1634
- * @description
1635
- * Returns the escaped +xml+ without affecting existing escaped entities.
1636
- *
1637
- * this.escapeOnce( "1 > 2 &amp; 3")
1638
- * # => "1 &gt; 2 &amp; 3"
1639
- */
1640
- WYMeditor.XmlHelper.prototype.escapeOnce = function(xml)
1641
- {
1642
- return this._fixDoubleEscape(this.escapeEntities(xml));
1643
- };
1644
-
1645
- /*
1646
- * @name _fixDoubleEscape
1647
- * @description
1648
- * Fix double-escaped entities, such as &amp;amp;, &amp;#123;, etc.
1649
- */
1650
- WYMeditor.XmlHelper.prototype._fixDoubleEscape = function(escaped)
1651
- {
1652
- return escaped.replace(/&amp;([a-z]+|(#\d+));/ig, "&$1;");
1653
- };
1654
-
1655
- /*
1656
- * @name tagOptions
1657
- * @description
1658
- * Takes an array like the one generated by Tag.parseAttributes
1659
- * [["src", "http://www.editam.com/?a=b&c=d&amp;f=g"], ["title", "Editam, <Simplified> CMS"]]
1660
- * or an object like {src:"http://www.editam.com/?a=b&c=d&amp;f=g", title:"Editam, <Simplified> CMS"}
1661
- * and returns a string properly escaped like
1662
- * ' src = "http://www.editam.com/?a=b&amp;c=d&amp;f=g" title = "Editam, &lt;Simplified&gt; CMS"'
1663
- * which is valid for strict XHTML
1664
- */
1665
- WYMeditor.XmlHelper.prototype.tagOptions = function(options)
1666
- {
1667
- var xml = this;
1668
- xml._formated_options = '';
1669
-
1670
- for (var key in options) {
1671
- var formated_options = '';
1672
- var value = options[key];
1673
- if(typeof value != 'function' && value.length > 0) {
1674
-
1675
- if(parseInt(key) == key && typeof value == 'object'){
1676
- key = value.shift();
1677
- value = value.pop();
1678
- }
1679
- if(key != '' && value != ''){
1680
- xml._formated_options += ' '+key+'="'+xml.escapeOnce(value)+'"';
1681
- }
1682
- }
1683
- }
1684
- return xml._formated_options;
1685
- };
1686
-
1687
- /*
1688
- * @name escapeEntities
1689
- * @description
1690
- * Escapes XML/HTML entities <, >, & and ". If seccond parameter is set to false it
1691
- * will not escape ". If set to true it will also escape '
1692
- */
1693
- WYMeditor.XmlHelper.prototype.escapeEntities = function(string, escape_quotes)
1694
- {
1695
- this._entitiesDiv.innerHTML = string;
1696
- this._entitiesDiv.textContent = string;
1697
- var result = this._entitiesDiv.innerHTML;
1698
- if(typeof escape_quotes == 'undefined'){
1699
- if(escape_quotes != false) result = result.replace('"', '&quot;');
1700
- if(escape_quotes == true) result = result.replace('"', '&#039;');
1701
- }
1702
- return result;
1703
- };
1704
-
1705
- /*
1706
- * Parses a string conatining tag attributes and values an returns an array formated like
1707
- * [["src", "http://www.editam.com"], ["title", "Editam, Simplified CMS"]]
1708
- */
1709
- WYMeditor.XmlHelper.prototype.parseAttributes = function(tag_attributes)
1710
- {
1711
- // Use a compounded regex to match single quoted, double quoted and unquoted attribute pairs
1712
- var result = [];
1713
- var matches = tag_attributes.split(/((=\s*")(")("))|((=\s*\')(\')(\'))|((=\s*[^>\s]*))/g);
1714
- if(matches.toString() != tag_attributes){
1715
- for (var k in matches) {
1716
- var v = matches[k];
1717
- if(typeof v != 'function' && v.length != 0){
1718
- var re = new RegExp('(\\w+)\\s*'+v);
1719
- if(match = tag_attributes.match(re) ){
1720
- var value = v.replace(/^[\s=]+/, "");
1721
- var delimiter = value.charAt(0);
1722
- delimiter = delimiter == '"' ? '"' : (delimiter=="'"?"'":'');
1723
- if(delimiter != ''){
1724
- value = delimiter == '"' ? value.replace(/^"|"+$/g, '') : value.replace(/^'|'+$/g, '');
1725
- }
1726
- tag_attributes = tag_attributes.replace(match[0],'');
1727
- result.push([match[1] , value]);
1728
- }
1729
- }
1730
- }
1731
- }
1732
- return result;
1733
- };
1734
-
1735
- /**
1736
- * XhtmlValidator for validating tag attributes
1737
- *
1738
- * @author Bermi Ferrer - http://bermi.org
1739
- */
1740
- WYMeditor.XhtmlValidator = {
1741
- "_attributes":
1742
- {
1743
- "core":
1744
- {
1745
- "except":[
1746
- "base",
1747
- "head",
1748
- "html",
1749
- "meta",
1750
- "param",
1751
- "script",
1752
- "style",
1753
- "title"
1754
- ],
1755
- "attributes":[
1756
- "class",
1757
- "id",
1758
- "style",
1759
- "title",
1760
- "accesskey",
1761
- "tabindex"
1762
- ]
1763
- },
1764
- "language":
1765
- {
1766
- "except":[
1767
- "base",
1768
- "br",
1769
- "hr",
1770
- "iframe",
1771
- "param",
1772
- "script"
1773
- ],
1774
- "attributes":
1775
- {
1776
- "dir":[
1777
- "ltr",
1778
- "rtl"
1779
- ],
1780
- "0":"lang",
1781
- "1":"xml:lang"
1782
- }
1783
- },
1784
- "keyboard":
1785
- {
1786
- "attributes":
1787
- {
1788
- "accesskey":/^(\w){1}$/,
1789
- "tabindex":/^(\d)+$/
1790
- }
1791
- }
1792
- },
1793
- "_events":
1794
- {
1795
- "window":
1796
- {
1797
- "only":[
1798
- "body"
1799
- ],
1800
- "attributes":[
1801
- "onload",
1802
- "onunload"
1803
- ]
1804
- },
1805
- "form":
1806
- {
1807
- "only":[
1808
- "form",
1809
- "input",
1810
- "textarea",
1811
- "select",
1812
- "a",
1813
- "label",
1814
- "button"
1815
- ],
1816
- "attributes":[
1817
- "onchange",
1818
- "onsubmit",
1819
- "onreset",
1820
- "onselect",
1821
- "onblur",
1822
- "onfocus"
1823
- ]
1824
- },
1825
- "keyboard":
1826
- {
1827
- "except":[
1828
- "base",
1829
- "bdo",
1830
- "br",
1831
- "frame",
1832
- "frameset",
1833
- "head",
1834
- "html",
1835
- "iframe",
1836
- "meta",
1837
- "param",
1838
- "script",
1839
- "style",
1840
- "title"
1841
- ],
1842
- "attributes":[
1843
- "onkeydown",
1844
- "onkeypress",
1845
- "onkeyup"
1846
- ]
1847
- },
1848
- "mouse":
1849
- {
1850
- "except":[
1851
- "base",
1852
- "bdo",
1853
- "br",
1854
- "head",
1855
- "html",
1856
- "meta",
1857
- "param",
1858
- "script",
1859
- "style",
1860
- "title"
1861
- ],
1862
- "attributes":[
1863
- "onclick",
1864
- "ondblclick",
1865
- "onmousedown",
1866
- "onmousemove",
1867
- "onmouseover",
1868
- "onmouseout",
1869
- "onmouseup"
1870
- ]
1871
- }
1872
- },
1873
- "_tags":
1874
- {
1875
- "a":
1876
- {
1877
- "attributes":
1878
- {
1879
- "0":"charset",
1880
- "1":"coords",
1881
- "2":"href",
1882
- "3":"hreflang",
1883
- "4":"name",
1884
- "rel":/^(alternate|designates|stylesheet|start|next|prev|contents|index|glossary|copyright|chapter|section|subsection|appendix|help|bookmark| |shortcut|icon)+$/,
1885
- "rev":/^(alternate|designates|stylesheet|start|next|prev|contents|index|glossary|copyright|chapter|section|subsection|appendix|help|bookmark| |shortcut|icon)+$/,
1886
- "shape":/^(rect|rectangle|circ|circle|poly|polygon)$/,
1887
- "5":"type"
1888
- }
1889
- },
1890
- "0":"abbr",
1891
- "1":"acronym",
1892
- "2":"address",
1893
- "area":
1894
- {
1895
- "attributes":
1896
- {
1897
- "0":"alt",
1898
- "1":"coords",
1899
- "2":"href",
1900
- "nohref":/^(true|false)$/,
1901
- "shape":/^(rect|rectangle|circ|circle|poly|polygon)$/
1902
- },
1903
- "required":[
1904
- "alt"
1905
- ]
1906
- },
1907
- "3":"b",
1908
- "base":
1909
- {
1910
- "attributes":[
1911
- "href"
1912
- ],
1913
- "required":[
1914
- "href"
1915
- ]
1916
- },
1917
- "bdo":
1918
- {
1919
- "attributes":
1920
- {
1921
- "dir":/^(ltr|rtl)$/
1922
- },
1923
- "required":[
1924
- "dir"
1925
- ]
1926
- },
1927
- "4":"big",
1928
- "blockquote":
1929
- {
1930
- "attributes":[
1931
- "cite"
1932
- ]
1933
- },
1934
- "5":"body",
1935
- "6":"br",
1936
- "button":
1937
- {
1938
- "attributes":
1939
- {
1940
- "disabled":/^(disabled)$/,
1941
- "type":/^(button|reset|submit)$/,
1942
- "0":"value"
1943
- },
1944
- "inside":"form"
1945
- },
1946
- "7":"caption",
1947
- "8":"cite",
1948
- "9":"code",
1949
- "col":
1950
- {
1951
- "attributes":
1952
- {
1953
- "align":/^(right|left|center|justify)$/,
1954
- "0":"char",
1955
- "1":"charoff",
1956
- "span":/^(\d)+$/,
1957
- "valign":/^(top|middle|bottom|baseline)$/,
1958
- "2":"width"
1959
- },
1960
- "inside":"colgroup"
1961
- },
1962
- "colgroup":
1963
- {
1964
- "attributes":
1965
- {
1966
- "align":/^(right|left|center|justify)$/,
1967
- "0":"char",
1968
- "1":"charoff",
1969
- "span":/^(\d)+$/,
1970
- "valign":/^(top|middle|bottom|baseline)$/,
1971
- "2":"width"
1972
- }
1973
- },
1974
- "10":"dd",
1975
- "del":
1976
- {
1977
- "attributes":
1978
- {
1979
- "0":"cite",
1980
- "datetime":/^([0-9]){8}/
1981
- }
1982
- },
1983
- "11":"div",
1984
- "12":"dfn",
1985
- "13":"dl",
1986
- "14":"dt",
1987
- "15":"em",
1988
- "fieldset":
1989
- {
1990
- "inside":"form"
1991
- },
1992
- "form":
1993
- {
1994
- "attributes":
1995
- {
1996
- "0":"action",
1997
- "1":"accept",
1998
- "2":"accept-charset",
1999
- "3":"enctype",
2000
- "method":/^(get|post)$/
2001
- },
2002
- "required":[
2003
- "action"
2004
- ]
2005
- },
2006
- "head":
2007
- {
2008
- "attributes":[
2009
- "profile"
2010
- ]
2011
- },
2012
- "16":"h1",
2013
- "17":"h2",
2014
- "18":"h3",
2015
- "19":"h4",
2016
- "20":"h5",
2017
- "21":"h6",
2018
- "22":"hr",
2019
- "html":
2020
- {
2021
- "attributes":[
2022
- "xmlns"
2023
- ]
2024
- },
2025
- "23":"i",
2026
- "img":
2027
- {
2028
- "attributes":[
2029
- "alt",
2030
- "src",
2031
- "height",
2032
- "ismap",
2033
- "longdesc",
2034
- "usemap",
2035
- "width"
2036
- ],
2037
- "required":[
2038
- "alt",
2039
- "src"
2040
- ]
2041
- },
2042
- "input":
2043
- {
2044
- "attributes":
2045
- {
2046
- "0":"accept",
2047
- "1":"alt",
2048
- "checked":/^(checked)$/,
2049
- "disabled":/^(disabled)$/,
2050
- "maxlength":/^(\d)+$/,
2051
- "2":"name",
2052
- "readonly":/^(readonly)$/,
2053
- "size":/^(\d)+$/,
2054
- "3":"src",
2055
- "type":/^(button|checkbox|file|hidden|image|password|radio|reset|submit|text)$/,
2056
- "4":"value"
2057
- },
2058
- "inside":"form"
2059
- },
2060
- "ins":
2061
- {
2062
- "attributes":
2063
- {
2064
- "0":"cite",
2065
- "datetime":/^([0-9]){8}/
2066
- }
2067
- },
2068
- "24":"kbd",
2069
- "label":
2070
- {
2071
- "attributes":[
2072
- "for"
2073
- ],
2074
- "inside":"form"
2075
- },
2076
- "25":"legend",
2077
- "26":"li",
2078
- "link":
2079
- {
2080
- "attributes":
2081
- {
2082
- "0":"charset",
2083
- "1":"href",
2084
- "2":"hreflang",
2085
- "media":/^(all|braille|print|projection|screen|speech|,|;| )+$/i,
2086
- //next comment line required by Opera!
2087
- /*"rel":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i,*/
2088
- "rel":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i,
2089
- "rev":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i,
2090
- "3":"type"
2091
- },
2092
- "inside":"head"
2093
- },
2094
- "map":
2095
- {
2096
- "attributes":[
2097
- "id",
2098
- "name"
2099
- ],
2100
- "required":[
2101
- "id"
2102
- ]
2103
- },
2104
- "meta":
2105
- {
2106
- "attributes":
2107
- {
2108
- "0":"content",
2109
- "http-equiv":/^(content\-type|expires|refresh|set\-cookie)$/i,
2110
- "1":"name",
2111
- "2":"scheme"
2112
- },
2113
- "required":[
2114
- "content"
2115
- ]
2116
- },
2117
- "27":"noscript",
2118
- "object":
2119
- {
2120
- "attributes":[
2121
- "archive",
2122
- "classid",
2123
- "codebase",
2124
- "codetype",
2125
- "data",
2126
- "declare",
2127
- "height",
2128
- "name",
2129
- "standby",
2130
- "type",
2131
- "usemap",
2132
- "width"
2133
- ]
2134
- },
2135
- "28":"ol",
2136
- "optgroup":
2137
- {
2138
- "attributes":
2139
- {
2140
- "0":"label",
2141
- "disabled": /^(disabled)$/
2142
- },
2143
- "required":[
2144
- "label"
2145
- ]
2146
- },
2147
- "option":
2148
- {
2149
- "attributes":
2150
- {
2151
- "0":"label",
2152
- "disabled":/^(disabled)$/,
2153
- "selected":/^(selected)$/,
2154
- "1":"value"
2155
- },
2156
- "inside":"select"
2157
- },
2158
- "29":"p",
2159
- "param":
2160
- {
2161
- "attributes":
2162
- {
2163
- "0":"type",
2164
- "valuetype":/^(data|ref|object)$/,
2165
- "1":"valuetype",
2166
- "2":"value"
2167
- },
2168
- "required":[
2169
- "name"
2170
- ]
2171
- },
2172
- "30":"pre",
2173
- "q":
2174
- {
2175
- "attributes":[
2176
- "cite"
2177
- ]
2178
- },
2179
- "31":"samp",
2180
- "script":
2181
- {
2182
- "attributes":
2183
- {
2184
- "type":/^(text\/ecmascript|text\/javascript|text\/jscript|text\/vbscript|text\/vbs|text\/xml)$/,
2185
- "0":"charset",
2186
- "defer":/^(defer)$/,
2187
- "1":"src"
2188
- },
2189
- "required":[
2190
- "type"
2191
- ]
2192
- },
2193
- "select":
2194
- {
2195
- "attributes":
2196
- {
2197
- "disabled":/^(disabled)$/,
2198
- "multiple":/^(multiple)$/,
2199
- "0":"name",
2200
- "1":"size"
2201
- },
2202
- "inside":"form"
2203
- },
2204
- "32":"small",
2205
- "33":"span",
2206
- "34":"strong",
2207
- "style":
2208
- {
2209
- "attributes":
2210
- {
2211
- "0":"type",
2212
- "media":/^(screen|tty|tv|projection|handheld|print|braille|aural|all)$/
2213
- },
2214
- "required":[
2215
- "type"
2216
- ]
2217
- },
2218
- "35":"sub",
2219
- "36":"sup",
2220
- "table":
2221
- {
2222
- "attributes":
2223
- {
2224
- "0":"border",
2225
- "1":"cellpadding",
2226
- "2":"cellspacing",
2227
- "frame":/^(void|above|below|hsides|lhs|rhs|vsides|box|border)$/,
2228
- "rules":/^(none|groups|rows|cols|all)$/,
2229
- "3":"summary",
2230
- "4":"width"
2231
- }
2232
- },
2233
- "tbody":
2234
- {
2235
- "attributes":
2236
- {
2237
- "align":/^(right|left|center|justify)$/,
2238
- "0":"char",
2239
- "1":"charoff",
2240
- "valign":/^(top|middle|bottom|baseline)$/
2241
- }
2242
- },
2243
- "td":
2244
- {
2245
- "attributes":
2246
- {
2247
- "0":"abbr",
2248
- "align":/^(left|right|center|justify|char)$/,
2249
- "1":"axis",
2250
- "2":"char",
2251
- "3":"charoff",
2252
- "colspan":/^(\d)+$/,
2253
- "4":"headers",
2254
- "rowspan":/^(\d)+$/,
2255
- "scope":/^(col|colgroup|row|rowgroup)$/,
2256
- "valign":/^(top|middle|bottom|baseline)$/
2257
- }
2258
- },
2259
- "textarea":
2260
- {
2261
- "attributes":[
2262
- "cols",
2263
- "rows",
2264
- "disabled",
2265
- "name",
2266
- "readonly"
2267
- ],
2268
- "required":[
2269
- "cols",
2270
- "rows"
2271
- ],
2272
- "inside":"form"
2273
- },
2274
- "tfoot":
2275
- {
2276
- "attributes":
2277
- {
2278
- "align":/^(right|left|center|justify)$/,
2279
- "0":"char",
2280
- "1":"charoff",
2281
- "valign":/^(top|middle|bottom)$/,
2282
- "2":"baseline"
2283
- }
2284
- },
2285
- "th":
2286
- {
2287
- "attributes":
2288
- {
2289
- "0":"abbr",
2290
- "align":/^(left|right|center|justify|char)$/,
2291
- "1":"axis",
2292
- "2":"char",
2293
- "3":"charoff",
2294
- "colspan":/^(\d)+$/,
2295
- "4":"headers",
2296
- "rowspan":/^(\d)+$/,
2297
- "scope":/^(col|colgroup|row|rowgroup)$/,
2298
- "valign":/^(top|middle|bottom|baseline)$/
2299
- }
2300
- },
2301
- "thead":
2302
- {
2303
- "attributes":
2304
- {
2305
- "align":/^(right|left|center|justify)$/,
2306
- "0":"char",
2307
- "1":"charoff",
2308
- "valign":/^(top|middle|bottom|baseline)$/
2309
- }
2310
- },
2311
- "37":"title",
2312
- "tr":
2313
- {
2314
- "attributes":
2315
- {
2316
- "align":/^(right|left|center|justify|char)$/,
2317
- "0":"char",
2318
- "1":"charoff",
2319
- "valign":/^(top|middle|bottom|baseline)$/
2320
- }
2321
- },
2322
- "38":"tt",
2323
- "39":"ul",
2324
- "40":"var"
2325
- },
2326
-
2327
- // Temporary skiped attributes
2328
- skiped_attributes : [],
2329
- skiped_attribute_values : [],
2330
-
2331
- getValidTagAttributes: function(tag, attributes)
2332
- {
2333
- var valid_attributes = {};
2334
- var possible_attributes = this.getPossibleTagAttributes(tag);
2335
- for(var attribute in attributes) {
2336
- var value = attributes[attribute];
2337
- var h = WYMeditor.Helper;
2338
- if(!h.contains(this.skiped_attributes, attribute) && !h.contains(this.skiped_attribute_values, value)){
2339
- if (typeof value != 'function' && h.contains(possible_attributes, attribute)) {
2340
- if (this.doesAttributeNeedsValidation(tag, attribute)) {
2341
- if(this.validateAttribute(tag, attribute, value)){
2342
- valid_attributes[attribute] = value;
2343
- }
2344
- }else{
2345
- valid_attributes[attribute] = value;
2346
- }
2347
- }
2348
- }
2349
- }
2350
- return valid_attributes;
2351
- },
2352
- getUniqueAttributesAndEventsForTag : function(tag)
2353
- {
2354
- var result = [];
2355
-
2356
- if (this._tags[tag] && this._tags[tag]['attributes']) {
2357
- for (k in this._tags[tag]['attributes']) {
2358
- result.push(parseInt(k) == k ? this._tags[tag]['attributes'][k] : k);
2359
- }
2360
- }
2361
- return result;
2362
- },
2363
- getDefaultAttributesAndEventsForTags : function()
2364
- {
2365
- var result = [];
2366
- for (var key in this._events){
2367
- result.push(this._events[key]);
2368
- }
2369
- for (var key in this._attributes){
2370
- result.push(this._attributes[key]);
2371
- }
2372
- return result;
2373
- },
2374
- isValidTag : function(tag)
2375
- {
2376
- if(this._tags[tag]){
2377
- return true;
2378
- }
2379
- for(var key in this._tags){
2380
- if(this._tags[key] == tag){
2381
- return true;
2382
- }
2383
- }
2384
- return false;
2385
- },
2386
- getDefaultAttributesAndEventsForTag : function(tag)
2387
- {
2388
- var default_attributes = [];
2389
- if (this.isValidTag(tag)) {
2390
- var default_attributes_and_events = this.getDefaultAttributesAndEventsForTags();
2391
-
2392
- for(var key in default_attributes_and_events) {
2393
- var defaults = default_attributes_and_events[key];
2394
- if(typeof defaults == 'object'){
2395
- var h = WYMeditor.Helper;
2396
- if ((defaults['except'] && h.contains(defaults['except'], tag)) || (defaults['only'] && !h.contains(defaults['only'], tag))) {
2397
- continue;
2398
- }
2399
-
2400
- var tag_defaults = defaults['attributes'] ? defaults['attributes'] : defaults['events'];
2401
- for(var k in tag_defaults) {
2402
- default_attributes.push(typeof tag_defaults[k] != 'string' ? k : tag_defaults[k]);
2403
- }
2404
- }
2405
- }
2406
- }
2407
- return default_attributes;
2408
- },
2409
- doesAttributeNeedsValidation: function(tag, attribute)
2410
- {
2411
- return this._tags[tag] && ((this._tags[tag]['attributes'] && this._tags[tag]['attributes'][attribute]) || (this._tags[tag]['required'] &&
2412
- WYMeditor.Helper.contains(this._tags[tag]['required'], attribute)));
2413
- },
2414
- validateAttribute : function(tag, attribute, value)
2415
- {
2416
- if ( this._tags[tag] &&
2417
- (this._tags[tag]['attributes'] && this._tags[tag]['attributes'][attribute] && value.length > 0 && !value.match(this._tags[tag]['attributes'][attribute])) || // invalid format
2418
- (this._tags[tag] && this._tags[tag]['required'] && WYMeditor.Helper.contains(this._tags[tag]['required'], attribute) && value.length == 0) // required attribute
2419
- ) {
2420
- return false;
2421
- }
2422
- return typeof this._tags[tag] != 'undefined';
2423
- },
2424
- getPossibleTagAttributes : function(tag)
2425
- {
2426
- if (!this._possible_tag_attributes) {
2427
- this._possible_tag_attributes = {};
2428
- }
2429
- if (!this._possible_tag_attributes[tag]) {
2430
- this._possible_tag_attributes[tag] = this.getUniqueAttributesAndEventsForTag(tag).concat(this.getDefaultAttributesAndEventsForTag(tag));
2431
- }
2432
- return this._possible_tag_attributes[tag];
2433
- }
2434
- };
2435
-
2436
-
2437
- /**
2438
- * Compounded regular expression. Any of
2439
- * the contained patterns could match and
2440
- * when one does, it's label is returned.
2441
- *
2442
- * Constructor. Starts with no patterns.
2443
- * @param boolean case True for case sensitive, false
2444
- * for insensitive.
2445
- * @access public
2446
- * @author Marcus Baker (http://lastcraft.com)
2447
- * @author Bermi Ferrer (http://bermi.org)
2448
- */
2449
- WYMeditor.ParallelRegex = function(case_sensitive)
2450
- {
2451
- this._case = case_sensitive;
2452
- this._patterns = [];
2453
- this._labels = [];
2454
- this._regex = null;
2455
- return this;
2456
- };
2457
-
2458
-
2459
- /**
2460
- * Adds a pattern with an optional label.
2461
- * @param string pattern Perl style regex, but ( and )
2462
- * lose the usual meaning.
2463
- * @param string label Label of regex to be returned
2464
- * on a match.
2465
- * @access public
2466
- */
2467
- WYMeditor.ParallelRegex.prototype.addPattern = function(pattern, label)
2468
- {
2469
- label = label || true;
2470
- var count = this._patterns.length;
2471
- this._patterns[count] = pattern;
2472
- this._labels[count] = label;
2473
- this._regex = null;
2474
- };
2475
-
2476
- /**
2477
- * Attempts to match all patterns at once against
2478
- * a string.
2479
- * @param string subject String to match against.
2480
- *
2481
- * @return boolean True on success.
2482
- * @return string match First matched portion of
2483
- * subject.
2484
- * @access public
2485
- */
2486
- WYMeditor.ParallelRegex.prototype.match = function(subject)
2487
- {
2488
- if (this._patterns.length == 0) {
2489
- return [false, ''];
2490
- }
2491
- var matches = subject.match(this._getCompoundedRegex());
2492
-
2493
- if(!matches){
2494
- return [false, ''];
2495
- }
2496
- var match = matches[0];
2497
- for (var i = 1; i < matches.length; i++) {
2498
- if (matches[i]) {
2499
- return [this._labels[i-1], match];
2500
- }
2501
- }
2502
- return [true, matches[0]];
2503
- };
2504
-
2505
- /**
2506
- * Compounds the patterns into a single
2507
- * regular expression separated with the
2508
- * "or" operator. Caches the regex.
2509
- * Will automatically escape (, ) and / tokens.
2510
- * @param array patterns List of patterns in order.
2511
- * @access private
2512
- */
2513
- WYMeditor.ParallelRegex.prototype._getCompoundedRegex = function()
2514
- {
2515
- if (this._regex == null) {
2516
- for (var i = 0, count = this._patterns.length; i < count; i++) {
2517
- this._patterns[i] = '(' + this._untokenizeRegex(this._tokenizeRegex(this._patterns[i]).replace(/([\/\(\)])/g,'\\$1')) + ')';
2518
- }
2519
- this._regex = new RegExp(this._patterns.join("|") ,this._getPerlMatchingFlags());
2520
- }
2521
- return this._regex;
2522
- };
2523
-
2524
- /**
2525
- * Escape lookahead/lookbehind blocks
2526
- */
2527
- WYMeditor.ParallelRegex.prototype._tokenizeRegex = function(regex)
2528
- {
2529
- return regex.
2530
- replace(/\(\?(i|m|s|x|U)\)/, '~~~~~~Tk1\$1~~~~~~').
2531
- replace(/\(\?(\-[i|m|s|x|U])\)/, '~~~~~~Tk2\$1~~~~~~').
2532
- replace(/\(\?\=(.*)\)/, '~~~~~~Tk3\$1~~~~~~').
2533
- replace(/\(\?\!(.*)\)/, '~~~~~~Tk4\$1~~~~~~').
2534
- replace(/\(\?\<\=(.*)\)/, '~~~~~~Tk5\$1~~~~~~').
2535
- replace(/\(\?\<\!(.*)\)/, '~~~~~~Tk6\$1~~~~~~').
2536
- replace(/\(\?\:(.*)\)/, '~~~~~~Tk7\$1~~~~~~');
2537
- };
2538
-
2539
- /**
2540
- * Unscape lookahead/lookbehind blocks
2541
- */
2542
- WYMeditor.ParallelRegex.prototype._untokenizeRegex = function(regex)
2543
- {
2544
- return regex.
2545
- replace(/~~~~~~Tk1(.{1})~~~~~~/, "(?\$1)").
2546
- replace(/~~~~~~Tk2(.{2})~~~~~~/, "(?\$1)").
2547
- replace(/~~~~~~Tk3(.*)~~~~~~/, "(?=\$1)").
2548
- replace(/~~~~~~Tk4(.*)~~~~~~/, "(?!\$1)").
2549
- replace(/~~~~~~Tk5(.*)~~~~~~/, "(?<=\$1)").
2550
- replace(/~~~~~~Tk6(.*)~~~~~~/, "(?<!\$1)").
2551
- replace(/~~~~~~Tk7(.*)~~~~~~/, "(?:\$1)");
2552
- };
2553
-
2554
-
2555
- /**
2556
- * Accessor for perl regex mode flags to use.
2557
- * @return string Perl regex flags.
2558
- * @access private
2559
- */
2560
- WYMeditor.ParallelRegex.prototype._getPerlMatchingFlags = function()
2561
- {
2562
- return (this._case ? "m" : "mi");
2563
- };
2564
-
2565
-
2566
-
2567
- /**
2568
- * States for a stack machine.
2569
- *
2570
- * Constructor. Starts in named state.
2571
- * @param string start Starting state name.
2572
- * @access public
2573
- * @author Marcus Baker (http://lastcraft.com)
2574
- * @author Bermi Ferrer (http://bermi.org)
2575
- */
2576
- WYMeditor.StateStack = function(start)
2577
- {
2578
- this._stack = [start];
2579
- return this;
2580
- };
2581
-
2582
- /**
2583
- * Accessor for current state.
2584
- * @return string State.
2585
- * @access public
2586
- */
2587
- WYMeditor.StateStack.prototype.getCurrent = function()
2588
- {
2589
- return this._stack[this._stack.length - 1];
2590
- };
2591
-
2592
- /**
2593
- * Adds a state to the stack and sets it
2594
- * to be the current state.
2595
- * @param string state New state.
2596
- * @access public
2597
- */
2598
- WYMeditor.StateStack.prototype.enter = function(state)
2599
- {
2600
- this._stack.push(state);
2601
- };
2602
-
2603
- /**
2604
- * Leaves the current state and reverts
2605
- * to the previous one.
2606
- * @return boolean False if we drop off
2607
- * the bottom of the list.
2608
- * @access public
2609
- */
2610
- WYMeditor.StateStack.prototype.leave = function()
2611
- {
2612
- if (this._stack.length == 1) {
2613
- return false;
2614
- }
2615
- this._stack.pop();
2616
- return true;
2617
- };
2618
-
2619
-
2620
- // GLOBALS
2621
- WYMeditor.LEXER_ENTER = 1;
2622
- WYMeditor.LEXER_MATCHED = 2;
2623
- WYMeditor.LEXER_UNMATCHED = 3;
2624
- WYMeditor.LEXER_EXIT = 4;
2625
- WYMeditor.LEXER_SPECIAL = 5;
2626
-
2627
-
2628
- /**
2629
- * Accepts text and breaks it into tokens.
2630
- * Some optimisation to make the sure the
2631
- * content is only scanned by the PHP regex
2632
- * parser once. Lexer modes must not start
2633
- * with leading underscores.
2634
- *
2635
- * Sets up the lexer in case insensitive matching
2636
- * by default.
2637
- * @param Parser parser Handling strategy by reference.
2638
- * @param string start Starting handler.
2639
- * @param boolean case True for case sensitive.
2640
- * @access public
2641
- * @author Marcus Baker (http://lastcraft.com)
2642
- * @author Bermi Ferrer (http://bermi.org)
2643
- */
2644
- WYMeditor.Lexer = function(parser, start, case_sensitive)
2645
- {
2646
- start = start || 'accept';
2647
- this._case = case_sensitive || false;
2648
- this._regexes = {};
2649
- this._parser = parser;
2650
- this._mode = new WYMeditor.StateStack(start);
2651
- this._mode_handlers = {};
2652
- this._mode_handlers[start] = start;
2653
- return this;
2654
- };
2655
-
2656
- /**
2657
- * Adds a token search pattern for a particular
2658
- * parsing mode. The pattern does not change the
2659
- * current mode.
2660
- * @param string pattern Perl style regex, but ( and )
2661
- * lose the usual meaning.
2662
- * @param string mode Should only apply this
2663
- * pattern when dealing with
2664
- * this type of input.
2665
- * @access public
2666
- */
2667
- WYMeditor.Lexer.prototype.addPattern = function(pattern, mode)
2668
- {
2669
- var mode = mode || "accept";
2670
- if (typeof this._regexes[mode] == 'undefined') {
2671
- this._regexes[mode] = new WYMeditor.ParallelRegex(this._case);
2672
- }
2673
- this._regexes[mode].addPattern(pattern);
2674
- if (typeof this._mode_handlers[mode] == 'undefined') {
2675
- this._mode_handlers[mode] = mode;
2676
- }
2677
- };
2678
-
2679
- /**
2680
- * Adds a pattern that will enter a new parsing
2681
- * mode. Useful for entering parenthesis, strings,
2682
- * tags, etc.
2683
- * @param string pattern Perl style regex, but ( and )
2684
- * lose the usual meaning.
2685
- * @param string mode Should only apply this
2686
- * pattern when dealing with
2687
- * this type of input.
2688
- * @param string new_mode Change parsing to this new
2689
- * nested mode.
2690
- * @access public
2691
- */
2692
- WYMeditor.Lexer.prototype.addEntryPattern = function(pattern, mode, new_mode)
2693
- {
2694
- if (typeof this._regexes[mode] == 'undefined') {
2695
- this._regexes[mode] = new WYMeditor.ParallelRegex(this._case);
2696
- }
2697
- this._regexes[mode].addPattern(pattern, new_mode);
2698
- if (typeof this._mode_handlers[new_mode] == 'undefined') {
2699
- this._mode_handlers[new_mode] = new_mode;
2700
- }
2701
- };
2702
-
2703
- /**
2704
- * Adds a pattern that will exit the current mode
2705
- * and re-enter the previous one.
2706
- * @param string pattern Perl style regex, but ( and )
2707
- * lose the usual meaning.
2708
- * @param string mode Mode to leave.
2709
- * @access public
2710
- */
2711
- WYMeditor.Lexer.prototype.addExitPattern = function(pattern, mode)
2712
- {
2713
- if (typeof this._regexes[mode] == 'undefined') {
2714
- this._regexes[mode] = new WYMeditor.ParallelRegex(this._case);
2715
- }
2716
- this._regexes[mode].addPattern(pattern, "__exit");
2717
- if (typeof this._mode_handlers[mode] == 'undefined') {
2718
- this._mode_handlers[mode] = mode;
2719
- }
2720
- };
2721
-
2722
- /**
2723
- * Adds a pattern that has a special mode. Acts as an entry
2724
- * and exit pattern in one go, effectively calling a special
2725
- * parser handler for this token only.
2726
- * @param string pattern Perl style regex, but ( and )
2727
- * lose the usual meaning.
2728
- * @param string mode Should only apply this
2729
- * pattern when dealing with
2730
- * this type of input.
2731
- * @param string special Use this mode for this one token.
2732
- * @access public
2733
- */
2734
- WYMeditor.Lexer.prototype.addSpecialPattern = function(pattern, mode, special)
2735
- {
2736
- if (typeof this._regexes[mode] == 'undefined') {
2737
- this._regexes[mode] = new WYMeditor.ParallelRegex(this._case);
2738
- }
2739
- this._regexes[mode].addPattern(pattern, '_'+special);
2740
- if (typeof this._mode_handlers[special] == 'undefined') {
2741
- this._mode_handlers[special] = special;
2742
- }
2743
- };
2744
-
2745
- /**
2746
- * Adds a mapping from a mode to another handler.
2747
- * @param string mode Mode to be remapped.
2748
- * @param string handler New target handler.
2749
- * @access public
2750
- */
2751
- WYMeditor.Lexer.prototype.mapHandler = function(mode, handler)
2752
- {
2753
- this._mode_handlers[mode] = handler;
2754
- };
2755
-
2756
- /**
2757
- * Splits the page text into tokens. Will fail
2758
- * if the handlers report an error or if no
2759
- * content is consumed. If successful then each
2760
- * unparsed and parsed token invokes a call to the
2761
- * held listener.
2762
- * @param string raw Raw HTML text.
2763
- * @return boolean True on success, else false.
2764
- * @access public
2765
- */
2766
- WYMeditor.Lexer.prototype.parse = function(raw)
2767
- {
2768
- if (typeof this._parser == 'undefined') {
2769
- return false;
2770
- }
2771
-
2772
- var length = raw.length;
2773
- var parsed;
2774
- while (typeof (parsed = this._reduce(raw)) == 'object') {
2775
- var raw = parsed[0];
2776
- var unmatched = parsed[1];
2777
- var matched = parsed[2];
2778
- var mode = parsed[3];
2779
-
2780
- if (! this._dispatchTokens(unmatched, matched, mode)) {
2781
- return false;
2782
- }
2783
-
2784
- if (raw == '') {
2785
- return true;
2786
- }
2787
- if (raw.length == length) {
2788
- return false;
2789
- }
2790
- length = raw.length;
2791
- }
2792
- if (! parsed ) {
2793
- return false;
2794
- }
2795
-
2796
- return this._invokeParser(raw, WYMeditor.LEXER_UNMATCHED);
2797
- };
2798
-
2799
- /**
2800
- * Sends the matched token and any leading unmatched
2801
- * text to the parser changing the lexer to a new
2802
- * mode if one is listed.
2803
- * @param string unmatched Unmatched leading portion.
2804
- * @param string matched Actual token match.
2805
- * @param string mode Mode after match. A boolean
2806
- * false mode causes no change.
2807
- * @return boolean False if there was any error
2808
- * from the parser.
2809
- * @access private
2810
- */
2811
- WYMeditor.Lexer.prototype._dispatchTokens = function(unmatched, matched, mode)
2812
- {
2813
- mode = mode || false;
2814
-
2815
- if (! this._invokeParser(unmatched, WYMeditor.LEXER_UNMATCHED)) {
2816
- return false;
2817
- }
2818
-
2819
- if (typeof mode == 'boolean') {
2820
- return this._invokeParser(matched, WYMeditor.LEXER_MATCHED);
2821
- }
2822
- if (this._isModeEnd(mode)) {
2823
- if (! this._invokeParser(matched, WYMeditor.LEXER_EXIT)) {
2824
- return false;
2825
- }
2826
- return this._mode.leave();
2827
- }
2828
- if (this._isSpecialMode(mode)) {
2829
- this._mode.enter(this._decodeSpecial(mode));
2830
- if (! this._invokeParser(matched, WYMeditor.LEXER_SPECIAL)) {
2831
- return false;
2832
- }
2833
- return this._mode.leave();
2834
- }
2835
- this._mode.enter(mode);
2836
-
2837
- return this._invokeParser(matched, WYMeditor.LEXER_ENTER);
2838
- };
2839
-
2840
- /**
2841
- * Tests to see if the new mode is actually to leave
2842
- * the current mode and pop an item from the matching
2843
- * mode stack.
2844
- * @param string mode Mode to test.
2845
- * @return boolean True if this is the exit mode.
2846
- * @access private
2847
- */
2848
- WYMeditor.Lexer.prototype._isModeEnd = function(mode)
2849
- {
2850
- return (mode === "__exit");
2851
- };
2852
-
2853
- /**
2854
- * Test to see if the mode is one where this mode
2855
- * is entered for this token only and automatically
2856
- * leaves immediately afterwoods.
2857
- * @param string mode Mode to test.
2858
- * @return boolean True if this is the exit mode.
2859
- * @access private
2860
- */
2861
- WYMeditor.Lexer.prototype._isSpecialMode = function(mode)
2862
- {
2863
- return (mode.substring(0,1) == "_");
2864
- };
2865
-
2866
- /**
2867
- * Strips the magic underscore marking single token
2868
- * modes.
2869
- * @param string mode Mode to decode.
2870
- * @return string Underlying mode name.
2871
- * @access private
2872
- */
2873
- WYMeditor.Lexer.prototype._decodeSpecial = function(mode)
2874
- {
2875
- return mode.substring(1);
2876
- };
2877
-
2878
- /**
2879
- * Calls the parser method named after the current
2880
- * mode. Empty content will be ignored. The lexer
2881
- * has a parser handler for each mode in the lexer.
2882
- * @param string content Text parsed.
2883
- * @param boolean is_match Token is recognised rather
2884
- * than unparsed data.
2885
- * @access private
2886
- */
2887
- WYMeditor.Lexer.prototype._invokeParser = function(content, is_match)
2888
- {
2889
-
2890
- if (!/ +/.test(content) && ((content === '') || (content == false))) {
2891
- return true;
2892
- }
2893
- var current = this._mode.getCurrent();
2894
- var handler = this._mode_handlers[current];
2895
- var result;
2896
- eval('result = this._parser.' + handler + '(content, is_match);');
2897
- return result;
2898
- };
2899
-
2900
- /**
2901
- * Tries to match a chunk of text and if successful
2902
- * removes the recognised chunk and any leading
2903
- * unparsed data. Empty strings will not be matched.
2904
- * @param string raw The subject to parse. This is the
2905
- * content that will be eaten.
2906
- * @return array/boolean Three item list of unparsed
2907
- * content followed by the
2908
- * recognised token and finally the
2909
- * action the parser is to take.
2910
- * True if no match, false if there
2911
- * is a parsing error.
2912
- * @access private
2913
- */
2914
- WYMeditor.Lexer.prototype._reduce = function(raw)
2915
- {
2916
- var matched = this._regexes[this._mode.getCurrent()].match(raw);
2917
- var match = matched[1];
2918
- var action = matched[0];
2919
- if (action) {
2920
- var unparsed_character_count = raw.indexOf(match);
2921
- var unparsed = raw.substr(0, unparsed_character_count);
2922
- raw = raw.substring(unparsed_character_count + match.length);
2923
- return [raw, unparsed, match, action];
2924
- }
2925
- return true;
2926
- };
2927
-
2928
-
2929
-
2930
- /**
2931
- * This are the rules for breaking the XHTML code into events
2932
- * handled by the provided parser.
2933
- *
2934
- * @author Marcus Baker (http://lastcraft.com)
2935
- * @author Bermi Ferrer (http://bermi.org)
2936
- */
2937
- WYMeditor.XhtmlLexer = function(parser)
2938
- {
2939
- jQuery.extend(this, new WYMeditor.Lexer(parser, 'Text'));
2940
-
2941
- this.mapHandler('Text', 'Text');
2942
-
2943
- this.addTokens();
2944
-
2945
- this.init();
2946
-
2947
- return this;
2948
- };
2949
-
2950
-
2951
- WYMeditor.XhtmlLexer.prototype.init = function()
2952
- {
2953
- };
2954
-
2955
- WYMeditor.XhtmlLexer.prototype.addTokens = function()
2956
- {
2957
- this.addCommentTokens('Text');
2958
- this.addScriptTokens('Text');
2959
- this.addCssTokens('Text');
2960
- this.addTagTokens('Text');
2961
- };
2962
-
2963
- WYMeditor.XhtmlLexer.prototype.addCommentTokens = function(scope)
2964
- {
2965
- this.addEntryPattern("<!--", scope, 'Comment');
2966
- this.addExitPattern("-->", 'Comment');
2967
- };
2968
-
2969
- WYMeditor.XhtmlLexer.prototype.addScriptTokens = function(scope)
2970
- {
2971
- this.addEntryPattern("<script", scope, 'Script');
2972
- this.addExitPattern("</script>", 'Script');
2973
- };
2974
-
2975
- WYMeditor.XhtmlLexer.prototype.addCssTokens = function(scope)
2976
- {
2977
- this.addEntryPattern("<style", scope, 'Css');
2978
- this.addExitPattern("</style>", 'Css');
2979
- };
2980
-
2981
- WYMeditor.XhtmlLexer.prototype.addTagTokens = function(scope)
2982
- {
2983
- this.addSpecialPattern("<\\s*[a-z0-9:\-]+\\s*>", scope, 'OpeningTag');
2984
- this.addEntryPattern("<[a-z0-9:\-]+"+'[\\\/ \\\>]+', scope, 'OpeningTag');
2985
- this.addInTagDeclarationTokens('OpeningTag');
2986
-
2987
- this.addSpecialPattern("</\\s*[a-z0-9:\-]+\\s*>", scope, 'ClosingTag');
2988
-
2989
- };
2990
-
2991
- WYMeditor.XhtmlLexer.prototype.addInTagDeclarationTokens = function(scope)
2992
- {
2993
- this.addSpecialPattern('\\s+', scope, 'Ignore');
2994
-
2995
- this.addAttributeTokens(scope);
2996
-
2997
- this.addExitPattern('/>', scope);
2998
- this.addExitPattern('>', scope);
2999
-
3000
- };
3001
-
3002
- WYMeditor.XhtmlLexer.prototype.addAttributeTokens = function(scope)
3003
- {
3004
- this.addSpecialPattern("\\s*[a-z-_0-9]*:?[a-z-_0-9]+\\s*(?=\=)\\s*", scope, 'TagAttributes');
3005
-
3006
- this.addEntryPattern('=\\s*"', scope, 'DoubleQuotedAttribute');
3007
- this.addPattern("\\\\\"", 'DoubleQuotedAttribute');
3008
- this.addExitPattern('"', 'DoubleQuotedAttribute');
3009
-
3010
- this.addEntryPattern("=\\s*'", scope, 'SingleQuotedAttribute');
3011
- this.addPattern("\\\\'", 'SingleQuotedAttribute');
3012
- this.addExitPattern("'", 'SingleQuotedAttribute');
3013
-
3014
- this.addSpecialPattern('=\\s*[^>\\s]*', scope, 'UnquotedAttribute');
3015
- };
3016
-
3017
-
3018
-
3019
- /**
3020
- * XHTML Parser.
3021
- *
3022
- * This XHTML parser will trigger the events available on on
3023
- * current SaxListener
3024
- *
3025
- * @author Bermi Ferrer (http://bermi.org)
3026
- */
3027
- WYMeditor.XhtmlParser = function(Listener, mode)
3028
- {
3029
- var mode = mode || 'Text';
3030
- this._Lexer = new WYMeditor.XhtmlLexer(this);
3031
- this._Listener = Listener;
3032
- this._mode = mode;
3033
- this._matches = [];
3034
- this._last_match = '';
3035
- this._current_match = '';
3036
-
3037
- return this;
3038
- };
3039
-
3040
- WYMeditor.XhtmlParser.prototype.parse = function(raw)
3041
- {
3042
- this._Lexer.parse(this.beforeParsing(raw));
3043
- return this.afterParsing(this._Listener.getResult());
3044
- };
3045
-
3046
- WYMeditor.XhtmlParser.prototype.beforeParsing = function(raw)
3047
- {
3048
- if(raw.match(/class="MsoNormal"/) || raw.match(/ns = "urn:schemas-microsoft-com/)){
3049
- // Usefull for cleaning up content pasted from other sources (MSWord)
3050
- this._Listener.avoidStylingTagsAndAttributes();
3051
- }
3052
- return this._Listener.beforeParsing(raw);
3053
- };
3054
-
3055
- WYMeditor.XhtmlParser.prototype.afterParsing = function(parsed)
3056
- {
3057
- if(this._Listener._avoiding_tags_implicitly){
3058
- this._Listener.allowStylingTagsAndAttributes();
3059
- }
3060
- return this._Listener.afterParsing(parsed);
3061
- };
3062
-
3063
-
3064
- WYMeditor.XhtmlParser.prototype.Ignore = function(match, state)
3065
- {
3066
- return true;
3067
- };
3068
-
3069
- WYMeditor.XhtmlParser.prototype.Text = function(text)
3070
- {
3071
- this._Listener.addContent(text);
3072
- return true;
3073
- };
3074
-
3075
- WYMeditor.XhtmlParser.prototype.Comment = function(match, status)
3076
- {
3077
- return this._addNonTagBlock(match, status, 'addComment');
3078
- };
3079
-
3080
- WYMeditor.XhtmlParser.prototype.Script = function(match, status)
3081
- {
3082
- return this._addNonTagBlock(match, status, 'addScript');
3083
- };
3084
-
3085
- WYMeditor.XhtmlParser.prototype.Css = function(match, status)
3086
- {
3087
- return this._addNonTagBlock(match, status, 'addCss');
3088
- };
3089
-
3090
- WYMeditor.XhtmlParser.prototype._addNonTagBlock = function(match, state, type)
3091
- {
3092
- switch (state){
3093
- case WYMeditor.LEXER_ENTER:
3094
- this._non_tag = match;
3095
- break;
3096
- case WYMeditor.LEXER_UNMATCHED:
3097
- this._non_tag += match;
3098
- break;
3099
- case WYMeditor.LEXER_EXIT:
3100
- switch(type) {
3101
- case 'addComment':
3102
- this._Listener.addComment(this._non_tag+match);
3103
- break;
3104
- case 'addScript':
3105
- this._Listener.addScript(this._non_tag+match);
3106
- break;
3107
- case 'addCss':
3108
- this._Listener.addCss(this._non_tag+match);
3109
- break;
3110
- }
3111
- }
3112
- return true;
3113
- };
3114
-
3115
- WYMeditor.XhtmlParser.prototype.OpeningTag = function(match, state)
3116
- {
3117
- switch (state){
3118
- case WYMeditor.LEXER_ENTER:
3119
- this._tag = this.normalizeTag(match);
3120
- this._tag_attributes = {};
3121
- break;
3122
- case WYMeditor.LEXER_SPECIAL:
3123
- this._callOpenTagListener(this.normalizeTag(match));
3124
- break;
3125
- case WYMeditor.LEXER_EXIT:
3126
- this._callOpenTagListener(this._tag, this._tag_attributes);
3127
- }
3128
- return true;
3129
- };
3130
-
3131
- WYMeditor.XhtmlParser.prototype.ClosingTag = function(match, state)
3132
- {
3133
- this._callCloseTagListener(this.normalizeTag(match));
3134
- return true;
3135
- };
3136
-
3137
- WYMeditor.XhtmlParser.prototype._callOpenTagListener = function(tag, attributes)
3138
- {
3139
- var attributes = attributes || {};
3140
- this.autoCloseUnclosedBeforeNewOpening(tag);
3141
-
3142
- if(this._Listener.isBlockTag(tag)){
3143
- this._Listener._tag_stack.push(tag);
3144
- this._Listener.fixNestingBeforeOpeningBlockTag(tag, attributes);
3145
- this._Listener.openBlockTag(tag, attributes);
3146
- this._increaseOpenTagCounter(tag);
3147
- }else if(this._Listener.isInlineTag(tag)){
3148
- this._Listener.inlineTag(tag, attributes);
3149
- }else{
3150
- this._Listener.openUnknownTag(tag, attributes);
3151
- this._increaseOpenTagCounter(tag);
3152
- }
3153
- this._Listener.last_tag = tag;
3154
- this._Listener.last_tag_opened = true;
3155
- this._Listener.last_tag_attributes = attributes;
3156
- };
3157
-
3158
- WYMeditor.XhtmlParser.prototype._callCloseTagListener = function(tag)
3159
- {
3160
- if(this._decreaseOpenTagCounter(tag)){
3161
- this.autoCloseUnclosedBeforeTagClosing(tag);
3162
-
3163
- if(this._Listener.isBlockTag(tag)){
3164
- var expected_tag = this._Listener._tag_stack.pop();
3165
- if(expected_tag == false){
3166
- return;
3167
- }else if(expected_tag != tag){
3168
- tag = expected_tag;
3169
- }
3170
- this._Listener.closeBlockTag(tag);
3171
- }else{
3172
- this._Listener.closeUnknownTag(tag);
3173
- }
3174
- }else{
3175
- this._Listener.closeUnopenedTag(tag);
3176
- }
3177
- this._Listener.last_tag = tag;
3178
- this._Listener.last_tag_opened = false;
3179
- };
3180
-
3181
- WYMeditor.XhtmlParser.prototype._increaseOpenTagCounter = function(tag)
3182
- {
3183
- this._Listener._open_tags[tag] = this._Listener._open_tags[tag] || 0;
3184
- this._Listener._open_tags[tag]++;
3185
- };
3186
-
3187
- WYMeditor.XhtmlParser.prototype._decreaseOpenTagCounter = function(tag)
3188
- {
3189
- if(this._Listener._open_tags[tag]){
3190
- this._Listener._open_tags[tag]--;
3191
- if(this._Listener._open_tags[tag] == 0){
3192
- this._Listener._open_tags[tag] = undefined;
3193
- }
3194
- return true;
3195
- }
3196
- return false;
3197
- };
3198
-
3199
- WYMeditor.XhtmlParser.prototype.autoCloseUnclosedBeforeNewOpening = function(new_tag)
3200
- {
3201
- this._autoCloseUnclosed(new_tag, false);
3202
- };
3203
-
3204
- WYMeditor.XhtmlParser.prototype.autoCloseUnclosedBeforeTagClosing = function(tag)
3205
- {
3206
- this._autoCloseUnclosed(tag, true);
3207
- };
3208
-
3209
- WYMeditor.XhtmlParser.prototype._autoCloseUnclosed = function(new_tag, closing)
3210
- {
3211
- var closing = closing || false;
3212
- if(this._Listener._open_tags){
3213
- for (var tag in this._Listener._open_tags) {
3214
- var counter = this._Listener._open_tags[tag];
3215
- if(counter > 0 && this._Listener.shouldCloseTagAutomatically(tag, new_tag, closing)){
3216
- this._callCloseTagListener(tag, true);
3217
- }
3218
- }
3219
- }
3220
- };
3221
-
3222
- WYMeditor.XhtmlParser.prototype.getTagReplacements = function()
3223
- {
3224
- return this._Listener.getTagReplacements();
3225
- };
3226
-
3227
- WYMeditor.XhtmlParser.prototype.normalizeTag = function(tag)
3228
- {
3229
- tag = tag.replace(/^([\s<\/>]*)|([\s<\/>]*)$/gm,'').toLowerCase();
3230
- var tags = this._Listener.getTagReplacements();
3231
- if(tags[tag]){
3232
- return tags[tag];
3233
- }
3234
- return tag;
3235
- };
3236
-
3237
- WYMeditor.XhtmlParser.prototype.TagAttributes = function(match, state)
3238
- {
3239
- if(WYMeditor.LEXER_SPECIAL == state){
3240
- this._current_attribute = match;
3241
- }
3242
- return true;
3243
- };
3244
-
3245
- WYMeditor.XhtmlParser.prototype.DoubleQuotedAttribute = function(match, state)
3246
- {
3247
- if(WYMeditor.LEXER_UNMATCHED == state){
3248
- this._tag_attributes[this._current_attribute] = match;
3249
- }
3250
- return true;
3251
- };
3252
-
3253
- WYMeditor.XhtmlParser.prototype.SingleQuotedAttribute = function(match, state)
3254
- {
3255
- if(WYMeditor.LEXER_UNMATCHED == state){
3256
- this._tag_attributes[this._current_attribute] = match;
3257
- }
3258
- return true;
3259
- };
3260
-
3261
- WYMeditor.XhtmlParser.prototype.UnquotedAttribute = function(match, state)
3262
- {
3263
- this._tag_attributes[this._current_attribute] = match.replace(/^=/,'');
3264
- return true;
3265
- };
3266
-
3267
-
3268
-
3269
- /**
3270
- * XHTML Sax parser.
3271
- *
3272
- * @author Bermi Ferrer (http://bermi.org)
3273
- */
3274
- WYMeditor.XhtmlSaxListener = function()
3275
- {
3276
- this.output = '';
3277
- this.helper = new WYMeditor.XmlHelper();
3278
- this._open_tags = {};
3279
- this.validator = WYMeditor.XhtmlValidator;
3280
- this._tag_stack = [];
3281
- this.avoided_tags = [];
3282
-
3283
- this.entities = {
3284
- '&nbsp;':'&#160;','&iexcl;':'&#161;','&cent;':'&#162;',
3285
- '&pound;':'&#163;','&curren;':'&#164;','&yen;':'&#165;',
3286
- '&brvbar;':'&#166;','&sect;':'&#167;','&uml;':'&#168;',
3287
- '&copy;':'&#169;','&ordf;':'&#170;','&laquo;':'&#171;',
3288
- '&not;':'&#172;','&shy;':'&#173;','&reg;':'&#174;',
3289
- '&macr;':'&#175;','&deg;':'&#176;','&plusmn;':'&#177;',
3290
- '&sup2;':'&#178;','&sup3;':'&#179;','&acute;':'&#180;',
3291
- '&micro;':'&#181;','&para;':'&#182;','&middot;':'&#183;',
3292
- '&cedil;':'&#184;','&sup1;':'&#185;','&ordm;':'&#186;',
3293
- '&raquo;':'&#187;','&frac14;':'&#188;','&frac12;':'&#189;',
3294
- '&frac34;':'&#190;','&iquest;':'&#191;','&Agrave;':'&#192;',
3295
- '&Aacute;':'&#193;','&Acirc;':'&#194;','&Atilde;':'&#195;',
3296
- '&Auml;':'&#196;','&Aring;':'&#197;','&AElig;':'&#198;',
3297
- '&Ccedil;':'&#199;','&Egrave;':'&#200;','&Eacute;':'&#201;',
3298
- '&Ecirc;':'&#202;','&Euml;':'&#203;','&Igrave;':'&#204;',
3299
- '&Iacute;':'&#205;','&Icirc;':'&#206;','&Iuml;':'&#207;',
3300
- '&ETH;':'&#208;','&Ntilde;':'&#209;','&Ograve;':'&#210;',
3301
- '&Oacute;':'&#211;','&Ocirc;':'&#212;','&Otilde;':'&#213;',
3302
- '&Ouml;':'&#214;','&times;':'&#215;','&Oslash;':'&#216;',
3303
- '&Ugrave;':'&#217;','&Uacute;':'&#218;','&Ucirc;':'&#219;',
3304
- '&Uuml;':'&#220;','&Yacute;':'&#221;','&THORN;':'&#222;',
3305
- '&szlig;':'&#223;','&agrave;':'&#224;','&aacute;':'&#225;',
3306
- '&acirc;':'&#226;','&atilde;':'&#227;','&auml;':'&#228;',
3307
- '&aring;':'&#229;','&aelig;':'&#230;','&ccedil;':'&#231;',
3308
- '&egrave;':'&#232;','&eacute;':'&#233;','&ecirc;':'&#234;',
3309
- '&euml;':'&#235;','&igrave;':'&#236;','&iacute;':'&#237;',
3310
- '&icirc;':'&#238;','&iuml;':'&#239;','&eth;':'&#240;',
3311
- '&ntilde;':'&#241;','&ograve;':'&#242;','&oacute;':'&#243;',
3312
- '&ocirc;':'&#244;','&otilde;':'&#245;','&ouml;':'&#246;',
3313
- '&divide;':'&#247;','&oslash;':'&#248;','&ugrave;':'&#249;',
3314
- '&uacute;':'&#250;','&ucirc;':'&#251;','&uuml;':'&#252;',
3315
- '&yacute;':'&#253;','&thorn;':'&#254;','&yuml;':'&#255;',
3316
- '&OElig;':'&#338;','&oelig;':'&#339;','&Scaron;':'&#352;',
3317
- '&scaron;':'&#353;','&Yuml;':'&#376;','&fnof;':'&#402;',
3318
- '&circ;':'&#710;','&tilde;':'&#732;','&Alpha;':'&#913;',
3319
- '&Beta;':'&#914;','&Gamma;':'&#915;','&Delta;':'&#916;',
3320
- '&Epsilon;':'&#917;','&Zeta;':'&#918;','&Eta;':'&#919;',
3321
- '&Theta;':'&#920;','&Iota;':'&#921;','&Kappa;':'&#922;',
3322
- '&Lambda;':'&#923;','&Mu;':'&#924;','&Nu;':'&#925;',
3323
- '&Xi;':'&#926;','&Omicron;':'&#927;','&Pi;':'&#928;',
3324
- '&Rho;':'&#929;','&Sigma;':'&#931;','&Tau;':'&#932;',
3325
- '&Upsilon;':'&#933;','&Phi;':'&#934;','&Chi;':'&#935;',
3326
- '&Psi;':'&#936;','&Omega;':'&#937;','&alpha;':'&#945;',
3327
- '&beta;':'&#946;','&gamma;':'&#947;','&delta;':'&#948;',
3328
- '&epsilon;':'&#949;','&zeta;':'&#950;','&eta;':'&#951;',
3329
- '&theta;':'&#952;','&iota;':'&#953;','&kappa;':'&#954;',
3330
- '&lambda;':'&#955;','&mu;':'&#956;','&nu;':'&#957;',
3331
- '&xi;':'&#958;','&omicron;':'&#959;','&pi;':'&#960;',
3332
- '&rho;':'&#961;','&sigmaf;':'&#962;','&sigma;':'&#963;',
3333
- '&tau;':'&#964;','&upsilon;':'&#965;','&phi;':'&#966;',
3334
- '&chi;':'&#967;','&psi;':'&#968;','&omega;':'&#969;',
3335
- '&thetasym;':'&#977;','&upsih;':'&#978;','&piv;':'&#982;',
3336
- '&ensp;':'&#8194;','&emsp;':'&#8195;','&thinsp;':'&#8201;',
3337
- '&zwnj;':'&#8204;','&zwj;':'&#8205;','&lrm;':'&#8206;',
3338
- '&rlm;':'&#8207;','&ndash;':'&#8211;','&mdash;':'&#8212;',
3339
- '&lsquo;':'&#8216;','&rsquo;':'&#8217;','&sbquo;':'&#8218;',
3340
- '&ldquo;':'&#8220;','&rdquo;':'&#8221;','&bdquo;':'&#8222;',
3341
- '&dagger;':'&#8224;','&Dagger;':'&#8225;','&bull;':'&#8226;',
3342
- '&hellip;':'&#8230;','&permil;':'&#8240;','&prime;':'&#8242;',
3343
- '&Prime;':'&#8243;','&lsaquo;':'&#8249;','&rsaquo;':'&#8250;',
3344
- '&oline;':'&#8254;','&frasl;':'&#8260;','&euro;':'&#8364;',
3345
- '&image;':'&#8465;','&weierp;':'&#8472;','&real;':'&#8476;',
3346
- '&trade;':'&#8482;','&alefsym;':'&#8501;','&larr;':'&#8592;',
3347
- '&uarr;':'&#8593;','&rarr;':'&#8594;','&darr;':'&#8595;',
3348
- '&harr;':'&#8596;','&crarr;':'&#8629;','&lArr;':'&#8656;',
3349
- '&uArr;':'&#8657;','&rArr;':'&#8658;','&dArr;':'&#8659;',
3350
- '&hArr;':'&#8660;','&forall;':'&#8704;','&part;':'&#8706;',
3351
- '&exist;':'&#8707;','&empty;':'&#8709;','&nabla;':'&#8711;',
3352
- '&isin;':'&#8712;','&notin;':'&#8713;','&ni;':'&#8715;',
3353
- '&prod;':'&#8719;','&sum;':'&#8721;','&minus;':'&#8722;',
3354
- '&lowast;':'&#8727;','&radic;':'&#8730;','&prop;':'&#8733;',
3355
- '&infin;':'&#8734;','&ang;':'&#8736;','&and;':'&#8743;',
3356
- '&or;':'&#8744;','&cap;':'&#8745;','&cup;':'&#8746;',
3357
- '&int;':'&#8747;','&there4;':'&#8756;','&sim;':'&#8764;',
3358
- '&cong;':'&#8773;','&asymp;':'&#8776;','&ne;':'&#8800;',
3359
- '&equiv;':'&#8801;','&le;':'&#8804;','&ge;':'&#8805;',
3360
- '&sub;':'&#8834;','&sup;':'&#8835;','&nsub;':'&#8836;',
3361
- '&sube;':'&#8838;','&supe;':'&#8839;','&oplus;':'&#8853;',
3362
- '&otimes;':'&#8855;','&perp;':'&#8869;','&sdot;':'&#8901;',
3363
- '&lceil;':'&#8968;','&rceil;':'&#8969;','&lfloor;':'&#8970;',
3364
- '&rfloor;':'&#8971;','&lang;':'&#9001;','&rang;':'&#9002;',
3365
- '&loz;':'&#9674;','&spades;':'&#9824;','&clubs;':'&#9827;',
3366
- '&hearts;':'&#9829;','&diams;':'&#9830;'};
3367
-
3368
- this.block_tags = ["a", "abbr", "acronym", "address", "area", "b",
3369
- "base", "bdo", "big", "blockquote", "body", "button",
3370
- "caption", "cite", "code", "col", "colgroup", "dd", "del", "div",
3371
- "dfn", "dl", "dt", "em", "fieldset", "form", "head", "h1", "h2",
3372
- "h3", "h4", "h5", "h6", "html", "i", "ins",
3373
- "kbd", "label", "legend", "li", "map", "noscript",
3374
- "object", "ol", "optgroup", "option", "p", "param", "pre", "q",
3375
- "samp", "script", "select", "small", "span", "strong", "style",
3376
- "sub", "sup", "table", "tbody", "td", "textarea", "tfoot", "th",
3377
- "thead", "title", "tr", "tt", "ul", "var", "extends"];
3378
-
3379
-
3380
- this.inline_tags = ["br", "hr", "img", "input"];
3381
-
3382
- return this;
3383
- };
3384
-
3385
- WYMeditor.XhtmlSaxListener.prototype.shouldCloseTagAutomatically = function(tag, now_on_tag, closing)
3386
- {
3387
- var closing = closing || false;
3388
- if(tag == 'td'){
3389
- if((closing && now_on_tag == 'tr') || (!closing && now_on_tag == 'td')){
3390
- return true;
3391
- }
3392
- }
3393
- if(tag == 'option'){
3394
- if((closing && now_on_tag == 'select') || (!closing && now_on_tag == 'option')){
3395
- return true;
3396
- }
3397
- }
3398
- return false;
3399
- };
3400
-
3401
- WYMeditor.XhtmlSaxListener.prototype.beforeParsing = function(raw)
3402
- {
3403
- this.output = '';
3404
- return raw;
3405
- };
3406
-
3407
- WYMeditor.XhtmlSaxListener.prototype.afterParsing = function(xhtml)
3408
- {
3409
- xhtml = this.replaceNamedEntities(xhtml);
3410
- xhtml = this.joinRepeatedEntities(xhtml);
3411
- xhtml = this.removeEmptyTags(xhtml);
3412
- return xhtml;
3413
- };
3414
-
3415
- WYMeditor.XhtmlSaxListener.prototype.replaceNamedEntities = function(xhtml)
3416
- {
3417
- for (var entity in this.entities) {
3418
- xhtml = xhtml.replace(entity, this.entities[entity]);
3419
- }
3420
- return xhtml;
3421
- };
3422
-
3423
- WYMeditor.XhtmlSaxListener.prototype.joinRepeatedEntities = function(xhtml)
3424
- {
3425
- var tags = 'em|strong|sub|sup|acronym|pre|del|address';
3426
- return xhtml.replace(new RegExp('<\/('+tags+')><\\1>' ,''),'').
3427
- replace(new RegExp('(\s*<('+tags+')>\s*){2}(.*)(\s*<\/\\2>\s*){2}' ,''),'<\$2>\$3<\$2>');
3428
- };
3429
-
3430
- WYMeditor.XhtmlSaxListener.prototype.removeEmptyTags = function(xhtml)
3431
- {
3432
- return xhtml.replace(new RegExp('<('+this.block_tags.join("|").replace(/\|td/,'')+')>(<br \/>|&#160;|&nbsp;|\\s)*<\/\\1>' ,'g'),'');
3433
- };
3434
-
3435
- WYMeditor.XhtmlSaxListener.prototype.getResult = function()
3436
- {
3437
- return this.output;
3438
- };
3439
-
3440
- WYMeditor.XhtmlSaxListener.prototype.getTagReplacements = function()
3441
- {
3442
- return {'b':'strong', 'i':'em'};
3443
- };
3444
-
3445
- WYMeditor.XhtmlSaxListener.prototype.addContent = function(text)
3446
- {
3447
- this.output += text;
3448
- };
3449
-
3450
- WYMeditor.XhtmlSaxListener.prototype.addComment = function(text)
3451
- {
3452
- if(this.remove_comments){
3453
- this.output += text;
3454
- }
3455
- };
3456
-
3457
- WYMeditor.XhtmlSaxListener.prototype.addScript = function(text)
3458
- {
3459
- if(!this.remove_scripts){
3460
- this.output += text;
3461
- }
3462
- };
3463
-
3464
- WYMeditor.XhtmlSaxListener.prototype.addCss = function(text)
3465
- {
3466
- if(!this.remove_embeded_styles){
3467
- this.output += text;
3468
- }
3469
- };
3470
-
3471
- WYMeditor.XhtmlSaxListener.prototype.openBlockTag = function(tag, attributes)
3472
- {
3473
- this.output += this.helper.tag(tag, this.validator.getValidTagAttributes(tag, attributes), true);
3474
- };
3475
-
3476
- WYMeditor.XhtmlSaxListener.prototype.inlineTag = function(tag, attributes)
3477
- {
3478
- this.output += this.helper.tag(tag, this.validator.getValidTagAttributes(tag, attributes));
3479
- };
3480
-
3481
- WYMeditor.XhtmlSaxListener.prototype.openUnknownTag = function(tag, attributes)
3482
- {
3483
- //this.output += this.helper.tag(tag, attributes, true);
3484
- };
3485
-
3486
- WYMeditor.XhtmlSaxListener.prototype.closeBlockTag = function(tag)
3487
- {
3488
- this.output = this.output.replace(/<br \/>$/, '')+this._getClosingTagContent('before', tag)+"</"+tag+">"+this._getClosingTagContent('after', tag);
3489
- };
3490
-
3491
- WYMeditor.XhtmlSaxListener.prototype.closeUnknownTag = function(tag)
3492
- {
3493
- //this.output += "</"+tag+">";
3494
- };
3495
-
3496
- WYMeditor.XhtmlSaxListener.prototype.closeUnopenedTag = function(tag)
3497
- {
3498
- this.output += "</"+tag+">";
3499
- };
3500
-
3501
- WYMeditor.XhtmlSaxListener.prototype.avoidStylingTagsAndAttributes = function()
3502
- {
3503
- this.avoided_tags = ['div','span'];
3504
- this.validator.skiped_attributes = ['style'];
3505
- this.validator.skiped_attribute_values = ['MsoNormal','main1']; // MS Word attributes for class
3506
- this._avoiding_tags_implicitly = true;
3507
- };
3508
-
3509
- WYMeditor.XhtmlSaxListener.prototype.allowStylingTagsAndAttributes = function()
3510
- {
3511
- this.avoided_tags = [];
3512
- this.validator.skiped_attributes = [];
3513
- this.validator.skiped_attribute_values = [];
3514
- this._avoiding_tags_implicitly = false;
3515
- };
3516
-
3517
- WYMeditor.XhtmlSaxListener.prototype.isBlockTag = function(tag)
3518
- {
3519
- return !WYMeditor.Helper.contains(this.avoided_tags, tag) && WYMeditor.Helper.contains(this.block_tags, tag);
3520
- };
3521
-
3522
- WYMeditor.XhtmlSaxListener.prototype.isInlineTag = function(tag)
3523
- {
3524
- return !WYMeditor.Helper.contains(this.avoided_tags, tag) && WYMeditor.Helper.contains(this.inline_tags, tag);
3525
- };
3526
-
3527
- WYMeditor.XhtmlSaxListener.prototype.insertContentAfterClosingTag = function(tag, content)
3528
- {
3529
- this._insertContentWhenClosingTag('after', tag, content);
3530
- };
3531
-
3532
- WYMeditor.XhtmlSaxListener.prototype.insertContentBeforeClosingTag = function(tag, content)
3533
- {
3534
- this._insertContentWhenClosingTag('before', tag, content);
3535
- };
3536
-
3537
- WYMeditor.XhtmlSaxListener.prototype.fixNestingBeforeOpeningBlockTag = function(tag, attributes)
3538
- {
3539
- if(tag != 'li' && (tag == 'ul' || tag == 'ol') && this.last_tag && !this.last_tag_opened && this.last_tag == 'li'){
3540
- this.output = this.output.replace(/<\/li>$/, '');
3541
- this.insertContentAfterClosingTag(tag, '</li>');
3542
- }
3543
- };
3544
-
3545
- WYMeditor.XhtmlSaxListener.prototype._insertContentWhenClosingTag = function(position, tag, content)
3546
- {
3547
- if(!this['_insert_'+position+'_closing']){
3548
- this['_insert_'+position+'_closing'] = [];
3549
- }
3550
- if(!this['_insert_'+position+'_closing'][tag]){
3551
- this['_insert_'+position+'_closing'][tag] = [];
3552
- }
3553
- this['_insert_'+position+'_closing'][tag].push(content);
3554
- };
3555
-
3556
- WYMeditor.XhtmlSaxListener.prototype._getClosingTagContent = function(position, tag)
3557
- {
3558
- if( this['_insert_'+position+'_closing'] &&
3559
- this['_insert_'+position+'_closing'][tag] &&
3560
- this['_insert_'+position+'_closing'][tag].length > 0){
3561
- return this['_insert_'+position+'_closing'][tag].pop();
3562
- }
3563
- return '';
3564
- };
3565
-
3566
-
3567
- /********** CSS PARSER **********/
3568
-
3569
-
3570
- WYMeditor.WymCssLexer = function(parser, only_wym_blocks)
3571
- {
3572
- var only_wym_blocks = (typeof only_wym_blocks == 'undefined' ? true : only_wym_blocks);
3573
-
3574
- jQuery.extend(this, new WYMeditor.Lexer(parser, (only_wym_blocks?'Ignore':'WymCss')));
3575
-
3576
- this.mapHandler('WymCss', 'Ignore');
3577
-
3578
- if(only_wym_blocks == true){
3579
- this.addEntryPattern("/\\\x2a[<\\s]*WYMeditor[>\\s]*\\\x2a/", 'Ignore', 'WymCss');
3580
- this.addExitPattern("/\\\x2a[<\/\\s]*WYMeditor[>\\s]*\\\x2a/", 'WymCss');
3581
- }
3582
-
3583
- this.addSpecialPattern("\\\x2e[a-z-_0-9]+[\\sa-z1-6]*", 'WymCss', 'WymCssStyleDeclaration');
3584
-
3585
- this.addEntryPattern("/\\\x2a", 'WymCss', 'WymCssComment');
3586
- this.addExitPattern("\\\x2a/", 'WymCssComment');
3587
-
3588
- this.addEntryPattern("\x7b", 'WymCss', 'WymCssStyle');
3589
- this.addExitPattern("\x7d", 'WymCssStyle');
3590
-
3591
- this.addEntryPattern("/\\\x2a", 'WymCssStyle', 'WymCssFeddbackStyle');
3592
- this.addExitPattern("\\\x2a/", 'WymCssFeddbackStyle');
3593
-
3594
- return this;
3595
- };
3596
-
3597
- WYMeditor.WymCssParser = function()
3598
- {
3599
- this._in_style = false;
3600
- this._has_title = false;
3601
- this.only_wym_blocks = true;
3602
- this.css_settings = {'classesItems':[], 'editorStyles':[], 'dialogStyles':[]};
3603
- return this;
3604
- };
3605
-
3606
- WYMeditor.WymCssParser.prototype.parse = function(raw, only_wym_blocks)
3607
- {
3608
- var only_wym_blocks = (typeof only_wym_blocks == 'undefined' ? this.only_wym_blocks : only_wym_blocks);
3609
- this._Lexer = new WYMeditor.WymCssLexer(this, only_wym_blocks);
3610
- this._Lexer.parse(raw);
3611
- };
3612
-
3613
- WYMeditor.WymCssParser.prototype.Ignore = function(match, state)
3614
- {
3615
- return true;
3616
- };
3617
-
3618
- WYMeditor.WymCssParser.prototype.WymCssComment = function(text, status)
3619
- {
3620
- if(text.match(/end[a-z0-9\s]*wym[a-z0-9\s]*/mi)){
3621
- return false;
3622
- }
3623
- if(status == WYMeditor.LEXER_UNMATCHED){
3624
- if(!this._in_style){
3625
- this._has_title = true;
3626
- this._current_item = {'title':WYMeditor.Helper.trim(text)};
3627
- }else{
3628
- if(this._current_item[this._current_element]){
3629
- if(!this._current_item[this._current_element].expressions){
3630
- this._current_item[this._current_element].expressions = [text];
3631
- }else{
3632
- this._current_item[this._current_element].expressions.push(text);
3633
- }
3634
- }
3635
- }
3636
- this._in_style = true;
3637
- }
3638
- return true;
3639
- };
3640
-
3641
- WYMeditor.WymCssParser.prototype.WymCssStyle = function(match, status)
3642
- {
3643
- if(status == WYMeditor.LEXER_UNMATCHED){
3644
- match = WYMeditor.Helper.trim(match);
3645
- if(match != ''){
3646
- this._current_item[this._current_element].style = match;
3647
- }
3648
- }else if (status == WYMeditor.LEXER_EXIT){
3649
- this._in_style = false;
3650
- this._has_title = false;
3651
- this.addStyleSetting(this._current_item);
3652
- }
3653
- return true;
3654
- };
3655
-
3656
- WYMeditor.WymCssParser.prototype.WymCssFeddbackStyle = function(match, status)
3657
- {
3658
- if(status == WYMeditor.LEXER_UNMATCHED){
3659
- this._current_item[this._current_element].feedback_style = match.replace(/^([\s\/\*]*)|([\s\/\*]*)$/gm,'');
3660
- }
3661
- return true;
3662
- };
3663
-
3664
- WYMeditor.WymCssParser.prototype.WymCssStyleDeclaration = function(match)
3665
- {
3666
- match = match.replace(/^([\s\.]*)|([\s\.*]*)$/gm, '');
3667
-
3668
- var tag = '';
3669
- if(match.indexOf(' ') > 0){
3670
- var parts = match.split(' ');
3671
- this._current_element = parts[0];
3672
- var tag = parts[1];
3673
- }else{
3674
- this._current_element = match;
3675
- }
3676
-
3677
- if(!this._has_title){
3678
- this._current_item = {'title':(!tag?'':tag.toUpperCase()+': ')+this._current_element};
3679
- this._has_title = true;
3680
- }
3681
-
3682
- if(!this._current_item[this._current_element]){
3683
- this._current_item[this._current_element] = {'name':this._current_element};
3684
- }
3685
- if(tag){
3686
- if(!this._current_item[this._current_element].tags){
3687
- this._current_item[this._current_element].tags = [tag];
3688
- }else{
3689
- this._current_item[this._current_element].tags.push(tag);
3690
- }
3691
- }
3692
- return true;
3693
- };
3694
-
3695
- WYMeditor.WymCssParser.prototype.addStyleSetting = function(style_details)
3696
- {
3697
- for (var name in style_details){
3698
- var details = style_details[name];
3699
- if(typeof details == 'object' && name != 'title'){
3700
-
3701
- this.css_settings.classesItems.push({
3702
- 'name': WYMeditor.Helper.trim(details.name),
3703
- 'title': style_details.title,
3704
- 'expr' : WYMeditor.Helper.trim((details.expressions||details.tags||[]).join(', '))
3705
- });
3706
- if(details.feedback_style){
3707
- this.css_settings.editorStyles.push({
3708
- 'name': '.'+ WYMeditor.Helper.trim(details.name),
3709
- 'css': details.feedback_style
3710
- });
3711
- }
3712
- if(details.style){
3713
- this.css_settings.dialogStyles.push({
3714
- 'name': '.'+ WYMeditor.Helper.trim(details.name),
3715
- 'css': details.style
3716
- });
3717
- }
3718
- }
3719
- }
3720
- };
3721
-
3722
- /********** HELPERS **********/
3723
-
3724
- // Returns true if it is a text node with whitespaces only
3725
- jQuery.fn.isPhantomNode = function() {
3726
- if (this[0].nodeType == 3)
3727
- return !(/[^\t\n\r ]/.test(this[0].data));
3728
-
3729
- return false;
3730
- };
3731
-
3732
- WYMeditor.isPhantomNode = function(n) {
3733
- if (n.nodeType == 3)
3734
- return !(/[^\t\n\r ]/.test(n.data));
3735
-
3736
- return false;
3737
- };
3738
-
3739
- WYMeditor.isPhantomString = function(str) {
3740
- return !(/[^\t\n\r ]/.test(str));
3741
- };
3742
-
3743
- // Returns the Parents or the node itself
3744
- // jqexpr = a jQuery expression
3745
- jQuery.fn.parentsOrSelf = function(jqexpr) {
3746
- var n = this;
3747
-
3748
- if (n[0].nodeType == 3)
3749
- n = n.parents().slice(0,1);
3750
-
3751
- // if (n.is(jqexpr)) // XXX should work, but doesn't (probably a jQuery bug)
3752
- if (n.filter(jqexpr).size() == 1)
3753
- return n;
3754
- else
3755
- return n.parents(jqexpr).slice(0,1);
3756
- };
3757
-
3758
- // String & array helpers
3759
-
3760
- WYMeditor.Helper = {
3761
-
3762
- //replace all instances of 'old' by 'rep' in 'str' string
3763
- replaceAll: function(str, old, rep) {
3764
- var rExp = new RegExp(old, "g");
3765
- return(str.replace(rExp, rep));
3766
- },
3767
-
3768
- //insert 'inserted' at position 'pos' in 'str' string
3769
- insertAt: function(str, inserted, pos) {
3770
- return(str.substr(0,pos) + inserted + str.substring(pos));
3771
- },
3772
-
3773
- //trim 'str' string
3774
- trim: function(str) {
3775
- return str.replace(/^(\s*)|(\s*)$/gm,'');
3776
- },
3777
-
3778
- //return true if 'arr' array contains 'elem', or false
3779
- contains: function(arr, elem) {
3780
- for (var i = 0; i < arr.length; i++) {
3781
- if (arr[i] === elem) return true;
3782
- }
3783
- return false;
3784
- },
3785
-
3786
- //return 'item' position in 'arr' array, or -1
3787
- indexOf: function(arr, item) {
3788
- var ret=-1;
3789
- for(var i = 0; i < arr.length; i++) {
3790
- if (arr[i] == item) {
3791
- ret = i;
3792
- break;
3793
- }
3794
- }
3795
- return(ret);
3796
- },
3797
-
3798
- //return 'item' object in 'arr' array, checking its 'name' property, or null
3799
- findByName: function(arr, name) {
3800
- for(var i = 0; i < arr.length; i++) {
3801
- var item = arr[i];
3802
- if(item.name == name) return(item);
3803
- }
3804
- return(null);
3805
- }
3806
- };
3807
-
3808
-
3809
- /*
3810
- * WYMeditor : what you see is What You Mean web-based editor
3811
- * Copyright (c) 2008 Jean-Francois Hovinne, http://www.wymeditor.org/
3812
- * Dual licensed under the MIT (MIT-license.txt)
3813
- * and GPL (GPL-license.txt) licenses.
3814
- *
3815
- * For further information visit:
3816
- * http://www.wymeditor.org/
3817
- *
3818
- * File Name:
3819
- * jquery.wymeditor.explorer.js
3820
- * MSIE specific class and functions.
3821
- * See the documentation for more info.
3822
- *
3823
- * File Authors:
3824
- * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg)
3825
- * Bermi Ferrer (wymeditor a-t bermi dotorg)
3826
- * Frédéric Palluel-Lafleur (fpalluel a-t gmail dotcom)
3827
- * Jonatan Lundin (jonatan.lundin _at_ gmail.com)
3828
- */
3829
-
3830
- WYMeditor.WymClassExplorer = function(wym) {
3831
-
3832
- this._wym = wym;
3833
- this._class = "className";
3834
- this._newLine = "\r\n";
3835
- };
3836
-
3837
- WYMeditor.WymClassExplorer.prototype.initIframe = function(iframe) {
3838
-
3839
- //This function is executed twice, though it is called once!
3840
- //But MSIE needs that, otherwise designMode won't work.
3841
- //Weird.
3842
-
3843
- this._iframe = iframe;
3844
- this._doc = iframe.contentWindow.document;
3845
-
3846
- //add css rules from options
3847
- var styles = this._doc.styleSheets[0];
3848
- var aCss = eval(this._options.editorStyles);
3849
-
3850
- this.addCssRules(this._doc, aCss);
3851
-
3852
- this._doc.title = this._wym._index;
3853
-
3854
- //set the text direction
3855
- jQuery('html', this._doc).attr('dir', this._options.direction);
3856
-
3857
- //init html value
3858
- jQuery(this._doc.body).html(this._wym._html);
3859
-
3860
- //handle events
3861
- var wym = this;
3862
-
3863
- this._doc.body.onfocus = function()
3864
- {wym._doc.designMode = "on"; wym._doc = iframe.contentWindow.document;};
3865
- this._doc.onbeforedeactivate = function() {wym.saveCaret();};
3866
- this._doc.onkeyup = function() {
3867
- wym.saveCaret();
3868
- wym.keyup();
3869
- };
3870
- this._doc.onclick = function() {wym.saveCaret();};
3871
-
3872
- this._doc.body.onbeforepaste = function() {
3873
- wym._iframe.contentWindow.event.returnValue = false;
3874
- };
3875
-
3876
- this._doc.body.onpaste = function() {
3877
- wym._iframe.contentWindow.event.returnValue = false;
3878
- wym.paste(window.clipboardData.getData("Text"));
3879
- };
3880
-
3881
- //callback can't be executed twice, so we check
3882
- if(this._initialized) {
3883
-
3884
- //pre-bind functions
3885
- if(jQuery.isFunction(this._options.preBind)) this._options.preBind(this);
3886
-
3887
- //bind external events
3888
- this._wym.bindEvents();
3889
-
3890
- //post-init functions
3891
- if(jQuery.isFunction(this._options.postInit)) this._options.postInit(this);
3892
-
3893
- //add event listeners to doc elements, e.g. images
3894
- this.listen();
3895
- }
3896
-
3897
- this._initialized = true;
3898
-
3899
- //init designMode
3900
- this._doc.designMode="on";
3901
- try{
3902
- // (bermi's note) noticed when running unit tests on IE6
3903
- // Is this really needed, it trigger an unexisting property on IE6
3904
- this._doc = iframe.contentWindow.document;
3905
- }catch(e){}
3906
- };
3907
-
3908
- WYMeditor.WymClassExplorer.prototype._exec = function(cmd,param) {
3909
-
3910
- switch(cmd) {
3911
-
3912
- case WYMeditor.INDENT: case WYMeditor.OUTDENT:
3913
-
3914
- var container = this.findUp(this.container(), WYMeditor.LI);
3915
- if(container)
3916
- this._doc.execCommand(cmd);
3917
- break;
3918
- default:
3919
- if(param) this._doc.execCommand(cmd,false,param);
3920
- else this._doc.execCommand(cmd);
3921
- break;
3922
- }
3923
-
3924
- this.listen();
3925
- };
3926
-
3927
- WYMeditor.WymClassExplorer.prototype.selected = function() {
3928
-
3929
- var caretPos = this._iframe.contentWindow.document.caretPos;
3930
- if(caretPos!=null) {
3931
- if(caretPos.parentElement!=undefined)
3932
- return(caretPos.parentElement());
3933
- }
3934
- };
3935
-
3936
- WYMeditor.WymClassExplorer.prototype.saveCaret = function() {
3937
-
3938
- this._doc.caretPos = this._doc.selection.createRange();
3939
- };
3940
-
3941
- WYMeditor.WymClassExplorer.prototype.addCssRule = function(styles, oCss) {
3942
-
3943
- styles.addRule(oCss.name, oCss.css);
3944
- };
3945
-
3946
- WYMeditor.WymClassExplorer.prototype.insert = function(html) {
3947
-
3948
- // Get the current selection
3949
- var range = this._doc.selection.createRange();
3950
-
3951
- // Check if the current selection is inside the editor
3952
- if ( jQuery(range.parentElement()).parents( this._options.iframeBodySelector ).is('*') ) {
3953
- try {
3954
- // Overwrite selection with provided html
3955
- range.pasteHTML(html);
3956
- } catch (e) { }
3957
- } else {
3958
- // Fall back to the internal paste function if there's no selection
3959
- this.paste(html);
3960
- }
3961
- };
3962
-
3963
- WYMeditor.WymClassExplorer.prototype.wrap = function(left, right) {
3964
-
3965
- // Get the current selection
3966
- var range = this._doc.selection.createRange();
3967
-
3968
- // Check if the current selection is inside the editor
3969
- if ( jQuery(range.parentElement()).parents( this._options.iframeBodySelector ).is('*') ) {
3970
- try {
3971
- // Overwrite selection with provided html
3972
- range.pasteHTML(left + range.text + right);
3973
- } catch (e) { }
3974
- }
3975
- };
3976
-
3977
- WYMeditor.WymClassExplorer.prototype.unwrap = function() {
3978
-
3979
- // Get the current selection
3980
- var range = this._doc.selection.createRange();
3981
-
3982
- // Check if the current selection is inside the editor
3983
- if ( jQuery(range.parentElement()).parents( this._options.iframeBodySelector ).is('*') ) {
3984
- try {
3985
- // Unwrap selection
3986
- var text = range.text;
3987
- this._exec( 'Cut' );
3988
- range.pasteHTML( text );
3989
- } catch (e) { }
3990
- }
3991
- };
3992
-
3993
- //keyup handler
3994
- WYMeditor.WymClassExplorer.prototype.keyup = function() {
3995
- this._selected_image = null;
3996
- };
3997
-
3998
- WYMeditor.WymClassExplorer.prototype.setFocusToNode = function(node) {
3999
- var range = this._doc.selection.createRange();
4000
- range.moveToElementText(node);
4001
- range.collapse(false);
4002
- range.move('character',-1);
4003
- range.select();
4004
- node.focus();
4005
- };
4006
-
4007
- /*
4008
- * WYMeditor : what you see is What You Mean web-based editor
4009
- * Copyright (c) 2008 Jean-Francois Hovinne, http://www.wymeditor.org/
4010
- * Dual licensed under the MIT (MIT-license.txt)
4011
- * and GPL (GPL-license.txt) licenses.
4012
- *
4013
- * For further information visit:
4014
- * http://www.wymeditor.org/
4015
- *
4016
- * File Name:
4017
- * jquery.wymeditor.mozilla.js
4018
- * Gecko specific class and functions.
4019
- * See the documentation for more info.
4020
- *
4021
- * File Authors:
4022
- * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg)
4023
- * Volker Mische (vmx a-t gmx dotde)
4024
- * Bermi Ferrer (wymeditor a-t bermi dotorg)
4025
- * Frédéric Palluel-Lafleur (fpalluel a-t gmail dotcom)
4026
- */
4027
-
4028
- WYMeditor.WymClassMozilla = function(wym) {
4029
-
4030
- this._wym = wym;
4031
- this._class = "class";
4032
- this._newLine = "\n";
4033
- };
4034
-
4035
- WYMeditor.WymClassMozilla.prototype.initIframe = function(iframe) {
4036
-
4037
- this._iframe = iframe;
4038
- this._doc = iframe.contentDocument;
4039
-
4040
- //add css rules from options
4041
-
4042
- var styles = this._doc.styleSheets[0];
4043
- var aCss = eval(this._options.editorStyles);
4044
-
4045
- this.addCssRules(this._doc, aCss);
4046
-
4047
- this._doc.title = this._wym._index;
4048
-
4049
- //set the text direction
4050
- jQuery('html', this._doc).attr('dir', this._options.direction);
4051
-
4052
- //init html value
4053
- this.html(this._wym._html);
4054
-
4055
- //init designMode
4056
- this.enableDesignMode();
4057
-
4058
- //pre-bind functions
4059
- if(jQuery.isFunction(this._options.preBind)) this._options.preBind(this);
4060
-
4061
- //bind external events
4062
- this._wym.bindEvents();
4063
-
4064
- //bind editor keydown events
4065
- jQuery(this._doc).bind("keydown", this.keydown);
4066
-
4067
- //bind editor keyup events
4068
- jQuery(this._doc).bind("keyup", this.keyup);
4069
-
4070
- //bind editor focus events (used to reset designmode - Gecko bug)
4071
- jQuery(this._doc).bind("focus", this.enableDesignMode);
4072
-
4073
- //post-init functions
4074
- if(jQuery.isFunction(this._options.postInit)) this._options.postInit(this);
4075
-
4076
- //add event listeners to doc elements, e.g. images
4077
- this.listen();
4078
- };
4079
-
4080
- /* @name html
4081
- * @description Get/Set the html value
4082
- */
4083
- WYMeditor.WymClassMozilla.prototype.html = function(html) {
4084
-
4085
- if(typeof html === 'string') {
4086
-
4087
- //disable designMode
4088
- try { this._doc.designMode = "off"; } catch(e) { };
4089
-
4090
- //replace em by i and strong by bold
4091
- //(designMode issue)
4092
- html = html.replace(/<em([^>]*)>/gi, "<i$1>")
4093
- .replace(/<\/em>/gi, "</i>")
4094
- .replace(/<strong([^>]*)>/gi, "<b$1>")
4095
- .replace(/<\/strong>/gi, "</b>");
4096
-
4097
- //update the html body
4098
- jQuery(this._doc.body).html(html);
4099
-
4100
- //re-init designMode
4101
- this.enableDesignMode();
4102
- }
4103
- else return(jQuery(this._doc.body).html());
4104
- };
4105
-
4106
- WYMeditor.WymClassMozilla.prototype._exec = function(cmd,param) {
4107
-
4108
- if(!this.selected()) return(false);
4109
-
4110
- switch(cmd) {
4111
-
4112
- case WYMeditor.INDENT: case WYMeditor.OUTDENT:
4113
-
4114
- var focusNode = this.selected();
4115
- var sel = this._iframe.contentWindow.getSelection();
4116
- var anchorNode = sel.anchorNode;
4117
- if(anchorNode.nodeName == "#text") anchorNode = anchorNode.parentNode;
4118
-
4119
- focusNode = this.findUp(focusNode, WYMeditor.BLOCKS);
4120
- anchorNode = this.findUp(anchorNode, WYMeditor.BLOCKS);
4121
-
4122
- if(focusNode && focusNode == anchorNode
4123
- && focusNode.tagName.toLowerCase() == WYMeditor.LI) {
4124
-
4125
- var ancestor = focusNode.parentNode.parentNode;
4126
-
4127
- if(focusNode.parentNode.childNodes.length>1
4128
- || ancestor.tagName.toLowerCase() == WYMeditor.OL
4129
- || ancestor.tagName.toLowerCase() == WYMeditor.UL)
4130
- this._doc.execCommand(cmd,'',null);
4131
- }
4132
-
4133
- break;
4134
-
4135
- default:
4136
-
4137
- if(param) this._doc.execCommand(cmd,'',param);
4138
- else this._doc.execCommand(cmd,'',null);
4139
- }
4140
-
4141
- //set to P if parent = BODY
4142
- var container = this.selected();
4143
- if(container.tagName.toLowerCase() == WYMeditor.BODY)
4144
- this._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P);
4145
-
4146
- //add event handlers on doc elements
4147
-
4148
- this.listen();
4149
- };
4150
-
4151
- /* @name selected
4152
- * @description Returns the selected container
4153
- */
4154
- WYMeditor.WymClassMozilla.prototype.selected = function() {
4155
-
4156
- var sel = this._iframe.contentWindow.getSelection();
4157
- var node = sel.focusNode;
4158
- if(node) {
4159
- if(node.nodeName == "#text") return(node.parentNode);
4160
- else return(node);
4161
- } else return(null);
4162
- };
4163
-
4164
- WYMeditor.WymClassMozilla.prototype.addCssRule = function(styles, oCss) {
4165
-
4166
- styles.insertRule(oCss.name + " {" + oCss.css + "}",
4167
- styles.cssRules.length);
4168
- };
4169
-
4170
-
4171
- //keydown handler, mainly used for keyboard shortcuts
4172
- WYMeditor.WymClassMozilla.prototype.keydown = function(evt) {
4173
-
4174
- //'this' is the doc
4175
- var wym = WYMeditor.INSTANCES[this.title];
4176
-
4177
- if(evt.ctrlKey){
4178
- if(evt.keyCode == 66){
4179
- //CTRL+b => STRONG
4180
- wym._exec(WYMeditor.BOLD);
4181
- return false;
4182
- }
4183
- if(evt.keyCode == 73){
4184
- //CTRL+i => EMPHASIS
4185
- wym._exec(WYMeditor.ITALIC);
4186
- return false;
4187
- }
4188
- }
4189
- };
4190
-
4191
- //keyup handler, mainly used for cleanups
4192
- WYMeditor.WymClassMozilla.prototype.keyup = function(evt) {
4193
-
4194
- //'this' is the doc
4195
- var wym = WYMeditor.INSTANCES[this.title];
4196
-
4197
- wym._selected_image = null;
4198
- var container = null;
4199
-
4200
- if(evt.keyCode == 13 && !evt.shiftKey) {
4201
-
4202
- //RETURN key
4203
- //cleanup <br><br> between paragraphs
4204
- jQuery(wym._doc.body).children(WYMeditor.BR).remove();
4205
-
4206
- //fix PRE bug #73
4207
- container = wym.selected();
4208
- if(container && container.tagName.toLowerCase() == WYMeditor.PRE)
4209
- wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P); //create P after PRE
4210
- }
4211
-
4212
- else if(evt.keyCode != 8
4213
- && evt.keyCode != 17
4214
- && evt.keyCode != 46
4215
- && evt.keyCode != 224
4216
- && !evt.metaKey
4217
- && !evt.ctrlKey) {
4218
-
4219
- //NOT BACKSPACE, NOT DELETE, NOT CTRL, NOT COMMAND
4220
- //text nodes replaced by P
4221
-
4222
- container = wym.selected();
4223
- var name = container.tagName.toLowerCase();
4224
-
4225
- //fix forbidden main containers
4226
- if(
4227
- name == "strong" ||
4228
- name == "b" ||
4229
- name == "em" ||
4230
- name == "i" ||
4231
- name == "sub" ||
4232
- name == "sup" ||
4233
- name == "a"
4234
-
4235
- ) name = container.parentNode.tagName.toLowerCase();
4236
-
4237
- if(name == WYMeditor.BODY) wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P);
4238
- }
4239
- };
4240
-
4241
- WYMeditor.WymClassMozilla.prototype.enableDesignMode = function() {
4242
- if(this.designMode == "off") {
4243
- try {
4244
- this.designMode = "on";
4245
- this.execCommand("styleWithCSS", '', false);
4246
- } catch(e) { }
4247
- }
4248
- };
4249
-
4250
- WYMeditor.WymClassMozilla.prototype.setFocusToNode = function(node) {
4251
- var range = document.createRange();
4252
- range.selectNode(node);
4253
- var selected = this._iframe.contentWindow.getSelection();
4254
- selected.addRange(range);
4255
- selected.collapse(node, node.childNodes.length);
4256
- this._iframe.contentWindow.focus();
4257
- };
4258
-
4259
- WYMeditor.WymClassMozilla.prototype.openBlockTag = function(tag, attributes)
4260
- {
4261
- var attributes = this.validator.getValidTagAttributes(tag, attributes);
4262
-
4263
- // Handle Mozilla styled spans
4264
- if(tag == 'span' && attributes.style){
4265
- var new_tag = this.getTagForStyle(attributes.style);
4266
- if(new_tag){
4267
- this._tag_stack.pop();
4268
- var tag = new_tag;
4269
- this._tag_stack.push(new_tag);
4270
- attributes.style = '';
4271
- }else{
4272
- return;
4273
- }
4274
- }
4275
-
4276
- this.output += this.helper.tag(tag, attributes, true);
4277
- };
4278
-
4279
- WYMeditor.WymClassMozilla.prototype.getTagForStyle = function(style) {
4280
-
4281
- if(/bold/.test(style)) return 'strong';
4282
- if(/italic/.test(style)) return 'em';
4283
- if(/sub/.test(style)) return 'sub';
4284
- if(/sub/.test(style)) return 'super';
4285
- return false;
4286
- };
4287
-
4288
- /*
4289
- * WYMeditor : what you see is What You Mean web-based editor
4290
- * Copyright (c) 2008 Jean-Francois Hovinne, http://www.wymeditor.org/
4291
- * Dual licensed under the MIT (MIT-license.txt)
4292
- * and GPL (GPL-license.txt) licenses.
4293
- *
4294
- * For further information visit:
4295
- * http://www.wymeditor.org/
4296
- *
4297
- * File Name:
4298
- * jquery.wymeditor.opera.js
4299
- * Opera specific class and functions.
4300
- * See the documentation for more info.
4301
- *
4302
- * File Authors:
4303
- * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg)
4304
- */
4305
-
4306
- WYMeditor.WymClassOpera = function(wym) {
4307
-
4308
- this._wym = wym;
4309
- this._class = "class";
4310
- this._newLine = "\r\n";
4311
- };
4312
-
4313
- WYMeditor.WymClassOpera.prototype.initIframe = function(iframe) {
4314
-
4315
- this._iframe = iframe;
4316
- this._doc = iframe.contentWindow.document;
4317
-
4318
- //add css rules from options
4319
- var styles = this._doc.styleSheets[0];
4320
- var aCss = eval(this._options.editorStyles);
4321
-
4322
- this.addCssRules(this._doc, aCss);
4323
-
4324
- this._doc.title = this._wym._index;
4325
-
4326
- //set the text direction
4327
- jQuery('html', this._doc).attr('dir', this._options.direction);
4328
-
4329
- //init designMode
4330
- this._doc.designMode = "on";
4331
-
4332
- //init html value
4333
- this.html(this._wym._html);
4334
-
4335
- //pre-bind functions
4336
- if(jQuery.isFunction(this._options.preBind)) this._options.preBind(this);
4337
-
4338
- //bind external events
4339
- this._wym.bindEvents();
4340
-
4341
- //bind editor keydown events
4342
- jQuery(this._doc).bind("keydown", this.keydown);
4343
-
4344
- //bind editor events
4345
- jQuery(this._doc).bind("keyup", this.keyup);
4346
-
4347
- //post-init functions
4348
- if(jQuery.isFunction(this._options.postInit)) this._options.postInit(this);
4349
-
4350
- //add event listeners to doc elements, e.g. images
4351
- this.listen();
4352
- };
4353
-
4354
- WYMeditor.WymClassOpera.prototype._exec = function(cmd,param) {
4355
-
4356
- if(param) this._doc.execCommand(cmd,false,param);
4357
- else this._doc.execCommand(cmd);
4358
-
4359
- this.listen();
4360
- };
4361
-
4362
- WYMeditor.WymClassOpera.prototype.selected = function() {
4363
-
4364
- var sel=this._iframe.contentWindow.getSelection();
4365
- var node=sel.focusNode;
4366
- if(node) {
4367
- if(node.nodeName=="#text")return(node.parentNode);
4368
- else return(node);
4369
- } else return(null);
4370
- };
4371
-
4372
- WYMeditor.WymClassOpera.prototype.addCssRule = function(styles, oCss) {
4373
-
4374
- styles.insertRule(oCss.name + " {" + oCss.css + "}",
4375
- styles.cssRules.length);
4376
- };
4377
-
4378
- //keydown handler
4379
- WYMeditor.WymClassOpera.prototype.keydown = function(evt) {
4380
-
4381
- //'this' is the doc
4382
- var wym = WYMeditor.INSTANCES[this.title];
4383
- var sel = wym._iframe.contentWindow.getSelection();
4384
- startNode = sel.getRangeAt(0).startContainer;
4385
-
4386
- //Get a P instead of no container
4387
- if(!jQuery(startNode).parentsOrSelf(
4388
- WYMeditor.MAIN_CONTAINERS.join(","))[0]
4389
- && !jQuery(startNode).parentsOrSelf('li')
4390
- && evt.keyCode != WYMeditor.KEY.ENTER
4391
- && evt.keyCode != WYMeditor.KEY.LEFT
4392
- && evt.keyCode != WYMeditor.KEY.UP
4393
- && evt.keyCode != WYMeditor.KEY.RIGHT
4394
- && evt.keyCode != WYMeditor.KEY.DOWN
4395
- && evt.keyCode != WYMeditor.KEY.BACKSPACE
4396
- && evt.keyCode != WYMeditor.KEY.DELETE)
4397
- wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P);
4398
-
4399
- };
4400
-
4401
- //keyup handler
4402
- WYMeditor.WymClassOpera.prototype.keyup = function(evt) {
4403
-
4404
- //'this' is the doc
4405
- var wym = WYMeditor.INSTANCES[this.title];
4406
- wym._selected_image = null;
4407
- };
4408
-
4409
- // TODO: implement me
4410
- WYMeditor.WymClassOpera.prototype.setFocusToNode = function(node) {
4411
-
4412
- };
4413
-
4414
- /*
4415
- * WYMeditor : what you see is What You Mean web-based editor
4416
- * Copyright (c) 2008 Jean-Francois Hovinne, http://www.wymeditor.org/
4417
- * Dual licensed under the MIT (MIT-license.txt)
4418
- * and GPL (GPL-license.txt) licenses.
4419
- *
4420
- * For further information visit:
4421
- * http://www.wymeditor.org/
4422
- *
4423
- * File Name:
4424
- * jquery.wymeditor.safari.js
4425
- * Safari specific class and functions.
4426
- * See the documentation for more info.
4427
- *
4428
- * File Authors:
4429
- * Jean-Francois Hovinne (jf.hovinne a-t wymeditor dotorg)
4430
- * Scott Lewis (lewiscot a-t gmail dotcom)
4431
- */
4432
-
4433
- WYMeditor.WymClassSafari = function(wym) {
4434
-
4435
- this._wym = wym;
4436
- this._class = "class";
4437
- this._newLine = "\n";
4438
- };
4439
-
4440
- WYMeditor.WymClassSafari.prototype.initIframe = function(iframe) {
4441
-
4442
- this._iframe = iframe;
4443
- this._doc = iframe.contentDocument;
4444
-
4445
- //add css rules from options
4446
-
4447
- var styles = this._doc.styleSheets[0];
4448
- var aCss = eval(this._options.editorStyles);
4449
-
4450
- this.addCssRules(this._doc, aCss);
4451
-
4452
- this._doc.title = this._wym._index;
4453
-
4454
- //set the text direction
4455
- jQuery('html', this._doc).attr('dir', this._options.direction);
4456
-
4457
- //init designMode
4458
- this._doc.designMode = "on";
4459
-
4460
- //init html value
4461
- this.html(this._wym._html);
4462
-
4463
- //pre-bind functions
4464
- if(jQuery.isFunction(this._options.preBind)) this._options.preBind(this);
4465
-
4466
- //bind external events
4467
- this._wym.bindEvents();
4468
-
4469
- //bind editor keydown events
4470
- jQuery(this._doc).bind("keydown", this.keydown);
4471
-
4472
- //bind editor keyup events
4473
- jQuery(this._doc).bind("keyup", this.keyup);
4474
-
4475
- //post-init functions
4476
- if(jQuery.isFunction(this._options.postInit)) this._options.postInit(this);
4477
-
4478
- //add event listeners to doc elements, e.g. images
4479
- this.listen();
4480
- };
4481
-
4482
- WYMeditor.WymClassSafari.prototype._exec = function(cmd,param) {
4483
-
4484
- if(!this.selected()) return(false);
4485
-
4486
- switch(cmd) {
4487
-
4488
- case WYMeditor.INDENT: case WYMeditor.OUTDENT:
4489
-
4490
- var focusNode = this.selected();
4491
- var sel = this._iframe.contentWindow.getSelection();
4492
- var anchorNode = sel.anchorNode;
4493
- if(anchorNode.nodeName == "#text") anchorNode = anchorNode.parentNode;
4494
-
4495
- focusNode = this.findUp(focusNode, WYMeditor.BLOCKS);
4496
- anchorNode = this.findUp(anchorNode, WYMeditor.BLOCKS);
4497
-
4498
- if(focusNode && focusNode == anchorNode
4499
- && focusNode.tagName.toLowerCase() == WYMeditor.LI) {
4500
-
4501
- var ancestor = focusNode.parentNode.parentNode;
4502
-
4503
- if(focusNode.parentNode.childNodes.length>1
4504
- || ancestor.tagName.toLowerCase() == WYMeditor.OL
4505
- || ancestor.tagName.toLowerCase() == WYMeditor.UL)
4506
- this._doc.execCommand(cmd,'',null);
4507
- }
4508
-
4509
- break;
4510
-
4511
- case WYMeditor.INSERT_ORDEREDLIST: case WYMeditor.INSERT_UNORDEREDLIST:
4512
-
4513
- this._doc.execCommand(cmd,'',null);
4514
-
4515
- //Safari creates lists in e.g. paragraphs.
4516
- //Find the container, and remove it.
4517
- var focusNode = this.selected();
4518
- var container = this.findUp(focusNode, WYMeditor.MAIN_CONTAINERS);
4519
- if(container) jQuery(container).replaceWith(jQuery(container).html());
4520
-
4521
- break;
4522
-
4523
- default:
4524
-
4525
- if(param) this._doc.execCommand(cmd,'',param);
4526
- else this._doc.execCommand(cmd,'',null);
4527
- }
4528
-
4529
- //set to P if parent = BODY
4530
- var container = this.selected();
4531
- if(container && container.tagName.toLowerCase() == WYMeditor.BODY)
4532
- this._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P);
4533
-
4534
- //add event handlers on doc elements
4535
- this.listen();
4536
- };
4537
-
4538
- /* @name selected
4539
- * @description Returns the selected container
4540
- */
4541
- WYMeditor.WymClassSafari.prototype.selected = function() {
4542
-
4543
- var sel = this._iframe.contentWindow.getSelection();
4544
- var node = sel.focusNode;
4545
- if(node) {
4546
- if(node.nodeName == "#text") return(node.parentNode);
4547
- else return(node);
4548
- } else return(null);
4549
- };
4550
-
4551
- WYMeditor.WymClassSafari.prototype.addCssRule = function(styles, oCss) {
4552
-
4553
- styles.insertRule(oCss.name + " {" + oCss.css + "}",
4554
- styles.cssRules.length);
4555
- };
4556
-
4557
-
4558
- //keydown handler, mainly used for keyboard shortcuts
4559
- WYMeditor.WymClassSafari.prototype.keydown = function(evt) {
4560
-
4561
- //'this' is the doc
4562
- var wym = WYMeditor.INSTANCES[this.title];
4563
-
4564
- if(evt.ctrlKey){
4565
- if(evt.keyCode == 66){
4566
- //CTRL+b => STRONG
4567
- wym._exec(WYMeditor.BOLD);
4568
- return false;
4569
- }
4570
- if(evt.keyCode == 73){
4571
- //CTRL+i => EMPHASIS
4572
- wym._exec(WYMeditor.ITALIC);
4573
- return false;
4574
- }
4575
- }
4576
- };
4577
-
4578
- //keyup handler, mainly used for cleanups
4579
- WYMeditor.WymClassSafari.prototype.keyup = function(evt) {
4580
-
4581
- //'this' is the doc
4582
- var wym = WYMeditor.INSTANCES[this.title];
4583
-
4584
- wym._selected_image = null;
4585
- var container = null;
4586
-
4587
- if(evt.keyCode == 13 && !evt.shiftKey) {
4588
-
4589
- //RETURN key
4590
- //cleanup <br><br> between paragraphs
4591
- jQuery(wym._doc.body).children(WYMeditor.BR).remove();
4592
-
4593
- //fix PRE bug #73
4594
- container = wym.selected();
4595
- if(container && container.tagName.toLowerCase() == WYMeditor.PRE)
4596
- wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P); //create P after PRE
4597
- }
4598
-
4599
- //fix #112
4600
- if(evt.keyCode == 13 && evt.shiftKey) {
4601
- wym._exec('InsertLineBreak');
4602
- }
4603
-
4604
- if(evt.keyCode != 8
4605
- && evt.keyCode != 17
4606
- && evt.keyCode != 46
4607
- && evt.keyCode != 224
4608
- && !evt.metaKey
4609
- && !evt.ctrlKey) {
4610
-
4611
- //NOT BACKSPACE, NOT DELETE, NOT CTRL, NOT COMMAND
4612
- //text nodes replaced by P
4613
-
4614
- container = wym.selected();
4615
- var name = container.tagName.toLowerCase();
4616
-
4617
- //fix forbidden main containers
4618
- if(
4619
- name == "strong" ||
4620
- name == "b" ||
4621
- name == "em" ||
4622
- name == "i" ||
4623
- name == "sub" ||
4624
- name == "sup" ||
4625
- name == "a" ||
4626
- name == "span" //fix #110
4627
-
4628
- ) name = container.parentNode.tagName.toLowerCase();
4629
-
4630
- if(name == WYMeditor.BODY || name == WYMeditor.DIV) wym._exec(WYMeditor.FORMAT_BLOCK, WYMeditor.P); //fix #110 for DIV
4631
- }
4632
- };
4633
-
4634
- //TODO
4635
- WYMeditor.WymClassSafari.prototype.setFocusToNode = function(node) {
4636
- /*var range = document.createRange();
4637
- range.selectNode(node);
4638
- var selected = this._iframe.contentWindow.getSelection();
4639
- selected.addRange(range);
4640
- selected.collapse(node, node.childNodes.length);
4641
- this._iframe.contentWindow.focus();*/
4642
- };
4643
-
4644
- WYMeditor.WymClassSafari.prototype.openBlockTag = function(tag, attributes)
4645
- {
4646
- var attributes = this.validator.getValidTagAttributes(tag, attributes);
4647
-
4648
- // Handle Safari styled spans
4649
- if(tag == 'span' && attributes.style) {
4650
- var new_tag = this.getTagForStyle(attributes.style);
4651
- if(new_tag){
4652
- this._tag_stack.pop();
4653
- var tag = new_tag;
4654
- this._tag_stack.push(new_tag);
4655
- attributes.style = '';
4656
-
4657
- //should fix #125 - also removed the xhtml() override
4658
- if(typeof attributes['class'] == 'string')
4659
- attributes['class'] = attributes['class'].replace(/apple-style-span/gi, '');
4660
-
4661
- } else {
4662
- return;
4663
- }
4664
- }
4665
-
4666
- this.output += this.helper.tag(tag, attributes, true);
4667
- };
4668
-
4669
- WYMeditor.WymClassSafari.prototype.getTagForStyle = function(style) {
4670
-
4671
- if(/bold/.test(style)) return 'strong';
4672
- if(/italic/.test(style)) return 'em';
4673
- if(/sub/.test(style)) return 'sub';
4674
- if(/super/.test(style)) return 'sup';
4675
- return false;
4676
- };