coalla-cms 0.4.2.0

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