spree_static_content 0.30.0 → 0.40.0

Sign up to get free protection for your applications and to get access to all the features.
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
- };