coalla-cms 0.4.4.3 → 0.5.1.8

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