ouvrages-tinymce-rails 3.4.6 → 3.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (308) hide show
  1. data/README.md +52 -16
  2. data/Rakefile +11 -20
  3. data/app/assets/javascripts/tinymce-jquery.js +3 -0
  4. data/app/assets/javascripts/tinymce.js +2 -0
  5. data/app/assets/javascripts/tinymce/preinit.js.erb +5 -0
  6. data/lib/tasks/assets.rake +7 -0
  7. data/lib/tinymce-rails.rb +1 -2
  8. data/lib/tinymce/rails.rb +12 -0
  9. data/lib/tinymce/rails/configuration.rb +67 -0
  10. data/lib/tinymce/rails/engine.rb +16 -0
  11. data/lib/tinymce/rails/helper.rb +29 -0
  12. data/lib/tinymce/rails/version.rb +6 -0
  13. data/vendor/assets/javascripts/tinymce/jquery.tinymce.js +1 -0
  14. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/langs/en.js +0 -0
  15. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/license.txt +0 -0
  16. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advhr/css/advhr.css +0 -0
  17. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advhr/editor_plugin.js +0 -0
  18. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advhr/editor_plugin_src.js +0 -0
  19. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advhr/js/rule.js +0 -0
  20. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advhr/langs/en_dlg.js +0 -0
  21. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advhr/rule.htm +0 -0
  22. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advimage/css/advimage.css +0 -0
  23. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advimage/editor_plugin.js +0 -0
  24. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advimage/editor_plugin_src.js +0 -0
  25. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advimage/image.htm +0 -0
  26. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advimage/img/sample.gif +0 -0
  27. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advimage/js/image.js +0 -0
  28. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advimage/langs/en_dlg.js +0 -0
  29. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advlink/css/advlink.css +0 -0
  30. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advlink/editor_plugin.js +0 -0
  31. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advlink/editor_plugin_src.js +0 -0
  32. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advlink/js/advlink.js +8 -1
  33. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advlink/langs/en_dlg.js +0 -0
  34. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advlink/link.htm +0 -0
  35. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advlist/editor_plugin.js +0 -0
  36. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/advlist/editor_plugin_src.js +0 -0
  37. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/autolink/editor_plugin.js +0 -0
  38. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/autolink/editor_plugin_src.js +0 -0
  39. data/vendor/assets/javascripts/tinymce/plugins/autoresize/editor_plugin.js +1 -0
  40. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/autoresize/editor_plugin_src.js +20 -38
  41. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/autosave/editor_plugin.js +0 -0
  42. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/autosave/editor_plugin_src.js +0 -0
  43. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/autosave/langs/en.js +0 -0
  44. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/bbcode/editor_plugin.js +0 -0
  45. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/bbcode/editor_plugin_src.js +0 -0
  46. data/vendor/assets/javascripts/tinymce/plugins/contextmenu/editor_plugin.js +1 -0
  47. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/contextmenu/editor_plugin_src.js +1 -0
  48. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/directionality/editor_plugin.js +0 -0
  49. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/directionality/editor_plugin_src.js +0 -0
  50. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/editor_plugin.js +0 -0
  51. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/editor_plugin_src.js +0 -0
  52. data/vendor/assets/javascripts/tinymce/plugins/emotions/emotions.htm +42 -0
  53. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-cool.gif +0 -0
  54. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-cry.gif +0 -0
  55. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-embarassed.gif +0 -0
  56. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-foot-in-mouth.gif +0 -0
  57. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-frown.gif +0 -0
  58. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-innocent.gif +0 -0
  59. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-kiss.gif +0 -0
  60. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-laughing.gif +0 -0
  61. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-money-mouth.gif +0 -0
  62. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-sealed.gif +0 -0
  63. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-smile.gif +0 -0
  64. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-surprised.gif +0 -0
  65. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-tongue-out.gif +0 -0
  66. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-undecided.gif +0 -0
  67. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-wink.gif +0 -0
  68. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/emotions/img/smiley-yell.gif +0 -0
  69. data/vendor/assets/javascripts/tinymce/plugins/emotions/js/emotions.js +43 -0
  70. data/vendor/assets/javascripts/tinymce/plugins/emotions/langs/en_dlg.js +1 -0
  71. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example/dialog.htm +0 -0
  72. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example/editor_plugin.js +0 -0
  73. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example/editor_plugin_src.js +0 -0
  74. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example/img/example.gif +0 -0
  75. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example/js/dialog.js +0 -0
  76. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example/langs/en.js +0 -0
  77. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example/langs/en_dlg.js +0 -0
  78. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example_dependency/editor_plugin.js +0 -0
  79. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/example_dependency/editor_plugin_src.js +0 -0
  80. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullpage/css/fullpage.css +0 -0
  81. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullpage/editor_plugin.js +0 -0
  82. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullpage/editor_plugin_src.js +0 -0
  83. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullpage/fullpage.htm +0 -0
  84. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullpage/js/fullpage.js +0 -0
  85. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullpage/langs/en_dlg.js +0 -0
  86. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullscreen/editor_plugin.js +0 -0
  87. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullscreen/editor_plugin_src.js +0 -0
  88. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/fullscreen/fullscreen.htm +0 -0
  89. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/iespell/editor_plugin.js +0 -0
  90. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/iespell/editor_plugin_src.js +0 -0
  91. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/editor_plugin.js +0 -0
  92. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/editor_plugin_src.js +0 -0
  93. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif +0 -0
  94. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/skins/clearlooks2/img/button.gif +0 -0
  95. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif +0 -0
  96. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif +0 -0
  97. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif +0 -0
  98. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif +0 -0
  99. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif +0 -0
  100. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/skins/clearlooks2/window.css +0 -0
  101. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/inlinepopups/template.htm +0 -0
  102. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/insertdatetime/editor_plugin.js +0 -0
  103. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/insertdatetime/editor_plugin_src.js +0 -0
  104. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/layer/editor_plugin.js +0 -0
  105. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/layer/editor_plugin_src.js +0 -0
  106. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/legacyoutput/editor_plugin.js +0 -0
  107. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/legacyoutput/editor_plugin_src.js +0 -0
  108. data/vendor/assets/javascripts/tinymce/plugins/lists/editor_plugin.js +1 -0
  109. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/lists/editor_plugin_src.js +221 -48
  110. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/media/css/media.css +0 -0
  111. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/media/editor_plugin.js +0 -0
  112. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/media/editor_plugin_src.js +0 -0
  113. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/media/js/embed.js +0 -0
  114. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/media/js/media.js +39 -22
  115. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/media/langs/en_dlg.js +1 -1
  116. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/media/media.htm +0 -0
  117. data/vendor/assets/javascripts/tinymce/plugins/media/moxieplayer.swf +0 -0
  118. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/nonbreaking/editor_plugin.js +0 -0
  119. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/nonbreaking/editor_plugin_src.js +0 -0
  120. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/noneditable/editor_plugin.js +0 -0
  121. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/noneditable/editor_plugin_src.js +0 -0
  122. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/pagebreak/editor_plugin.js +0 -0
  123. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/pagebreak/editor_plugin_src.js +0 -0
  124. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/paste/editor_plugin.js +0 -0
  125. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/paste/editor_plugin_src.js +0 -0
  126. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/paste/js/pastetext.js +0 -0
  127. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/paste/js/pasteword.js +0 -0
  128. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/paste/langs/en_dlg.js +0 -0
  129. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/paste/pastetext.htm +0 -0
  130. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/paste/pasteword.htm +0 -0
  131. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/preview/editor_plugin.js +0 -0
  132. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/preview/editor_plugin_src.js +0 -0
  133. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/preview/example.html +0 -0
  134. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/preview/jscripts/embed.js +0 -0
  135. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/preview/preview.html +0 -0
  136. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/print/editor_plugin.js +0 -0
  137. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/print/editor_plugin_src.js +0 -0
  138. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/save/editor_plugin.js +0 -0
  139. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/save/editor_plugin_src.js +0 -0
  140. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/searchreplace/css/searchreplace.css +0 -0
  141. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/searchreplace/editor_plugin.js +0 -0
  142. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/searchreplace/editor_plugin_src.js +0 -0
  143. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/searchreplace/js/searchreplace.js +0 -0
  144. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/searchreplace/langs/en_dlg.js +0 -0
  145. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/searchreplace/searchreplace.htm +0 -0
  146. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/spellchecker/css/content.css +0 -0
  147. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/spellchecker/editor_plugin.js +0 -0
  148. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/spellchecker/editor_plugin_src.js +0 -0
  149. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/spellchecker/img/wline.gif +0 -0
  150. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/style/css/props.css +0 -0
  151. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/style/editor_plugin.js +0 -0
  152. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/style/editor_plugin_src.js +0 -0
  153. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/style/js/props.js +15 -0
  154. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/style/langs/en_dlg.js +0 -0
  155. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/style/props.htm +1 -1
  156. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/tabfocus/editor_plugin.js +0 -0
  157. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/tabfocus/editor_plugin_src.js +0 -0
  158. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/cell.htm +0 -0
  159. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/css/cell.css +0 -0
  160. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/css/row.css +0 -0
  161. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/css/table.css +0 -0
  162. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/editor_plugin.js +1 -1
  163. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/editor_plugin_src.js +108 -46
  164. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/js/cell.js +0 -0
  165. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/js/merge_cells.js +0 -0
  166. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/js/row.js +0 -0
  167. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/js/table.js +50 -12
  168. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/langs/en_dlg.js +0 -0
  169. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/merge_cells.htm +0 -0
  170. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/row.htm +0 -0
  171. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/table/table.htm +1 -1
  172. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/template/blank.htm +0 -0
  173. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/template/css/template.css +0 -0
  174. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/template/editor_plugin.js +0 -0
  175. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/template/editor_plugin_src.js +0 -0
  176. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/template/js/template.js +0 -0
  177. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/template/langs/en_dlg.js +0 -0
  178. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/template/template.htm +0 -0
  179. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/visualchars/editor_plugin.js +0 -0
  180. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/visualchars/editor_plugin_src.js +0 -0
  181. data/vendor/assets/javascripts/tinymce/plugins/wordcount/editor_plugin.js +1 -0
  182. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/wordcount/editor_plugin_src.js +14 -6
  183. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/abbr.htm +0 -0
  184. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/acronym.htm +0 -0
  185. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/attributes.htm +0 -0
  186. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/cite.htm +0 -0
  187. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/css/attributes.css +0 -0
  188. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/css/popup.css +0 -0
  189. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/del.htm +0 -0
  190. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/editor_plugin.js +0 -0
  191. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/editor_plugin_src.js +0 -0
  192. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/ins.htm +0 -0
  193. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/js/abbr.js +0 -0
  194. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/js/acronym.js +0 -0
  195. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/js/attributes.js +0 -0
  196. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/js/cite.js +0 -0
  197. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/js/del.js +0 -0
  198. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/js/element_common.js +0 -0
  199. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/js/ins.js +0 -0
  200. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/plugins/xhtmlxtras/langs/en_dlg.js +0 -0
  201. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/about.htm +0 -0
  202. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/anchor.htm +0 -0
  203. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/charmap.htm +5 -1
  204. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/color_picker.htm +0 -0
  205. data/vendor/assets/javascripts/tinymce/themes/advanced/editor_template.js +1 -0
  206. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/editor_template_src.js +7 -3
  207. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/image.htm +0 -0
  208. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/colorpicker.jpg +0 -0
  209. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/flash.gif +0 -0
  210. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/icons.gif +0 -0
  211. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/iframe.gif +0 -0
  212. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/pagebreak.gif +0 -0
  213. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/quicktime.gif +0 -0
  214. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/realmedia.gif +0 -0
  215. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/shockwave.gif +0 -0
  216. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/trans.gif +0 -0
  217. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/video.gif +0 -0
  218. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/img/windowsmedia.gif +0 -0
  219. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/js/about.js +0 -0
  220. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/js/anchor.js +0 -0
  221. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/js/charmap.js +11 -3
  222. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/js/color_picker.js +4 -4
  223. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/js/image.js +0 -0
  224. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/js/link.js +0 -0
  225. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/js/source_editor.js +0 -0
  226. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/langs/en.js +0 -0
  227. data/vendor/assets/javascripts/tinymce/themes/advanced/langs/en_dlg.js +1 -0
  228. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/link.htm +0 -0
  229. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/shortcuts.htm +0 -0
  230. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/content.css +0 -0
  231. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/dialog.css +0 -0
  232. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/img/buttons.png +0 -0
  233. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/img/items.gif +0 -0
  234. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/img/menu_arrow.gif +0 -0
  235. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/img/menu_check.gif +0 -0
  236. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/img/progress.gif +0 -0
  237. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/img/tabs.gif +0 -0
  238. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/default/ui.css +0 -0
  239. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/highcontrast/content.css +0 -0
  240. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/highcontrast/dialog.css +0 -0
  241. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/highcontrast/ui.css +0 -0
  242. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/o2k7/content.css +0 -0
  243. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/o2k7/dialog.css +0 -0
  244. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/o2k7/img/button_bg.png +0 -0
  245. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/o2k7/img/button_bg_black.png +0 -0
  246. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/o2k7/img/button_bg_silver.png +0 -0
  247. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/o2k7/ui.css +0 -0
  248. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/o2k7/ui_black.css +0 -0
  249. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/skins/o2k7/ui_silver.css +0 -0
  250. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/advanced/source_editor.htm +0 -0
  251. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/editor_template.js +0 -0
  252. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/editor_template_src.js +0 -0
  253. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/img/icons.gif +0 -0
  254. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/langs/en.js +0 -0
  255. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/skins/default/content.css +0 -0
  256. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/skins/default/ui.css +0 -0
  257. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/skins/o2k7/content.css +0 -0
  258. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/skins/o2k7/img/button_bg.png +0 -0
  259. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/themes/simple/skins/o2k7/ui.css +0 -0
  260. data/vendor/assets/javascripts/tinymce/tiny_mce.js +1 -0
  261. data/vendor/assets/javascripts/tinymce/tiny_mce_jquery.js +1 -0
  262. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/tiny_mce_jquery_src.js +774 -409
  263. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/tiny_mce_popup.js +0 -0
  264. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/tiny_mce_src.js +774 -409
  265. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/utils/editable_selects.js +0 -0
  266. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/utils/form_utils.js +0 -0
  267. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/utils/mctabs.js +0 -0
  268. data/{assets/precompiled → vendor/assets/javascripts}/tinymce/utils/validate.js +0 -0
  269. metadata +294 -318
  270. data/assets/integration/tinymce-jquery.js +0 -3
  271. data/assets/integration/tinymce.js +0 -2
  272. data/assets/integration/tinymce/preinit.js.erb +0 -5
  273. data/assets/precompiled/tinymce/jquery.tinymce.js +0 -1
  274. data/assets/precompiled/tinymce/langs/fr.js +0 -1
  275. data/assets/precompiled/tinymce/plugins/advhr/langs/fr_dlg.js +0 -1
  276. data/assets/precompiled/tinymce/plugins/advimage/langs/fr_dlg.js +0 -1
  277. data/assets/precompiled/tinymce/plugins/advlink/langs/fr_dlg.js +0 -1
  278. data/assets/precompiled/tinymce/plugins/autoresize/editor_plugin.js +0 -1
  279. data/assets/precompiled/tinymce/plugins/contextmenu/editor_plugin.js +0 -1
  280. data/assets/precompiled/tinymce/plugins/emotions/emotions.htm +0 -41
  281. data/assets/precompiled/tinymce/plugins/emotions/js/emotions.js +0 -22
  282. data/assets/precompiled/tinymce/plugins/emotions/langs/en_dlg.js +0 -1
  283. data/assets/precompiled/tinymce/plugins/emotions/langs/fr_dlg.js +0 -1
  284. data/assets/precompiled/tinymce/plugins/fullpage/langs/fr_dlg.js +0 -1
  285. data/assets/precompiled/tinymce/plugins/lists/editor_plugin.js +0 -1
  286. data/assets/precompiled/tinymce/plugins/media/langs/fr_dlg.js +0 -1
  287. data/assets/precompiled/tinymce/plugins/media/moxieplayer.swf +0 -0
  288. data/assets/precompiled/tinymce/plugins/paste/langs/fr_dlg.js +0 -1
  289. data/assets/precompiled/tinymce/plugins/searchreplace/langs/fr_dlg.js +0 -1
  290. data/assets/precompiled/tinymce/plugins/style/langs/fr_dlg.js +0 -1
  291. data/assets/precompiled/tinymce/plugins/table/langs/fr_dlg.js +0 -1
  292. data/assets/precompiled/tinymce/plugins/template/langs/fr_dlg.js +0 -1
  293. data/assets/precompiled/tinymce/plugins/wordcount/editor_plugin.js +0 -1
  294. data/assets/precompiled/tinymce/plugins/xhtmlxtras/langs/fr_dlg.js +0 -1
  295. data/assets/precompiled/tinymce/themes/advanced/editor_template.js +0 -1
  296. data/assets/precompiled/tinymce/themes/advanced/langs/en_dlg.js +0 -1
  297. data/assets/precompiled/tinymce/themes/advanced/langs/fr.js +0 -1
  298. data/assets/precompiled/tinymce/themes/advanced/langs/fr_dlg.js +0 -1
  299. data/assets/precompiled/tinymce/themes/simple/langs/fr.js +0 -1
  300. data/assets/precompiled/tinymce/tiny_mce.js +0 -1
  301. data/assets/precompiled/tinymce/tiny_mce_jquery.js +0 -1
  302. data/assets/vendor/tinymce/jquery-tinymce.js +0 -1
  303. data/assets/vendor/tinymce/tiny_mce.js +0 -16479
  304. data/assets/vendor/tinymce/tiny_mce_jquery.js +0 -15656
  305. data/lib/tinymce/assets.rake +0 -7
  306. data/lib/tinymce/rails-3.1.0.rake +0 -65
  307. data/lib/tinymce/railtie.rb +0 -27
  308. data/lib/tinymce/version.rb +0 -4
@@ -5,9 +5,9 @@
5
5
  var tinymce = {
6
6
  majorVersion : '3',
7
7
 
8
- minorVersion : '4.6',
8
+ minorVersion : '4.9',
9
9
 
10
- releaseDate : '2011-09-29',
10
+ releaseDate : '2012-02-23',
11
11
 
12
12
  _init : function() {
13
13
  var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
@@ -535,7 +535,7 @@ tinymce.create('tinymce.util.Dispatcher', {
535
535
  // And this is also more efficient
536
536
  for (i = 0; i<li.length; i++) {
537
537
  c = li[i];
538
- s = c.cb.apply(c.scope, a);
538
+ s = c.cb.apply(c.scope, a.length > 0 ? a : [c.scope]);
539
539
 
540
540
  if (s === false)
541
541
  break;
@@ -578,7 +578,7 @@ tinymce.create('tinymce.util.Dispatcher', {
578
578
 
579
579
  // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
580
580
  u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
581
- u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);
581
+ u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);
582
582
  each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {
583
583
  var s = u[i];
584
584
 
@@ -901,8 +901,11 @@ tinymce.create('tinymce.util.Dispatcher', {
901
901
 
902
902
  v = '{';
903
903
 
904
- for (i in o)
905
- v += typeof o[i] != 'function' ? (v.length > 1 ? ',' + quote : quote) + i + quote +':' + serialize(o[i], quote) : '';
904
+ for (i in o) {
905
+ if (o.hasOwnProperty(i)) {
906
+ v += typeof o[i] != 'function' ? (v.length > 1 ? ',' + quote : quote) + i + quote +':' + serialize(o[i], quote) : '';
907
+ }
908
+ }
906
909
 
907
910
  return v + '}';
908
911
  }
@@ -923,6 +926,7 @@ tinymce.create('tinymce.util.Dispatcher', {
923
926
 
924
927
  };
925
928
  })();
929
+
926
930
  tinymce.create('static tinymce.util.XHR', {
927
931
  send : function(o) {
928
932
  var x, t, w = window, c = 0;
@@ -1038,11 +1042,17 @@ tinymce.create('static tinymce.util.XHR', {
1038
1042
  }());
1039
1043
  (function(tinymce){
1040
1044
  tinymce.VK = {
1041
- DELETE:46,
1042
- BACKSPACE:8
1043
-
1045
+ DELETE: 46,
1046
+ BACKSPACE: 8,
1047
+ ENTER: 13,
1048
+ TAB: 9,
1049
+ SPACEBAR: 32,
1050
+ UP: 38,
1051
+ DOWN: 40,
1052
+ modifierPressed: function (e) {
1053
+ return e.shiftKey || e.ctrlKey || e.altKey;
1054
+ }
1044
1055
  }
1045
-
1046
1056
  })(tinymce);
1047
1057
 
1048
1058
  (function(tinymce) {
@@ -1055,7 +1065,7 @@ tinymce.create('static tinymce.util.XHR', {
1055
1065
  var rng, blockElm, node, clonedSpan, isDelete;
1056
1066
 
1057
1067
  isDelete = e.keyCode == DELETE;
1058
- if (isDelete || e.keyCode == BACKSPACE) {
1068
+ if ((isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {
1059
1069
  e.preventDefault();
1060
1070
  rng = selection.getRng();
1061
1071
 
@@ -1071,7 +1081,7 @@ tinymce.create('static tinymce.util.XHR', {
1071
1081
  node = blockElm.firstChild;
1072
1082
 
1073
1083
  // Ignore empty text nodes
1074
- while (node.nodeType == 3 && node.nodeValue.length == 0)
1084
+ while (node && node.nodeType == 3 && node.nodeValue.length == 0)
1075
1085
  node = node.nextSibling;
1076
1086
 
1077
1087
  if (node && node.nodeName === 'SPAN') {
@@ -1079,7 +1089,7 @@ tinymce.create('static tinymce.util.XHR', {
1079
1089
  }
1080
1090
  }
1081
1091
 
1082
- // Do the backspace/delete actiopn
1092
+ // Do the backspace/delete action
1083
1093
  ed.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null);
1084
1094
 
1085
1095
  // Find all odd apple-style-spans
@@ -1101,17 +1111,36 @@ tinymce.create('static tinymce.util.XHR', {
1101
1111
  };
1102
1112
 
1103
1113
  function emptyEditorWhenDeleting(ed) {
1104
- ed.onKeyUp.add(function(ed, e) {
1105
- var keyCode = e.keyCode;
1106
1114
 
1115
+ function serializeRng(rng) {
1116
+ var body = ed.dom.create("body");
1117
+ var contents = rng.cloneContents();
1118
+ body.appendChild(contents);
1119
+ return ed.selection.serializer.serialize(body, {format: 'html'});
1120
+ }
1121
+
1122
+ function allContentsSelected(rng) {
1123
+ var selection = serializeRng(rng);
1124
+
1125
+ var allRng = ed.dom.createRng();
1126
+ allRng.selectNode(ed.getBody());
1127
+
1128
+ var allSelection = serializeRng(allRng);
1129
+ return selection === allSelection;
1130
+ }
1131
+
1132
+ ed.onKeyDown.addToTop(function(ed, e) {
1133
+ var keyCode = e.keyCode;
1107
1134
  if (keyCode == DELETE || keyCode == BACKSPACE) {
1108
- if (ed.dom.isEmpty(ed.getBody())) {
1135
+ var rng = ed.selection.getRng(true);
1136
+ if (!rng.collapsed && allContentsSelected(rng)) {
1109
1137
  ed.setContent('', {format : 'raw'});
1110
1138
  ed.nodeChanged();
1111
- return;
1139
+ e.preventDefault();
1112
1140
  }
1113
1141
  }
1114
1142
  });
1143
+
1115
1144
  };
1116
1145
 
1117
1146
  function inputMethodFocus(ed) {
@@ -1120,6 +1149,21 @@ tinymce.create('static tinymce.util.XHR', {
1120
1149
  });
1121
1150
  };
1122
1151
 
1152
+ function removeHrOnBackspace(ed) {
1153
+ ed.onKeyDown.add(function(ed, e) {
1154
+ if (e.keyCode === BACKSPACE) {
1155
+ if (ed.selection.isCollapsed() && ed.selection.getRng(true).startOffset === 0) {
1156
+ var node = ed.selection.getNode();
1157
+ var previousSibling = node.previousSibling;
1158
+ if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") {
1159
+ ed.dom.remove(previousSibling);
1160
+ tinymce.dom.Event.cancel(e);
1161
+ }
1162
+ }
1163
+ }
1164
+ })
1165
+ }
1166
+
1123
1167
  function focusBody(ed) {
1124
1168
  // Fix for a focus bug in FF 3.x where the body element
1125
1169
  // wouldn't get proper focus if the user clicked on the HTML element
@@ -1157,6 +1201,51 @@ tinymce.create('static tinymce.util.XHR', {
1157
1201
  });
1158
1202
  };
1159
1203
 
1204
+ function removeStylesOnPTagsInheritedFromHeadingTag(ed) {
1205
+ ed.onKeyDown.add(function(ed, event) {
1206
+ function checkInHeadingTag(ed) {
1207
+ var currentNode = ed.selection.getNode();
1208
+ var headingTags = 'h1,h2,h3,h4,h5,h6';
1209
+ return ed.dom.is(currentNode, headingTags) || ed.dom.getParent(currentNode, headingTags) !== null;
1210
+ }
1211
+
1212
+ if (event.keyCode === VK.ENTER && !VK.modifierPressed(event) && checkInHeadingTag(ed)) {
1213
+ setTimeout(function() {
1214
+ var currentNode = ed.selection.getNode();
1215
+ if (ed.dom.is(currentNode, 'p')) {
1216
+ ed.dom.setAttrib(currentNode, 'style', null);
1217
+ // While tiny's content is correct after this method call, the content shown is not representative of it and needs to be 'repainted'
1218
+ ed.execCommand('mceCleanup');
1219
+ }
1220
+ }, 0);
1221
+ }
1222
+ });
1223
+ }
1224
+ function selectionChangeNodeChanged(ed) {
1225
+ var lastRng, selectionTimer;
1226
+
1227
+ ed.dom.bind(ed.getDoc(), 'selectionchange', function() {
1228
+ if (selectionTimer) {
1229
+ clearTimeout(selectionTimer);
1230
+ selectionTimer = 0;
1231
+ }
1232
+
1233
+ selectionTimer = window.setTimeout(function() {
1234
+ var rng = ed.selection.getRng();
1235
+
1236
+ // Compare the ranges to see if it was a real change or not
1237
+ if (!lastRng || !tinymce.dom.RangeUtils.compareRanges(rng, lastRng)) {
1238
+ ed.nodeChanged();
1239
+ lastRng = rng;
1240
+ }
1241
+ }, 50);
1242
+ });
1243
+ }
1244
+
1245
+ function ensureBodyHasRoleApplication(ed) {
1246
+ document.body.setAttribute("role", "application");
1247
+ }
1248
+
1160
1249
  tinymce.create('tinymce.util.Quirks', {
1161
1250
  Quirks: function(ed) {
1162
1251
  // WebKit
@@ -1165,24 +1254,34 @@ tinymce.create('static tinymce.util.XHR', {
1165
1254
  emptyEditorWhenDeleting(ed);
1166
1255
  inputMethodFocus(ed);
1167
1256
  selectControlElements(ed);
1257
+
1258
+ // iOS
1259
+ if (tinymce.isIDevice) {
1260
+ selectionChangeNodeChanged(ed);
1261
+ }
1168
1262
  }
1169
1263
 
1170
1264
  // IE
1171
1265
  if (tinymce.isIE) {
1266
+ removeHrOnBackspace(ed);
1172
1267
  emptyEditorWhenDeleting(ed);
1268
+ ensureBodyHasRoleApplication(ed);
1269
+ removeStylesOnPTagsInheritedFromHeadingTag(ed)
1173
1270
  }
1174
1271
 
1175
1272
  // Gecko
1176
1273
  if (tinymce.isGecko) {
1274
+ removeHrOnBackspace(ed);
1177
1275
  focusBody(ed);
1178
1276
  }
1179
1277
  }
1180
1278
  });
1181
1279
  })(tinymce);
1280
+
1182
1281
  (function(tinymce) {
1183
1282
  var namedEntities, baseEntities, reverseEntities,
1184
- attrsCharsRegExp = /[&<>\"\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
1185
- textCharsRegExp = /[<>&\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
1283
+ attrsCharsRegExp = /[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
1284
+ textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
1186
1285
  rawCharsRegExp = /[<>&\"\']/g,
1187
1286
  entityRegExp = /&(#x|#)?([\w]+);/g,
1188
1287
  asciiMap = {
@@ -2168,7 +2267,7 @@ tinymce.html.Styles = function(settings, schema) {
2168
2267
  '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
2169
2268
  '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
2170
2269
  '(?:\\/([^>]+)>)|' + // End element
2171
- '(?:([^\\s\\/<>]+)\\s*((?:[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*)>)' + // Start element
2270
+ '(?:([^\\s\\/<>]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/)>)' + // Start element
2172
2271
  ')', 'g');
2173
2272
 
2174
2273
  attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;
@@ -2698,6 +2797,10 @@ tinymce.html.Styles = function(settings, schema) {
2698
2797
  }
2699
2798
  }
2700
2799
 
2800
+ // Keep comments
2801
+ if (node.type === 8)
2802
+ return false;
2803
+
2701
2804
  // Keep non whitespace text nodes
2702
2805
  if ((node.type === 3 && !whiteSpaceRegExp.test(node.value)))
2703
2806
  return false;
@@ -3873,52 +3976,59 @@ tinymce.html.Writer = function(settings) {
3873
3976
 
3874
3977
  return this.run(e, function(e) {
3875
3978
  var s = t.settings;
3979
+ var originalValue = e.getAttribute(n);
3980
+ if (v !== null) {
3981
+ switch (n) {
3982
+ case "style":
3983
+ if (!is(v, 'string')) {
3984
+ each(v, function(v, n) {
3985
+ t.setStyle(e, n, v);
3986
+ });
3876
3987
 
3877
- switch (n) {
3878
- case "style":
3879
- if (!is(v, 'string')) {
3880
- each(v, function(v, n) {
3881
- t.setStyle(e, n, v);
3882
- });
3883
-
3884
- return;
3885
- }
3988
+ return;
3989
+ }
3886
3990
 
3887
- // No mce_style for elements with these since they might get resized by the user
3888
- if (s.keep_values) {
3889
- if (v && !t._isRes(v))
3890
- e.setAttribute('data-mce-style', v, 2);
3891
- else
3892
- e.removeAttribute('data-mce-style', 2);
3893
- }
3991
+ // No mce_style for elements with these since they might get resized by the user
3992
+ if (s.keep_values) {
3993
+ if (v && !t._isRes(v))
3994
+ e.setAttribute('data-mce-style', v, 2);
3995
+ else
3996
+ e.removeAttribute('data-mce-style', 2);
3997
+ }
3894
3998
 
3895
- e.style.cssText = v;
3896
- break;
3999
+ e.style.cssText = v;
4000
+ break;
3897
4001
 
3898
- case "class":
3899
- e.className = v || ''; // Fix IE null bug
3900
- break;
4002
+ case "class":
4003
+ e.className = v || ''; // Fix IE null bug
4004
+ break;
3901
4005
 
3902
- case "src":
3903
- case "href":
3904
- if (s.keep_values) {
3905
- if (s.url_converter)
3906
- v = s.url_converter.call(s.url_converter_scope || t, v, n, e);
4006
+ case "src":
4007
+ case "href":
4008
+ if (s.keep_values) {
4009
+ if (s.url_converter)
4010
+ v = s.url_converter.call(s.url_converter_scope || t, v, n, e);
3907
4011
 
3908
- t.setAttrib(e, 'data-mce-' + n, v, 2);
3909
- }
4012
+ t.setAttrib(e, 'data-mce-' + n, v, 2);
4013
+ }
3910
4014
 
3911
- break;
4015
+ break;
3912
4016
 
3913
- case "shape":
3914
- e.setAttribute('data-mce-style', v);
3915
- break;
4017
+ case "shape":
4018
+ e.setAttribute('data-mce-style', v);
4019
+ break;
4020
+ }
3916
4021
  }
3917
-
3918
4022
  if (is(v) && v !== null && v.length !== 0)
3919
4023
  e.setAttribute(n, '' + v, 2);
3920
4024
  else
3921
4025
  e.removeAttribute(n, 2);
4026
+
4027
+ // fire onChangeAttrib event for attributes that have changed
4028
+ if (tinyMCE.activeEditor && originalValue != v) {
4029
+ var ed = tinyMCE.activeEditor;
4030
+ ed.onSetAttrib.dispatch(ed, e, n, v);
4031
+ }
3922
4032
  });
3923
4033
  },
3924
4034
 
@@ -4562,6 +4672,10 @@ tinymce.html.Writer = function(settings) {
4562
4672
  }
4563
4673
  }
4564
4674
 
4675
+ // Keep comment nodes
4676
+ if (type == 8)
4677
+ return false;
4678
+
4565
4679
  // Keep non whitespace text nodes
4566
4680
  if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue)))
4567
4681
  return false;
@@ -4624,6 +4738,12 @@ tinymce.html.Writer = function(settings) {
4624
4738
  function trim(node) {
4625
4739
  var i, children = node.childNodes, type = node.nodeType;
4626
4740
 
4741
+ function surroundedBySpans(node) {
4742
+ var previousIsSpan = node.previousSibling && node.previousSibling.nodeName == 'SPAN';
4743
+ var nextIsSpan = node.nextSibling && node.nextSibling.nodeName == 'SPAN';
4744
+ return previousIsSpan && nextIsSpan;
4745
+ }
4746
+
4627
4747
  if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark')
4628
4748
  return;
4629
4749
 
@@ -4634,7 +4754,10 @@ tinymce.html.Writer = function(settings) {
4634
4754
  // Keep non whitespace text nodes
4635
4755
  if (type == 3 && node.nodeValue.length > 0) {
4636
4756
  // If parent element isn't a block or there isn't any useful contents for example "<p> </p>"
4637
- if (!t.isBlock(node.parentNode) || tinymce.trim(node.nodeValue).length > 0)
4757
+ // Also keep text nodes with only spaces if surrounded by spans.
4758
+ // eg. "<p><span>a</span> <span>b</span></p>" should keep space between a and b
4759
+ var trimmedLength = tinymce.trim(node.nodeValue).length;
4760
+ if (!t.isBlock(node.parentNode) || trimmedLength > 0 || trimmedLength == 0 && surroundedBySpans(node))
4638
4761
  return;
4639
4762
  } else if (type == 1) {
4640
4763
  // If the only child is a bookmark then move it up
@@ -4671,9 +4794,9 @@ tinymce.html.Writer = function(settings) {
4671
4794
 
4672
4795
  // Insert middle chunk
4673
4796
  if (re)
4674
- pa.replaceChild(re, e);
4675
- else
4676
- pa.insertBefore(e, pe);
4797
+ pa.replaceChild(re, e);
4798
+ else
4799
+ pa.insertBefore(e, pe);
4677
4800
 
4678
4801
  // Insert after chunk
4679
4802
  pa.insertBefore(trim(aft), pe);
@@ -5690,7 +5813,7 @@ tinymce.html.Writer = function(settings) {
5690
5813
  parent = node.parentNode;
5691
5814
  root = dom.getRoot().parentNode;
5692
5815
 
5693
- while (parent != root) {
5816
+ while (parent != root && parent.nodeType !== 9) {
5694
5817
  children = parent.children;
5695
5818
 
5696
5819
  i = children.length;
@@ -7173,6 +7296,12 @@ window.tinymce.dom.Sizzle = Sizzle;
7173
7296
  return;
7174
7297
  }
7175
7298
 
7299
+ // When loaded asynchronously, the DOM Content may already be loaded
7300
+ if (doc.readyState === 'complete') {
7301
+ t._pageInit(win);
7302
+ return;
7303
+ }
7304
+
7176
7305
  // Use IE method
7177
7306
  if (doc.attachEvent) {
7178
7307
  doc.attachEvent("onreadystatechange", function() {
@@ -7973,7 +8102,8 @@ window.tinymce.dom.Sizzle = Sizzle;
7973
8102
  }
7974
8103
 
7975
8104
  s.addRange(r);
7976
- t.selectedRange = s.getRangeAt(0);
8105
+ // adding range isn't always successful so we need to check range count otherwise an exception can occur
8106
+ t.selectedRange = s.rangeCount > 0 ? s.getRangeAt(0) : null;
7977
8107
  }
7978
8108
  } else {
7979
8109
  // Is W3C Range
@@ -8069,7 +8199,8 @@ window.tinymce.dom.Sizzle = Sizzle;
8069
8199
  if (sb && eb && sb != eb) {
8070
8200
  n = sb;
8071
8201
 
8072
- while ((n = n.nextSibling) && n != eb) {
8202
+ var walker = new tinymce.dom.TreeWalker(sb, dom.getRoot());
8203
+ while ((n = walker.next()) && n != eb) {
8073
8204
  if (dom.isBlock(n))
8074
8205
  bl.push(n);
8075
8206
  }
@@ -8084,6 +8215,11 @@ window.tinymce.dom.Sizzle = Sizzle;
8084
8215
  normalize : function() {
8085
8216
  var self = this, rng, normalized;
8086
8217
 
8218
+ // TODO:
8219
+ // Retain selection direction.
8220
+ // Lean left/right on Gecko for inline elements.
8221
+ // Run this on mouse up/key up when the user manually moves the selection
8222
+
8087
8223
  // Normalize only on non IE browsers for now
8088
8224
  if (tinymce.isIE)
8089
8225
  return;
@@ -8118,18 +8254,24 @@ window.tinymce.dom.Sizzle = Sizzle;
8118
8254
  if (node.nodeType === 3) {
8119
8255
  offset = start ? 0 : node.nodeValue.length - 1;
8120
8256
  container = node;
8257
+ normalized = true;
8121
8258
  break;
8122
8259
  }
8123
8260
 
8124
- // Found a BR element that we can place the caret before
8125
- if (node.nodeName === 'BR') {
8261
+ // Found a BR/IMG element that we can place the caret before
8262
+ if (/^(BR|IMG)$/.test(node.nodeName)) {
8126
8263
  offset = dom.nodeIndex(node);
8127
8264
  container = node.parentNode;
8265
+
8266
+ // Put caret after image when moving the end point
8267
+ if (node.nodeName == "IMG" && !start) {
8268
+ offset++;
8269
+ }
8270
+
8271
+ normalized = true;
8128
8272
  break;
8129
8273
  }
8130
8274
  } while (node = (start ? walker.next() : walker.prev()));
8131
-
8132
- normalized = true;
8133
8275
  }
8134
8276
  }
8135
8277
  }
@@ -8144,7 +8286,7 @@ window.tinymce.dom.Sizzle = Sizzle;
8144
8286
  // Normalize the end points
8145
8287
  normalizeEndPoint(true);
8146
8288
 
8147
- if (rng.collapsed)
8289
+ if (!rng.collapsed)
8148
8290
  normalizeEndPoint();
8149
8291
 
8150
8292
  // Set the selection if it was normalized
@@ -8256,12 +8398,11 @@ window.tinymce.dom.Sizzle = Sizzle;
8256
8398
  if (!settings.apply_source_formatting)
8257
8399
  settings.indent = false;
8258
8400
 
8259
- settings.remove_trailing_brs = true;
8260
-
8261
8401
  // Default DOM and Schema if they are undefined
8262
8402
  dom = dom || tinymce.DOM;
8263
8403
  schema = schema || new tinymce.html.Schema(settings);
8264
8404
  settings.entity_encoding = settings.entity_encoding || 'named';
8405
+ settings.remove_trailing_brs = "remove_trailing_brs" in settings ? settings.remove_trailing_brs : true;
8265
8406
 
8266
8407
  onPreProcess = new tinymce.util.Dispatcher(self);
8267
8408
 
@@ -8325,8 +8466,8 @@ window.tinymce.dom.Sizzle = Sizzle;
8325
8466
  function trim(value) {
8326
8467
  return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n')
8327
8468
  .replace(/^[\r\n]*|[\r\n]*$/g, '')
8328
- .replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g, '')
8329
- .replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g, '');
8469
+ .replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi, '')
8470
+ .replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, '');
8330
8471
  };
8331
8472
 
8332
8473
  while (i--) {
@@ -8475,7 +8616,7 @@ window.tinymce.dom.Sizzle = Sizzle;
8475
8616
 
8476
8617
  // Replace all BOM characters for now until we can find a better solution
8477
8618
  if (!args.cleanup)
8478
- args.content = args.content.replace(/\uFEFF/g, '');
8619
+ args.content = args.content.replace(/\uFEFF|\u200B/g, '');
8479
8620
 
8480
8621
  // Post process
8481
8622
  if (!args.no_events)
@@ -8769,6 +8910,24 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
8769
8910
  return;
8770
8911
  }
8771
8912
 
8913
+ function exclude(nodes) {
8914
+ var node;
8915
+
8916
+ // First node is excluded
8917
+ node = nodes[0];
8918
+ if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) {
8919
+ nodes.splice(0, 1);
8920
+ }
8921
+
8922
+ // Last node is excluded
8923
+ node = nodes[nodes.length - 1];
8924
+ if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) {
8925
+ nodes.splice(nodes.length - 1, 1);
8926
+ }
8927
+
8928
+ return nodes;
8929
+ };
8930
+
8772
8931
  function collectSiblings(node, name, end_node) {
8773
8932
  var siblings = [];
8774
8933
 
@@ -8798,7 +8957,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
8798
8957
  if (!next)
8799
8958
  siblings.reverse();
8800
8959
 
8801
- callback(siblings);
8960
+ callback(exclude(siblings));
8802
8961
  }
8803
8962
  }
8804
8963
  };
@@ -8811,28 +8970,28 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
8811
8970
  if (endContainer.nodeType == 1 && endContainer.hasChildNodes())
8812
8971
  endContainer = endContainer.childNodes[Math.min(endOffset - 1, endContainer.childNodes.length - 1)];
8813
8972
 
8814
- // Find common ancestor and end points
8815
- ancestor = dom.findCommonAncestor(startContainer, endContainer);
8816
-
8817
8973
  // Same container
8818
8974
  if (startContainer == endContainer)
8819
- return callback([startContainer]);
8975
+ return callback(exclude([startContainer]));
8820
8976
 
8977
+ // Find common ancestor and end points
8978
+ ancestor = dom.findCommonAncestor(startContainer, endContainer);
8979
+
8821
8980
  // Process left side
8822
8981
  for (node = startContainer; node; node = node.parentNode) {
8823
- if (node == endContainer)
8982
+ if (node === endContainer)
8824
8983
  return walkBoundary(startContainer, ancestor, true);
8825
8984
 
8826
- if (node == ancestor)
8985
+ if (node === ancestor)
8827
8986
  break;
8828
8987
  }
8829
8988
 
8830
8989
  // Process right side
8831
8990
  for (node = endContainer; node; node = node.parentNode) {
8832
- if (node == startContainer)
8991
+ if (node === startContainer)
8833
8992
  return walkBoundary(endContainer, ancestor);
8834
8993
 
8835
- if (node == ancestor)
8994
+ if (node === ancestor)
8836
8995
  break;
8837
8996
  }
8838
8997
 
@@ -8851,48 +9010,46 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
8851
9010
  );
8852
9011
 
8853
9012
  if (siblings.length)
8854
- callback(siblings);
9013
+ callback(exclude(siblings));
8855
9014
 
8856
9015
  // Walk right leaf
8857
9016
  walkBoundary(endContainer, endPoint);
8858
9017
  };
8859
9018
 
8860
- /* this.split = function(rng) {
9019
+ this.split = function(rng) {
8861
9020
  var startContainer = rng.startContainer,
8862
9021
  startOffset = rng.startOffset,
8863
9022
  endContainer = rng.endContainer,
8864
9023
  endOffset = rng.endOffset;
8865
9024
 
8866
9025
  function splitText(node, offset) {
8867
- if (offset == node.nodeValue.length)
8868
- node.appendData(INVISIBLE_CHAR);
8869
-
8870
- node = node.splitText(offset);
8871
-
8872
- if (node.nodeValue === INVISIBLE_CHAR)
8873
- node.nodeValue = '';
8874
-
8875
- return node;
9026
+ return node.splitText(offset);
8876
9027
  };
8877
9028
 
8878
9029
  // Handle single text node
8879
- if (startContainer == endContainer) {
8880
- if (startContainer.nodeType == 3) {
8881
- if (startOffset != 0)
8882
- startContainer = endContainer = splitText(startContainer, startOffset);
8883
-
8884
- if (endOffset - startOffset != startContainer.nodeValue.length)
8885
- splitText(startContainer, endOffset - startOffset);
9030
+ if (startContainer == endContainer && startContainer.nodeType == 3) {
9031
+ if (startOffset > 0 && startOffset < startContainer.nodeValue.length) {
9032
+ endContainer = splitText(startContainer, startOffset);
9033
+ startContainer = endContainer.previousSibling;
9034
+
9035
+ if (endOffset > startOffset) {
9036
+ endOffset = endOffset - startOffset;
9037
+ startContainer = endContainer = splitText(endContainer, endOffset).previousSibling;
9038
+ endOffset = endContainer.nodeValue.length;
9039
+ startOffset = 0;
9040
+ } else {
9041
+ endOffset = 0;
9042
+ }
8886
9043
  }
8887
9044
  } else {
8888
9045
  // Split startContainer text node if needed
8889
- if (startContainer.nodeType == 3 && startOffset != 0) {
9046
+ if (startContainer.nodeType == 3 && startOffset > 0 && startOffset < startContainer.nodeValue.length) {
8890
9047
  startContainer = splitText(startContainer, startOffset);
8891
9048
  startOffset = 0;
8892
9049
  }
8893
9050
 
8894
9051
  // Split endContainer text node if needed
8895
- if (endContainer.nodeType == 3 && endOffset != endContainer.nodeValue.length) {
9052
+ if (endContainer.nodeType == 3 && endOffset > 0 && endOffset < endContainer.nodeValue.length) {
8896
9053
  endContainer = splitText(endContainer, endOffset).previousSibling;
8897
9054
  endOffset = endContainer.nodeValue.length;
8898
9055
  }
@@ -8905,7 +9062,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
8905
9062
  endOffset : endOffset
8906
9063
  };
8907
9064
  };
8908
- */
9065
+
8909
9066
  };
8910
9067
 
8911
9068
  tinymce.dom.RangeUtils.compareRanges = function(rng1, rng2) {
@@ -9611,7 +9768,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
9611
9768
  // Internal functions
9612
9769
  _setupKeyboardNav : function(){
9613
9770
  var contextMenu, menuItems, t=this;
9614
- contextMenu = DOM.select('#menu_' + t.id)[0];
9771
+ contextMenu = DOM.get('menu_' + t.id);
9615
9772
  menuItems = DOM.select('a[role=option]', 'menu_' + t.id);
9616
9773
  menuItems.splice(0,0,contextMenu);
9617
9774
  t.keyboardNav = new tinymce.ui.KeyboardNavigation({
@@ -9718,10 +9875,27 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
9718
9875
  },
9719
9876
 
9720
9877
  postRender : function() {
9721
- var t = this, s = t.settings;
9722
-
9878
+ var t = this, s = t.settings, imgBookmark;
9879
+
9880
+ // In IE a large image that occupies the entire editor area will be deselected when a button is clicked, so
9881
+ // need to keep the selection in case the selection is lost
9882
+ if (tinymce.isIE && t.editor) {
9883
+ tinymce.dom.Event.add(t.id, 'mousedown', function(e) {
9884
+ var nodeName = t.editor.selection.getNode().nodeName;
9885
+ imgBookmark = nodeName === 'IMG' ? t.editor.selection.getBookmark() : null;
9886
+ });
9887
+ }
9723
9888
  tinymce.dom.Event.add(t.id, 'click', function(e) {
9724
- if (!t.isDisabled())
9889
+ if (!t.isDisabled()) {
9890
+ // restore the selection in case the selection is lost in IE
9891
+ if (tinymce.isIE && t.editor && imgBookmark !== null) {
9892
+ t.editor.selection.moveToBookmark(imgBookmark);
9893
+ }
9894
+ return s.onclick.call(s.scope, e);
9895
+ }
9896
+ });
9897
+ tinymce.dom.Event.add(t.id, 'keyup', function(e) {
9898
+ if (!t.isDisabled() && e.keyCode==tinymce.VK.SPACEBAR)
9725
9899
  return s.onclick.call(s.scope, e);
9726
9900
  });
9727
9901
  }
@@ -9757,7 +9931,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
9757
9931
  return t.selectByIndex(-1);
9758
9932
 
9759
9933
  // Is string or number make function selector
9760
- if (va && va.call)
9934
+ if (va && typeof(va)=="function")
9761
9935
  f = va;
9762
9936
  else {
9763
9937
  f = function(v) {
@@ -10034,7 +10208,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
10034
10208
  return t.selectByIndex(-1);
10035
10209
 
10036
10210
  // Is string or number make function selector
10037
- if (va && va.call)
10211
+ if (va && typeof(va)=="function")
10038
10212
  f = va;
10039
10213
  else {
10040
10214
  f = function(v) {
@@ -10428,15 +10602,21 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
10428
10602
  }
10429
10603
 
10430
10604
  n = DOM.add(tr, 'td');
10431
- n = DOM.add(n, 'a', {
10432
- role : 'option',
10605
+ var settings = {
10433
10606
  href : 'javascript:;',
10434
10607
  style : {
10435
10608
  backgroundColor : '#' + c
10436
10609
  },
10437
10610
  'title': t.editor.getLang('colors.' + c, c),
10438
10611
  'data-mce-color' : '#' + c
10439
- });
10612
+ };
10613
+
10614
+ // adding a proper ARIA role = button causes JAWS to read things incorrectly on IE.
10615
+ if (!tinymce.isIE ) {
10616
+ settings['role']= 'option';
10617
+ }
10618
+
10619
+ n = DOM.add(n, 'a', settings);
10440
10620
 
10441
10621
  if (t.editor.forcedHighContrastMode) {
10442
10622
  n = DOM.add(n, 'canvas', { width: 16, height: 16, 'aria-hidden': 'true' });
@@ -11072,7 +11252,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
11072
11252
  Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isGecko = tinymce.isGecko,
11073
11253
  isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, is = tinymce.is,
11074
11254
  ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager,
11075
- inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode;
11255
+ inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode, VK = tinymce.VK;
11076
11256
 
11077
11257
  tinymce.create('tinymce.Editor', {
11078
11258
  Editor : function(id, s) {
@@ -11096,6 +11276,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
11096
11276
 
11097
11277
  'onPostRender',
11098
11278
 
11279
+ 'onLoad',
11280
+
11099
11281
  'onInit',
11100
11282
 
11101
11283
  'onRemove',
@@ -11158,7 +11340,9 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
11158
11340
 
11159
11341
  'onVisualAid',
11160
11342
 
11161
- 'onSetProgressState'
11343
+ 'onSetProgressState',
11344
+
11345
+ 'onSetAttrib'
11162
11346
  ], function(e) {
11163
11347
  t[e] = new Dispatcher(t);
11164
11348
  });
@@ -11192,6 +11376,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
11192
11376
  visual_table_class : 'mceItemTable',
11193
11377
  visual : 1,
11194
11378
  font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',
11379
+ font_size_legacy_values : 'xx-small,small,medium,large,x-large,xx-large,300%', // See: http://www.w3.org/TR/CSS2/fonts.html#propdef-font-size
11195
11380
  apply_source_formatting : 1,
11196
11381
  directionality : 'ltr',
11197
11382
  forced_root_block : 'p',
@@ -11497,6 +11682,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
11497
11682
  t.iframeHTML += '<link type="text/css" rel="stylesheet" href="' + t.contentCSS[i] + '" />';
11498
11683
  }
11499
11684
 
11685
+ t.contentCSS = [];
11686
+
11500
11687
  bi = s.body_id || 'tinymce';
11501
11688
  if (bi.indexOf('=') != -1) {
11502
11689
  bi = t.getParam('body_id', '', 'hash');
@@ -11509,7 +11696,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
11509
11696
  bc = bc[t.id] || '';
11510
11697
  }
11511
11698
 
11512
- t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"><br></body></html>';
11699
+ t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '" onload="window.parent.tinyMCE.get(\'' + t.id + '\').onLoad.dispatch();"><br></body></html>';
11513
11700
 
11514
11701
  // Domain relaxing enabled, then set document domain
11515
11702
  if (tinymce.relaxedDomain && (isIE || (tinymce.isOpera && parseFloat(opera.version()) < 11))) {
@@ -11623,10 +11810,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
11623
11810
 
11624
11811
  // Keep scripts from executing
11625
11812
  t.parser.addNodeFilter('script', function(nodes, name) {
11626
- var i = nodes.length;
11813
+ var i = nodes.length, node;
11627
11814
 
11628
- while (i--)
11629
- nodes[i].attr('type', 'mce-text/javascript');
11815
+ while (i--) {
11816
+ node = nodes[i];
11817
+ node.attr('type', 'mce-' + (node.attr('type') || 'text/javascript'));
11818
+ }
11630
11819
  });
11631
11820
 
11632
11821
  t.parser.addNodeFilter('#cdata', function(nodes, name) {
@@ -11975,7 +12164,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
11975
12164
  }
11976
12165
 
11977
12166
  t._refreshContentEditable();
11978
- selection.normalize();
11979
12167
 
11980
12168
  // Is not content editable
11981
12169
  if (!ce)
@@ -12175,9 +12363,9 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
12175
12363
  if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))
12176
12364
  t.focus();
12177
12365
 
12178
- o = {};
12179
- t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);
12180
- if (o.terminate)
12366
+ a = extend({}, a);
12367
+ t.onBeforeExecCommand.dispatch(t, cmd, ui, val, a);
12368
+ if (a.terminate)
12181
12369
  return false;
12182
12370
 
12183
12371
  // Command callback
@@ -12747,30 +12935,32 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
12747
12935
 
12748
12936
  // Add block quote deletion handler
12749
12937
  t.onKeyDown.add(function(ed, e) {
12750
- // Was the BACKSPACE key pressed?
12751
- if (e.keyCode != 8)
12938
+ if (e.keyCode != VK.BACKSPACE)
12752
12939
  return;
12753
12940
 
12754
- var n = ed.selection.getRng().startContainer;
12755
- var offset = ed.selection.getRng().startOffset;
12941
+ var rng = ed.selection.getRng();
12942
+ if (!rng.collapsed)
12943
+ return;
12944
+
12945
+ var n = rng.startContainer;
12946
+ var offset = rng.startOffset;
12756
12947
 
12757
12948
  while (n && n.nodeType && n.nodeType != 1 && n.parentNode)
12758
12949
  n = n.parentNode;
12759
-
12950
+
12760
12951
  // Is the cursor at the beginning of a blockquote?
12761
12952
  if (n && n.parentNode && n.parentNode.tagName === 'BLOCKQUOTE' && n.parentNode.firstChild == n && offset == 0) {
12762
12953
  // Remove the blockquote
12763
12954
  ed.formatter.toggle('blockquote', null, n.parentNode);
12764
12955
 
12765
12956
  // Move the caret to the beginning of n
12766
- var rng = ed.selection.getRng();
12767
12957
  rng.setStart(n, 0);
12768
12958
  rng.setEnd(n, 0);
12769
12959
  ed.selection.setRng(rng);
12770
12960
  ed.selection.collapse(false);
12771
12961
  }
12772
12962
  });
12773
-
12963
+
12774
12964
 
12775
12965
 
12776
12966
  // Add reset handler
@@ -12907,7 +13097,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
12907
13097
  t.undoManager.add();
12908
13098
  };
12909
13099
 
12910
- dom.bind(t.getDoc(), 'focusout', function(e) {
13100
+ var focusLostFunc = tinymce.isGecko ? 'blur' : 'focusout';
13101
+ dom.bind(t.getDoc(), focusLostFunc, function(e){
12911
13102
  if (!t.removed && t.undoManager.typing)
12912
13103
  addUndo();
12913
13104
  });
@@ -12967,21 +13158,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
12967
13158
  });
12968
13159
  }
12969
13160
 
12970
- // Fire a nodeChanged when the selection is changed on WebKit this fixes selection issues on iOS5
12971
- // It only fires the nodeChange event every 50ms since it would other wise update the UI when you type and it hogs the CPU
12972
- if (tinymce.isWebKit) {
12973
- dom.bind(t.getDoc(), 'selectionchange', function() {
12974
- if (t.selectionTimer) {
12975
- clearTimeout(t.selectionTimer);
12976
- t.selectionTimer = 0;
12977
- }
12978
-
12979
- t.selectionTimer = window.setTimeout(function() {
12980
- t.nodeChanged();
12981
- }, 50);
12982
- });
12983
- }
12984
-
12985
13161
  // Bug fix for FireFox keeping styles from end of selection instead of start.
12986
13162
  if (tinymce.isGecko) {
12987
13163
  function getAttributeApplyFunction() {
@@ -12991,11 +13167,11 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
12991
13167
  var target = t.selection.getStart();
12992
13168
 
12993
13169
  if (target !== t.getBody()) {
12994
- t.dom.removeAllAttribs(target);
13170
+ t.dom.setAttrib(target, "style", null);
12995
13171
 
12996
- each(template, function(attr) {
12997
- target.setAttributeNode(attr.cloneNode(true));
12998
- });
13172
+ each(template, function(attr) {
13173
+ target.setAttributeNode(attr.cloneNode(true));
13174
+ });
12999
13175
  }
13000
13176
  };
13001
13177
  }
@@ -13307,6 +13483,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
13307
13483
  var parser, serializer, parentNode, rootNode, fragment, args,
13308
13484
  marker, nodeRect, viewPortRect, rng, node, node2, bookmarkHtml, viewportBodyElement;
13309
13485
 
13486
+ //selection.normalize();
13487
+
13310
13488
  // Setup parser and serializer
13311
13489
  parser = editor.parser;
13312
13490
  serializer = new tinymce.html.Serializer({}, editor.schema);
@@ -13533,7 +13711,14 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
13533
13711
  addCommands({
13534
13712
  // Override justify commands
13535
13713
  'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) {
13536
- return isFormatMatch('align' + command.substring(7));
13714
+ var name = 'align' + command.substring(7);
13715
+ // Use Formatter.matchNode instead of Formatter.match so that we don't match on parent node. This fixes bug where for both left
13716
+ // and right align buttons can be active. This could occur when selected nodes have align right and the parent has align left.
13717
+ var nodes = selection.isCollapsed() ? [selection.getNode()] : selection.getSelectedBlocks();
13718
+ var matches = tinymce.map(nodes, function(node) {
13719
+ return !!formatter.matchNode(node, name);
13720
+ });
13721
+ return tinymce.inArray(matches, TRUE) !== -1;
13537
13722
  },
13538
13723
 
13539
13724
  'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) {
@@ -14844,8 +15029,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
14844
15029
  MCE_ATTR_RE = /^(src|href|style)$/,
14845
15030
  FALSE = false,
14846
15031
  TRUE = true,
14847
- undefined,
14848
- pendingFormats = {apply : [], remove : []};
15032
+ undefined;
14849
15033
 
14850
15034
  function isArray(obj) {
14851
15035
  return obj instanceof Array;
@@ -14856,7 +15040,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
14856
15040
  };
14857
15041
 
14858
15042
  function isCaretNode(node) {
14859
- return node.nodeType === 1 && (node.face === 'mceinline' || node.style.fontFamily === 'mceinline');
15043
+ return node.nodeType === 1 && node.id === '_mce_caret';
14860
15044
  };
14861
15045
 
14862
15046
  // Public functions
@@ -14931,30 +15115,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
14931
15115
  function apply(name, vars, node) {
14932
15116
  var formatList = get(name), format = formatList[0], bookmark, rng, i, isCollapsed = selection.isCollapsed();
14933
15117
 
14934
- function moveStart(rng) {
14935
- var container = rng.startContainer,
14936
- offset = rng.startOffset,
14937
- walker, node;
14938
-
14939
- // Move startContainer/startOffset in to a suitable node
14940
- if (container.nodeType == 1 || container.nodeValue === "") {
14941
- container = container.nodeType == 1 ? container.childNodes[offset] : container;
14942
-
14943
- // Might fail if the offset is behind the last element in it's container
14944
- if (container) {
14945
- walker = new TreeWalker(container, container.parentNode);
14946
- for (node = walker.current(); node; node = walker.next()) {
14947
- if (node.nodeType == 3 && !isWhiteSpaceNode(node)) {
14948
- rng.setStart(node, 0);
14949
- break;
14950
- }
14951
- }
14952
- }
14953
- }
14954
-
14955
- return rng;
14956
- };
14957
-
14958
15118
  function setElementFormat(elm, fmt) {
14959
15119
  fmt = fmt || format;
14960
15120
 
@@ -15061,7 +15221,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15061
15221
  }
15062
15222
  };
15063
15223
 
15064
- function applyRngStyle(rng, bookmark) {
15224
+ function applyRngStyle(rng, bookmark, node_specific) {
15065
15225
  var newWrappers = [], wrapName, wrapElm;
15066
15226
 
15067
15227
  // Setup wrapper element
@@ -15125,7 +15285,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15125
15285
 
15126
15286
  // Is it valid to wrap this item
15127
15287
  if (isValid(wrapName, nodeName) && isValid(parentName, wrapName) &&
15128
- !(node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279)) {
15288
+ !(!node_specific && node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279) && !isCaretNode(node)) {
15129
15289
  // Start wrapping
15130
15290
  if (!currentWrapElm) {
15131
15291
  // Wrap the node
@@ -15280,12 +15440,14 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15280
15440
 
15281
15441
  if (format) {
15282
15442
  if (node) {
15283
- rng = dom.createRng();
15284
-
15285
- rng.setStartBefore(node);
15286
- rng.setEndAfter(node);
15287
-
15288
- applyRngStyle(expandRng(rng, formatList));
15443
+ if (node.nodeType) {
15444
+ rng = dom.createRng();
15445
+ rng.setStartBefore(node);
15446
+ rng.setEndAfter(node);
15447
+ applyRngStyle(expandRng(rng, formatList), null, true);
15448
+ } else {
15449
+ applyRngStyle(node, null, true);
15450
+ }
15289
15451
  } else {
15290
15452
  if (!isCollapsed || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) {
15291
15453
  // Obtain selection node before selection is unselected by applyRngStyle()
@@ -15303,7 +15465,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15303
15465
  }
15304
15466
 
15305
15467
  selection.moveToBookmark(bookmark);
15306
- selection.setRng(moveStart(selection.getRng(TRUE)));
15468
+ moveStart(selection.getRng(TRUE));
15307
15469
  ed.nodeChanged();
15308
15470
  } else
15309
15471
  performCaretAction('apply', name, vars);
@@ -15313,44 +15475,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15313
15475
 
15314
15476
  function remove(name, vars, node) {
15315
15477
  var formatList = get(name), format = formatList[0], bookmark, i, rng;
15316
- function moveStart(rng) {
15317
- var container = rng.startContainer,
15318
- offset = rng.startOffset,
15319
- walker, node, nodes, tmpNode;
15320
-
15321
- // Convert text node into index if possible
15322
- if (container.nodeType == 3 && offset >= container.nodeValue.length - 1) {
15323
- container = container.parentNode;
15324
- offset = nodeIndex(container) + 1;
15325
- }
15326
-
15327
- // Move startContainer/startOffset in to a suitable node
15328
- if (container.nodeType == 1) {
15329
- nodes = container.childNodes;
15330
- container = nodes[Math.min(offset, nodes.length - 1)];
15331
- walker = new TreeWalker(container);
15332
-
15333
- // If offset is at end of the parent node walk to the next one
15334
- if (offset > nodes.length - 1)
15335
- walker.next();
15336
-
15337
- for (node = walker.current(); node; node = walker.next()) {
15338
- if (node.nodeType == 3 && !isWhiteSpaceNode(node)) {
15339
- // IE has a "neat" feature where it moves the start node into the closest element
15340
- // we can avoid this by inserting an element before it and then remove it after we set the selection
15341
- tmpNode = dom.create('a', null, INVISIBLE_CHAR);
15342
- node.parentNode.insertBefore(tmpNode, node);
15343
-
15344
- // Set selection and remove tmpNode
15345
- rng.setStart(node, 0);
15346
- selection.setRng(rng);
15347
- dom.remove(tmpNode);
15348
-
15349
- return;
15350
- }
15351
- }
15352
- }
15353
- };
15354
15478
 
15355
15479
  // Merges the styles for each node
15356
15480
  function process(node) {
@@ -15499,10 +15623,15 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15499
15623
 
15500
15624
  // Handle node
15501
15625
  if (node) {
15502
- rng = dom.createRng();
15503
- rng.setStartBefore(node);
15504
- rng.setEndAfter(node);
15505
- removeRngStyle(rng);
15626
+ if (node.nodeType) {
15627
+ rng = dom.createRng();
15628
+ rng.setStartBefore(node);
15629
+ rng.setEndAfter(node);
15630
+ removeRngStyle(rng);
15631
+ } else {
15632
+ removeRngStyle(node);
15633
+ }
15634
+
15506
15635
  return;
15507
15636
  }
15508
15637
 
@@ -15519,6 +15648,11 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15519
15648
  ed.nodeChanged();
15520
15649
  } else
15521
15650
  performCaretAction('remove', name, vars);
15651
+
15652
+ // When you remove formatting from a table cell in WebKit (cell, not the contents of a cell) there is a rendering issue with column width
15653
+ if (tinymce.isWebKit) {
15654
+ ed.execCommand('mceCleanup');
15655
+ }
15522
15656
  };
15523
15657
 
15524
15658
  function toggle(name, vars, node) {
@@ -15593,7 +15727,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15593
15727
  };
15594
15728
 
15595
15729
  function match(name, vars, node) {
15596
- var startNode, i;
15730
+ var startNode;
15597
15731
 
15598
15732
  function matchParents(node) {
15599
15733
  // Find first node with similar format settings
@@ -15609,21 +15743,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15609
15743
  if (node)
15610
15744
  return matchParents(node);
15611
15745
 
15612
- // Check pending formats
15613
- if (selection.isCollapsed()) {
15614
- for (i = pendingFormats.apply.length - 1; i >= 0; i--) {
15615
- if (pendingFormats.apply[i].name == name)
15616
- return true;
15617
- }
15618
-
15619
- for (i = pendingFormats.remove.length - 1; i >= 0; i--) {
15620
- if (pendingFormats.remove[i].name == name)
15621
- return false;
15622
- }
15623
-
15624
- return matchParents(selection.getNode());
15625
- }
15626
-
15627
15746
  // Check selected node
15628
15747
  node = selection.getNode();
15629
15748
  if (matchParents(node))
@@ -15642,33 +15761,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15642
15761
  function matchAll(names, vars) {
15643
15762
  var startElement, matchedFormatNames = [], checkedMap = {}, i, ni, name;
15644
15763
 
15645
- // If the selection is collapsed then check pending formats
15646
- if (selection.isCollapsed()) {
15647
- for (ni = 0; ni < names.length; ni++) {
15648
- // If the name is to be removed, then stop it from being added
15649
- for (i = pendingFormats.remove.length - 1; i >= 0; i--) {
15650
- name = names[ni];
15651
-
15652
- if (pendingFormats.remove[i].name == name) {
15653
- checkedMap[name] = true;
15654
- break;
15655
- }
15656
- }
15657
- }
15658
-
15659
- // If the format is to be applied
15660
- for (i = pendingFormats.apply.length - 1; i >= 0; i--) {
15661
- for (ni = 0; ni < names.length; ni++) {
15662
- name = names[ni];
15663
-
15664
- if (!checkedMap[name] && pendingFormats.apply[i].name == name) {
15665
- checkedMap[name] = true;
15666
- matchedFormatNames.push(name);
15667
- }
15668
- }
15669
- }
15670
- }
15671
-
15672
15764
  // Check start of selection for formats
15673
15765
  startElement = selection.getStart();
15674
15766
  dom.getParent(startElement, function(node) {
@@ -15777,7 +15869,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15777
15869
  };
15778
15870
 
15779
15871
  function isWhiteSpaceNode(node) {
15780
- return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue);
15872
+ return node && node.nodeType === 3 && /^([\t \r\n]+|)$/.test(node.nodeValue);
15781
15873
  };
15782
15874
 
15783
15875
  function wrap(node, name, attrs) {
@@ -15793,31 +15885,42 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15793
15885
  var startContainer = rng.startContainer,
15794
15886
  startOffset = rng.startOffset,
15795
15887
  endContainer = rng.endContainer,
15796
- endOffset = rng.endOffset, sibling, lastIdx, leaf;
15888
+ endOffset = rng.endOffset, sibling, lastIdx, leaf, endPoint;
15797
15889
 
15798
15890
  // This function walks up the tree if there is no siblings before/after the node
15799
- function findParentContainer(container, child_name, sibling_name, root) {
15800
- var parent, child;
15891
+ function findParentContainer(start) {
15892
+ var container, parent, child, sibling, siblingName;
15801
15893
 
15802
- root = root || dom.getRoot();
15894
+ container = parent = start ? startContainer : endContainer;
15895
+ siblingName = start ? 'previousSibling' : 'nextSibling';
15896
+ root = dom.getRoot();
15803
15897
 
15804
- for (;;) {
15805
- // Check if we can move up are we at root level or body level
15806
- parent = container.parentNode;
15807
-
15808
- // Stop expanding on block elements or root depending on format
15809
- if (parent == root || (!format[0].block_expand && isBlock(parent)))
15898
+ // If it's a text node and the offset is inside the text
15899
+ if (container.nodeType == 3 && !isWhiteSpaceNode(container)) {
15900
+ if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {
15810
15901
  return container;
15902
+ }
15903
+ }
15811
15904
 
15812
- for (sibling = parent[child_name]; sibling && sibling != container; sibling = sibling[sibling_name]) {
15813
- if (sibling.nodeType == 1 && !isBookmarkNode(sibling))
15814
- return container;
15905
+ for (;;) {
15906
+ // Stop expanding on block elements
15907
+ if (!format[0].block_expand && isBlock(parent))
15908
+ return parent;
15909
+
15910
+ // Walk left/right
15911
+ for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
15912
+ if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling)) {
15913
+ return parent;
15914
+ }
15915
+ }
15815
15916
 
15816
- if (sibling.nodeType == 3 && !isWhiteSpaceNode(sibling))
15817
- return container;
15917
+ // Check if we can move up are we at root level or body level
15918
+ if (parent.parentNode == root) {
15919
+ container = parent;
15920
+ break;
15818
15921
  }
15819
15922
 
15820
- container = container.parentNode;
15923
+ parent = parent.parentNode;
15821
15924
  }
15822
15925
 
15823
15926
  return container;
@@ -15855,23 +15958,103 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15855
15958
  }
15856
15959
 
15857
15960
  // Exclude bookmark nodes if possible
15858
- if (isBookmarkNode(startContainer.parentNode))
15859
- startContainer = startContainer.parentNode;
15860
-
15861
- if (isBookmarkNode(startContainer))
15961
+ if (isBookmarkNode(startContainer.parentNode) || isBookmarkNode(startContainer)) {
15962
+ startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode;
15862
15963
  startContainer = startContainer.nextSibling || startContainer;
15863
15964
 
15864
- if (isBookmarkNode(endContainer.parentNode)) {
15865
- endOffset = dom.nodeIndex(endContainer);
15866
- endContainer = endContainer.parentNode;
15965
+ if (startContainer.nodeType == 3)
15966
+ startOffset = 0;
15867
15967
  }
15868
15968
 
15869
- if (isBookmarkNode(endContainer) && endContainer.previousSibling) {
15870
- endContainer = endContainer.previousSibling;
15871
- endOffset = endContainer.length;
15969
+ if (isBookmarkNode(endContainer.parentNode) || isBookmarkNode(endContainer)) {
15970
+ endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode;
15971
+ endContainer = endContainer.previousSibling || endContainer;
15972
+
15973
+ if (endContainer.nodeType == 3)
15974
+ endOffset = endContainer.length;
15872
15975
  }
15873
15976
 
15874
15977
  if (format[0].inline) {
15978
+ if (rng.collapsed) {
15979
+ function findWordEndPoint(container, offset, start) {
15980
+ var walker, node, pos, lastTextNode;
15981
+
15982
+ function findSpace(node, offset) {
15983
+ var pos, pos2, str = node.nodeValue;
15984
+
15985
+ if (typeof(offset) == "undefined") {
15986
+ offset = start ? str.length : 0;
15987
+ }
15988
+
15989
+ if (start) {
15990
+ pos = str.lastIndexOf(' ', offset);
15991
+ pos2 = str.lastIndexOf('\u00a0', offset);
15992
+ pos = pos > pos2 ? pos : pos2;
15993
+
15994
+ // Include the space on remove to avoid tag soup
15995
+ if (pos !== -1 && !remove) {
15996
+ pos++;
15997
+ }
15998
+ } else {
15999
+ pos = str.indexOf(' ', offset);
16000
+ pos2 = str.indexOf('\u00a0', offset);
16001
+ pos = pos !== -1 && (pos2 === -1 || pos < pos2) ? pos : pos2;
16002
+ }
16003
+
16004
+ return pos;
16005
+ };
16006
+
16007
+ if (container.nodeType === 3) {
16008
+ pos = findSpace(container, offset);
16009
+
16010
+ if (pos !== -1) {
16011
+ return {container : container, offset : pos};
16012
+ }
16013
+
16014
+ lastTextNode = container;
16015
+ }
16016
+
16017
+ // Walk the nodes inside the block
16018
+ walker = new TreeWalker(container, dom.getParent(container, isBlock) || ed.getBody());
16019
+ while (node = walker[start ? 'prev' : 'next']()) {
16020
+ if (node.nodeType === 3) {
16021
+ lastTextNode = node;
16022
+ pos = findSpace(node);
16023
+
16024
+ if (pos !== -1) {
16025
+ return {container : node, offset : pos};
16026
+ }
16027
+ } else if (isBlock(node)) {
16028
+ break;
16029
+ }
16030
+ }
16031
+
16032
+ if (lastTextNode) {
16033
+ if (start) {
16034
+ offset = 0;
16035
+ } else {
16036
+ offset = lastTextNode.length;
16037
+ }
16038
+
16039
+ return {container: lastTextNode, offset: offset};
16040
+ }
16041
+ }
16042
+
16043
+ // Expand left to closest word boundery
16044
+ endPoint = findWordEndPoint(startContainer, startOffset, true);
16045
+ if (endPoint) {
16046
+ startContainer = endPoint.container;
16047
+ startOffset = endPoint.offset;
16048
+ }
16049
+
16050
+ // Expand right to closest word boundery
16051
+ endPoint = findWordEndPoint(endContainer, endOffset);
16052
+ if (endPoint) {
16053
+ endContainer = endPoint.container;
16054
+ endOffset = endPoint.offset;
16055
+ }
16056
+ }
16057
+
15875
16058
  // Avoid applying formatting to a trailing space.
15876
16059
  leaf = findLeaf(endContainer, endOffset);
15877
16060
  if (leaf.node) {
@@ -15885,19 +16068,25 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15885
16068
  endContainer = leaf.node;
15886
16069
  endContainer.splitText(leaf.offset - 1);
15887
16070
  } else if (leaf.node.previousSibling) {
15888
- endContainer = leaf.node.previousSibling;
16071
+ // TODO: Figure out why this is in here
16072
+ //endContainer = leaf.node.previousSibling;
15889
16073
  }
15890
16074
  }
15891
16075
  }
15892
16076
  }
15893
-
16077
+
15894
16078
  // Move start/end point up the tree if the leaves are sharp and if we are in different containers
15895
16079
  // Example * becomes !: !<p><b><i>*text</i><i>text*</i></b></p>!
15896
16080
  // This will reduce the number of wrapper elements that needs to be created
15897
16081
  // Move start point up the tree
15898
16082
  if (format[0].inline || format[0].block_expand) {
15899
- startContainer = findParentContainer(startContainer, 'firstChild', 'nextSibling');
15900
- endContainer = findParentContainer(endContainer, 'lastChild', 'previousSibling');
16083
+ if (!format[0].inline || (startContainer.nodeType != 3 || startOffset === 0)) {
16084
+ startContainer = findParentContainer(true);
16085
+ }
16086
+
16087
+ if (!format[0].inline || (endContainer.nodeType != 3 || endOffset === endContainer.nodeValue.length)) {
16088
+ endContainer = findParentContainer();
16089
+ }
15901
16090
  }
15902
16091
 
15903
16092
  // Expand start/end container to matching selector
@@ -15971,10 +16160,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
15971
16160
  // Non block element then try to expand up the leaf
15972
16161
  if (format[0].block) {
15973
16162
  if (!isBlock(startContainer))
15974
- startContainer = findParentContainer(startContainer, 'firstChild', 'nextSibling');
16163
+ startContainer = findParentContainer(true);
15975
16164
 
15976
16165
  if (!isBlock(endContainer))
15977
- endContainer = findParentContainer(endContainer, 'lastChild', 'previousSibling');
16166
+ endContainer = findParentContainer();
15978
16167
  }
15979
16168
  }
15980
16169
 
@@ -16267,7 +16456,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
16267
16456
  };
16268
16457
 
16269
16458
  function getContainer(rng, start) {
16270
- var container, offset, lastIdx;
16459
+ var container, offset, lastIdx, walker;
16271
16460
 
16272
16461
  container = rng[start ? 'startContainer' : 'endContainer'];
16273
16462
  offset = rng[start ? 'startOffset' : 'endOffset'];
@@ -16281,142 +16470,318 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
16281
16470
  container = container.childNodes[offset > lastIdx ? lastIdx : offset];
16282
16471
  }
16283
16472
 
16473
+ // If start text node is excluded then walk to the next node
16474
+ if (container.nodeType === 3 && start && offset >= container.nodeValue.length) {
16475
+ container = new TreeWalker(container, ed.getBody()).next() || container;
16476
+ }
16477
+
16478
+ // If end text node is excluded then walk to the previous node
16479
+ if (container.nodeType === 3 && !start && offset == 0) {
16480
+ container = new TreeWalker(container, ed.getBody()).prev() || container;
16481
+ }
16482
+
16284
16483
  return container;
16285
16484
  };
16286
16485
 
16287
16486
  function performCaretAction(type, name, vars) {
16288
- var i, currentPendingFormats = pendingFormats[type],
16289
- otherPendingFormats = pendingFormats[type == 'apply' ? 'remove' : 'apply'];
16487
+ var invisibleChar, caretContainerId = '_mce_caret', debug = ed.settings.caret_debug;
16290
16488
 
16291
- function hasPending() {
16292
- return pendingFormats.apply.length || pendingFormats.remove.length;
16489
+ // Setup invisible character use zero width space on Gecko since it doesn't change the heigt of the container
16490
+ invisibleChar = tinymce.isGecko ? '\u200B' : INVISIBLE_CHAR;
16491
+
16492
+ // Creates a caret container bogus element
16493
+ function createCaretContainer(fill) {
16494
+ var caretContainer = dom.create('span', {id: caretContainerId, 'data-mce-bogus': true, style: debug ? 'color:red' : ''});
16495
+
16496
+ if (fill) {
16497
+ caretContainer.appendChild(ed.getDoc().createTextNode(invisibleChar));
16498
+ }
16499
+
16500
+ return caretContainer;
16293
16501
  };
16294
16502
 
16295
- function resetPending() {
16296
- pendingFormats.apply = [];
16297
- pendingFormats.remove = [];
16503
+ function isCaretContainerEmpty(node, nodes) {
16504
+ while (node) {
16505
+ if ((node.nodeType === 3 && node.nodeValue !== invisibleChar) || node.childNodes.length > 1) {
16506
+ return false;
16507
+ }
16508
+
16509
+ // Collect nodes
16510
+ if (nodes && node.nodeType === 1) {
16511
+ nodes.push(node);
16512
+ }
16513
+
16514
+ node = node.firstChild;
16515
+ }
16516
+
16517
+ return true;
16298
16518
  };
16519
+
16520
+ // Returns any parent caret container element
16521
+ function getParentCaretContainer(node) {
16522
+ while (node) {
16523
+ if (node.id === caretContainerId) {
16524
+ return node;
16525
+ }
16299
16526
 
16300
- function perform(caret_node) {
16301
- // Apply pending formats
16302
- each(pendingFormats.apply.reverse(), function(item) {
16303
- apply(item.name, item.vars, caret_node);
16527
+ node = node.parentNode;
16528
+ }
16529
+ };
16304
16530
 
16305
- // Colored nodes should be underlined so that the color of the underline matches the text color.
16306
- if (item.name === 'forecolor' && item.vars.value)
16307
- processUnderlineAndColor(caret_node.parentNode);
16308
- });
16531
+ // Finds the first text node in the specified node
16532
+ function findFirstTextNode(node) {
16533
+ var walker;
16309
16534
 
16310
- // Remove pending formats
16311
- each(pendingFormats.remove.reverse(), function(item) {
16312
- remove(item.name, item.vars, caret_node);
16313
- });
16535
+ if (node) {
16536
+ walker = new TreeWalker(node, node);
16537
+
16538
+ for (node = walker.current(); node; node = walker.next()) {
16539
+ if (node.nodeType === 3) {
16540
+ return node;
16541
+ }
16542
+ }
16543
+ }
16544
+ };
16545
+
16546
+ // Removes the caret container for the specified node or all on the current document
16547
+ function removeCaretContainer(node, move_caret) {
16548
+ var child, rng;
16549
+
16550
+ if (!node) {
16551
+ node = getParentCaretContainer(selection.getStart());
16552
+
16553
+ if (!node) {
16554
+ while (node = dom.get(caretContainerId)) {
16555
+ removeCaretContainer(node, false);
16556
+ }
16557
+ }
16558
+ } else {
16559
+ rng = selection.getRng(true);
16560
+
16561
+ if (isCaretContainerEmpty(node)) {
16562
+ if (move_caret !== false) {
16563
+ rng.setStartBefore(node);
16564
+ rng.setEndBefore(node);
16565
+ }
16566
+
16567
+ dom.remove(node);
16568
+ } else {
16569
+ child = findFirstTextNode(node);
16314
16570
 
16315
- dom.remove(caret_node, 1);
16316
- resetPending();
16571
+ if (child.nodeValue.charAt(0) === INVISIBLE_CHAR) {
16572
+ child = child.deleteData(0, 1);
16573
+ }
16574
+
16575
+ dom.remove(node, 1);
16576
+ }
16577
+
16578
+ selection.setRng(rng);
16579
+ }
16317
16580
  };
16581
+
16582
+ // Applies formatting to the caret postion
16583
+ function applyCaretFormat() {
16584
+ var rng, caretContainer, textNode, offset, bookmark, container, text;
16585
+
16586
+ rng = selection.getRng(true);
16587
+ offset = rng.startOffset;
16588
+ container = rng.startContainer;
16589
+ text = container.nodeValue;
16590
+
16591
+ caretContainer = getParentCaretContainer(selection.getStart());
16592
+ if (caretContainer) {
16593
+ textNode = findFirstTextNode(caretContainer);
16594
+ }
16595
+
16596
+ // Expand to word is caret is in the middle of a text node and the char before/after is a alpha numeric character
16597
+ if (text && offset > 0 && offset < text.length && /\w/.test(text.charAt(offset)) && /\w/.test(text.charAt(offset - 1))) {
16598
+ // Get bookmark of caret position
16599
+ bookmark = selection.getBookmark();
16600
+
16601
+ // Collapse bookmark range (WebKit)
16602
+ rng.collapse(true);
16318
16603
 
16319
- // Check if it already exists then ignore it
16320
- for (i = currentPendingFormats.length - 1; i >= 0; i--) {
16321
- if (currentPendingFormats[i].name == name)
16604
+ // Expand the range to the closest word and split it at those points
16605
+ rng = expandRng(rng, get(name));
16606
+ rng = rangeUtils.split(rng);
16607
+
16608
+ // Apply the format to the range
16609
+ apply(name, vars, rng);
16610
+
16611
+ // Move selection back to caret position
16612
+ selection.moveToBookmark(bookmark);
16613
+ } else {
16614
+ if (!caretContainer || textNode.nodeValue !== invisibleChar) {
16615
+ caretContainer = createCaretContainer(true);
16616
+ textNode = caretContainer.firstChild;
16617
+
16618
+ rng.insertNode(caretContainer);
16619
+ offset = 1;
16620
+
16621
+ apply(name, vars, caretContainer);
16622
+ } else {
16623
+ apply(name, vars, caretContainer);
16624
+ }
16625
+
16626
+ // Move selection to text node
16627
+ selection.setCursorLocation(textNode, offset);
16628
+ }
16629
+ };
16630
+
16631
+ function removeCaretFormat() {
16632
+ var rng = selection.getRng(true), container, offset, bookmark,
16633
+ hasContentAfter, node, formatNode, parents = [], i, caretContainer;
16634
+
16635
+ container = rng.startContainer;
16636
+ offset = rng.startOffset;
16637
+ node = container;
16638
+
16639
+ if (container.nodeType == 3) {
16640
+ if (offset != container.nodeValue.length || container.nodeValue === invisibleChar) {
16641
+ hasContentAfter = true;
16642
+ }
16643
+
16644
+ node = node.parentNode;
16645
+ }
16646
+
16647
+ while (node) {
16648
+ if (matchNode(node, name, vars)) {
16649
+ formatNode = node;
16650
+ break;
16651
+ }
16652
+
16653
+ if (node.nextSibling) {
16654
+ hasContentAfter = true;
16655
+ }
16656
+
16657
+ parents.push(node);
16658
+ node = node.parentNode;
16659
+ }
16660
+
16661
+ // Node doesn't have the specified format
16662
+ if (!formatNode) {
16322
16663
  return;
16323
- }
16664
+ }
16324
16665
 
16325
- currentPendingFormats.push({name : name, vars : vars});
16666
+ // Is there contents after the caret then remove the format on the element
16667
+ if (hasContentAfter) {
16668
+ // Get bookmark of caret position
16669
+ bookmark = selection.getBookmark();
16326
16670
 
16327
- // Check if it's in the other type, then remove it
16328
- for (i = otherPendingFormats.length - 1; i >= 0; i--) {
16329
- if (otherPendingFormats[i].name == name)
16330
- otherPendingFormats.splice(i, 1);
16331
- }
16671
+ // Collapse bookmark range (WebKit)
16672
+ rng.collapse(true);
16332
16673
 
16333
- // Pending apply or remove formats
16334
- if (hasPending()) {
16335
- ed.getDoc().execCommand('FontName', false, 'mceinline');
16336
- pendingFormats.lastRng = selection.getRng();
16674
+ // Expand the range to the closest word and split it at those points
16675
+ rng = expandRng(rng, get(name), true);
16676
+ rng = rangeUtils.split(rng);
16337
16677
 
16338
- // IE will convert the current word
16339
- each(dom.select('font,span'), function(node) {
16340
- var bookmark;
16678
+ // Remove the format from the range
16679
+ remove(name, vars, rng);
16341
16680
 
16342
- if (isCaretNode(node)) {
16343
- bookmark = selection.getBookmark();
16344
- perform(node);
16345
- selection.moveToBookmark(bookmark);
16346
- ed.nodeChanged();
16681
+ // Move selection back to caret position
16682
+ selection.moveToBookmark(bookmark);
16683
+ } else {
16684
+ caretContainer = createCaretContainer();
16685
+
16686
+ node = caretContainer;
16687
+ for (i = parents.length - 1; i >= 0; i--) {
16688
+ node.appendChild(parents[i].cloneNode(false));
16689
+ node = node.firstChild;
16690
+ }
16691
+
16692
+ // Insert invisible character into inner most format element
16693
+ node.appendChild(dom.doc.createTextNode(invisibleChar));
16694
+ node = node.firstChild;
16695
+
16696
+ // Insert caret container after the formated node
16697
+ dom.insertAfter(caretContainer, formatNode);
16698
+
16699
+ // Move selection to text node
16700
+ selection.setCursorLocation(node, 1);
16701
+ }
16702
+ };
16703
+
16704
+ // Only bind the caret events once
16705
+ if (!self._hasCaretEvents) {
16706
+ // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements
16707
+ ed.onBeforeGetContent.addToTop(function() {
16708
+ var nodes = [], i;
16709
+
16710
+ if (isCaretContainerEmpty(getParentCaretContainer(selection.getStart()), nodes)) {
16711
+ // Mark children
16712
+ i = nodes.length;
16713
+ while (i--) {
16714
+ dom.setAttrib(nodes[i], 'data-mce-bogus', '1');
16715
+ }
16347
16716
  }
16348
16717
  });
16349
16718
 
16350
- // Only register listeners once if we need to
16351
- if (!pendingFormats.isListening && hasPending()) {
16352
- pendingFormats.isListening = true;
16353
- function performPendingFormat(node, textNode) {
16354
- var rng = dom.createRng();
16355
- perform(node);
16719
+ // Remove caret container on mouse up and on key up
16720
+ tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) {
16721
+ ed[name].addToTop(function() {
16722
+ removeCaretContainer();
16723
+ });
16724
+ });
16356
16725
 
16357
- rng.setStart(textNode, textNode.nodeValue.length);
16358
- rng.setEnd(textNode, textNode.nodeValue.length);
16359
- selection.setRng(rng);
16360
- ed.nodeChanged();
16726
+ // Remove caret container on keydown and it's a backspace, enter or left/right arrow keys
16727
+ ed.onKeyDown.addToTop(function(ed, e) {
16728
+ var keyCode = e.keyCode;
16729
+
16730
+ if (keyCode == 8 || keyCode == 37 || keyCode == 39) {
16731
+ removeCaretContainer(getParentCaretContainer(selection.getStart()));
16361
16732
  }
16362
- var enterKeyPressed = false;
16733
+ });
16363
16734
 
16364
- each('onKeyDown,onKeyUp,onKeyPress,onMouseUp'.split(','), function(event) {
16365
- ed[event].addToTop(function(ed, e) {
16366
- if (e.keyCode==13 && !e.shiftKey) {
16367
- enterKeyPressed = true;
16368
- return;
16369
- }
16370
- // Do we have pending formats and is the selection moved has moved
16371
- if (hasPending() && !tinymce.dom.RangeUtils.compareRanges(pendingFormats.lastRng, selection.getRng())) {
16372
- var foundCaret = false;
16373
- each(dom.select('font,span'), function(node) {
16374
- var textNode, rng;
16375
-
16376
- // Look for marker
16377
- if (isCaretNode(node)) {
16378
- foundCaret = true;
16379
- textNode = node.firstChild;
16380
-
16381
- // Find the first text node within node
16382
- while (textNode && textNode.nodeType != 3)
16383
- textNode = textNode.firstChild;
16384
-
16385
- if (textNode)
16386
- performPendingFormat(node, textNode);
16387
- else
16388
- dom.remove(node);
16389
- }
16390
- });
16391
-
16392
- // no caret - so we are
16393
- if (enterKeyPressed && !foundCaret) {
16394
- var node = selection.getNode();
16395
- var textNode = node;
16396
-
16397
- // Find the first text node within node
16398
- while (textNode && textNode.nodeType != 3)
16399
- textNode = textNode.firstChild;
16400
- if (textNode) {
16401
- node=textNode.parentNode;
16402
- while (!isBlock(node)){
16403
- node=node.parentNode;
16404
- }
16405
- performPendingFormat(node, textNode);
16406
- }
16407
- }
16735
+ self._hasCaretEvents = true;
16736
+ }
16408
16737
 
16409
- // Always unbind and clear pending styles on keyup
16410
- if (e.type == 'keyup' || e.type == 'mouseup') {
16411
- resetPending();
16412
- enterKeyPressed=false;
16413
- }
16414
- }
16415
- });
16416
- });
16738
+ // Do apply or remove caret format
16739
+ if (type == "apply") {
16740
+ applyCaretFormat();
16741
+ } else {
16742
+ removeCaretFormat();
16743
+ }
16744
+ };
16745
+
16746
+ function moveStart(rng) {
16747
+ var container = rng.startContainer,
16748
+ offset = rng.startOffset,
16749
+ walker, node, nodes, tmpNode;
16750
+
16751
+ // Convert text node into index if possible
16752
+ if (container.nodeType == 3 && offset >= container.nodeValue.length - 1) {
16753
+ container = container.parentNode;
16754
+ offset = nodeIndex(container) + 1;
16755
+ }
16756
+
16757
+ // Move startContainer/startOffset in to a suitable node
16758
+ if (container.nodeType == 1) {
16759
+ nodes = container.childNodes;
16760
+ container = nodes[Math.min(offset, nodes.length - 1)];
16761
+ walker = new TreeWalker(container);
16762
+
16763
+ // If offset is at end of the parent node walk to the next one
16764
+ if (offset > nodes.length - 1)
16765
+ walker.next();
16766
+
16767
+ for (node = walker.current(); node; node = walker.next()) {
16768
+ if (node.nodeType == 3 && !isWhiteSpaceNode(node)) {
16769
+ // IE has a "neat" feature where it moves the start node into the closest element
16770
+ // we can avoid this by inserting an element before it and then remove it after we set the selection
16771
+ tmpNode = dom.create('a', null, INVISIBLE_CHAR);
16772
+ node.parentNode.insertBefore(tmpNode, node);
16773
+
16774
+ // Set selection and remove tmpNode
16775
+ rng.setStart(node, 0);
16776
+ selection.setRng(rng);
16777
+ dom.remove(tmpNode);
16778
+
16779
+ return;
16780
+ }
16417
16781
  }
16418
16782
  }
16419
16783
  };
16784
+
16420
16785
  };
16421
16786
  })(tinymce);
16422
16787
 
@@ -16424,7 +16789,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
16424
16789
  var filters, fontSizes, dom, settings = ed.settings;
16425
16790
 
16426
16791
  if (settings.inline_styles) {
16427
- fontSizes = tinymce.explode(settings.font_size_style_values);
16792
+ fontSizes = tinymce.explode(settings.font_size_legacy_values);
16428
16793
 
16429
16794
  function replaceWithSpan(node, styles) {
16430
16795
  tinymce.each(styles, function(value, name) {