coalla-cms 0.4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +81 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +168 -0
  5. data/Rakefile +29 -0
  6. data/app/assets/fonts/glyphicons/glyphicons-halflings-regular.eot +0 -0
  7. data/app/assets/fonts/glyphicons/glyphicons-halflings-regular.svg +229 -0
  8. data/app/assets/fonts/glyphicons/glyphicons-halflings-regular.ttf +0 -0
  9. data/app/assets/fonts/glyphicons/glyphicons-halflings-regular.woff +0 -0
  10. data/app/assets/images/ajax-loader.gif +0 -0
  11. data/app/assets/images/blank.gif +0 -0
  12. data/app/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
  13. data/app/assets/images/bootstrap/glyphicons-halflings.png +0 -0
  14. data/app/assets/javascripts/admin/admin.js +295 -0
  15. data/app/assets/javascripts/admin/custom_admin.js +0 -0
  16. data/app/assets/javascripts/admin/jquery-migrate.min.js +2 -0
  17. data/app/assets/javascripts/admin/photo_uploader.js +67 -0
  18. data/app/assets/javascripts/admin/vendor/bootstrap.min.js +7 -0
  19. data/app/assets/javascripts/admin/vendor/jquery-ui-timepicker-addon-ru.js +40 -0
  20. data/app/assets/javascripts/admin/vendor/jquery.tagsinput.js +365 -0
  21. data/app/assets/javascripts/admin/vendor/jquery.tokeninput.patched.js +875 -0
  22. data/app/assets/javascripts/admin/vendor/underscore-min.js +5 -0
  23. data/app/assets/javascripts/ckeditor/plugins/autogrow/plugin.js +209 -0
  24. data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/hidpi/mediaembed.png +0 -0
  25. data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/mediaembed.png +0 -0
  26. data/app/assets/javascripts/ckeditor/plugins/mediaembed/plugin.js +64 -0
  27. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/LICENSE.txt +303 -0
  28. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad-gallery-css-diff.htm +831 -0
  29. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad_next.png +0 -0
  30. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad_prev.png +0 -0
  31. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad_scroll_back.png +0 -0
  32. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad_scroll_forward.png +0 -0
  33. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/jquery.ad-gallery.css +185 -0
  34. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/jquery.ad-gallery.js +984 -0
  35. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/jquery.ad-gallery.min - ref.js +10 -0
  36. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/jquery.ad-gallery.min.js +1 -0
  37. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/loader.gif +0 -0
  38. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/opa75.png +0 -0
  39. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/placeholder.png +0 -0
  40. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/ad-gallery/trans.gif +0 -0
  41. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/blank.gif +0 -0
  42. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_loading.gif +0 -0
  43. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_loading@2x.gif +0 -0
  44. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_overlay.png +0 -0
  45. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_sprite.png +0 -0
  46. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_sprite@2x.png +0 -0
  47. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/fancybox_buttons.png +0 -0
  48. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-buttons.css +97 -0
  49. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-buttons.js +122 -0
  50. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-media.js +199 -0
  51. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-thumbs.css +55 -0
  52. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-thumbs.js +162 -0
  53. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/jquery.fancybox.css +274 -0
  54. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/jquery.fancybox.js +2020 -0
  55. data/app/assets/javascripts/ckeditor/plugins/slideshow/3rdParty/fancybox2/jquery.fancybox.pack.js +46 -0
  56. data/app/assets/javascripts/ckeditor/plugins/slideshow/README.md +66 -0
  57. data/app/assets/javascripts/ckeditor/plugins/slideshow/dialogs/slideshow.js +1396 -0
  58. data/app/assets/javascripts/ckeditor/plugins/slideshow/dialogs/slideshow.min.js +1 -0
  59. data/app/assets/javascripts/ckeditor/plugins/slideshow/icons/placeholder.png +0 -0
  60. data/app/assets/javascripts/ckeditor/plugins/slideshow/icons/slideshow.png +0 -0
  61. data/app/assets/javascripts/ckeditor/plugins/slideshow/lang/Serbian_translation.txt +9 -0
  62. data/app/assets/javascripts/ckeditor/plugins/slideshow/lang/el.js +37 -0
  63. data/app/assets/javascripts/ckeditor/plugins/slideshow/lang/en.js +35 -0
  64. data/app/assets/javascripts/ckeditor/plugins/slideshow/lang/fr.js +35 -0
  65. data/app/assets/javascripts/ckeditor/plugins/slideshow/lang/ru.js +35 -0
  66. data/app/assets/javascripts/ckeditor/plugins/slideshow/lang/sr-latn.js +35 -0
  67. data/app/assets/javascripts/ckeditor/plugins/slideshow/lang/sr.js +35 -0
  68. data/app/assets/javascripts/ckeditor/plugins/slideshow/plugin.js +217 -0
  69. data/app/assets/stylesheets/admin/admin.scss +302 -0
  70. data/app/assets/stylesheets/admin/custom_admin.scss +1 -0
  71. data/app/assets/stylesheets/admin/vendor/bootstrap.min.css +14 -0
  72. data/app/assets/stylesheets/admin/vendor/jquery.tagsinput.css +99 -0
  73. data/app/assets/stylesheets/admin/vendor/token-input-facebook.patched.css +126 -0
  74. data/app/assets/stylesheets/admin/vendor/token-input.patched.css +116 -0
  75. data/app/controllers/admin/autocomplete_controller.rb +14 -0
  76. data/app/controllers/admin/image_upload_controller.rb +27 -0
  77. data/app/controllers/admin/lookups_controller.rb +47 -0
  78. data/app/controllers/admin/sortable_controller.rb +26 -0
  79. data/app/controllers/concerns/admin/path_history.rb +39 -0
  80. data/app/helpers/admin/search_helper.rb +59 -0
  81. data/app/helpers/admin_helper.rb +29 -0
  82. data/app/helpers/common_helper.rb +16 -0
  83. data/app/helpers/lookup_helper.rb +45 -0
  84. data/app/helpers/nested_fields_helper.rb +12 -0
  85. data/app/helpers/static_text_formatter.rb +25 -0
  86. data/app/helpers/twitter_builder_helper.rb +253 -0
  87. data/app/helpers/twitter_form_builder.rb +196 -0
  88. data/app/models/file_upload.rb +19 -0
  89. data/app/models/lookup.rb +6 -0
  90. data/app/uploaders/file_uploader.rb +10 -0
  91. data/app/uploaders/generic_image_uploader.rb +74 -0
  92. data/app/utils/admin_structure.rb +67 -0
  93. data/app/utils/bootstrap_link_renderer.rb +40 -0
  94. data/app/utils/table_helpers.rb +196 -0
  95. data/app/views/admin/base/_sort.haml +34 -0
  96. data/app/views/admin/common/_file_upload_template.haml +14 -0
  97. data/app/views/admin/common/_header.html.haml +27 -0
  98. data/app/views/admin/common/_image_upload_template.html.haml +40 -0
  99. data/app/views/admin/common/_menu.html.haml +2 -0
  100. data/app/views/admin/common/_menu_section.haml +10 -0
  101. data/app/views/admin/common/_menu_separator.haml +1 -0
  102. data/app/views/admin/common/_nested_fields_for.html.haml +5 -0
  103. data/app/views/admin/common/_nested_fields_for_element.html.haml +5 -0
  104. data/app/views/admin/common/_slide.haml +41 -0
  105. data/app/views/admin/common/_slides.html.haml +17 -0
  106. data/app/views/admin/common/_table_template.html.haml +14 -0
  107. data/app/views/admin/common/_upload_form.html.haml +5 -0
  108. data/app/views/admin/common/image_uploaded.js.haml +7 -0
  109. data/app/views/admin/common/upload_failed.js.erb +11 -0
  110. data/app/views/admin/common/upload_image.js.erb +6 -0
  111. data/app/views/admin/home/dashboard.html.haml +5 -0
  112. data/app/views/admin/lookups/_form.html.haml +16 -0
  113. data/app/views/admin/lookups/edit.html.haml +5 -0
  114. data/app/views/admin/lookups/index.html.haml +6 -0
  115. data/app/views/layouts/admin.html.haml +38 -0
  116. data/app/views/structure/_section.haml +16 -0
  117. data/coalla-cms.gemspec +39 -0
  118. data/config/locales/devise.ru.yml +59 -0
  119. data/config/locales/will_paginate.ru.yml +6 -0
  120. data/lib/coalla/cms/engine.rb +16 -0
  121. data/lib/coalla/cms/version.rb +5 -0
  122. data/lib/coalla/ext/mapper.rb +14 -0
  123. data/lib/coalla/orm/page_slider.rb +53 -0
  124. data/lib/coalla/orm/relation.rb +32 -0
  125. data/lib/coalla/orm/sanitized.rb +16 -0
  126. data/lib/coalla/sanitize/config/default.rb +526 -0
  127. data/lib/coalla-cms.rb +16 -0
  128. data/lib/generators/coalla/cms/create_admin_generator.rb +50 -0
  129. data/lib/generators/coalla/cms/create_admin_login_view_generator.rb +23 -0
  130. data/lib/generators/coalla/cms/file_uploads/install_generator.rb +35 -0
  131. data/lib/generators/coalla/cms/file_uploads/mount_generator.rb +34 -0
  132. data/lib/generators/coalla/cms/file_uploads/templates/add_column_migration.rb.erb +5 -0
  133. data/lib/generators/coalla/cms/file_uploads/templates/migration.rb +17 -0
  134. data/lib/generators/coalla/cms/image/install_generator.rb +39 -0
  135. data/lib/generators/coalla/cms/image/mount_generator.rb +50 -0
  136. data/lib/generators/coalla/cms/image/templates/migration.rb.erb +9 -0
  137. data/lib/generators/coalla/cms/image/templates/model.rb.erb +5 -0
  138. data/lib/generators/coalla/cms/image/templates/mount/migration.rb.erb +6 -0
  139. data/lib/generators/coalla/cms/image/templates/mount/uploader.rb.erb +3 -0
  140. data/lib/generators/coalla/cms/image/templates/uploader.rb.erb +3 -0
  141. data/lib/generators/coalla/cms/init_generator.rb +113 -0
  142. data/lib/generators/coalla/cms/lookups/install_generator.rb +43 -0
  143. data/lib/generators/coalla/cms/lookups/templates/migration.rb +13 -0
  144. data/lib/generators/coalla/cms/market/install_generator.rb +71 -0
  145. data/lib/generators/coalla/cms/market/templates/controllers/categories_controller.rb +47 -0
  146. data/lib/generators/coalla/cms/market/templates/controllers/products_controller.rb +50 -0
  147. data/lib/generators/coalla/cms/market/templates/controllers/properties_controller.rb +59 -0
  148. data/lib/generators/coalla/cms/market/templates/market.rb +5 -0
  149. data/lib/generators/coalla/cms/market/templates/market.ru.yml +53 -0
  150. data/lib/generators/coalla/cms/market/templates/migrations/create_categories.rb +15 -0
  151. data/lib/generators/coalla/cms/market/templates/migrations/create_product_properties.rb +18 -0
  152. data/lib/generators/coalla/cms/market/templates/migrations/create_products.rb +18 -0
  153. data/lib/generators/coalla/cms/market/templates/migrations/create_properties.rb +11 -0
  154. data/lib/generators/coalla/cms/market/templates/models/category.rb +36 -0
  155. data/lib/generators/coalla/cms/market/templates/models/product.rb +16 -0
  156. data/lib/generators/coalla/cms/market/templates/models/product_property.rb +14 -0
  157. data/lib/generators/coalla/cms/market/templates/models/property.rb +7 -0
  158. data/lib/generators/coalla/cms/market/templates/views/categories/_form.html.haml +10 -0
  159. data/lib/generators/coalla/cms/market/templates/views/categories/edit.html.haml +5 -0
  160. data/lib/generators/coalla/cms/market/templates/views/categories/index.html.haml +17 -0
  161. data/lib/generators/coalla/cms/market/templates/views/categories/new.html.haml +4 -0
  162. data/lib/generators/coalla/cms/market/templates/views/products/_form.html.haml +17 -0
  163. data/lib/generators/coalla/cms/market/templates/views/products/_product_property_fields.html.haml +13 -0
  164. data/lib/generators/coalla/cms/market/templates/views/products/edit.html.haml +5 -0
  165. data/lib/generators/coalla/cms/market/templates/views/products/index.html.haml +17 -0
  166. data/lib/generators/coalla/cms/market/templates/views/products/new.html.haml +4 -0
  167. data/lib/generators/coalla/cms/market/templates/views/properties/_form.html.haml +9 -0
  168. data/lib/generators/coalla/cms/market/templates/views/properties/edit.html.haml +5 -0
  169. data/lib/generators/coalla/cms/market/templates/views/properties/index.html.haml +15 -0
  170. data/lib/generators/coalla/cms/market/templates/views/properties/new.html.haml +4 -0
  171. data/lib/generators/coalla/cms/news/scaffold_generator.rb +50 -0
  172. data/lib/generators/coalla/cms/news/templates/entity.rb.erb +10 -0
  173. data/lib/generators/coalla/cms/news/templates/entity_controller_template.rb.erb +47 -0
  174. data/lib/generators/coalla/cms/news/templates/entity_image_uploader.rb.erb +7 -0
  175. data/lib/generators/coalla/cms/news/templates/migration.rb.erb +15 -0
  176. data/lib/generators/coalla/cms/news/templates/views/_form.haml.erb +16 -0
  177. data/lib/generators/coalla/cms/news/templates/views/edit.haml.erb +5 -0
  178. data/lib/generators/coalla/cms/news/templates/views/index.haml.erb +18 -0
  179. data/lib/generators/coalla/cms/news/templates/views/new.haml.erb +5 -0
  180. data/lib/generators/coalla/cms/orm_helpers.rb +31 -0
  181. data/lib/generators/coalla/cms/scaffold_generator.rb +53 -0
  182. data/lib/generators/coalla/cms/scaffold_helper.rb +11 -0
  183. data/lib/generators/coalla/cms/setup_admin_generator.rb +60 -0
  184. data/lib/generators/coalla/cms/setup_routes_generator.rb +28 -0
  185. data/lib/generators/coalla/cms/slider/init_generator.rb +41 -0
  186. data/lib/generators/coalla/cms/slider/templates/migration.rb.erb +25 -0
  187. data/lib/generators/coalla/cms/slider/templates/slider_image.rb.erb +10 -0
  188. data/lib/generators/coalla/cms/slider/templates/slider_image_uploader.rb.erb +7 -0
  189. data/lib/generators/coalla/cms/slider/templates/slider_upload_controller.rb.erb +19 -0
  190. data/lib/generators/coalla/cms/templates/.gitattributes +4 -0
  191. data/lib/generators/coalla/cms/templates/.gitignore +86 -0
  192. data/lib/generators/coalla/cms/templates/activerecord.ru.yml +13 -0
  193. data/lib/generators/coalla/cms/templates/assets.rb +13 -0
  194. data/lib/generators/coalla/cms/templates/controllers/admin/base_controller.rb.erb +35 -0
  195. data/lib/generators/coalla/cms/templates/controllers/admin/home_controller.rb.erb +6 -0
  196. data/lib/generators/coalla/cms/templates/controllers/admin/scaffold_controller_template.rb.erb +45 -0
  197. data/lib/generators/coalla/cms/templates/controllers/home_controller.rb.erb +6 -0
  198. data/lib/generators/coalla/cms/templates/database.yml.erb +35 -0
  199. data/lib/generators/coalla/cms/templates/devise.ru.yml +59 -0
  200. data/lib/generators/coalla/cms/templates/initializers/carrierwave.rb +51 -0
  201. data/lib/generators/coalla/cms/templates/migration.rb +11 -0
  202. data/lib/generators/coalla/cms/templates/migration_existing.rb +15 -0
  203. data/lib/generators/coalla/cms/templates/schedule.rb +3 -0
  204. data/lib/generators/coalla/cms/templates/structure.rb +0 -0
  205. data/lib/generators/coalla/cms/templates/views/admin/scaffold_template/_form.html.haml.erb +14 -0
  206. data/lib/generators/coalla/cms/templates/views/admin/scaffold_template/edit.html.haml.erb +5 -0
  207. data/lib/generators/coalla/cms/templates/views/admin/scaffold_template/index.html.haml.erb +15 -0
  208. data/lib/generators/coalla/cms/templates/views/admin/scaffold_template/new.html.haml.erb +4 -0
  209. data/lib/generators/coalla/cms/templates/views/administrators/sessions/new.html.haml +19 -0
  210. data/lib/generators/coalla/cms/templates/views/home/index.html.haml.erb +1 -0
  211. data/lib/generators/coalla/cms/wysiwyg/ckeditor_generator.rb +17 -0
  212. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/mediaembed/icons/hidpi/mediaembed.png +0 -0
  213. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/mediaembed/icons/mediaembed.png +0 -0
  214. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/mediaembed/plugin.js +64 -0
  215. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/LICENSE.txt +303 -0
  216. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad-gallery-css-diff.htm +831 -0
  217. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad_next.png +0 -0
  218. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad_prev.png +0 -0
  219. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad_scroll_back.png +0 -0
  220. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/ad_scroll_forward.png +0 -0
  221. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/jquery.ad-gallery.css +185 -0
  222. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/jquery.ad-gallery.js +984 -0
  223. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/jquery.ad-gallery.min - ref.js +10 -0
  224. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/jquery.ad-gallery.min.js +1 -0
  225. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/loader.gif +0 -0
  226. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/opa75.png +0 -0
  227. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/placeholder.png +0 -0
  228. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/ad-gallery/trans.gif +0 -0
  229. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/blank.gif +0 -0
  230. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_loading.gif +0 -0
  231. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_loading@2x.gif +0 -0
  232. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_overlay.png +0 -0
  233. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_sprite.png +0 -0
  234. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/fancybox_sprite@2x.png +0 -0
  235. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/fancybox_buttons.png +0 -0
  236. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-buttons.css +97 -0
  237. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-buttons.js +122 -0
  238. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-media.js +199 -0
  239. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-thumbs.css +55 -0
  240. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/helpers/jquery.fancybox-thumbs.js +162 -0
  241. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/jquery.fancybox.css +274 -0
  242. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/jquery.fancybox.js +2020 -0
  243. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/3rdParty/fancybox2/jquery.fancybox.pack.js +46 -0
  244. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/README.md +66 -0
  245. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/dialogs/slideshow.js +1396 -0
  246. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/dialogs/slideshow.min.js +1 -0
  247. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/icons/placeholder.png +0 -0
  248. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/icons/slideshow.png +0 -0
  249. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/lang/Serbian_translation.txt +9 -0
  250. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/lang/el.js +37 -0
  251. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/lang/en.js +35 -0
  252. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/lang/fr.js +35 -0
  253. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/lang/ru.js +35 -0
  254. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/lang/sr-latn.js +35 -0
  255. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/lang/sr.js +35 -0
  256. data/lib/generators/coalla/cms/wysiwyg/templates/ckeditor/plugins/slideshow/plugin.js +217 -0
  257. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-blockquote.png +0 -0
  258. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-h1.png +0 -0
  259. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-h2.png +0 -0
  260. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-h3.png +0 -0
  261. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-h4.png +0 -0
  262. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-h5.png +0 -0
  263. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-h6.png +0 -0
  264. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-p.png +0 -0
  265. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/lbl-pre.png +0 -0
  266. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/wymiframe.css +276 -0
  267. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/iframe/default/wymiframe.html +26 -0
  268. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/jquery.wymeditor.js +4819 -0
  269. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/lang/en.js +45 -0
  270. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/lang/ru.js +55 -0
  271. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/plugins/imageupload/icons.png +0 -0
  272. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/plugins/imageupload/jquery.wymeditor.imageupload.js +150 -0
  273. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/plugins/resizable/jquery.wymeditor.resizable.js +91 -0
  274. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/plugins/resizable/readme.txt +124 -0
  275. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/compact/icons.png +0 -0
  276. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/compact/skin.css +134 -0
  277. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/compact/skin.js +35 -0
  278. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/default/icons.png +0 -0
  279. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/default/skin.css +341 -0
  280. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/default/skin.js +40 -0
  281. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/minimal/images/bg.header.gif +0 -0
  282. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/minimal/images/bg.selector.silver.gif +0 -0
  283. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/minimal/images/bg.wymeditor.png +0 -0
  284. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/minimal/images/icons.silver.gif +0 -0
  285. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/minimal/skin.css +131 -0
  286. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/minimal/skin.js +30 -0
  287. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/silver/COPYING +674 -0
  288. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/silver/README +27 -0
  289. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/silver/images/bg.header.gif +0 -0
  290. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/silver/images/bg.selector.silver.gif +0 -0
  291. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/silver/images/bg.wymeditor.png +0 -0
  292. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/silver/images/icons.silver.gif +0 -0
  293. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/silver/skin.css +297 -0
  294. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/silver/skin.js +61 -0
  295. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/twopanels/icons.png +0 -0
  296. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/twopanels/skin.css +134 -0
  297. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/twopanels/skin.js +39 -0
  298. data/lib/generators/coalla/cms/wysiwyg/templates/wymeditor/skins/wymeditor_icon.png +0 -0
  299. data/lib/generators/coalla/cms/wysiwyg/wymeditor_generator.rb +17 -0
  300. metadata +581 -0
@@ -0,0 +1,4819 @@
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
+ };