skylinecms 3.0.8 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. data/CHANGELOG +131 -10
  2. data/README.md +1 -2
  3. data/Rakefile +3 -3
  4. data/app/controllers/skyline/application_controller.rb +40 -4
  5. data/app/controllers/skyline/articles_controller.rb +4 -4
  6. data/app/controllers/skyline/browser/tabs/media_library/media_files_controller.rb +1 -1
  7. data/app/controllers/skyline/content_controller.rb +4 -3
  8. data/app/controllers/skyline/{media_files_data_controller.rb → media/data_controller.rb} +61 -59
  9. data/app/controllers/skyline/media/dirs_controller.rb +83 -0
  10. data/app/controllers/skyline/media/files_controller.rb +80 -0
  11. data/app/controllers/skyline/sections_controller.rb +10 -3
  12. data/app/controllers/skyline/settings_controller.rb +4 -2
  13. data/app/controllers/skyline/user_preferences_controller.rb +18 -0
  14. data/app/controllers/skyline/users_controller.rb +1 -1
  15. data/app/controllers/skyline/variant_current_editor_controller.rb +2 -0
  16. data/app/helpers/skyline/application_helper.rb +39 -35
  17. data/app/helpers/skyline/dialog_helper.rb +11 -10
  18. data/app/helpers/skyline/editors/boolean.rb +2 -2
  19. data/app/helpers/skyline/editors/page_browser.rb +2 -0
  20. data/app/helpers/skyline/editors/wysiwyg.rb +1 -1
  21. data/app/helpers/skyline/js_layout_helper.rb +19 -0
  22. data/app/helpers/skyline/media/dirs_helper.rb +2 -0
  23. data/app/helpers/skyline/media/files_helper.rb +6 -0
  24. data/app/helpers/skyline/media_files_helper.rb +2 -2
  25. data/app/helpers/skyline/menu_helper.rb +33 -0
  26. data/app/helpers/skyline/message_generator.rb +5 -1
  27. data/app/helpers/skyline/notification_generator.rb +6 -0
  28. data/app/helpers/skyline/plugin_helper.rb +21 -0
  29. data/app/helpers/skyline/presenters/presenter.rb +4 -13
  30. data/app/helpers/skyline/presenters/table.rb +0 -27
  31. data/app/helpers/skyline/ref_object_helper.rb +2 -2
  32. data/app/helpers/skyline/tree_helper.rb +74 -5
  33. data/app/models/skyline/article.rb +18 -6
  34. data/app/models/skyline/article_version.rb +1 -1
  35. data/app/models/skyline/image_ref.rb +9 -5
  36. data/app/models/skyline/inline_ref.rb +3 -2
  37. data/app/models/skyline/link_section_link.rb +2 -2
  38. data/app/models/skyline/media_file.rb +33 -10
  39. data/app/models/skyline/page.rb +10 -9
  40. data/app/models/skyline/section.rb +1 -1
  41. data/app/models/skyline/sections/content_collection_section.rb +1 -1
  42. data/app/models/skyline/sections/content_item_section.rb +1 -1
  43. data/app/models/skyline/sections/heading_section.rb +1 -1
  44. data/app/models/skyline/sections/iframe_section.rb +2 -2
  45. data/app/models/skyline/sections/link_section.rb +1 -1
  46. data/app/models/skyline/sections/media_section.rb +32 -5
  47. data/app/models/skyline/sections/page_fragment_section.rb +1 -1
  48. data/app/models/skyline/sections/raw_section.rb +1 -1
  49. data/app/models/skyline/sections/redirect_section.rb +4 -4
  50. data/app/models/skyline/sections/rss_section.rb +7 -2
  51. data/app/models/skyline/sections/splitter_section.rb +1 -1
  52. data/app/models/skyline/sections/wysiwyg_section.rb +3 -3
  53. data/app/models/skyline/site.rb +1 -1
  54. data/app/models/skyline/user.rb +1 -1
  55. data/app/models/skyline/user_preference.rb +69 -0
  56. data/app/models/skyline/variant.rb +1 -1
  57. data/app/templates/skyline/sections/content_item_section/default/index.html.erb +1 -1
  58. data/app/templates/skyline/sections/media_section/default/index.html.erb +9 -9
  59. data/app/views/skyline/articles/_list.html.erb +34 -0
  60. data/app/views/skyline/articles/edit.html.erb +13 -6
  61. data/app/views/skyline/articles/index.html.erb +12 -43
  62. data/app/views/skyline/articles/page/_index.html.erb +13 -11
  63. data/app/views/skyline/authentications/new.html.erb +2 -2
  64. data/app/views/skyline/browser/links/_index.html.erb +4 -2
  65. data/app/views/skyline/browser/tabs/media_library/_index.html.erb +12 -13
  66. data/app/views/skyline/browser/tabs/media_library/media_files/_index.html.erb +122 -51
  67. data/app/views/skyline/browser/tabs/media_library/media_files/_show.html.erb +7 -7
  68. data/app/views/skyline/content/list.rhtml +1 -3
  69. data/app/views/skyline/content/presenters/_table.html.erb +45 -0
  70. data/app/views/skyline/layouts/content.html.erb +1 -1
  71. data/app/views/skyline/layouts/media.html.erb +2 -1
  72. data/app/views/skyline/layouts/pages.html.erb +10 -0
  73. data/app/views/skyline/link_section_links/_form.html.erb +0 -1
  74. data/app/views/skyline/locales/show.js.erb +2 -2
  75. data/app/views/skyline/media/dirs/_edit.html.erb +42 -0
  76. data/app/views/skyline/media/dirs/_index.html.erb +14 -0
  77. data/app/views/skyline/media/dirs/_show.html.erb +34 -0
  78. data/app/views/skyline/media/dirs/index.html.erb +36 -0
  79. data/app/views/skyline/media/files/_edit.html.erb +101 -0
  80. data/app/views/skyline/media/files/_index.html.erb +68 -0
  81. data/app/views/skyline/media/files/_new.html.erb +45 -0
  82. data/app/views/skyline/publications/_index.html.erb +2 -2
  83. data/app/views/skyline/sections/_media_section.html.erb +12 -2
  84. data/app/views/skyline/sections/_wysiwyg_section.html.erb +2 -3
  85. data/app/views/skyline/settings/index.html +14 -0
  86. data/app/views/skyline/shared/_head.html.erb +2 -0
  87. data/app/views/skyline/shared/_header_area.html.erb +7 -5
  88. data/app/views/skyline/users/index.html.erb +31 -16
  89. data/config/initializers/dependencies.rb +6 -1
  90. data/config/initializers/observers.rb +1 -2
  91. data/config/initializers/rails_defaults.rb +1 -1
  92. data/config/locales/en-US.yml +110 -68
  93. data/config/locales/nl-NL.yml +117 -77
  94. data/config/routes.rb +36 -32
  95. data/db/fixtures/roles_and_rights.rb +65 -40
  96. data/db/migrate/20090302102548_add_media_nodes.rb +2 -2
  97. data/db/migrate/20090309133933_add_description_to_media_nodes.rb +2 -2
  98. data/db/migrate/20090309134731_add_tags.rb +2 -2
  99. data/db/migrate/20090309135746_create_media_files_tags.rb +2 -2
  100. data/db/migrate/20090319091342_create_media_caches.rb +2 -2
  101. data/db/migrate/20090327083240_create_users.rb +2 -2
  102. data/db/migrate/20090327084656_create_roles.rb +2 -2
  103. data/db/migrate/20090327084719_create_rights.rb +2 -2
  104. data/db/migrate/20090327084739_create_grants.rb +2 -2
  105. data/db/migrate/20090327090918_create_rights_roles.rb +2 -2
  106. data/db/migrate/20090408115155_create_ref_objects.rb +2 -2
  107. data/db/migrate/20090504140044_create_test_sections.rb +2 -2
  108. data/db/migrate/20090506083107_add_refering_column_name_to_ref_objects.rb +2 -2
  109. data/db/migrate/20090706124019_add_skyline_media_node_title.rb +1 -1
  110. data/db/migrate/20090904121447_create_skyline_referable_uris.rb +6 -6
  111. data/db/migrate/20091221145204_add_skyline_media_section_link.rb +11 -0
  112. data/db/migrate/20100109145958_add_associated_tags_index.rb +9 -0
  113. data/db/migrate/20100115111440_create_skyline_user_preferences.rb +14 -0
  114. data/db/migrate/20100120113953_remove_unused_articles_index.rb +9 -0
  115. data/db/migrate/20100409073447_change_referable_uri_to_text.rb +9 -0
  116. data/doc/Bundler.md +33 -28
  117. data/doc/MIGRATION.md +48 -0
  118. data/lib/skyline/{content_item.rb → belongs_to_referable.rb} +57 -88
  119. data/lib/skyline/configuration.rb +14 -15
  120. data/lib/skyline/content/content.rb +14 -2
  121. data/lib/skyline/deprecated/version3_0_8.rb +106 -0
  122. data/lib/skyline/{form_builder_with_errors.rb → form_builder.rb} +5 -5
  123. data/lib/skyline/{referable.rb → has_many_referables_in.rb} +22 -12
  124. data/lib/skyline/javascript_generator_methods.rb +1 -1
  125. data/lib/skyline/plugins_manager.rb +135 -14
  126. data/lib/skyline/rendering/helpers/renderer_helper.rb +14 -9
  127. data/lib/skyline/{renderer.rb → rendering/renderer.rb} +3 -4
  128. data/lib/skyline/{renderable_scope_interface.rb → rendering/scopes/interface.rb} +1 -1
  129. data/lib/skyline/{wildcard_renderable_scope.rb → rendering/scopes/wildcard.rb} +3 -3
  130. data/lib/skyline/{section_item.rb → sections/interface.rb} +17 -10
  131. data/lib/skyline/settings.rb +29 -19
  132. data/lib/skyline/taggable.rb +3 -3
  133. data/lib/skyline/version.rb +2 -2
  134. data/{tasks → lib/tasks}/database.rake +14 -2
  135. data/{tasks → lib/tasks}/implementation.rake +0 -0
  136. data/lib/tasks/testing.rake +41 -0
  137. data/public/skyline/images/backgrounds/panel-dt.gif +0 -0
  138. data/public/skyline/javascripts/src/application.js +114 -120
  139. data/public/skyline/javascripts/src/browser.js +22 -4
  140. data/public/skyline/javascripts/src/library_uploader.js +13 -3
  141. data/public/skyline/javascripts/src/sections.js +57 -6
  142. data/public/skyline/javascripts/src/skyline/src/dialog.js +6 -0
  143. data/public/skyline/javascripts/src/skyline/src/drag.js +6 -0
  144. data/public/skyline/javascripts/src/skyline/src/events.js +50 -0
  145. data/public/skyline/javascripts/src/skyline/src/field_replicator.js +12 -11
  146. data/public/skyline/javascripts/src/skyline/src/layout.js +172 -30
  147. data/public/skyline/javascripts/src/skyline/src/menu.js +3 -0
  148. data/public/skyline/javascripts/src/skyline/src/menubutton.js +3 -0
  149. data/public/skyline/javascripts/src/skyline/src/skyline.js +3 -0
  150. data/public/skyline/javascripts/src/skyline/src/table.js +398 -0
  151. data/public/skyline/javascripts/src/skyline/src/tabs.js +2 -2
  152. data/public/skyline/javascripts/src/skyline/src/tag_selector.js +34 -26
  153. data/public/skyline/javascripts/src/skyline/src/tree.js +3 -0
  154. data/public/skyline/javascripts/src/skyline/src/uploader.js +2 -2
  155. data/public/skyline/javascripts/src/skyline/src/utils.js +3 -0
  156. data/public/skyline/javascripts/src/skyline/test/_dynamic_right.html +24 -0
  157. data/public/skyline/javascripts/src/skyline/test/_right_content.html +1 -0
  158. data/public/skyline/javascripts/src/skyline/test/basic_layout.html +190 -0
  159. data/public/skyline/javascripts/src/skyline/test/dialog.html +101 -0
  160. data/public/skyline/javascripts/src/skyline/test/draggablefiles.html +196 -0
  161. data/public/skyline/javascripts/src/skyline/test/dynamic_layout.html +89 -0
  162. data/public/skyline/javascripts/src/skyline/test/field_replicator.html +60 -0
  163. data/public/skyline/javascripts/src/skyline/test/last-closed.gif +0 -0
  164. data/public/skyline/javascripts/src/skyline/test/last-open.gif +0 -0
  165. data/public/skyline/javascripts/src/skyline/test/menubutton.html +81 -0
  166. data/public/skyline/javascripts/src/skyline/test/middle.gif +0 -0
  167. data/public/skyline/javascripts/src/skyline/test/sortable.html +121 -0
  168. data/public/skyline/javascripts/src/skyline/test/table.html +521 -0
  169. data/public/skyline/javascripts/src/skyline/test/tagselector.html +72 -0
  170. data/public/skyline/javascripts/src/skyline/test/toggle.html +95 -0
  171. data/public/skyline/javascripts/src/skyline/test/tree.html +310 -0
  172. data/public/skyline/javascripts/src/skyline/test/tree.png +0 -0
  173. data/public/skyline/javascripts/src/skyline/test/undohtml.css +27 -0
  174. data/public/skyline/javascripts/src/skyline/vendor/fancyupload/Swiff.Uploader.js +2 -2
  175. data/public/skyline/javascripts/src/skyline/vendor/mootools/mootools-core.js +1 -354
  176. data/public/skyline/javascripts/src/skyline/vendor/mootools/mootools-more.js +64 -52
  177. data/public/skyline/javascripts/src/skyline.editor/assets/content.css +1 -1
  178. data/public/skyline/javascripts/src/skyline.editor/src/script_loader.js +156 -75
  179. data/public/skyline/javascripts/src/skyline.editor/src/skyline.editor.js +14 -4
  180. data/public/skyline/javascripts/src/skyline.editor/src/theme.js +8 -0
  181. data/public/skyline/javascripts/src/skyline.editor/test/dialog.html +28 -0
  182. data/public/skyline/javascripts/src/skyline.editor/test/lorem.html +7 -0
  183. data/public/skyline/javascripts/src/skyline.editor/test/multiple_editors.html +87 -0
  184. data/public/skyline/javascripts/src/skyline.editor/test/undohtml.css +27 -0
  185. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/changelog.txt +205 -0
  186. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/css/content.css +54 -0
  187. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/custom_formats.html +111 -0
  188. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/full.html +19 -3
  189. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/menu.html +1 -0
  190. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/simple.html +6 -2
  191. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/skins.html +14 -10
  192. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/translate.html +7 -3
  193. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/word.html +8 -4
  194. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/langs/en.js +18 -2
  195. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advhr/editor_plugin_src.js +6 -3
  196. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advhr/rule.htm +2 -7
  197. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advimage/editor_plugin_src.js +6 -3
  198. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advimage/image.htm +2 -7
  199. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advimage/js/image.js +1 -1
  200. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advlink/editor_plugin_src.js +6 -3
  201. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advlink/js/advlink.js +1 -1
  202. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advlink/link.htm +2 -7
  203. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advlist/editor_plugin.js +1 -0
  204. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/advlist/editor_plugin_src.js +154 -0
  205. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/autoresize/editor_plugin.js +1 -1
  206. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/autoresize/editor_plugin_src.js +52 -44
  207. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/autosave/editor_plugin.js +1 -1
  208. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/autosave/editor_plugin_src.js +388 -17
  209. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/autosave/langs/en.js +4 -0
  210. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/bbcode/editor_plugin_src.js +6 -3
  211. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/contextmenu/editor_plugin.js +1 -1
  212. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/contextmenu/editor_plugin_src.js +58 -6
  213. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/directionality/editor_plugin_src.js +6 -3
  214. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/emotions/editor_plugin.js +1 -1
  215. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/emotions/editor_plugin_src.js +8 -5
  216. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/example/dialog.htm +2 -7
  217. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/example/editor_plugin_src.js +6 -3
  218. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/fullpage/editor_plugin.js +1 -1
  219. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/fullpage/editor_plugin_src.js +10 -3
  220. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/fullpage/fullpage.htm +2 -7
  221. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/fullpage/js/fullpage.js +18 -8
  222. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/fullscreen/editor_plugin.js +1 -1
  223. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/fullscreen/editor_plugin_src.js +12 -6
  224. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/fullscreen/fullscreen.htm +0 -1
  225. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/iespell/editor_plugin_src.js +6 -3
  226. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/inlinepopups/editor_plugin_src.js +6 -3
  227. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/insertdatetime/editor_plugin_src.js +6 -3
  228. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/layer/editor_plugin_src.js +6 -3
  229. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/legacyoutput/editor_plugin.js +1 -0
  230. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/legacyoutput/editor_plugin_src.js +136 -0
  231. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/media/editor_plugin.js +1 -1
  232. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/media/editor_plugin_src.js +18 -9
  233. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/media/media.htm +2 -7
  234. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/nonbreaking/editor_plugin.js +1 -1
  235. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/nonbreaking/editor_plugin_src.js +7 -4
  236. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/noneditable/editor_plugin_src.js +6 -3
  237. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/pagebreak/editor_plugin_src.js +6 -3
  238. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/paste/editor_plugin.js +1 -1
  239. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/paste/editor_plugin_src.js +564 -124
  240. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/paste/pastetext.htm +2 -8
  241. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/paste/pasteword.htm +2 -8
  242. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/preview/editor_plugin_src.js +6 -3
  243. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/print/editor_plugin_src.js +6 -3
  244. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/save/editor_plugin_src.js +6 -3
  245. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/searchreplace/editor_plugin.js +1 -1
  246. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/searchreplace/editor_plugin_src.js +7 -4
  247. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/searchreplace/js/searchreplace.js +4 -0
  248. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/searchreplace/searchreplace.htm +4 -9
  249. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/spellchecker/editor_plugin.js +1 -1
  250. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/spellchecker/editor_plugin_src.js +106 -27
  251. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/style/editor_plugin_src.js +6 -3
  252. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/style/props.htm +4 -11
  253. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/tabfocus/editor_plugin.js +1 -1
  254. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/tabfocus/editor_plugin_src.js +7 -4
  255. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/cell.htm +2 -7
  256. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/editor_plugin.js +1 -1
  257. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/editor_plugin_src.js +921 -918
  258. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/js/cell.js +41 -24
  259. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/js/merge_cells.js +18 -20
  260. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/js/row.js +48 -23
  261. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/js/table.js +24 -15
  262. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/merge_cells.htm +3 -8
  263. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/row.htm +2 -7
  264. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/table/table.htm +2 -7
  265. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/template/editor_plugin.js +1 -1
  266. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/template/editor_plugin_src.js +10 -7
  267. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/template/template.htm +2 -9
  268. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/visualchars/editor_plugin.js +1 -1
  269. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/visualchars/editor_plugin_src.js +26 -16
  270. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/wordcount/editor_plugin.js +1 -0
  271. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/wordcount/editor_plugin_src.js +98 -0
  272. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/abbr.htm +3 -10
  273. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/acronym.htm +3 -10
  274. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/attributes.htm +2 -7
  275. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/cite.htm +3 -10
  276. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/del.htm +3 -11
  277. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin.js +1 -1
  278. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js +11 -15
  279. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/ins.htm +3 -11
  280. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/abbr.js +8 -5
  281. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/acronym.js +7 -4
  282. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/attributes.js +7 -4
  283. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/cite.js +7 -4
  284. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/del.js +7 -4
  285. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/element_common.js +8 -8
  286. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/xhtmlxtras/js/ins.js +7 -4
  287. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/about.htm +1 -3
  288. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/anchor.htm +2 -7
  289. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/charmap.htm +0 -1
  290. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/color_picker.htm +2 -4
  291. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/editor_template.js +1 -1
  292. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/editor_template_src.js +252 -188
  293. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/image.htm +2 -7
  294. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/img/icons.gif +0 -0
  295. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/js/anchor.js +7 -7
  296. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/js/charmap.js +10 -0
  297. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/js/image.js +2 -2
  298. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/js/link.js +4 -4
  299. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/link.htm +2 -7
  300. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/content.css +7 -3
  301. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/dialog.css +4 -3
  302. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/ui.css +5 -6
  303. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/content.css +7 -3
  304. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css +3 -2
  305. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/skins/o2k7/ui.css +4 -4
  306. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/advanced/source_editor.htm +2 -8
  307. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/themes/simple/editor_template_src.js +5 -5
  308. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/tiny_mce.js +1 -1
  309. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/tiny_mce_popup.js +1 -1
  310. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/tiny_mce_src.js +5492 -4341
  311. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/utils/editable_selects.js +5 -4
  312. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/utils/form_utils.js +6 -5
  313. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/utils/mctabs.js +5 -4
  314. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/utils/validate.js +5 -4
  315. data/public/skyline/javascripts/src/skyline.js +3 -1
  316. data/public/skyline/javascripts/src/user_preferences.js +49 -0
  317. data/public/skyline/stylesheets/general.css +149 -47
  318. data/rails/init.rb +3 -3
  319. data/test/factories.rb +28 -0
  320. data/test/integration/media_browser_super_access_test.rb +52 -0
  321. data/test/integration/media_browser_user_access_test.rb +50 -0
  322. data/test/integration/user_preferences_test.rb +73 -0
  323. data/test/mocks/test_content_object.rb +32 -0
  324. data/test/mocks/test_section.rb +22 -0
  325. data/test/test_helper.rb +60 -0
  326. data/test/unit/inline_ref_test.rb +195 -0
  327. data/test/unit/locales_test.rb +82 -0
  328. data/test/unit/page_test.rb +204 -0
  329. data/test/unit/test_content_object_test.rb +69 -0
  330. data/test/unit/test_section_test.rb +247 -0
  331. data/test/unit/user_preference_test.rb +123 -0
  332. data/test/unit/user_test.rb +74 -0
  333. data/test/user_access_helper.rb +36 -0
  334. data/vendor/digitpaint/personify/test/fixtures/multiple_tags.txt +8 -0
  335. data/vendor/digitpaint/personify/test/parse_runner.rb +25 -0
  336. data/vendor/digitpaint/personify/test/parser_test.rb +109 -0
  337. data/vendor/digitpaint/personify/test/test_helper.rb +16 -0
  338. data/vendor/digitpaint/personify/vendor/treetop/.gitignore +5 -0
  339. data/vendor/mootools-on-rails/lib/mootools_on_rails/mootools_helper.rb +13 -4
  340. data/vendor/mootools-on-rails/test/mootools_helper_test.rb +138 -0
  341. data/vendor/mootools-on-rails/test/test_helper.rb +5 -0
  342. data/vendor/weppos/url_validation.rb +76 -0
  343. metadata +384 -189
  344. data/app/controllers/skyline/media_dirs_controller.rb +0 -56
  345. data/app/controllers/skyline/media_files_controller.rb +0 -87
  346. data/app/helpers/skyline/presenters/article_list.rb +0 -139
  347. data/app/observers/skyline/media_file_observer.rb +0 -32
  348. data/app/views/skyline/media_dirs/_edit.html.erb +0 -25
  349. data/app/views/skyline/media_dirs/_index.html.erb +0 -14
  350. data/app/views/skyline/media_dirs/index.html.erb +0 -42
  351. data/app/views/skyline/media_files/_edit.html.erb +0 -75
  352. data/app/views/skyline/media_files/_header.html.erb +0 -3
  353. data/app/views/skyline/media_files/_index.html.erb +0 -51
  354. data/app/views/skyline/media_files/_new.html.erb +0 -50
  355. data/db/migrate/20090603104115_prefix_tables_for_skyline.rb +0 -30
  356. data/lib/skyline/indexer.rb +0 -36
  357. data/lib/skyline/renderable_scope.rb +0 -27
  358. data/lib/skyline/rendering/helpers/settings_helper.rb +0 -26
  359. data/lib/skyline/searchable_item.rb +0 -132
  360. data/lib/skyline/url_validation.rb +0 -66
  361. data/public/skyline/images/backgrounds/splitter.gif +0 -0
  362. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/build.bat +0 -2
  363. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/build.xml +0 -364
  364. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/examples/full_jquery.html +0 -94
  365. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/AddOnManager.js +0 -95
  366. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/CommandManager.js +0 -54
  367. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ControlManager.js +0 -489
  368. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/Developer.js +0 -91
  369. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/Editor.js +0 -2295
  370. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/EditorCommands.js +0 -934
  371. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/EditorManager.js +0 -453
  372. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ForceBlocks.js +0 -644
  373. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/Popup.js +0 -412
  374. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/UndoManager.js +0 -183
  375. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/WindowManager.js +0 -169
  376. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/adapter/jquery/adapter.js +0 -240
  377. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/adapter/jquery/jquery.tinymce.js +0 -179
  378. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/adapter/prototype/adapter.js +0 -38
  379. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/commands/BlockQuote.js +0 -135
  380. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/commands/CutCopyPaste.js +0 -24
  381. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/commands/InsertHorizontalRule.js +0 -15
  382. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/commands/RemoveFormat.js +0 -173
  383. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/commands/UndoRedo.js +0 -38
  384. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/DOMUtils.js +0 -1823
  385. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/Element.js +0 -199
  386. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/EventUtils.js +0 -349
  387. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/Range.js +0 -721
  388. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/ScriptLoader.js +0 -351
  389. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/Selection.js +0 -747
  390. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/Serializer.js +0 -979
  391. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/Sizzle.js +0 -975
  392. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/StringWriter.js +0 -200
  393. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/TridentSelection.js +0 -273
  394. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/dom/XMLWriter.js +0 -155
  395. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/firebug/firebug-lite.js +0 -2518
  396. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/tinymce.js +0 -549
  397. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/Button.js +0 -68
  398. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/ColorSplitButton.js +0 -212
  399. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/Container.js +0 -56
  400. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/Control.js +0 -182
  401. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/DropMenu.js +0 -397
  402. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/ListBox.js +0 -320
  403. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/Menu.js +0 -175
  404. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/MenuButton.js +0 -128
  405. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/MenuItem.js +0 -69
  406. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/NativeListBox.js +0 -198
  407. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/Separator.js +0 -34
  408. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/SplitButton.js +0 -99
  409. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/ui/Toolbar.js +0 -86
  410. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/util/Cookie.js +0 -126
  411. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/util/Dispatcher.js +0 -101
  412. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/util/JSON.js +0 -81
  413. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/util/JSONP.js +0 -25
  414. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/util/JSONRequest.js +0 -87
  415. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/util/URI.js +0 -289
  416. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/util/XHR.js +0 -80
  417. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/classes/xml/Parser.js +0 -126
  418. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/jquery.tinymce.js +0 -1
  419. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/compat2x/editor_plugin.js +0 -1
  420. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/compat2x/editor_plugin_src.js +0 -616
  421. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/safari/blank.htm +0 -1
  422. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/safari/editor_plugin.js +0 -1
  423. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/plugins/safari/editor_plugin_src.js +0 -438
  424. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/tiny_mce_dev.js +0 -128
  425. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/tiny_mce_jquery.js +0 -1
  426. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/tiny_mce_jquery_src.js +0 -12198
  427. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/tiny_mce_prototype.js +0 -1
  428. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/jscripts/tiny_mce/tiny_mce_prototype_src.js +0 -13057
  429. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/api.html +0 -18
  430. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/api_jquery.html +0 -18
  431. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/api_prototype.html +0 -19
  432. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/basic.html +0 -548
  433. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/crossdomain.html +0 -87
  434. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/css/unit.css +0 -120
  435. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/index.html +0 -10
  436. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/jquery_plugin.html +0 -112
  437. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/js/api.js +0 -1438
  438. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/js/testrunner.js +0 -791
  439. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/main.html +0 -8
  440. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/media.html +0 -221
  441. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/menu.html +0 -22
  442. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/parts.html +0 -90
  443. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/paste.html +0 -132
  444. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/performance.html +0 -152
  445. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/range.html +0 -522
  446. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/removeformat.html +0 -88
  447. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/selection.html +0 -235
  448. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/config.ini +0 -27
  449. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/footer.html +0 -3
  450. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/header.html +0 -6
  451. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/index.php +0 -1
  452. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/instructions.txt +0 -4
  453. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/logo.png +0 -0
  454. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/selectors.list +0 -40
  455. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/style.css +0 -181
  456. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/system/index.php +0 -112
  457. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/system/slickspeed.js +0 -147
  458. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/system/template.php +0 -47
  459. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/slickspeed/template.html +0 -2865
  460. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tests/test.xml +0 -6
  461. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tools/ant/ant-contrib.jar +0 -0
  462. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tools/ant/js_build_tools.jar +0 -0
  463. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tools/ant/svnClientAdapter.jar +0 -0
  464. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tools/ant/svnant.jar +0 -0
  465. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tools/ant/svnjavahl.jar +0 -0
  466. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tools/ant/svnkit.jar +0 -0
  467. data/public/skyline/javascripts/src/skyline.editor/vendor/tinymce/tools/ant/yuicompressor.jar +0 -0
@@ -1,1136 +1,1139 @@
1
1
  /**
2
- * $Id: editor_plugin_src.js 953 2008-11-04 10:16:50Z spocke $
2
+ * editor_plugin_src.js
3
3
  *
4
- * @author Moxiecode
5
- * @copyright Copyright 2004-2008, Moxiecode Systems AB, All rights reserved.
4
+ * Copyright 2009, Moxiecode Systems AB
5
+ * Released under LGPL License.
6
+ *
7
+ * License: http://tinymce.moxiecode.com/license
8
+ * Contributing: http://tinymce.moxiecode.com/contributing
6
9
  */
7
10
 
8
- (function() {
11
+ (function(tinymce) {
9
12
  var each = tinymce.each;
10
13
 
11
- tinymce.create('tinymce.plugins.TablePlugin', {
12
- init : function(ed, url) {
13
- var t = this;
14
+ // Checks if the selection/caret is at the start of the specified block element
15
+ function isAtStart(rng, par) {
16
+ var doc = par.ownerDocument, rng2 = doc.createRange(), elm;
14
17
 
15
- t.editor = ed;
16
- t.url = url;
18
+ rng2.setStartBefore(par);
19
+ rng2.setEnd(rng.endContainer, rng.endOffset);
17
20
 
18
- // Register buttons
19
- each([
20
- ['table', 'table.desc', 'mceInsertTable', true],
21
- ['delete_table', 'table.del', 'mceTableDelete'],
22
- ['delete_col', 'table.delete_col_desc', 'mceTableDeleteCol'],
23
- ['delete_row', 'table.delete_row_desc', 'mceTableDeleteRow'],
24
- ['col_after', 'table.col_after_desc', 'mceTableInsertColAfter'],
25
- ['col_before', 'table.col_before_desc', 'mceTableInsertColBefore'],
26
- ['row_after', 'table.row_after_desc', 'mceTableInsertRowAfter'],
27
- ['row_before', 'table.row_before_desc', 'mceTableInsertRowBefore'],
28
- ['row_props', 'table.row_desc', 'mceTableRowProps', true],
29
- ['cell_props', 'table.cell_desc', 'mceTableCellProps', true],
30
- ['split_cells', 'table.split_cells_desc', 'mceTableSplitCells', true],
31
- ['merge_cells', 'table.merge_cells_desc', 'mceTableMergeCells', true]
32
- ], function(c) {
33
- ed.addButton(c[0], {title : c[1], cmd : c[2], ui : c[3]});
34
- });
21
+ elm = doc.createElement('body');
22
+ elm.appendChild(rng2.cloneContents());
35
23
 
36
- if (ed.getParam('inline_styles')) {
37
- // Force move of attribs to styles in strict mode
38
- ed.onPreProcess.add(function(ed, o) {
39
- var dom = ed.dom;
24
+ // Check for text characters of other elements that should be treated as content
25
+ return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length == 0;
26
+ };
40
27
 
41
- each(dom.select('table', o.node), function(n) {
42
- var v;
28
+ /**
29
+ * Table Grid class.
30
+ */
31
+ function TableGrid(table, dom, selection) {
32
+ var grid, startPos, endPos, selectedCell;
43
33
 
44
- if (v = dom.getAttrib(n, 'width')) {
45
- dom.setStyle(n, 'width', v);
46
- dom.setAttrib(n, 'width');
47
- }
34
+ buildGrid();
35
+ selectedCell = dom.getParent(selection.getStart(), 'th,td');
36
+ if (selectedCell) {
37
+ startPos = getPos(selectedCell);
38
+ endPos = findEndPos();
39
+ selectedCell = getCell(startPos.x, startPos.y);
40
+ }
48
41
 
49
- if (v = dom.getAttrib(n, 'height')) {
50
- dom.setStyle(n, 'height', v);
51
- dom.setAttrib(n, 'height');
52
- }
53
- });
54
- });
55
- }
42
+ function cloneNode(node, children) {
43
+ node = node.cloneNode(children);
44
+ node.removeAttribute('id');
56
45
 
57
- ed.onInit.add(function() {
58
- if (ed && ed.plugins.contextmenu) {
59
- ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {
60
- var sm, se = ed.selection, el = se.getNode() || ed.getBody();
46
+ return node;
47
+ }
61
48
 
62
- if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th')) {
63
- m.removeAll();
49
+ function buildGrid() {
50
+ var startY = 0;
64
51
 
65
- if (el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) {
66
- m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true});
67
- m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'});
68
- m.addSeparator();
69
- }
52
+ grid = [];
70
53
 
71
- if (el.nodeName == 'IMG' && el.className.indexOf('mceItem') == -1) {
72
- m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true});
73
- m.addSeparator();
74
- }
54
+ each(['thead', 'tbody', 'tfoot'], function(part) {
55
+ var rows = dom.select('> ' + part + ' tr', table);
75
56
 
76
- m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true, value : {action : 'insert'}});
77
- m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable', ui : true});
78
- m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete', ui : true});
79
- m.addSeparator();
57
+ each(rows, function(tr, y) {
58
+ y += startY;
80
59
 
81
- // Cell menu
82
- sm = m.addMenu({title : 'table.cell'});
83
- sm.add({title : 'table.cell_desc', icon : 'cell_props', cmd : 'mceTableCellProps', ui : true});
84
- sm.add({title : 'table.split_cells_desc', icon : 'split_cells', cmd : 'mceTableSplitCells', ui : true});
85
- sm.add({title : 'table.merge_cells_desc', icon : 'merge_cells', cmd : 'mceTableMergeCells', ui : true});
60
+ each(dom.select('> td, > th', tr), function(td, x) {
61
+ var x2, y2, rowspan, colspan;
86
62
 
87
- // Row menu
88
- sm = m.addMenu({title : 'table.row'});
89
- sm.add({title : 'table.row_desc', icon : 'row_props', cmd : 'mceTableRowProps', ui : true});
90
- sm.add({title : 'table.row_before_desc', icon : 'row_before', cmd : 'mceTableInsertRowBefore'});
91
- sm.add({title : 'table.row_after_desc', icon : 'row_after', cmd : 'mceTableInsertRowAfter'});
92
- sm.add({title : 'table.delete_row_desc', icon : 'delete_row', cmd : 'mceTableDeleteRow'});
93
- sm.addSeparator();
94
- sm.add({title : 'table.cut_row_desc', icon : 'cut', cmd : 'mceTableCutRow'});
95
- sm.add({title : 'table.copy_row_desc', icon : 'copy', cmd : 'mceTableCopyRow'});
96
- sm.add({title : 'table.paste_row_before_desc', icon : 'paste', cmd : 'mceTablePasteRowBefore'});
97
- sm.add({title : 'table.paste_row_after_desc', icon : 'paste', cmd : 'mceTablePasteRowAfter'});
63
+ // Skip over existing cells produced by rowspan
64
+ if (grid[y]) {
65
+ while (grid[y][x])
66
+ x++;
67
+ }
98
68
 
99
- // Column menu
100
- sm = m.addMenu({title : 'table.col'});
101
- sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'});
102
- sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'});
103
- sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'});
104
- } else
105
- m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true});
69
+ // Get col/rowspan from cell
70
+ rowspan = getSpanVal(td, 'rowspan');
71
+ colspan = getSpanVal(td, 'colspan');
72
+
73
+ // Fill out rowspan/colspan right and down
74
+ for (y2 = y; y2 < y + rowspan; y2++) {
75
+ if (!grid[y2])
76
+ grid[y2] = [];
77
+
78
+ for (x2 = x; x2 < x + colspan; x2++) {
79
+ grid[y2][x2] = {
80
+ part : part,
81
+ real : y2 == y && x2 == x,
82
+ elm : td,
83
+ rowspan : rowspan,
84
+ colspan : colspan
85
+ };
86
+ }
87
+ }
106
88
  });
107
- }
89
+ });
90
+
91
+ startY += rows.length;
108
92
  });
93
+ };
109
94
 
110
- // Add undo level when new rows are created using the tab key
111
- ed.onKeyDown.add(function(ed, e) {
112
- if (e.keyCode == 9 && ed.dom.getParent(ed.selection.getNode(), 'TABLE')) {
113
- if (!tinymce.isGecko && !tinymce.isOpera) {
114
- tinyMCE.execInstanceCommand(ed.editorId, "mceTableMoveToNextRow", true);
115
- return tinymce.dom.Event.cancel(e);
116
- }
95
+ function getCell(x, y) {
96
+ var row;
117
97
 
118
- ed.undoManager.add();
119
- }
98
+ row = grid[y];
99
+ if (row)
100
+ return row[x];
101
+ };
102
+
103
+ function getSpanVal(td, name) {
104
+ return parseInt(td.getAttribute(name) || 1);
105
+ };
106
+
107
+ function isCellSelected(cell) {
108
+ return dom.hasClass(cell.elm, 'mceSelected') || cell == selectedCell;
109
+ };
110
+
111
+ function getSelectedRows() {
112
+ var rows = [];
113
+
114
+ each(table.rows, function(row) {
115
+ each(row.cells, function(cell) {
116
+ if (dom.hasClass(cell, 'mceSelected') || cell == selectedCell.elm) {
117
+ rows.push(row);
118
+ return false;
119
+ }
120
+ });
120
121
  });
121
122
 
122
- // Select whole table is a table border is clicked
123
- if (!tinymce.isIE) {
124
- if (ed.getParam('table_selection', true)) {
125
- ed.onClick.add(function(ed, e) {
126
- e = e.target;
123
+ return rows;
124
+ };
127
125
 
128
- if (e.nodeName === 'TABLE')
129
- ed.selection.select(e);
130
- });
131
- }
132
- }
126
+ function deleteTable() {
127
+ var rng = dom.createRng();
133
128
 
134
- ed.onNodeChange.add(function(ed, cm, n) {
135
- var p = ed.dom.getParent(n, 'td,th,caption');
129
+ rng.setStartAfter(table);
130
+ rng.setEndAfter(table);
136
131
 
137
- cm.setActive('table', n.nodeName === 'TABLE' || !!p);
138
- if (p && p.nodeName === 'CAPTION')
139
- p = null;
132
+ selection.setRng(rng);
140
133
 
141
- cm.setDisabled('delete_table', !p);
142
- cm.setDisabled('delete_col', !p);
143
- cm.setDisabled('delete_table', !p);
144
- cm.setDisabled('delete_row', !p);
145
- cm.setDisabled('col_after', !p);
146
- cm.setDisabled('col_before', !p);
147
- cm.setDisabled('row_after', !p);
148
- cm.setDisabled('row_before', !p);
149
- cm.setDisabled('row_props', !p);
150
- cm.setDisabled('cell_props', !p);
151
- cm.setDisabled('split_cells', !p || (parseInt(ed.dom.getAttrib(p, 'colspan', '1')) < 2 && parseInt(ed.dom.getAttrib(p, 'rowspan', '1')) < 2));
152
- cm.setDisabled('merge_cells', !p);
153
- });
134
+ dom.remove(table);
135
+ };
154
136
 
155
- // Padd empty table cells
156
- if (!tinymce.isIE) {
157
- ed.onBeforeSetContent.add(function(ed, o) {
158
- if (o.initial)
159
- o.content = o.content.replace(/<(td|th)([^>]+|)>\s*<\/(td|th)>/g, tinymce.isOpera ? '<$1$2>&nbsp;</$1>' : '<$1$2><br mce_bogus="1" /></$1>');
160
- });
161
- }
162
- },
163
-
164
- execCommand : function(cmd, ui, val) {
165
- var ed = this.editor, b;
166
-
167
- // Is table command
168
- switch (cmd) {
169
- case "mceTableMoveToNextRow":
170
- case "mceInsertTable":
171
- case "mceTableRowProps":
172
- case "mceTableCellProps":
173
- case "mceTableSplitCells":
174
- case "mceTableMergeCells":
175
- case "mceTableInsertRowBefore":
176
- case "mceTableInsertRowAfter":
177
- case "mceTableDeleteRow":
178
- case "mceTableInsertColBefore":
179
- case "mceTableInsertColAfter":
180
- case "mceTableDeleteCol":
181
- case "mceTableCutRow":
182
- case "mceTableCopyRow":
183
- case "mceTablePasteRowBefore":
184
- case "mceTablePasteRowAfter":
185
- case "mceTableDelete":
186
- ed.execCommand('mceBeginUndoLevel');
187
- this._doExecCommand(cmd, ui, val);
188
- ed.execCommand('mceEndUndoLevel');
189
-
190
- return true;
191
- }
137
+ function cloneCell(cell) {
138
+ var formatNode;
192
139
 
193
- // Pass to next handler in chain
194
- return false;
195
- },
196
-
197
- getInfo : function() {
198
- return {
199
- longname : 'Tables',
200
- author : 'Moxiecode Systems AB',
201
- authorurl : 'http://tinymce.moxiecode.com',
202
- infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',
203
- version : tinymce.majorVersion + "." + tinymce.minorVersion
204
- };
205
- },
206
-
207
- // Private plugin internal methods
208
-
209
- /**
210
- * Executes the table commands.
211
- */
212
- _doExecCommand : function(command, user_interface, value) {
213
- var inst = this.editor, ed = inst, url = this.url;
214
- var focusElm = inst.selection.getNode();
215
- var trElm = inst.dom.getParent(focusElm, "tr");
216
- var tdElm = inst.dom.getParent(focusElm, "td,th");
217
- var tableElm = inst.dom.getParent(focusElm, "table");
218
- var doc = inst.contentWindow.document;
219
- var tableBorder = tableElm ? tableElm.getAttribute("border") : "";
220
-
221
- // Get first TD if no TD found
222
- if (trElm && tdElm == null)
223
- tdElm = trElm.cells[0];
224
-
225
- function inArray(ar, v) {
226
- for (var i=0; i<ar.length; i++) {
227
- // Is array
228
- if (ar[i].length > 0 && inArray(ar[i], v))
229
- return true;
230
-
231
- // Found value
232
- if (ar[i] == v)
233
- return true;
234
- }
140
+ // Clone formats
141
+ tinymce.walk(cell, function(node) {
142
+ var curNode;
235
143
 
236
- return false;
237
- }
144
+ if (node.nodeType == 3) {
145
+ each(dom.getParents(node.parentNode, null, cell).reverse(), function(node) {
146
+ node = cloneNode(node, false);
238
147
 
239
- function select(dx, dy) {
240
- var td;
148
+ if (!formatNode)
149
+ formatNode = curNode = node;
150
+ else if (curNode)
151
+ curNode.appendChild(node);
241
152
 
242
- grid = getTableGrid(tableElm);
243
- dx = dx || 0;
244
- dy = dy || 0;
245
- dx = Math.max(cpos.cellindex + dx, 0);
246
- dy = Math.max(cpos.rowindex + dy, 0);
153
+ curNode = node;
154
+ });
247
155
 
248
- // Recalculate grid and select
249
- inst.execCommand('mceRepaint');
250
- td = getCell(grid, dy, dx);
156
+ // Add something to the inner node
157
+ if (curNode)
158
+ curNode.innerHTML = tinymce.isIE ? '&nbsp;' : '<br _mce_bogus="1" />';
251
159
 
252
- if (td) {
253
- inst.selection.select(td.firstChild || td);
254
- inst.selection.collapse(1);
160
+ return false;
255
161
  }
256
- };
162
+ }, 'childNodes');
257
163
 
258
- function makeTD() {
259
- var newTD = doc.createElement("td");
164
+ cell = cloneNode(cell, false);
165
+ cell.rowSpan = cell.colSpan = 1;
260
166
 
167
+ if (formatNode) {
168
+ cell.appendChild(formatNode);
169
+ } else {
261
170
  if (!tinymce.isIE)
262
- newTD.innerHTML = '<br mce_bogus="1"/>';
171
+ cell.innerHTML = '<br _mce_bogus="1" />';
263
172
  }
264
173
 
265
- function getColRowSpan(td) {
266
- var colspan = inst.dom.getAttrib(td, "colspan");
267
- var rowspan = inst.dom.getAttrib(td, "rowspan");
174
+ return cell;
175
+ };
268
176
 
269
- colspan = colspan == "" ? 1 : parseInt(colspan);
270
- rowspan = rowspan == "" ? 1 : parseInt(rowspan);
177
+ function cleanup() {
178
+ var rng = dom.createRng();
271
179
 
272
- return {colspan : colspan, rowspan : rowspan};
180
+ // Empty rows
181
+ each(dom.select('tr', table), function(tr) {
182
+ if (tr.cells.length == 0)
183
+ dom.remove(tr);
184
+ });
185
+
186
+ // Empty table
187
+ if (dom.select('tr', table).length == 0) {
188
+ rng.setStartAfter(table);
189
+ rng.setEndAfter(table);
190
+ selection.setRng(rng);
191
+ dom.remove(table);
192
+ return;
273
193
  }
274
194
 
275
- function getCellPos(grid, td) {
276
- var x, y;
195
+ // Empty header/body/footer
196
+ each(dom.select('thead,tbody,tfoot', table), function(part) {
197
+ if (part.rows.length == 0)
198
+ dom.remove(part);
199
+ });
277
200
 
278
- for (y=0; y<grid.length; y++) {
279
- for (x=0; x<grid[y].length; x++) {
280
- if (grid[y][x] == td)
281
- return {cellindex : x, rowindex : y};
282
- }
283
- }
201
+ // Restore selection to start position if it still exists
202
+ buildGrid();
284
203
 
285
- return null;
204
+ // Restore the selection to the closest table position
205
+ row = grid[Math.min(grid.length - 1, startPos.y)];
206
+ if (row) {
207
+ selection.select(row[Math.min(row.length - 1, startPos.x)].elm, true);
208
+ selection.collapse(true);
286
209
  }
210
+ };
287
211
 
288
- function getCell(grid, row, col) {
289
- if (grid[row] && grid[row][col])
290
- return grid[row][col];
212
+ function fillLeftDown(x, y, rows, cols) {
213
+ var tr, x2, r, c, cell;
291
214
 
292
- return null;
293
- }
215
+ tr = grid[y][x].elm.parentNode;
216
+ for (r = 1; r <= rows; r++) {
217
+ tr = dom.getNext(tr, 'tr');
294
218
 
295
- function getNextCell(table, cell) {
296
- var cells = [], x = 0, i, j, cell, nextCell;
219
+ if (tr) {
220
+ // Loop left to find real cell
221
+ for (x2 = x; x2 >= 0; x2--) {
222
+ cell = grid[y + r][x2].elm;
297
223
 
298
- for (i = 0; i < table.rows.length; i++)
299
- for (j = 0; j < table.rows[i].cells.length; j++, x++)
300
- cells[x] = table.rows[i].cells[j];
224
+ if (cell.parentNode == tr) {
225
+ // Append clones after
226
+ for (c = 1; c <= cols; c++)
227
+ dom.insertAfter(cloneCell(cell), cell);
301
228
 
302
- for (i = 0; i < cells.length; i++)
303
- if (cells[i] == cell)
304
- if (nextCell = cells[i+1])
305
- return nextCell;
229
+ break;
230
+ }
231
+ }
232
+
233
+ if (x2 == -1) {
234
+ // Insert nodes before first cell
235
+ for (c = 1; c <= cols; c++)
236
+ tr.insertBefore(cloneCell(tr.cells[0]), tr.cells[0]);
237
+ }
238
+ }
306
239
  }
240
+ };
307
241
 
308
- function getTableGrid(table) {
309
- var grid = [], rows = table.rows, x, y, td, sd, xstart, x2, y2;
242
+ function split() {
243
+ each(grid, function(row, y) {
244
+ each(row, function(cell, x) {
245
+ var colSpan, rowSpan, newCell, i;
310
246
 
311
- for (y=0; y<rows.length; y++) {
312
- for (x=0; x<rows[y].cells.length; x++) {
313
- td = rows[y].cells[x];
314
- sd = getColRowSpan(td);
247
+ if (isCellSelected(cell)) {
248
+ cell = cell.elm;
249
+ colSpan = getSpanVal(cell, 'colspan');
250
+ rowSpan = getSpanVal(cell, 'rowspan');
315
251
 
316
- // All ready filled
317
- for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;
252
+ if (colSpan > 1 || rowSpan > 1) {
253
+ cell.colSpan = cell.rowSpan = 1;
318
254
 
319
- // Fill box
320
- for (y2=y; y2<y+sd['rowspan']; y2++) {
321
- if (!grid[y2])
322
- grid[y2] = [];
255
+ // Insert cells right
256
+ for (i = 0; i < colSpan - 1; i++)
257
+ dom.insertAfter(cloneCell(cell), cell);
258
+
259
+ fillLeftDown(x, y, rowSpan - 1, colSpan);
260
+ }
261
+ }
262
+ });
263
+ });
264
+ };
265
+
266
+ function merge(cell, cols, rows) {
267
+ var startX, startY, endX, endY, x, y, startCell, endCell, cell, children;
268
+
269
+ // Use specified cell and cols/rows
270
+ if (cell) {
271
+ pos = getPos(cell);
272
+ startX = pos.x;
273
+ startY = pos.y;
274
+ endX = startX + (cols - 1);
275
+ endY = startY + (rows - 1);
276
+ } else {
277
+ // Use selection
278
+ startX = startPos.x;
279
+ startY = startPos.y;
280
+ endX = endPos.x;
281
+ endY = endPos.y;
282
+ }
323
283
 
324
- for (x2=xstart; x2<xstart+sd['colspan']; x2++)
325
- grid[y2][x2] = td;
284
+ // Find start/end cells
285
+ startCell = getCell(startX, startY);
286
+ endCell = getCell(endX, endY);
287
+
288
+ // Check if the cells exists and if they are of the same part for example tbody = tbody
289
+ if (startCell && endCell && startCell.part == endCell.part) {
290
+ // Split and rebuild grid
291
+ split();
292
+ buildGrid();
293
+
294
+ // Set row/col span to start cell
295
+ startCell = getCell(startX, startY).elm;
296
+ startCell.colSpan = (endX - startX) + 1;
297
+ startCell.rowSpan = (endY - startY) + 1;
298
+
299
+ // Remove other cells and add it's contents to the start cell
300
+ for (y = startY; y <= endY; y++) {
301
+ for (x = startX; x <= endX; x++) {
302
+ cell = grid[y][x].elm;
303
+
304
+ if (cell != startCell) {
305
+ // Move children to startCell
306
+ children = tinymce.grep(cell.childNodes);
307
+ each(children, function(node, i) {
308
+ // Jump over last BR element
309
+ if (node.nodeName != 'BR' || i != children.length - 1)
310
+ startCell.appendChild(node);
311
+ });
312
+
313
+ // Remove cell
314
+ dom.remove(cell);
326
315
  }
327
316
  }
328
317
  }
329
318
 
330
- return grid;
319
+ // Remove empty rows etc and restore caret location
320
+ cleanup();
331
321
  }
322
+ };
323
+
324
+ function insertRow(before) {
325
+ var posY, cell, lastCell, x, rowElm, newRow, newCell, otherCell;
326
+
327
+ // Find first/last row
328
+ each(grid, function(row, y) {
329
+ each(row, function(cell, x) {
330
+ if (isCellSelected(cell)) {
331
+ cell = cell.elm;
332
+ rowElm = cell.parentNode;
333
+ newRow = cloneNode(rowElm, false);
334
+ posY = y;
335
+
336
+ if (before)
337
+ return false;
338
+ }
339
+ });
332
340
 
333
- function trimRow(table, tr, td, new_tr) {
334
- var grid = getTableGrid(table), cpos = getCellPos(grid, td);
335
- var cells, lastElm;
336
-
337
- // Time to crop away some
338
- if (new_tr.cells.length != tr.childNodes.length) {
339
- cells = tr.childNodes;
340
- lastElm = null;
341
-
342
- for (var x=0; td = getCell(grid, cpos.rowindex, x); x++) {
343
- var remove = true;
344
- var sd = getColRowSpan(td);
345
-
346
- // Remove due to rowspan
347
- if (inArray(cells, td)) {
348
- new_tr.childNodes[x]._delete = true;
349
- } else if ((lastElm == null || td != lastElm) && sd.colspan > 1) { // Remove due to colspan
350
- for (var i=x; i<x+td.colSpan; i++)
351
- new_tr.childNodes[i]._delete = true;
352
- }
341
+ if (before)
342
+ return !posY;
343
+ });
353
344
 
354
- if ((lastElm == null || td != lastElm) && sd.rowspan > 1)
355
- td.rowSpan = sd.rowspan + 1;
345
+ for (x = 0; x < grid[0].length; x++) {
346
+ cell = grid[posY][x].elm;
356
347
 
357
- lastElm = td;
348
+ if (cell != lastCell) {
349
+ if (!before) {
350
+ rowSpan = getSpanVal(cell, 'rowspan');
351
+ if (rowSpan > 1) {
352
+ cell.rowSpan = rowSpan + 1;
353
+ continue;
354
+ }
355
+ } else {
356
+ // Check if cell above can be expanded
357
+ if (posY > 0 && grid[posY - 1][x]) {
358
+ otherCell = grid[posY - 1][x].elm;
359
+ rowSpan = getSpanVal(otherCell, 'rowspan');
360
+ if (rowSpan > 1) {
361
+ otherCell.rowSpan = rowSpan + 1;
362
+ continue;
363
+ }
364
+ }
358
365
  }
359
366
 
360
- deleteMarked(tableElm);
361
- }
362
- }
367
+ // Insert new cell into new row
368
+ newCell = cloneCell(cell)
369
+ newCell.colSpan = cell.colSpan;
370
+ newRow.appendChild(newCell);
363
371
 
364
- function prevElm(node, name) {
365
- while ((node = node.previousSibling) != null) {
366
- if (node.nodeName == name)
367
- return node;
372
+ lastCell = cell;
368
373
  }
374
+ }
369
375
 
370
- return null;
376
+ if (newRow.hasChildNodes()) {
377
+ if (!before)
378
+ dom.insertAfter(newRow, rowElm);
379
+ else
380
+ rowElm.parentNode.insertBefore(newRow, rowElm);
371
381
  }
382
+ };
372
383
 
373
- function nextElm(node, names) {
374
- var namesAr = names.split(',');
384
+ function insertCol(before) {
385
+ var posX, lastCell;
375
386
 
376
- while ((node = node.nextSibling) != null) {
377
- for (var i=0; i<namesAr.length; i++) {
378
- if (node.nodeName.toLowerCase() == namesAr[i].toLowerCase() )
379
- return node;
387
+ // Find first/last column
388
+ each(grid, function(row, y) {
389
+ each(row, function(cell, x) {
390
+ if (isCellSelected(cell)) {
391
+ posX = x;
392
+
393
+ if (before)
394
+ return false;
380
395
  }
381
- }
396
+ });
382
397
 
383
- return null;
384
- }
398
+ if (before)
399
+ return !posX;
400
+ });
385
401
 
386
- function deleteMarked(tbl) {
387
- if (tbl.rows == 0)
388
- return;
402
+ each(grid, function(row, y) {
403
+ var cell = row[posX].elm, rowSpan, colSpan;
389
404
 
390
- var tr = tbl.rows[0];
391
- do {
392
- var next = nextElm(tr, "TR");
405
+ if (cell != lastCell) {
406
+ colSpan = getSpanVal(cell, 'colspan');
407
+ rowSpan = getSpanVal(cell, 'rowspan');
393
408
 
394
- // Delete row
395
- if (tr._delete) {
396
- tr.parentNode.removeChild(tr);
397
- continue;
398
- }
409
+ if (colSpan == 1) {
410
+ if (!before) {
411
+ dom.insertAfter(cloneCell(cell), cell);
412
+ fillLeftDown(posX, y, rowSpan - 1, colSpan);
413
+ } else {
414
+ cell.parentNode.insertBefore(cloneCell(cell), cell);
415
+ fillLeftDown(posX, y, rowSpan - 1, colSpan);
416
+ }
417
+ } else
418
+ cell.colSpan++;
419
+
420
+ lastCell = cell;
421
+ }
422
+ });
423
+ };
424
+
425
+ function deleteCols() {
426
+ var cols = [];
399
427
 
400
- // Delete cells
401
- var td = tr.cells[0];
402
- if (td.cells > 1) {
403
- do {
404
- var nexttd = nextElm(td, "TD,TH");
428
+ // Get selected column indexes
429
+ each(grid, function(row, y) {
430
+ each(row, function(cell, x) {
431
+ if (isCellSelected(cell) && tinymce.inArray(cols, x) === -1) {
432
+ each(grid, function(row) {
433
+ var cell = row[x].elm, colSpan;
434
+
435
+ colSpan = getSpanVal(cell, 'colspan');
436
+
437
+ if (colSpan > 1)
438
+ cell.colSpan = colSpan - 1;
439
+ else
440
+ dom.remove(cell);
441
+ });
405
442
 
406
- if (td._delete)
407
- td.parentNode.removeChild(td);
408
- } while ((td = nexttd) != null);
443
+ cols.push(x);
409
444
  }
410
- } while ((tr = next) != null);
411
- }
445
+ });
446
+ });
412
447
 
413
- function addRows(td_elm, tr_elm, rowspan) {
414
- // Add rows
415
- td_elm.rowSpan = 1;
416
- var trNext = nextElm(tr_elm, "TR");
417
- for (var i=1; i<rowspan && trNext; i++) {
418
- var newTD = doc.createElement("td");
448
+ cleanup();
449
+ };
419
450
 
420
- if (!tinymce.isIE)
421
- newTD.innerHTML = '<br mce_bogus="1"/>';
451
+ function deleteRows() {
452
+ var rows;
422
453
 
423
- if (tinymce.isIE)
424
- trNext.insertBefore(newTD, trNext.cells(td_elm.cellIndex));
425
- else
426
- trNext.insertBefore(newTD, trNext.cells[td_elm.cellIndex]);
454
+ function deleteRow(tr) {
455
+ var nextTr, pos, lastCell;
427
456
 
428
- trNext = nextElm(trNext, "TR");
429
- }
430
- }
457
+ nextTr = dom.getNext(tr, 'tr');
431
458
 
432
- function copyRow(doc, table, tr) {
433
- var grid = getTableGrid(table);
434
- var newTR = tr.cloneNode(false);
435
- var cpos = getCellPos(grid, tr.cells[0]);
436
- var lastCell = null;
437
- var tableBorder = inst.dom.getAttrib(table, "border");
438
- var tdElm = null;
439
-
440
- for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
441
- var newTD = null;
442
-
443
- if (lastCell != tdElm) {
444
- for (var i=0; i<tr.cells.length; i++) {
445
- if (tdElm == tr.cells[i]) {
446
- newTD = tdElm.cloneNode(true);
447
- break;
448
- }
449
- }
459
+ // Move down row spanned cells
460
+ each(tr.cells, function(cell) {
461
+ var rowSpan = getSpanVal(cell, 'rowspan');
462
+
463
+ if (rowSpan > 1) {
464
+ cell.rowSpan = rowSpan - 1;
465
+ pos = getPos(cell);
466
+ fillLeftDown(pos.x, pos.y, 1, 1);
450
467
  }
468
+ });
469
+
470
+ // Delete cells
471
+ pos = getPos(tr.cells[0]);
472
+ each(grid[pos.y], function(cell) {
473
+ var rowSpan;
474
+
475
+ cell = cell.elm;
451
476
 
452
- if (newTD == null) {
453
- newTD = doc.createElement("td");
477
+ if (cell != lastCell) {
478
+ rowSpan = getSpanVal(cell, 'rowspan');
454
479
 
455
- if (!tinymce.isIE)
456
- newTD.innerHTML = '<br mce_bogus="1"/>';
480
+ if (rowSpan <= 1)
481
+ dom.remove(cell);
482
+ else
483
+ cell.rowSpan = rowSpan - 1;
484
+
485
+ lastCell = cell;
457
486
  }
487
+ });
488
+ };
458
489
 
459
- // Reset col/row span
460
- newTD.colSpan = 1;
461
- newTD.rowSpan = 1;
490
+ // Get selected rows and move selection out of scope
491
+ rows = getSelectedRows();
462
492
 
463
- newTR.appendChild(newTD);
493
+ // Delete all selected rows
494
+ each(rows.reverse(), function(tr) {
495
+ deleteRow(tr);
496
+ });
464
497
 
465
- lastCell = tdElm;
466
- }
498
+ cleanup();
499
+ };
467
500
 
468
- return newTR;
469
- }
501
+ function cutRows() {
502
+ var rows = getSelectedRows();
470
503
 
471
- // ---- Commands -----
504
+ dom.remove(rows);
505
+ cleanup();
472
506
 
473
- // Handle commands
474
- switch (command) {
475
- case "mceTableMoveToNextRow":
476
- var nextCell = getNextCell(tableElm, tdElm);
507
+ return rows;
508
+ };
477
509
 
478
- if (!nextCell) {
479
- inst.execCommand("mceTableInsertRowAfter", tdElm);
480
- nextCell = getNextCell(tableElm, tdElm);
481
- }
510
+ function copyRows() {
511
+ var rows = getSelectedRows();
482
512
 
483
- inst.selection.select(nextCell);
484
- inst.selection.collapse(true);
513
+ each(rows, function(row, i) {
514
+ rows[i] = cloneNode(row, true);
515
+ });
485
516
 
486
- return true;
517
+ return rows;
518
+ };
487
519
 
488
- case "mceTableRowProps":
489
- if (trElm == null)
490
- return true;
520
+ function pasteRows(rows, before) {
521
+ var selectedRows = getSelectedRows(),
522
+ targetRow = selectedRows[before ? 0 : selectedRows.length - 1],
523
+ targetCellCount = targetRow.cells.length;
491
524
 
492
- if (user_interface) {
493
- inst.windowManager.open({
494
- url : url + '/row.htm',
495
- width : 400 + parseInt(inst.getLang('table.rowprops_delta_width', 0)),
496
- height : 295 + parseInt(inst.getLang('table.rowprops_delta_height', 0)),
497
- inline : 1
498
- }, {
499
- plugin_url : url
500
- });
501
- }
525
+ // Calc target cell count
526
+ each(grid, function(row) {
527
+ var match;
502
528
 
503
- return true;
529
+ targetCellCount = 0;
530
+ each(row, function(cell, x) {
531
+ if (cell.real)
532
+ targetCellCount += cell.colspan;
504
533
 
505
- case "mceTableCellProps":
506
- if (tdElm == null)
507
- return true;
534
+ if (cell.elm.parentNode == targetRow)
535
+ match = 1;
536
+ });
508
537
 
509
- if (user_interface) {
510
- inst.windowManager.open({
511
- url : url + '/cell.htm',
512
- width : 400 + parseInt(inst.getLang('table.cellprops_delta_width', 0)),
513
- height : 295 + parseInt(inst.getLang('table.cellprops_delta_height', 0)),
514
- inline : 1
515
- }, {
516
- plugin_url : url
517
- });
518
- }
538
+ if (match)
539
+ return false;
540
+ });
519
541
 
520
- return true;
542
+ if (!before)
543
+ rows.reverse();
521
544
 
522
- case "mceInsertTable":
523
- if (user_interface) {
524
- inst.windowManager.open({
525
- url : url + '/table.htm',
526
- width : 400 + parseInt(inst.getLang('table.table_delta_width', 0)),
527
- height : 320 + parseInt(inst.getLang('table.table_delta_height', 0)),
528
- inline : 1
529
- }, {
530
- plugin_url : url,
531
- action : value ? value.action : 0
532
- });
533
- }
545
+ each(rows, function(row) {
546
+ var cellCount = row.cells.length, cell;
534
547
 
535
- return true;
548
+ // Remove col/rowspans
549
+ for (i = 0; i < cellCount; i++) {
550
+ cell = row.cells[i];
551
+ cell.colSpan = cell.rowSpan = 1;
552
+ }
536
553
 
537
- case "mceTableDelete":
538
- var table = inst.dom.getParent(inst.selection.getNode(), "table");
539
- if (table) {
540
- table.parentNode.removeChild(table);
541
- inst.execCommand('mceRepaint');
542
- }
543
- return true;
544
-
545
- case "mceTableSplitCells":
546
- case "mceTableMergeCells":
547
- case "mceTableInsertRowBefore":
548
- case "mceTableInsertRowAfter":
549
- case "mceTableDeleteRow":
550
- case "mceTableInsertColBefore":
551
- case "mceTableInsertColAfter":
552
- case "mceTableDeleteCol":
553
- case "mceTableCutRow":
554
- case "mceTableCopyRow":
555
- case "mceTablePasteRowBefore":
556
- case "mceTablePasteRowAfter":
557
- // No table just return (invalid command)
558
- if (!tableElm)
559
- return true;
560
-
561
- // Table has a tbody use that reference
562
- // Changed logic by ApTest 2005.07.12 (www.aptest.com)
563
- // Now lookk at the focused element and take its parentNode. That will be a tbody or a table.
564
- if (trElm && tableElm != trElm.parentNode)
565
- tableElm = trElm.parentNode;
566
-
567
- if (tableElm && trElm) {
568
- switch (command) {
569
- case "mceTableCutRow":
570
- if (!trElm || !tdElm)
571
- return true;
572
-
573
- inst.tableRowClipboard = copyRow(doc, tableElm, trElm);
574
- inst.execCommand("mceTableDeleteRow");
575
- break;
576
-
577
- case "mceTableCopyRow":
578
- if (!trElm || !tdElm)
579
- return true;
580
-
581
- inst.tableRowClipboard = copyRow(doc, tableElm, trElm);
582
- break;
583
-
584
- case "mceTablePasteRowBefore":
585
- if (!trElm || !tdElm)
586
- return true;
587
-
588
- var newTR = inst.tableRowClipboard.cloneNode(true);
589
-
590
- var prevTR = prevElm(trElm, "TR");
591
- if (prevTR != null)
592
- trimRow(tableElm, prevTR, prevTR.cells[0], newTR);
593
-
594
- trElm.parentNode.insertBefore(newTR, trElm);
595
- break;
596
-
597
- case "mceTablePasteRowAfter":
598
- if (!trElm || !tdElm)
599
- return true;
600
-
601
- var nextTR = nextElm(trElm, "TR");
602
- var newTR = inst.tableRowClipboard.cloneNode(true);
603
-
604
- trimRow(tableElm, trElm, tdElm, newTR);
605
-
606
- if (nextTR == null)
607
- trElm.parentNode.appendChild(newTR);
608
- else
609
- nextTR.parentNode.insertBefore(newTR, nextTR);
610
-
611
- break;
612
-
613
- case "mceTableInsertRowBefore":
614
- if (!trElm || !tdElm)
615
- return true;
616
-
617
- var grid = getTableGrid(tableElm);
618
- var cpos = getCellPos(grid, tdElm);
619
- var newTR = doc.createElement("tr");
620
- var lastTDElm = null;
621
-
622
- cpos.rowindex--;
623
- if (cpos.rowindex < 0)
624
- cpos.rowindex = 0;
625
-
626
- // Create cells
627
- for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
628
- if (tdElm != lastTDElm) {
629
- var sd = getColRowSpan(tdElm);
630
-
631
- if (sd['rowspan'] == 1) {
632
- var newTD = doc.createElement("td");
633
-
634
- if (!tinymce.isIE)
635
- newTD.innerHTML = '<br mce_bogus="1"/>';
636
-
637
- newTD.colSpan = tdElm.colSpan;
638
-
639
- newTR.appendChild(newTD);
640
- } else
641
- tdElm.rowSpan = sd['rowspan'] + 1;
642
-
643
- lastTDElm = tdElm;
644
- }
645
- }
554
+ // Needs more cells
555
+ for (i = cellCount; i < targetCellCount; i++)
556
+ row.appendChild(cloneCell(row.cells[cellCount - 1]));
646
557
 
647
- trElm.parentNode.insertBefore(newTR, trElm);
648
- select(0, 1);
649
- break;
558
+ // Needs less cells
559
+ for (i = targetCellCount; i < cellCount; i++)
560
+ dom.remove(row.cells[i]);
650
561
 
651
- case "mceTableInsertRowAfter":
652
- if (!trElm || !tdElm)
653
- return true;
562
+ // Add before/after
563
+ if (before)
564
+ targetRow.parentNode.insertBefore(row, targetRow);
565
+ else
566
+ dom.insertAfter(row, targetRow);
567
+ });
568
+ };
654
569
 
655
- var grid = getTableGrid(tableElm);
656
- var cpos = getCellPos(grid, tdElm);
657
- var newTR = doc.createElement("tr");
658
- var lastTDElm = null;
570
+ function getPos(target) {
571
+ var pos;
659
572
 
660
- // Create cells
661
- for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
662
- if (tdElm != lastTDElm) {
663
- var sd = getColRowSpan(tdElm);
573
+ each(grid, function(row, y) {
574
+ each(row, function(cell, x) {
575
+ if (cell.elm == target) {
576
+ pos = {x : x, y : y};
577
+ return false;
578
+ }
579
+ });
664
580
 
665
- if (sd['rowspan'] == 1) {
666
- var newTD = doc.createElement("td");
581
+ return !pos;
582
+ });
667
583
 
668
- if (!tinymce.isIE)
669
- newTD.innerHTML = '<br mce_bogus="1"/>';
584
+ return pos;
585
+ };
670
586
 
671
- newTD.colSpan = tdElm.colSpan;
587
+ function setStartCell(cell) {
588
+ startPos = getPos(cell);
589
+ };
672
590
 
673
- newTR.appendChild(newTD);
674
- } else
675
- tdElm.rowSpan = sd['rowspan'] + 1;
591
+ function findEndPos() {
592
+ var pos, maxX, maxY;
676
593
 
677
- lastTDElm = tdElm;
678
- }
679
- }
594
+ maxX = maxY = 0;
680
595
 
681
- if (newTR.hasChildNodes()) {
682
- var nextTR = nextElm(trElm, "TR");
683
- if (nextTR)
684
- nextTR.parentNode.insertBefore(newTR, nextTR);
685
- else
686
- tableElm.appendChild(newTR);
687
- }
596
+ each(grid, function(row, y) {
597
+ each(row, function(cell, x) {
598
+ var colSpan, rowSpan;
688
599
 
689
- select(0, 1);
690
- break;
600
+ if (isCellSelected(cell)) {
601
+ cell = grid[y][x];
691
602
 
692
- case "mceTableDeleteRow":
693
- if (!trElm || !tdElm)
694
- return true;
603
+ if (x > maxX)
604
+ maxX = x;
695
605
 
696
- var grid = getTableGrid(tableElm);
697
- var cpos = getCellPos(grid, tdElm);
606
+ if (y > maxY)
607
+ maxY = y;
698
608
 
699
- // Only one row, remove whole table
700
- if (grid.length == 1 && tableElm.nodeName == 'TBODY') {
701
- inst.dom.remove(inst.dom.getParent(tableElm, "table"));
702
- return true;
703
- }
609
+ if (cell.real) {
610
+ colSpan = cell.colspan - 1;
611
+ rowSpan = cell.rowspan - 1;
704
612
 
705
- // Move down row spanned cells
706
- var cells = trElm.cells;
707
- var nextTR = nextElm(trElm, "TR");
708
- for (var x=0; x<cells.length; x++) {
709
- if (cells[x].rowSpan > 1) {
710
- var newTD = cells[x].cloneNode(true);
711
- var sd = getColRowSpan(cells[x]);
613
+ if (colSpan) {
614
+ if (x + colSpan > maxX)
615
+ maxX = x + colSpan;
616
+ }
712
617
 
713
- newTD.rowSpan = sd.rowspan - 1;
618
+ if (rowSpan) {
619
+ if (y + rowSpan > maxY)
620
+ maxY = y + rowSpan;
621
+ }
622
+ }
623
+ }
624
+ });
625
+ });
714
626
 
715
- var nextTD = nextTR.cells[x];
627
+ return {x : maxX, y : maxY};
628
+ };
716
629
 
717
- if (nextTD == null)
718
- nextTR.appendChild(newTD);
719
- else
720
- nextTR.insertBefore(newTD, nextTD);
721
- }
722
- }
630
+ function setEndCell(cell) {
631
+ var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan;
723
632
 
724
- // Delete cells
725
- var lastTDElm = null;
726
- for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
727
- if (tdElm != lastTDElm) {
728
- var sd = getColRowSpan(tdElm);
633
+ endPos = getPos(cell);
729
634
 
730
- if (sd.rowspan > 1) {
731
- tdElm.rowSpan = sd.rowspan - 1;
732
- } else {
733
- trElm = tdElm.parentNode;
635
+ if (startPos && endPos) {
636
+ // Get start/end positions
637
+ startX = Math.min(startPos.x, endPos.x);
638
+ startY = Math.min(startPos.y, endPos.y);
639
+ endX = Math.max(startPos.x, endPos.x);
640
+ endY = Math.max(startPos.y, endPos.y);
734
641
 
735
- if (trElm.parentNode)
736
- trElm._delete = true;
737
- }
642
+ // Expand end positon to include spans
643
+ maxX = endX;
644
+ maxY = endY;
738
645
 
739
- lastTDElm = tdElm;
740
- }
741
- }
646
+ // Expand startX
647
+ for (y = startY; y <= maxY; y++) {
648
+ cell = grid[y][startX];
742
649
 
743
- deleteMarked(tableElm);
650
+ if (!cell.real) {
651
+ if (startX - (cell.colspan - 1) < startX)
652
+ startX -= cell.colspan - 1;
653
+ }
654
+ }
744
655
 
745
- select(0, -1);
746
- break;
656
+ // Expand startY
657
+ for (x = startX; x <= maxX; x++) {
658
+ cell = grid[startY][x];
747
659
 
748
- case "mceTableInsertColBefore":
749
- if (!trElm || !tdElm)
750
- return true;
660
+ if (!cell.real) {
661
+ if (startY - (cell.rowspan - 1) < startY)
662
+ startY -= cell.rowspan - 1;
663
+ }
664
+ }
751
665
 
752
- var grid = getTableGrid(inst.dom.getParent(tableElm, "table"));
753
- var cpos = getCellPos(grid, tdElm);
754
- var lastTDElm = null;
666
+ // Find max X, Y
667
+ for (y = startY; y <= endY; y++) {
668
+ for (x = startX; x <= endX; x++) {
669
+ cell = grid[y][x];
755
670
 
756
- for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
757
- if (tdElm != lastTDElm) {
758
- var sd = getColRowSpan(tdElm);
671
+ if (cell.real) {
672
+ colSpan = cell.colspan - 1;
673
+ rowSpan = cell.rowspan - 1;
759
674
 
760
- if (sd['colspan'] == 1) {
761
- var newTD = doc.createElement(tdElm.nodeName);
675
+ if (colSpan) {
676
+ if (x + colSpan > maxX)
677
+ maxX = x + colSpan;
678
+ }
762
679
 
763
- if (!tinymce.isIE)
764
- newTD.innerHTML = '<br mce_bogus="1"/>';
680
+ if (rowSpan) {
681
+ if (y + rowSpan > maxY)
682
+ maxY = y + rowSpan;
683
+ }
684
+ }
685
+ }
686
+ }
765
687
 
766
- newTD.rowSpan = tdElm.rowSpan;
688
+ // Remove current selection
689
+ dom.removeClass(dom.select('td.mceSelected,th.mceSelected'), 'mceSelected');
767
690
 
768
- tdElm.parentNode.insertBefore(newTD, tdElm);
769
- } else
770
- tdElm.colSpan++;
691
+ // Add new selection
692
+ for (y = startY; y <= maxY; y++) {
693
+ for (x = startX; x <= maxX; x++)
694
+ dom.addClass(grid[y][x].elm, 'mceSelected');
695
+ }
696
+ }
697
+ };
698
+
699
+ // Expose to public
700
+ tinymce.extend(this, {
701
+ deleteTable : deleteTable,
702
+ split : split,
703
+ merge : merge,
704
+ insertRow : insertRow,
705
+ insertCol : insertCol,
706
+ deleteCols : deleteCols,
707
+ deleteRows : deleteRows,
708
+ cutRows : cutRows,
709
+ copyRows : copyRows,
710
+ pasteRows : pasteRows,
711
+ getPos : getPos,
712
+ setStartCell : setStartCell,
713
+ setEndCell : setEndCell
714
+ });
715
+ };
771
716
 
772
- lastTDElm = tdElm;
773
- }
774
- }
717
+ tinymce.create('tinymce.plugins.TablePlugin', {
718
+ init : function(ed, url) {
719
+ var winMan, clipboardRows;
775
720
 
776
- select();
777
- break;
721
+ function createTableGrid(node) {
722
+ var selection = ed.selection, tblElm = ed.dom.getParent(node || selection.getNode(), 'table');
778
723
 
779
- case "mceTableInsertColAfter":
780
- if (!trElm || !tdElm)
781
- return true;
724
+ if (tblElm)
725
+ return new TableGrid(tblElm, ed.dom, selection);
726
+ };
782
727
 
783
- var grid = getTableGrid(inst.dom.getParent(tableElm, "table"));
784
- var cpos = getCellPos(grid, tdElm);
785
- var lastTDElm = null;
728
+ function cleanup() {
729
+ // Restore selection possibilities
730
+ ed.getBody().style.webkitUserSelect = '';
731
+ ed.dom.removeClass(ed.dom.select('td.mceSelected,th.mceSelected'), 'mceSelected');
732
+ };
786
733
 
787
- for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
788
- if (tdElm != lastTDElm) {
789
- var sd = getColRowSpan(tdElm);
734
+ // Register buttons
735
+ each([
736
+ ['table', 'table.desc', 'mceInsertTable', true],
737
+ ['delete_table', 'table.del', 'mceTableDelete'],
738
+ ['delete_col', 'table.delete_col_desc', 'mceTableDeleteCol'],
739
+ ['delete_row', 'table.delete_row_desc', 'mceTableDeleteRow'],
740
+ ['col_after', 'table.col_after_desc', 'mceTableInsertColAfter'],
741
+ ['col_before', 'table.col_before_desc', 'mceTableInsertColBefore'],
742
+ ['row_after', 'table.row_after_desc', 'mceTableInsertRowAfter'],
743
+ ['row_before', 'table.row_before_desc', 'mceTableInsertRowBefore'],
744
+ ['row_props', 'table.row_desc', 'mceTableRowProps', true],
745
+ ['cell_props', 'table.cell_desc', 'mceTableCellProps', true],
746
+ ['split_cells', 'table.split_cells_desc', 'mceTableSplitCells', true],
747
+ ['merge_cells', 'table.merge_cells_desc', 'mceTableMergeCells', true]
748
+ ], function(c) {
749
+ ed.addButton(c[0], {title : c[1], cmd : c[2], ui : c[3]});
750
+ });
790
751
 
791
- if (sd['colspan'] == 1) {
792
- var newTD = doc.createElement(tdElm.nodeName);
752
+ // Select whole table is a table border is clicked
753
+ if (!tinymce.isIE) {
754
+ ed.onClick.add(function(ed, e) {
755
+ e = e.target;
793
756
 
794
- if (!tinymce.isIE)
795
- newTD.innerHTML = '<br mce_bogus="1"/>';
757
+ if (e.nodeName === 'TABLE')
758
+ ed.selection.select(e);
759
+ });
760
+ }
796
761
 
797
- newTD.rowSpan = tdElm.rowSpan;
762
+ // Handle node change updates
763
+ ed.onNodeChange.add(function(ed, cm, n) {
764
+ var p;
798
765
 
799
- var nextTD = nextElm(tdElm, "TD,TH");
800
- if (nextTD == null)
801
- tdElm.parentNode.appendChild(newTD);
802
- else
803
- nextTD.parentNode.insertBefore(newTD, nextTD);
804
- } else
805
- tdElm.colSpan++;
766
+ n = ed.selection.getStart();
767
+ p = ed.dom.getParent(n, 'td,th,caption');
768
+ cm.setActive('table', n.nodeName === 'TABLE' || !!p);
806
769
 
807
- lastTDElm = tdElm;
808
- }
809
- }
770
+ // Disable table tools if we are in caption
771
+ if (p && p.nodeName === 'CAPTION')
772
+ p = 0;
810
773
 
811
- select(1);
812
- break;
774
+ cm.setDisabled('delete_table', !p);
775
+ cm.setDisabled('delete_col', !p);
776
+ cm.setDisabled('delete_table', !p);
777
+ cm.setDisabled('delete_row', !p);
778
+ cm.setDisabled('col_after', !p);
779
+ cm.setDisabled('col_before', !p);
780
+ cm.setDisabled('row_after', !p);
781
+ cm.setDisabled('row_before', !p);
782
+ cm.setDisabled('row_props', !p);
783
+ cm.setDisabled('cell_props', !p);
784
+ cm.setDisabled('split_cells', !p);
785
+ cm.setDisabled('merge_cells', !p);
786
+ });
813
787
 
814
- case "mceTableDeleteCol":
815
- if (!trElm || !tdElm)
816
- return true;
788
+ ed.onInit.add(function(ed) {
789
+ var startTable, startCell, dom = ed.dom, tableGrid;
817
790
 
818
- var grid = getTableGrid(tableElm);
819
- var cpos = getCellPos(grid, tdElm);
820
- var lastTDElm = null;
791
+ winMan = ed.windowManager;
821
792
 
822
- // Only one col, remove whole table
823
- if ((grid.length > 1 && grid[0].length <= 1) && tableElm.nodeName == 'TBODY') {
824
- inst.dom.remove(inst.dom.getParent(tableElm, "table"));
825
- return true;
826
- }
793
+ // Add cell selection logic
794
+ ed.onMouseDown.add(function(ed, e) {
795
+ if (e.button != 2) {
796
+ cleanup();
827
797
 
828
- // Delete cells
829
- for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
830
- if (tdElm != lastTDElm) {
831
- var sd = getColRowSpan(tdElm);
798
+ startCell = dom.getParent(e.target, 'td,th');
799
+ startTable = dom.getParent(startCell, 'table');
800
+ }
801
+ });
832
802
 
833
- if (sd['colspan'] > 1)
834
- tdElm.colSpan = sd['colspan'] - 1;
835
- else {
836
- if (tdElm.parentNode)
837
- tdElm.parentNode.removeChild(tdElm);
838
- }
803
+ dom.bind(ed.getDoc(), 'mouseover', function(e) {
804
+ var sel, table, target = e.target;
839
805
 
840
- lastTDElm = tdElm;
841
- }
842
- }
806
+ if (startCell && (tableGrid || target != startCell) && (target.nodeName == 'TD' || target.nodeName == 'TH')) {
807
+ table = dom.getParent(target, 'table');
808
+ if (table == startTable) {
809
+ if (!tableGrid) {
810
+ tableGrid = createTableGrid(table);
811
+ tableGrid.setStartCell(startCell);
843
812
 
844
- select(-1);
845
- break;
813
+ ed.getBody().style.webkitUserSelect = 'none';
814
+ }
846
815
 
847
- case "mceTableSplitCells":
848
- if (!trElm || !tdElm)
849
- return true;
816
+ tableGrid.setEndCell(target);
817
+ }
850
818
 
851
- var spandata = getColRowSpan(tdElm);
819
+ // Remove current selection
820
+ sel = ed.selection.getSel();
852
821
 
853
- var colspan = spandata["colspan"];
854
- var rowspan = spandata["rowspan"];
822
+ if (sel.removeAllRanges)
823
+ sel.removeAllRanges();
824
+ else
825
+ sel.empty();
855
826
 
856
- // Needs splitting
857
- if (colspan > 1 || rowspan > 1) {
858
- // Generate cols
859
- tdElm.colSpan = 1;
860
- for (var i=1; i<colspan; i++) {
861
- var newTD = doc.createElement("td");
827
+ e.preventDefault();
828
+ }
829
+ });
862
830
 
863
- if (!tinymce.isIE)
864
- newTD.innerHTML = '<br mce_bogus="1"/>';
831
+ ed.onMouseUp.add(function(ed, e) {
832
+ var rng, sel = ed.selection, selectedCells, nativeSel = sel.getSel(), walker, node, lastNode, endNode;
865
833
 
866
- trElm.insertBefore(newTD, nextElm(tdElm, "TD,TH"));
834
+ // Move selection to startCell
835
+ if (startCell) {
836
+ if (tableGrid)
837
+ ed.getBody().style.webkitUserSelect = '';
867
838
 
868
- if (rowspan > 1)
869
- addRows(newTD, trElm, rowspan);
870
- }
839
+ function setPoint(node, start) {
840
+ var walker = new tinymce.dom.TreeWalker(node, node);
871
841
 
872
- addRows(tdElm, trElm, rowspan);
873
- }
842
+ do {
843
+ // Text node
844
+ if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length != 0) {
845
+ if (start)
846
+ rng.setStart(node, 0);
847
+ else
848
+ rng.setEnd(node, node.nodeValue.length);
874
849
 
875
- // Apply visual aids
876
- tableElm = inst.dom.getParent(inst.selection.getNode(), "table");
877
- break;
850
+ return;
851
+ }
878
852
 
879
- case "mceTableMergeCells":
880
- var rows = [];
881
- var sel = inst.selection.getSel();
882
- var grid = getTableGrid(tableElm);
883
-
884
- if (tinymce.isIE || sel.rangeCount == 1) {
885
- if (user_interface) {
886
- // Setup template
887
- var sp = getColRowSpan(tdElm);
888
-
889
- inst.windowManager.open({
890
- url : url + '/merge_cells.htm',
891
- width : 240 + parseInt(inst.getLang('table.merge_cells_delta_width', 0)),
892
- height : 110 + parseInt(inst.getLang('table.merge_cells_delta_height', 0)),
893
- inline : 1
894
- }, {
895
- action : "update",
896
- numcols : sp.colspan,
897
- numrows : sp.rowspan,
898
- plugin_url : url
899
- });
900
-
901
- return true;
902
- } else {
903
- var numRows = parseInt(value['numrows']);
904
- var numCols = parseInt(value['numcols']);
905
- var cpos = getCellPos(grid, tdElm);
906
-
907
- if (("" + numRows) == "NaN")
908
- numRows = 1;
909
-
910
- if (("" + numCols) == "NaN")
911
- numCols = 1;
912
-
913
- // Get rows and cells
914
- var tRows = tableElm.rows;
915
- for (var y=cpos.rowindex; y<grid.length; y++) {
916
- var rowCells = [];
917
-
918
- for (var x=cpos.cellindex; x<grid[y].length; x++) {
919
- var td = getCell(grid, y, x);
920
-
921
- if (td && !inArray(rows, td) && !inArray(rowCells, td)) {
922
- var cp = getCellPos(grid, td);
923
-
924
- // Within range
925
- if (cp.cellindex < cpos.cellindex+numCols && cp.rowindex < cpos.rowindex+numRows)
926
- rowCells[rowCells.length] = td;
927
- }
928
- }
929
-
930
- if (rowCells.length > 0)
931
- rows[rows.length] = rowCells;
932
-
933
- var td = getCell(grid, cpos.rowindex, cpos.cellindex);
934
- each(ed.dom.select('br', td), function(e, i) {
935
- if (i > 0 && ed.dom.getAttrib('mce_bogus'))
936
- ed.dom.remove(e);
937
- });
938
- }
853
+ // BR element
854
+ if (node.nodeName == 'BR') {
855
+ if (start)
856
+ rng.setStartBefore(node);
857
+ else
858
+ rng.setEndBefore(node);
939
859
 
940
- //return true;
860
+ return;
941
861
  }
942
- } else {
943
- var cells = [];
944
- var sel = inst.selection.getSel();
945
- var lastTR = null;
946
- var curRow = null;
947
- var x1 = -1, y1 = -1, x2, y2;
948
-
949
- // Only one cell selected, whats the point?
950
- if (sel.rangeCount < 2)
951
- return true;
952
-
953
- // Get all selected cells
954
- for (var i=0; i<sel.rangeCount; i++) {
955
- var rng = sel.getRangeAt(i);
956
- var tdElm = rng.startContainer.childNodes[rng.startOffset];
957
-
958
- if (!tdElm)
862
+ } while (node = (start ? walker.next() : walker.prev()));
863
+ };
864
+
865
+ // Try to expand text selection as much as we can only Gecko supports cell selection
866
+ selectedCells = dom.select('td.mceSelected,th.mceSelected');
867
+ if (selectedCells.length > 0) {
868
+ rng = dom.createRng();
869
+ node = selectedCells[0];
870
+ endNode = selectedCells[selectedCells.length - 1];
871
+
872
+ setPoint(node, 1);
873
+ walker = new tinymce.dom.TreeWalker(node, dom.getParent(selectedCells[0], 'table'));
874
+
875
+ do {
876
+ if (node.nodeName == 'TD' || node.nodeName == 'TH') {
877
+ if (!dom.hasClass(node, 'mceSelected'))
959
878
  break;
960
879
 
961
- if (tdElm.nodeName == "TD" || tdElm.nodeName == "TH")
962
- cells[cells.length] = tdElm;
880
+ lastNode = node;
963
881
  }
882
+ } while (node = walker.next());
964
883
 
965
- // Get rows and cells
966
- var tRows = tableElm.rows;
967
- for (var y=0; y<tRows.length; y++) {
968
- var rowCells = [];
884
+ setPoint(lastNode);
969
885
 
970
- for (var x=0; x<tRows[y].cells.length; x++) {
971
- var td = tRows[y].cells[x];
886
+ sel.setRng(rng);
887
+ }
972
888
 
973
- for (var i=0; i<cells.length; i++) {
974
- if (td == cells[i]) {
975
- rowCells[rowCells.length] = td;
976
- }
977
- }
978
- }
889
+ ed.nodeChanged();
890
+ startCell = tableGrid = startTable = null;
891
+ }
892
+ });
979
893
 
980
- if (rowCells.length > 0)
981
- rows[rows.length] = rowCells;
982
- }
894
+ ed.onKeyUp.add(function(ed, e) {
895
+ cleanup();
896
+ });
983
897
 
984
- // Find selected cells in grid and box
985
- var curRow = [];
986
- var lastTR = null;
987
- for (var y=0; y<grid.length; y++) {
988
- for (var x=0; x<grid[y].length; x++) {
989
- grid[y][x]._selected = false;
990
-
991
- for (var i=0; i<cells.length; i++) {
992
- if (grid[y][x] == cells[i]) {
993
- // Get start pos
994
- if (x1 == -1) {
995
- x1 = x;
996
- y1 = y;
997
- }
998
-
999
- // Get end pos
1000
- x2 = x;
1001
- y2 = y;
1002
-
1003
- grid[y][x]._selected = true;
1004
- }
1005
- }
1006
- }
1007
- }
898
+ // Add context menu
899
+ if (ed && ed.plugins.contextmenu) {
900
+ ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {
901
+ var sm, se = ed.selection, el = se.getNode() || ed.getBody();
1008
902
 
1009
- // Is there gaps, if so deny
1010
- for (var y=y1; y<=y2; y++) {
1011
- for (var x=x1; x<=x2; x++) {
1012
- if (!grid[y][x]._selected) {
1013
- alert("Invalid selection for merge.");
1014
- return true;
1015
- }
1016
- }
1017
- }
903
+ if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th') || ed.dom.select('td.mceSelected,th.mceSelected').length) {
904
+ m.removeAll();
905
+
906
+ if (el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) {
907
+ m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true});
908
+ m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'});
909
+ m.addSeparator();
1018
910
  }
1019
911
 
1020
- // Validate selection and get total rowspan and colspan
1021
- var rowSpan = 1, colSpan = 1;
912
+ if (el.nodeName == 'IMG' && el.className.indexOf('mceItem') == -1) {
913
+ m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true});
914
+ m.addSeparator();
915
+ }
1022
916
 
1023
- // Validate horizontal and get total colspan
1024
- var lastRowSpan = -1;
1025
- for (var y=0; y<rows.length; y++) {
1026
- var rowColSpan = 0;
917
+ m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', value : {action : 'insert'}});
918
+ m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable'});
919
+ m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete'});
920
+ m.addSeparator();
1027
921
 
1028
- for (var x=0; x<rows[y].length; x++) {
1029
- var sd = getColRowSpan(rows[y][x]);
922
+ // Cell menu
923
+ sm = m.addMenu({title : 'table.cell'});
924
+ sm.add({title : 'table.cell_desc', icon : 'cell_props', cmd : 'mceTableCellProps'});
925
+ sm.add({title : 'table.split_cells_desc', icon : 'split_cells', cmd : 'mceTableSplitCells'});
926
+ sm.add({title : 'table.merge_cells_desc', icon : 'merge_cells', cmd : 'mceTableMergeCells'});
1030
927
 
1031
- rowColSpan += sd['colspan'];
928
+ // Row menu
929
+ sm = m.addMenu({title : 'table.row'});
930
+ sm.add({title : 'table.row_desc', icon : 'row_props', cmd : 'mceTableRowProps'});
931
+ sm.add({title : 'table.row_before_desc', icon : 'row_before', cmd : 'mceTableInsertRowBefore'});
932
+ sm.add({title : 'table.row_after_desc', icon : 'row_after', cmd : 'mceTableInsertRowAfter'});
933
+ sm.add({title : 'table.delete_row_desc', icon : 'delete_row', cmd : 'mceTableDeleteRow'});
934
+ sm.addSeparator();
935
+ sm.add({title : 'table.cut_row_desc', icon : 'cut', cmd : 'mceTableCutRow'});
936
+ sm.add({title : 'table.copy_row_desc', icon : 'copy', cmd : 'mceTableCopyRow'});
937
+ sm.add({title : 'table.paste_row_before_desc', icon : 'paste', cmd : 'mceTablePasteRowBefore'}).setDisabled(!clipboardRows);
938
+ sm.add({title : 'table.paste_row_after_desc', icon : 'paste', cmd : 'mceTablePasteRowAfter'}).setDisabled(!clipboardRows);
1032
939
 
1033
- if (lastRowSpan != -1 && sd['rowspan'] != lastRowSpan) {
1034
- alert("Invalid selection for merge.");
1035
- return true;
1036
- }
940
+ // Column menu
941
+ sm = m.addMenu({title : 'table.col'});
942
+ sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'});
943
+ sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'});
944
+ sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'});
945
+ } else
946
+ m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable'});
947
+ });
948
+ }
1037
949
 
1038
- lastRowSpan = sd['rowspan'];
1039
- }
950
+ // Fixes an issue on Gecko where it's impossible to place the caret behind a table
951
+ // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled
952
+ if (!tinymce.isIE) {
953
+ function fixTableCaretPos() {
954
+ var last;
1040
955
 
1041
- if (rowColSpan > colSpan)
1042
- colSpan = rowColSpan;
956
+ // Skip empty text nodes form the end
957
+ for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ;
1043
958
 
1044
- lastRowSpan = -1;
1045
- }
959
+ if (last && last.nodeName == 'TABLE')
960
+ ed.dom.add(ed.getBody(), 'p', null, '<br mce_bogus="1" />');
961
+ };
1046
962
 
1047
- // Validate vertical and get total rowspan
1048
- var lastColSpan = -1;
1049
- for (var x=0; x<rows[0].length; x++) {
1050
- var colRowSpan = 0;
963
+ // Fixes an bug where it's impossible to place the caret before a table in Gecko
964
+ // this fix solves it by detecting when the caret is at the beginning of such a table
965
+ // and then manually moves the caret infront of the table
966
+ if (tinymce.isGecko) {
967
+ ed.onKeyDown.add(function(ed, e) {
968
+ var rng, table, dom = ed.dom;
1051
969
 
1052
- for (var y=0; y<rows.length; y++) {
1053
- var sd = getColRowSpan(rows[y][x]);
970
+ // On gecko it's not possible to place the caret before a table
971
+ if (e.keyCode == 37 || e.keyCode == 38) {
972
+ rng = ed.selection.getRng();
973
+ table = dom.getParent(rng.startContainer, 'table');
1054
974
 
1055
- colRowSpan += sd['rowspan'];
975
+ if (table && ed.getBody().firstChild == table) {
976
+ if (isAtStart(rng, table)) {
977
+ rng = dom.createRng();
1056
978
 
1057
- if (lastColSpan != -1 && sd['colspan'] != lastColSpan) {
1058
- alert("Invalid selection for merge.");
1059
- return true;
1060
- }
979
+ rng.setStartBefore(table);
980
+ rng.setEndBefore(table);
1061
981
 
1062
- lastColSpan = sd['colspan'];
982
+ ed.selection.setRng(rng);
983
+
984
+ e.preventDefault();
985
+ }
1063
986
  }
987
+ }
988
+ });
989
+ }
1064
990
 
1065
- if (colRowSpan > rowSpan)
1066
- rowSpan = colRowSpan;
991
+ ed.onKeyUp.add(fixTableCaretPos);
992
+ ed.onSetContent.add(fixTableCaretPos);
993
+ ed.onVisualAid.add(fixTableCaretPos);
1067
994
 
1068
- lastColSpan = -1;
1069
- }
995
+ ed.onPreProcess.add(function(ed, o) {
996
+ var last = o.node.lastChild;
1070
997
 
1071
- // Setup td
1072
- tdElm = rows[0][0];
1073
- tdElm.rowSpan = rowSpan;
1074
- tdElm.colSpan = colSpan;
998
+ if (last && last.childNodes.length == 1 && last.firstChild.nodeName == 'BR')
999
+ ed.dom.remove(last);
1000
+ });
1075
1001
 
1076
- // Merge cells
1077
- for (var y=0; y<rows.length; y++) {
1078
- for (var x=0; x<rows[y].length; x++) {
1079
- var html = rows[y][x].innerHTML;
1080
- var chk = html.replace(/[ \t\r\n]/g, "");
1002
+ fixTableCaretPos();
1003
+ }
1004
+ });
1081
1005
 
1082
- if (chk != "<br/>" && chk != "<br>" && chk != '<br mce_bogus="1"/>' && (x+y > 0))
1083
- tdElm.innerHTML += html;
1006
+ // Register action commands
1007
+ each({
1008
+ mceTableSplitCells : function(grid) {
1009
+ grid.split();
1010
+ },
1084
1011
 
1085
- // Not current cell
1086
- if (rows[y][x] != tdElm && !rows[y][x]._deleted) {
1087
- var cpos = getCellPos(grid, rows[y][x]);
1088
- var tr = rows[y][x].parentNode;
1012
+ mceTableMergeCells : function(grid) {
1013
+ var rowSpan, colSpan, cell;
1089
1014
 
1090
- tr.removeChild(rows[y][x]);
1091
- rows[y][x]._deleted = true;
1015
+ cell = ed.dom.getParent(ed.selection.getNode(), 'th,td');
1016
+ if (cell) {
1017
+ rowSpan = cell.rowSpan;
1018
+ colSpan = cell.colSpan;
1019
+ }
1092
1020
 
1093
- // Empty TR, remove it
1094
- if (!tr.hasChildNodes()) {
1095
- tr.parentNode.removeChild(tr);
1021
+ if (!ed.dom.select('td.mceSelected,th.mceSelected').length) {
1022
+ winMan.open({
1023
+ url : url + '/merge_cells.htm',
1024
+ width : 240 + parseInt(ed.getLang('table.merge_cells_delta_width', 0)),
1025
+ height : 110 + parseInt(ed.getLang('table.merge_cells_delta_height', 0)),
1026
+ inline : 1
1027
+ }, {
1028
+ rows : rowSpan,
1029
+ cols : colSpan,
1030
+ onaction : function(data) {
1031
+ grid.merge(cell, data.cols, data.rows);
1032
+ },
1033
+ plugin_url : url
1034
+ });
1035
+ } else
1036
+ grid.merge();
1037
+ },
1096
1038
 
1097
- var lastCell = null;
1098
- for (var x=0; cellElm = getCell(grid, cpos.rowindex, x); x++) {
1099
- if (cellElm != lastCell && cellElm.rowSpan > 1)
1100
- cellElm.rowSpan--;
1039
+ mceTableInsertRowBefore : function(grid) {
1040
+ grid.insertRow(true);
1041
+ },
1101
1042
 
1102
- lastCell = cellElm;
1103
- }
1043
+ mceTableInsertRowAfter : function(grid) {
1044
+ grid.insertRow();
1045
+ },
1104
1046
 
1105
- if (tdElm.rowSpan > 1)
1106
- tdElm.rowSpan--;
1107
- }
1108
- }
1109
- }
1110
- }
1047
+ mceTableInsertColBefore : function(grid) {
1048
+ grid.insertCol(true);
1049
+ },
1111
1050
 
1112
- // Remove all but one bogus br
1113
- each(ed.dom.select('br', tdElm), function(e, i) {
1114
- if (i > 0 && ed.dom.getAttrib(e, 'mce_bogus'))
1115
- ed.dom.remove(e);
1116
- });
1051
+ mceTableInsertColAfter : function(grid) {
1052
+ grid.insertCol();
1053
+ },
1117
1054
 
1118
- break;
1119
- }
1055
+ mceTableDeleteCol : function(grid) {
1056
+ grid.deleteCols();
1057
+ },
1120
1058
 
1121
- tableElm = inst.dom.getParent(inst.selection.getNode(), "table");
1122
- inst.addVisual(tableElm);
1123
- inst.nodeChanged();
1124
- }
1059
+ mceTableDeleteRow : function(grid) {
1060
+ grid.deleteRows();
1061
+ },
1125
1062
 
1126
- return true;
1127
- }
1063
+ mceTableCutRow : function(grid) {
1064
+ clipboardRows = grid.cutRows();
1065
+ },
1066
+
1067
+ mceTableCopyRow : function(grid) {
1068
+ clipboardRows = grid.copyRows();
1069
+ },
1070
+
1071
+ mceTablePasteRowBefore : function(grid) {
1072
+ grid.pasteRows(clipboardRows, true);
1073
+ },
1074
+
1075
+ mceTablePasteRowAfter : function(grid) {
1076
+ grid.pasteRows(clipboardRows);
1077
+ },
1128
1078
 
1129
- // Pass to next handler in chain
1130
- return false;
1079
+ mceTableDelete : function(grid) {
1080
+ grid.deleteTable();
1081
+ }
1082
+ }, function(func, name) {
1083
+ ed.addCommand(name, function() {
1084
+ var grid = createTableGrid();
1085
+
1086
+ if (grid) {
1087
+ func(grid);
1088
+ ed.execCommand('mceRepaint');
1089
+ cleanup();
1090
+ }
1091
+ });
1092
+ });
1093
+
1094
+ // Register dialog commands
1095
+ each({
1096
+ mceInsertTable : function(val) {
1097
+ winMan.open({
1098
+ url : url + '/table.htm',
1099
+ width : 400 + parseInt(ed.getLang('table.table_delta_width', 0)),
1100
+ height : 320 + parseInt(ed.getLang('table.table_delta_height', 0)),
1101
+ inline : 1
1102
+ }, {
1103
+ plugin_url : url,
1104
+ action : val ? val.action : 0
1105
+ });
1106
+ },
1107
+
1108
+ mceTableRowProps : function() {
1109
+ winMan.open({
1110
+ url : url + '/row.htm',
1111
+ width : 400 + parseInt(ed.getLang('table.rowprops_delta_width', 0)),
1112
+ height : 295 + parseInt(ed.getLang('table.rowprops_delta_height', 0)),
1113
+ inline : 1
1114
+ }, {
1115
+ plugin_url : url
1116
+ });
1117
+ },
1118
+
1119
+ mceTableCellProps : function() {
1120
+ winMan.open({
1121
+ url : url + '/cell.htm',
1122
+ width : 400 + parseInt(ed.getLang('table.cellprops_delta_width', 0)),
1123
+ height : 295 + parseInt(ed.getLang('table.cellprops_delta_height', 0)),
1124
+ inline : 1
1125
+ }, {
1126
+ plugin_url : url
1127
+ });
1128
+ }
1129
+ }, function(func, name) {
1130
+ ed.addCommand(name, function(ui, val) {
1131
+ func(val);
1132
+ });
1133
+ });
1131
1134
  }
1132
1135
  });
1133
1136
 
1134
1137
  // Register plugin
1135
1138
  tinymce.PluginManager.add('table', tinymce.plugins.TablePlugin);
1136
- })();
1139
+ })(tinymce);