esp-ckeditor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (340) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +32 -0
  3. data/Rakefile +28 -0
  4. data/app/assets/javascripts/esp-ckeditor/_source/core/_bootstrap.js +87 -0
  5. data/app/assets/javascripts/esp-ckeditor/_source/core/ckeditor.js +141 -0
  6. data/app/assets/javascripts/esp-ckeditor/_source/core/ckeditor_base.js +227 -0
  7. data/app/assets/javascripts/esp-ckeditor/_source/core/ckeditor_basic.js +238 -0
  8. data/app/assets/javascripts/esp-ckeditor/_source/core/command.js +209 -0
  9. data/app/assets/javascripts/esp-ckeditor/_source/core/commanddefinition.js +129 -0
  10. data/app/assets/javascripts/esp-ckeditor/_source/core/config.js +423 -0
  11. data/app/assets/javascripts/esp-ckeditor/_source/core/dataprocessor.js +65 -0
  12. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/comment.js +32 -0
  13. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/document.js +251 -0
  14. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/documentfragment.js +49 -0
  15. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/domobject.js +258 -0
  16. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/element.js +1691 -0
  17. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/elementpath.js +119 -0
  18. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/event.js +145 -0
  19. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/node.js +696 -0
  20. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/nodelist.js +26 -0
  21. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/range.js +2054 -0
  22. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/rangelist.js +213 -0
  23. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/text.js +128 -0
  24. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/walker.js +462 -0
  25. data/app/assets/javascripts/esp-ckeditor/_source/core/dom/window.js +96 -0
  26. data/app/assets/javascripts/esp-ckeditor/_source/core/dom.js +20 -0
  27. data/app/assets/javascripts/esp-ckeditor/_source/core/dtd.js +266 -0
  28. data/app/assets/javascripts/esp-ckeditor/_source/core/editor.js +1060 -0
  29. data/app/assets/javascripts/esp-ckeditor/_source/core/editor_basic.js +186 -0
  30. data/app/assets/javascripts/esp-ckeditor/_source/core/env.js +305 -0
  31. data/app/assets/javascripts/esp-ckeditor/_source/core/event.js +342 -0
  32. data/app/assets/javascripts/esp-ckeditor/_source/core/eventInfo.js +120 -0
  33. data/app/assets/javascripts/esp-ckeditor/_source/core/focusmanager.js +152 -0
  34. data/app/assets/javascripts/esp-ckeditor/_source/core/htmlparser/basicwriter.js +145 -0
  35. data/app/assets/javascripts/esp-ckeditor/_source/core/htmlparser/cdata.js +43 -0
  36. data/app/assets/javascripts/esp-ckeditor/_source/core/htmlparser/comment.js +60 -0
  37. data/app/assets/javascripts/esp-ckeditor/_source/core/htmlparser/element.js +308 -0
  38. data/app/assets/javascripts/esp-ckeditor/_source/core/htmlparser/filter.js +288 -0
  39. data/app/assets/javascripts/esp-ckeditor/_source/core/htmlparser/fragment.js +518 -0
  40. data/app/assets/javascripts/esp-ckeditor/_source/core/htmlparser/text.js +53 -0
  41. data/app/assets/javascripts/esp-ckeditor/_source/core/htmlparser.js +224 -0
  42. data/app/assets/javascripts/esp-ckeditor/_source/core/lang.js +157 -0
  43. data/app/assets/javascripts/esp-ckeditor/_source/core/loader.js +240 -0
  44. data/app/assets/javascripts/esp-ckeditor/_source/core/plugindefinition.js +83 -0
  45. data/app/assets/javascripts/esp-ckeditor/_source/core/plugins.js +103 -0
  46. data/app/assets/javascripts/esp-ckeditor/_source/core/resourcemanager.js +238 -0
  47. data/app/assets/javascripts/esp-ckeditor/_source/core/scriptloader.js +180 -0
  48. data/app/assets/javascripts/esp-ckeditor/_source/core/skins.js +184 -0
  49. data/app/assets/javascripts/esp-ckeditor/_source/core/themes.js +19 -0
  50. data/app/assets/javascripts/esp-ckeditor/_source/core/tools.js +763 -0
  51. data/app/assets/javascripts/esp-ckeditor/_source/core/ui.js +128 -0
  52. data/app/assets/javascripts/esp-ckeditor/_source/lang/_languages.js +27 -0
  53. data/app/assets/javascripts/esp-ckeditor/_source/lang/en.js +815 -0
  54. data/app/assets/javascripts/esp-ckeditor/_source/lang/ru.js +815 -0
  55. data/app/assets/javascripts/esp-ckeditor/_source/plugins/a11yhelp/dialogs/a11yhelp.js +222 -0
  56. data/app/assets/javascripts/esp-ckeditor/_source/plugins/a11yhelp/lang/en.js +108 -0
  57. data/app/assets/javascripts/esp-ckeditor/_source/plugins/a11yhelp/lang/he.js +216 -0
  58. data/app/assets/javascripts/esp-ckeditor/_source/plugins/a11yhelp/plugin.js +47 -0
  59. data/app/assets/javascripts/esp-ckeditor/_source/plugins/basicstyles/plugin.js +129 -0
  60. data/app/assets/javascripts/esp-ckeditor/_source/plugins/button/plugin.js +290 -0
  61. data/app/assets/javascripts/esp-ckeditor/_source/plugins/clipboard/dialogs/paste.js +223 -0
  62. data/app/assets/javascripts/esp-ckeditor/_source/plugins/clipboard/plugin.js +453 -0
  63. data/app/assets/javascripts/esp-ckeditor/_source/plugins/contextmenu/plugin.js +179 -0
  64. data/app/assets/javascripts/esp-ckeditor/_source/plugins/dialog/dialogDefinition.js +1166 -0
  65. data/app/assets/javascripts/esp-ckeditor/_source/plugins/dialog/plugin.js +3308 -0
  66. data/app/assets/javascripts/esp-ckeditor/_source/plugins/dialogadvtab/plugin.js +208 -0
  67. data/app/assets/javascripts/esp-ckeditor/_source/plugins/dialogui/plugin.js +1541 -0
  68. data/app/assets/javascripts/esp-ckeditor/_source/plugins/domiterator/plugin.js +361 -0
  69. data/app/assets/javascripts/esp-ckeditor/_source/plugins/editingblock/plugin.js +278 -0
  70. data/app/assets/javascripts/esp-ckeditor/_source/plugins/elementspath/plugin.js +218 -0
  71. data/app/assets/javascripts/esp-ckeditor/_source/plugins/enterkey/plugin.js +433 -0
  72. data/app/assets/javascripts/esp-ckeditor/_source/plugins/entities/plugin.js +250 -0
  73. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_attachment/dialogs/esp_attachment.js +234 -0
  74. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_attachment/images/esp_attachment.png +0 -0
  75. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_attachment/lang/en.js +22 -0
  76. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_attachment/lang/ru.js +22 -0
  77. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_attachment/lang/uk.js +22 -0
  78. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_attachment/plugin.js +23 -0
  79. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_audio/dialogs/esp_audio.js +207 -0
  80. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_audio/images/esp_audio.png +0 -0
  81. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_audio/images/placeholder.png +0 -0
  82. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_audio/lang/en.js +18 -0
  83. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_audio/lang/ru.js +18 -0
  84. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_audio/lang/uk.js +18 -0
  85. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_audio/plugin.js +182 -0
  86. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_blockquote/dialogs/esp_blockquote.js +132 -0
  87. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_blockquote/plugin.js +235 -0
  88. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_image/dialogs/esp_image.js +1414 -0
  89. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_image/images/esp_image.png +0 -0
  90. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_image/lang/en.js +9 -0
  91. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_image/lang/ru.js +9 -0
  92. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_image/lang/uk.js +9 -0
  93. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_image/plugin.js +80 -0
  94. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/dialogs/esp_anchor.js +145 -0
  95. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/dialogs/esp_link.js +1396 -0
  96. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/images/anchor.png +0 -0
  97. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/images/esp_anchor.png +0 -0
  98. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/images/esp_link.png +0 -0
  99. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/images/esp_unlink.png +0 -0
  100. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/lang/en.js +8 -0
  101. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/lang/ru.js +8 -0
  102. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/lang/uk.js +8 -0
  103. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_link/plugin.js +379 -0
  104. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_address.png +0 -0
  105. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_blockquote.png +0 -0
  106. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_div.png +0 -0
  107. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_h1.png +0 -0
  108. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_h2.png +0 -0
  109. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_h3.png +0 -0
  110. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_h4.png +0 -0
  111. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_h5.png +0 -0
  112. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_h6.png +0 -0
  113. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_p.png +0 -0
  114. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/block_pre.png +0 -0
  115. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/images/esp_showblocks.png +0 -0
  116. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_showblocks/plugin.js +163 -0
  117. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_video/dialogs/esp_video.js +277 -0
  118. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_video/images/esp_video.png +0 -0
  119. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_video/images/placeholder.png +0 -0
  120. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_video/lang/en.js +19 -0
  121. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_video/lang/ru.js +19 -0
  122. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_video/lang/uk.js +19 -0
  123. data/app/assets/javascripts/esp-ckeditor/_source/plugins/esp_video/plugin.js +182 -0
  124. data/app/assets/javascripts/esp-ckeditor/_source/plugins/fakeobjects/plugin.js +175 -0
  125. data/app/assets/javascripts/esp-ckeditor/_source/plugins/filebrowser/plugin.js +534 -0
  126. data/app/assets/javascripts/esp-ckeditor/_source/plugins/find/dialogs/find.js +915 -0
  127. data/app/assets/javascripts/esp-ckeditor/_source/plugins/find/plugin.js +47 -0
  128. data/app/assets/javascripts/esp-ckeditor/_source/plugins/floatpanel/plugin.js +428 -0
  129. data/app/assets/javascripts/esp-ckeditor/_source/plugins/format/plugin.js +197 -0
  130. data/app/assets/javascripts/esp-ckeditor/_source/plugins/htmldataprocessor/plugin.js +596 -0
  131. data/app/assets/javascripts/esp-ckeditor/_source/plugins/htmlwriter/plugin.js +319 -0
  132. data/app/assets/javascripts/esp-ckeditor/_source/plugins/image/dialogs/image.js +1407 -0
  133. data/app/assets/javascripts/esp-ckeditor/_source/plugins/image/plugin.js +81 -0
  134. data/app/assets/javascripts/esp-ckeditor/_source/plugins/indent/plugin.js +461 -0
  135. data/app/assets/javascripts/esp-ckeditor/_source/plugins/justify/plugin.js +253 -0
  136. data/app/assets/javascripts/esp-ckeditor/_source/plugins/keystrokes/plugin.js +225 -0
  137. data/app/assets/javascripts/esp-ckeditor/_source/plugins/list/plugin.js +774 -0
  138. data/app/assets/javascripts/esp-ckeditor/_source/plugins/listblock/plugin.js +266 -0
  139. data/app/assets/javascripts/esp-ckeditor/_source/plugins/liststyle/dialogs/liststyle.js +225 -0
  140. data/app/assets/javascripts/esp-ckeditor/_source/plugins/liststyle/plugin.js +66 -0
  141. data/app/assets/javascripts/esp-ckeditor/_source/plugins/maximize/plugin.js +353 -0
  142. data/app/assets/javascripts/esp-ckeditor/_source/plugins/menu/plugin.js +541 -0
  143. data/app/assets/javascripts/esp-ckeditor/_source/plugins/panel/plugin.js +400 -0
  144. data/app/assets/javascripts/esp-ckeditor/_source/plugins/pastefromword/filter/default.js +1367 -0
  145. data/app/assets/javascripts/esp-ckeditor/_source/plugins/pastefromword/plugin.js +141 -0
  146. data/app/assets/javascripts/esp-ckeditor/_source/plugins/pastetext/dialogs/pastetext.js +67 -0
  147. data/app/assets/javascripts/esp-ckeditor/_source/plugins/pastetext/plugin.js +98 -0
  148. data/app/assets/javascripts/esp-ckeditor/_source/plugins/popup/plugin.js +64 -0
  149. data/app/assets/javascripts/esp-ckeditor/_source/plugins/removeformat/plugin.js +185 -0
  150. data/app/assets/javascripts/esp-ckeditor/_source/plugins/resize/plugin.js +168 -0
  151. data/app/assets/javascripts/esp-ckeditor/_source/plugins/richcombo/plugin.js +381 -0
  152. data/app/assets/javascripts/esp-ckeditor/_source/plugins/selection/plugin.js +1729 -0
  153. data/app/assets/javascripts/esp-ckeditor/_source/plugins/showborders/plugin.js +207 -0
  154. data/app/assets/javascripts/esp-ckeditor/_source/plugins/sourcearea/plugin.js +209 -0
  155. data/app/assets/javascripts/esp-ckeditor/_source/plugins/styles/plugin.js +1700 -0
  156. data/app/assets/javascripts/esp-ckeditor/_source/plugins/styles/styles/default.js +88 -0
  157. data/app/assets/javascripts/esp-ckeditor/_source/plugins/stylescombo/plugin.js +218 -0
  158. data/app/assets/javascripts/esp-ckeditor/_source/plugins/tab/plugin.js +367 -0
  159. data/app/assets/javascripts/esp-ckeditor/_source/plugins/table/dialogs/table.js +623 -0
  160. data/app/assets/javascripts/esp-ckeditor/_source/plugins/table/plugin.js +78 -0
  161. data/app/assets/javascripts/esp-ckeditor/_source/plugins/tabletools/dialogs/tableCell.js +525 -0
  162. data/app/assets/javascripts/esp-ckeditor/_source/plugins/tabletools/plugin.js +1194 -0
  163. data/app/assets/javascripts/esp-ckeditor/_source/plugins/toolbar/plugin.js +545 -0
  164. data/app/assets/javascripts/esp-ckeditor/_source/plugins/undo/plugin.js +578 -0
  165. data/app/assets/javascripts/esp-ckeditor/_source/plugins/wysiwygarea/plugin.js +1347 -0
  166. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/dialog.css +988 -0
  167. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/editor.css +25 -0
  168. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/elementspath.css +73 -0
  169. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/icons.css +367 -0
  170. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/icons.png +0 -0
  171. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/icons_rtl.png +0 -0
  172. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/images/dialog_sides.gif +0 -0
  173. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/images/dialog_sides.png +0 -0
  174. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/images/dialog_sides_rtl.png +0 -0
  175. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/images/mini.gif +0 -0
  176. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/images/noimage.png +0 -0
  177. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/images/sprites.png +0 -0
  178. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/images/sprites_ie6.png +0 -0
  179. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/images/toolbar_start.gif +0 -0
  180. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/mainui.css +209 -0
  181. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/menu.css +232 -0
  182. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/panel.css +227 -0
  183. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/presets.css +49 -0
  184. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/reset.css +85 -0
  185. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/richcombo.css +287 -0
  186. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/skin.js +236 -0
  187. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/templates.css +88 -0
  188. data/app/assets/javascripts/esp-ckeditor/_source/skins/kama/toolbar.css +412 -0
  189. data/app/assets/javascripts/esp-ckeditor/_source/themes/default/theme.js +407 -0
  190. data/app/assets/javascripts/esp-ckeditor/application.js +8 -0
  191. data/app/assets/javascripts/esp-ckeditor/ckeditor.js +137 -0
  192. data/app/assets/javascripts/esp-ckeditor/ckeditor.pack +194 -0
  193. data/app/assets/javascripts/esp-ckeditor/ckeditor_source.js +35 -0
  194. data/app/assets/javascripts/esp-ckeditor/ckpackager.jar +0 -0
  195. data/app/assets/javascripts/esp-ckeditor/ckpackager.txt +2 -0
  196. data/app/assets/javascripts/esp-ckeditor/config.js +147 -0
  197. data/app/assets/javascripts/esp-ckeditor/contents.css +38 -0
  198. data/app/assets/javascripts/esp-ckeditor/images/spacer.gif +0 -0
  199. data/app/assets/javascripts/esp-ckeditor/init_ckeditor.js +1 -0
  200. data/app/assets/javascripts/esp-ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js +1 -0
  201. data/app/assets/javascripts/esp-ckeditor/plugins/a11yhelp/lang/en.js +1 -0
  202. data/app/assets/javascripts/esp-ckeditor/plugins/a11yhelp/lang/he.js +1 -0
  203. data/app/assets/javascripts/esp-ckeditor/plugins/a11yhelp/plugin.js +1 -0
  204. data/app/assets/javascripts/esp-ckeditor/plugins/basicstyles/plugin.js +1 -0
  205. data/app/assets/javascripts/esp-ckeditor/plugins/button/plugin.js +1 -0
  206. data/app/assets/javascripts/esp-ckeditor/plugins/clipboard/dialogs/paste.js +1 -0
  207. data/app/assets/javascripts/esp-ckeditor/plugins/clipboard/plugin.js +1 -0
  208. data/app/assets/javascripts/esp-ckeditor/plugins/contextmenu/plugin.js +1 -0
  209. data/app/assets/javascripts/esp-ckeditor/plugins/dialog/dialogDefinition.js +0 -0
  210. data/app/assets/javascripts/esp-ckeditor/plugins/dialog/plugin.js +1 -0
  211. data/app/assets/javascripts/esp-ckeditor/plugins/dialogadvtab/plugin.js +1 -0
  212. data/app/assets/javascripts/esp-ckeditor/plugins/dialogui/plugin.js +1 -0
  213. data/app/assets/javascripts/esp-ckeditor/plugins/domiterator/plugin.js +1 -0
  214. data/app/assets/javascripts/esp-ckeditor/plugins/editingblock/plugin.js +1 -0
  215. data/app/assets/javascripts/esp-ckeditor/plugins/elementspath/plugin.js +1 -0
  216. data/app/assets/javascripts/esp-ckeditor/plugins/enterkey/plugin.js +1 -0
  217. data/app/assets/javascripts/esp-ckeditor/plugins/entities/plugin.js +1 -0
  218. data/app/assets/javascripts/esp-ckeditor/plugins/esp_attachment/dialogs/esp_attachment.js +1 -0
  219. data/app/assets/javascripts/esp-ckeditor/plugins/esp_attachment/images/esp_attachment.png +0 -0
  220. data/app/assets/javascripts/esp-ckeditor/plugins/esp_attachment/lang/en.js +1 -0
  221. data/app/assets/javascripts/esp-ckeditor/plugins/esp_attachment/lang/ru.js +1 -0
  222. data/app/assets/javascripts/esp-ckeditor/plugins/esp_attachment/lang/uk.js +1 -0
  223. data/app/assets/javascripts/esp-ckeditor/plugins/esp_attachment/plugin.js +1 -0
  224. data/app/assets/javascripts/esp-ckeditor/plugins/esp_audio/dialogs/esp_audio.js +1 -0
  225. data/app/assets/javascripts/esp-ckeditor/plugins/esp_audio/images/esp_audio.png +0 -0
  226. data/app/assets/javascripts/esp-ckeditor/plugins/esp_audio/images/placeholder.png +0 -0
  227. data/app/assets/javascripts/esp-ckeditor/plugins/esp_audio/lang/en.js +1 -0
  228. data/app/assets/javascripts/esp-ckeditor/plugins/esp_audio/lang/ru.js +1 -0
  229. data/app/assets/javascripts/esp-ckeditor/plugins/esp_audio/lang/uk.js +1 -0
  230. data/app/assets/javascripts/esp-ckeditor/plugins/esp_audio/plugin.js +1 -0
  231. data/app/assets/javascripts/esp-ckeditor/plugins/esp_blockquote/dialogs/esp_blockquote.js +1 -0
  232. data/app/assets/javascripts/esp-ckeditor/plugins/esp_blockquote/plugin.js +1 -0
  233. data/app/assets/javascripts/esp-ckeditor/plugins/esp_image/dialogs/esp_image.js +1 -0
  234. data/app/assets/javascripts/esp-ckeditor/plugins/esp_image/images/esp_image.png +0 -0
  235. data/app/assets/javascripts/esp-ckeditor/plugins/esp_image/lang/en.js +1 -0
  236. data/app/assets/javascripts/esp-ckeditor/plugins/esp_image/lang/ru.js +1 -0
  237. data/app/assets/javascripts/esp-ckeditor/plugins/esp_image/lang/uk.js +1 -0
  238. data/app/assets/javascripts/esp-ckeditor/plugins/esp_image/plugin.js +1 -0
  239. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/dialogs/esp_anchor.js +1 -0
  240. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/dialogs/esp_link.js +1 -0
  241. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/images/anchor.png +0 -0
  242. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/images/esp_anchor.png +0 -0
  243. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/images/esp_link.png +0 -0
  244. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/images/esp_unlink.png +0 -0
  245. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/lang/en.js +1 -0
  246. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/lang/ru.js +1 -0
  247. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/lang/uk.js +1 -0
  248. data/app/assets/javascripts/esp-ckeditor/plugins/esp_link/plugin.js +1 -0
  249. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_address.png +0 -0
  250. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_blockquote.png +0 -0
  251. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_div.png +0 -0
  252. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_h1.png +0 -0
  253. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_h2.png +0 -0
  254. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_h3.png +0 -0
  255. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_h4.png +0 -0
  256. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_h5.png +0 -0
  257. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_h6.png +0 -0
  258. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_p.png +0 -0
  259. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/block_pre.png +0 -0
  260. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/images/esp_showblocks.png +0 -0
  261. data/app/assets/javascripts/esp-ckeditor/plugins/esp_showblocks/plugin.js +1 -0
  262. data/app/assets/javascripts/esp-ckeditor/plugins/esp_video/dialogs/esp_video.js +1 -0
  263. data/app/assets/javascripts/esp-ckeditor/plugins/esp_video/images/esp_video.png +0 -0
  264. data/app/assets/javascripts/esp-ckeditor/plugins/esp_video/images/placeholder.png +0 -0
  265. data/app/assets/javascripts/esp-ckeditor/plugins/esp_video/lang/en.js +1 -0
  266. data/app/assets/javascripts/esp-ckeditor/plugins/esp_video/lang/ru.js +1 -0
  267. data/app/assets/javascripts/esp-ckeditor/plugins/esp_video/lang/uk.js +1 -0
  268. data/app/assets/javascripts/esp-ckeditor/plugins/esp_video/plugin.js +1 -0
  269. data/app/assets/javascripts/esp-ckeditor/plugins/fakeobjects/plugin.js +1 -0
  270. data/app/assets/javascripts/esp-ckeditor/plugins/filebrowser/plugin.js +1 -0
  271. data/app/assets/javascripts/esp-ckeditor/plugins/find/dialogs/find.js +1 -0
  272. data/app/assets/javascripts/esp-ckeditor/plugins/find/plugin.js +1 -0
  273. data/app/assets/javascripts/esp-ckeditor/plugins/floatpanel/plugin.js +1 -0
  274. data/app/assets/javascripts/esp-ckeditor/plugins/format/plugin.js +1 -0
  275. data/app/assets/javascripts/esp-ckeditor/plugins/htmldataprocessor/plugin.js +1 -0
  276. data/app/assets/javascripts/esp-ckeditor/plugins/htmlwriter/plugin.js +1 -0
  277. data/app/assets/javascripts/esp-ckeditor/plugins/image/dialogs/image.js +1 -0
  278. data/app/assets/javascripts/esp-ckeditor/plugins/image/plugin.js +1 -0
  279. data/app/assets/javascripts/esp-ckeditor/plugins/indent/plugin.js +1 -0
  280. data/app/assets/javascripts/esp-ckeditor/plugins/justify/plugin.js +1 -0
  281. data/app/assets/javascripts/esp-ckeditor/plugins/keystrokes/plugin.js +1 -0
  282. data/app/assets/javascripts/esp-ckeditor/plugins/list/plugin.js +1 -0
  283. data/app/assets/javascripts/esp-ckeditor/plugins/listblock/plugin.js +1 -0
  284. data/app/assets/javascripts/esp-ckeditor/plugins/liststyle/dialogs/liststyle.js +1 -0
  285. data/app/assets/javascripts/esp-ckeditor/plugins/liststyle/plugin.js +1 -0
  286. data/app/assets/javascripts/esp-ckeditor/plugins/maximize/plugin.js +1 -0
  287. data/app/assets/javascripts/esp-ckeditor/plugins/menu/plugin.js +1 -0
  288. data/app/assets/javascripts/esp-ckeditor/plugins/panel/plugin.js +1 -0
  289. data/app/assets/javascripts/esp-ckeditor/plugins/pastefromword/filter/default.js +1 -0
  290. data/app/assets/javascripts/esp-ckeditor/plugins/pastefromword/plugin.js +1 -0
  291. data/app/assets/javascripts/esp-ckeditor/plugins/pastetext/dialogs/pastetext.js +1 -0
  292. data/app/assets/javascripts/esp-ckeditor/plugins/pastetext/plugin.js +1 -0
  293. data/app/assets/javascripts/esp-ckeditor/plugins/popup/plugin.js +1 -0
  294. data/app/assets/javascripts/esp-ckeditor/plugins/removeformat/plugin.js +1 -0
  295. data/app/assets/javascripts/esp-ckeditor/plugins/resize/plugin.js +1 -0
  296. data/app/assets/javascripts/esp-ckeditor/plugins/richcombo/plugin.js +1 -0
  297. data/app/assets/javascripts/esp-ckeditor/plugins/selection/plugin.js +1 -0
  298. data/app/assets/javascripts/esp-ckeditor/plugins/showborders/plugin.js +1 -0
  299. data/app/assets/javascripts/esp-ckeditor/plugins/sourcearea/plugin.js +1 -0
  300. data/app/assets/javascripts/esp-ckeditor/plugins/styles/plugin.js +1 -0
  301. data/app/assets/javascripts/esp-ckeditor/plugins/styles/styles/default.js +1 -0
  302. data/app/assets/javascripts/esp-ckeditor/plugins/stylescombo/plugin.js +1 -0
  303. data/app/assets/javascripts/esp-ckeditor/plugins/tab/plugin.js +1 -0
  304. data/app/assets/javascripts/esp-ckeditor/plugins/table/dialogs/table.js +1 -0
  305. data/app/assets/javascripts/esp-ckeditor/plugins/table/plugin.js +1 -0
  306. data/app/assets/javascripts/esp-ckeditor/plugins/tabletools/dialogs/tableCell.js +1 -0
  307. data/app/assets/javascripts/esp-ckeditor/plugins/tabletools/plugin.js +1 -0
  308. data/app/assets/javascripts/esp-ckeditor/plugins/toolbar/plugin.js +1 -0
  309. data/app/assets/javascripts/esp-ckeditor/plugins/undo/plugin.js +1 -0
  310. data/app/assets/javascripts/esp-ckeditor/plugins/wysiwygarea/plugin.js +1 -0
  311. data/app/assets/javascripts/esp-ckeditor/skins/kama/dialog.css +988 -0
  312. data/app/assets/javascripts/esp-ckeditor/skins/kama/editor.css +25 -0
  313. data/app/assets/javascripts/esp-ckeditor/skins/kama/elementspath.css +73 -0
  314. data/app/assets/javascripts/esp-ckeditor/skins/kama/icons.css +367 -0
  315. data/app/assets/javascripts/esp-ckeditor/skins/kama/icons.png +0 -0
  316. data/app/assets/javascripts/esp-ckeditor/skins/kama/icons_rtl.png +0 -0
  317. data/app/assets/javascripts/esp-ckeditor/skins/kama/images/dialog_sides.gif +0 -0
  318. data/app/assets/javascripts/esp-ckeditor/skins/kama/images/dialog_sides.png +0 -0
  319. data/app/assets/javascripts/esp-ckeditor/skins/kama/images/dialog_sides_rtl.png +0 -0
  320. data/app/assets/javascripts/esp-ckeditor/skins/kama/images/mini.gif +0 -0
  321. data/app/assets/javascripts/esp-ckeditor/skins/kama/images/noimage.png +0 -0
  322. data/app/assets/javascripts/esp-ckeditor/skins/kama/images/sprites.png +0 -0
  323. data/app/assets/javascripts/esp-ckeditor/skins/kama/images/sprites_ie6.png +0 -0
  324. data/app/assets/javascripts/esp-ckeditor/skins/kama/images/toolbar_start.gif +0 -0
  325. data/app/assets/javascripts/esp-ckeditor/skins/kama/mainui.css +209 -0
  326. data/app/assets/javascripts/esp-ckeditor/skins/kama/menu.css +232 -0
  327. data/app/assets/javascripts/esp-ckeditor/skins/kama/panel.css +227 -0
  328. data/app/assets/javascripts/esp-ckeditor/skins/kama/presets.css +49 -0
  329. data/app/assets/javascripts/esp-ckeditor/skins/kama/reset.css +85 -0
  330. data/app/assets/javascripts/esp-ckeditor/skins/kama/richcombo.css +287 -0
  331. data/app/assets/javascripts/esp-ckeditor/skins/kama/skin.js +236 -0
  332. data/app/assets/javascripts/esp-ckeditor/skins/kama/templates.css +88 -0
  333. data/app/assets/javascripts/esp-ckeditor/skins/kama/toolbar.css +412 -0
  334. data/app/inputs/ckeditor_input.rb +42 -0
  335. data/config/routes.rb +2 -0
  336. data/lib/esp-ckeditor/engine.rb +9 -0
  337. data/lib/esp-ckeditor/version.rb +3 -0
  338. data/lib/esp-ckeditor.rb +17 -0
  339. data/lib/tasks/esp-ckeditor_tasks.rake +4 -0
  340. metadata +434 -0
@@ -0,0 +1,1729 @@
1
+ /*
2
+ Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3
+ For licensing, see LICENSE.html or http://ckeditor.com/license
4
+ */
5
+
6
+ (function()
7
+ {
8
+ // #### checkSelectionChange : START
9
+
10
+ // The selection change check basically saves the element parent tree of
11
+ // the current node and check it on successive requests. If there is any
12
+ // change on the tree, then the selectionChange event gets fired.
13
+ function checkSelectionChange()
14
+ {
15
+ try
16
+ {
17
+ // In IE, the "selectionchange" event may still get thrown when
18
+ // releasing the WYSIWYG mode, so we need to check it first.
19
+ var sel = this.getSelection();
20
+ if ( !sel || !sel.document.getWindow().$ )
21
+ return;
22
+
23
+ var firstElement = sel.getStartElement();
24
+ var currentPath = new CKEDITOR.dom.elementPath( firstElement );
25
+
26
+ if ( !currentPath.compare( this._.selectionPreviousPath ) )
27
+ {
28
+ this._.selectionPreviousPath = currentPath;
29
+ this.fire( 'selectionChange', { selection : sel, path : currentPath, element : firstElement } );
30
+ }
31
+ }
32
+ catch (e)
33
+ {}
34
+ }
35
+
36
+ var checkSelectionChangeTimer,
37
+ checkSelectionChangeTimeoutPending;
38
+
39
+ function checkSelectionChangeTimeout()
40
+ {
41
+ // Firing the "OnSelectionChange" event on every key press started to
42
+ // be too slow. This function guarantees that there will be at least
43
+ // 200ms delay between selection checks.
44
+
45
+ checkSelectionChangeTimeoutPending = true;
46
+
47
+ if ( checkSelectionChangeTimer )
48
+ return;
49
+
50
+ checkSelectionChangeTimeoutExec.call( this );
51
+
52
+ checkSelectionChangeTimer = CKEDITOR.tools.setTimeout( checkSelectionChangeTimeoutExec, 200, this );
53
+ }
54
+
55
+ function checkSelectionChangeTimeoutExec()
56
+ {
57
+ checkSelectionChangeTimer = null;
58
+
59
+ if ( checkSelectionChangeTimeoutPending )
60
+ {
61
+ // Call this with a timeout so the browser properly moves the
62
+ // selection after the mouseup. It happened that the selection was
63
+ // being moved after the mouseup when clicking inside selected text
64
+ // with Firefox.
65
+ CKEDITOR.tools.setTimeout( checkSelectionChange, 0, this );
66
+
67
+ checkSelectionChangeTimeoutPending = false;
68
+ }
69
+ }
70
+
71
+ // #### checkSelectionChange : END
72
+
73
+ function rangeRequiresFix( range )
74
+ {
75
+ function isInlineCt( node )
76
+ {
77
+ return node && node.type == CKEDITOR.NODE_ELEMENT
78
+ && node.getName() in CKEDITOR.dtd.$removeEmpty;
79
+ }
80
+
81
+ function singletonBlock( node )
82
+ {
83
+ var body = range.document.getBody();
84
+ return !node.is( 'body' ) && body.getChildCount() == 1;
85
+ }
86
+
87
+ var start = range.startContainer,
88
+ offset = range.startOffset;
89
+
90
+ if ( start.type == CKEDITOR.NODE_TEXT )
91
+ return false;
92
+
93
+ // 1. Empty inline element. <span>^</span>
94
+ // 2. Adjoin to inline element. <p><strong>text</strong>^</p>
95
+ // 3. The only empty block in document. <body><p>^</p></body> (#7222)
96
+ return !CKEDITOR.tools.trim( start.getHtml() ) ? isInlineCt( start ) || singletonBlock( start )
97
+ : isInlineCt( start.getChild( offset - 1 ) ) || isInlineCt( start.getChild( offset ) );
98
+ }
99
+
100
+ var selectAllCmd =
101
+ {
102
+ modes : { wysiwyg : 1, source : 1 },
103
+ readOnly : CKEDITOR.env.ie || CKEDITOR.env.webkit,
104
+ exec : function( editor )
105
+ {
106
+ switch ( editor.mode )
107
+ {
108
+ case 'wysiwyg' :
109
+ editor.document.$.execCommand( 'SelectAll', false, null );
110
+ // Force triggering selectionChange (#7008)
111
+ editor.forceNextSelectionCheck();
112
+ editor.selectionChange();
113
+ break;
114
+ case 'source' :
115
+ // Select the contents of the textarea
116
+ var textarea = editor.textarea.$;
117
+ if ( CKEDITOR.env.ie )
118
+ textarea.createTextRange().execCommand( 'SelectAll' );
119
+ else
120
+ {
121
+ textarea.selectionStart = 0;
122
+ textarea.selectionEnd = textarea.value.length;
123
+ }
124
+ textarea.focus();
125
+ }
126
+ },
127
+ canUndo : false
128
+ };
129
+
130
+ function createFillingChar( doc )
131
+ {
132
+ removeFillingChar( doc );
133
+
134
+ var fillingChar = doc.createText( '\u200B' );
135
+ doc.setCustomData( 'cke-fillingChar', fillingChar );
136
+
137
+ return fillingChar;
138
+ }
139
+
140
+ function getFillingChar( doc )
141
+ {
142
+ return doc && doc.getCustomData( 'cke-fillingChar' );
143
+ }
144
+
145
+ // Checks if a filling char has been used, eventualy removing it (#1272).
146
+ function checkFillingChar( doc )
147
+ {
148
+ var fillingChar = doc && getFillingChar( doc );
149
+ if ( fillingChar )
150
+ {
151
+ // Use this flag to avoid removing the filling char right after
152
+ // creating it.
153
+ if ( fillingChar.getCustomData( 'ready' ) )
154
+ removeFillingChar( doc );
155
+ else
156
+ fillingChar.setCustomData( 'ready', 1 );
157
+ }
158
+ }
159
+
160
+ function removeFillingChar( doc )
161
+ {
162
+ var fillingChar = doc && doc.removeCustomData( 'cke-fillingChar' );
163
+ if ( fillingChar )
164
+ {
165
+ // We can't simply remove the filling node because the user
166
+ // will actually enlarge it when typing, so we just remove the
167
+ // invisible char from it.
168
+ fillingChar.setText( fillingChar.getText().replace( /\u200B/g, '' ) );
169
+ fillingChar = 0;
170
+ }
171
+ }
172
+
173
+ CKEDITOR.plugins.add( 'selection',
174
+ {
175
+ init : function( editor )
176
+ {
177
+ // On WebKit only, we need a special "filling" char on some situations
178
+ // (#1272). Here we set the events that should invalidate that char.
179
+ if ( CKEDITOR.env.webkit )
180
+ {
181
+ editor.on( 'selectionChange', function() { checkFillingChar( editor.document ); } );
182
+ editor.on( 'beforeSetMode', function() { removeFillingChar( editor.document ); } );
183
+ editor.on( 'key', function( e )
184
+ {
185
+ // Remove the filling char before some keys get
186
+ // executed, so they'll not get blocked by it.
187
+ switch ( e.data.keyCode )
188
+ {
189
+ case 13 : // ENTER
190
+ case CKEDITOR.SHIFT + 13 : // SHIFT-ENTER
191
+ case 37 : // LEFT-ARROW
192
+ case 39 : // RIGHT-ARROW
193
+ case 8 : // BACKSPACE
194
+ removeFillingChar( editor.document );
195
+ }
196
+ }, null, null, 10 );
197
+
198
+ var fillingCharBefore,
199
+ resetSelection;
200
+
201
+ function beforeData()
202
+ {
203
+ var doc = editor.document,
204
+ fillingChar = getFillingChar( doc );
205
+
206
+ if ( fillingChar )
207
+ {
208
+ // If cursor is right blinking by side of the filler node, save it for restoring,
209
+ // as the following text substitution will blind it. (#7437)
210
+ var sel = doc.$.defaultView.getSelection();
211
+ if ( sel.type == 'Caret' && sel.anchorNode == fillingChar.$ )
212
+ resetSelection = 1;
213
+
214
+ fillingCharBefore = fillingChar.getText();
215
+ fillingChar.setText( fillingCharBefore.replace( /\u200B/g, '' ) );
216
+ }
217
+ }
218
+ function afterData()
219
+ {
220
+ var doc = editor.document,
221
+ fillingChar = getFillingChar( doc );
222
+
223
+ if ( fillingChar )
224
+ {
225
+ fillingChar.setText( fillingCharBefore );
226
+
227
+ if ( resetSelection )
228
+ {
229
+ doc.$.defaultView.getSelection().setPosition( fillingChar.$,fillingChar.getLength() );
230
+ resetSelection = 0;
231
+ }
232
+ }
233
+ }
234
+ editor.on( 'beforeUndoImage', beforeData );
235
+ editor.on( 'afterUndoImage', afterData );
236
+ editor.on( 'beforeGetData', beforeData, null, null, 0 );
237
+ editor.on( 'getData', afterData );
238
+ }
239
+
240
+ editor.on( 'contentDom', function()
241
+ {
242
+ var doc = editor.document,
243
+ body = doc.getBody(),
244
+ html = doc.getDocumentElement();
245
+
246
+ if ( CKEDITOR.env.ie )
247
+ {
248
+ // Other browsers don't loose the selection if the
249
+ // editor document loose the focus. In IE, we don't
250
+ // have support for it, so we reproduce it here, other
251
+ // than firing the selection change event.
252
+
253
+ var savedRange,
254
+ saveEnabled,
255
+ restoreEnabled = 1;
256
+
257
+ // "onfocusin" is fired before "onfocus". It makes it
258
+ // possible to restore the selection before click
259
+ // events get executed.
260
+ body.on( 'focusin', function( evt )
261
+ {
262
+ // If there are elements with layout they fire this event but
263
+ // it must be ignored to allow edit its contents #4682
264
+ if ( evt.data.$.srcElement.nodeName != 'BODY' )
265
+ return;
266
+
267
+ // If we have saved a range, restore it at this
268
+ // point.
269
+ if ( savedRange )
270
+ {
271
+ if ( restoreEnabled )
272
+ {
273
+ // Well not break because of this.
274
+ try
275
+ {
276
+ savedRange.select();
277
+ }
278
+ catch (e)
279
+ {}
280
+
281
+ // Update locked selection because of the normalized text nodes. (#6083, #6987)
282
+ var lockedSelection = doc.getCustomData( 'cke_locked_selection' );
283
+ if ( lockedSelection )
284
+ {
285
+ lockedSelection.unlock();
286
+ lockedSelection.lock();
287
+ }
288
+ }
289
+
290
+ savedRange = null;
291
+ }
292
+ });
293
+
294
+ body.on( 'focus', function()
295
+ {
296
+ // Enable selections to be saved.
297
+ saveEnabled = 1;
298
+
299
+ saveSelection();
300
+ });
301
+
302
+ body.on( 'beforedeactivate', function( evt )
303
+ {
304
+ // Ignore this event if it's caused by focus switch between
305
+ // internal editable control type elements, e.g. layouted paragraph. (#4682)
306
+ if ( evt.data.$.toElement )
307
+ return;
308
+
309
+ // Disable selections from being saved.
310
+ saveEnabled = 0;
311
+ restoreEnabled = 1;
312
+ });
313
+
314
+ // IE before version 8 will leave cursor blinking inside the document after
315
+ // editor blurred unless we clean up the selection. (#4716)
316
+ if ( CKEDITOR.env.ie && CKEDITOR.env.version < 8 )
317
+ {
318
+ editor.on( 'blur', function( evt )
319
+ {
320
+ // Try/Catch to avoid errors if the editor is hidden. (#6375)
321
+ try
322
+ {
323
+ editor.document && editor.document.$.selection.empty();
324
+ }
325
+ catch (e) {}
326
+ });
327
+ }
328
+
329
+ // Listening on document element ensures that
330
+ // scrollbar is included. (#5280)
331
+ html.on( 'mousedown', function()
332
+ {
333
+ // Lock restore selection now, as we have
334
+ // a followed 'click' event which introduce
335
+ // new selection. (#5735)
336
+ restoreEnabled = 0;
337
+ });
338
+
339
+ html.on( 'mouseup', function()
340
+ {
341
+ restoreEnabled = 1;
342
+ });
343
+
344
+ // In IE6/7 the blinking cursor appears, but contents are
345
+ // not editable. (#5634)
346
+ if ( CKEDITOR.env.ie && ( CKEDITOR.env.ie7Compat || CKEDITOR.env.version < 8 || CKEDITOR.env.quirks ) )
347
+ {
348
+ // The 'click' event is not fired when clicking the
349
+ // scrollbars, so we can use it to check whether
350
+ // the empty space following <body> has been clicked.
351
+ html.on( 'click', function( evt )
352
+ {
353
+ if ( evt.data.getTarget().getName() == 'html' )
354
+ editor.getSelection().getRanges()[ 0 ].select();
355
+ });
356
+ }
357
+
358
+ var scroll;
359
+ // IE fires the "selectionchange" event when clicking
360
+ // inside a selection. We don't want to capture that.
361
+ body.on( 'mousedown', function( evt )
362
+ {
363
+ // IE scrolls document to top on right mousedown
364
+ // when editor has no focus, remember this scroll
365
+ // position and revert it before context menu opens. (#5778)
366
+ if ( evt.data.$.button == 2 )
367
+ {
368
+ var sel = editor.document.$.selection;
369
+ if ( sel.type == 'None' )
370
+ scroll = editor.window.getScrollPosition();
371
+ }
372
+ disableSave();
373
+ });
374
+
375
+ body.on( 'mouseup',
376
+ function( evt )
377
+ {
378
+ // Restore recorded scroll position when needed on right mouseup.
379
+ if ( evt.data.$.button == 2 && scroll )
380
+ {
381
+ editor.document.$.documentElement.scrollLeft = scroll.x;
382
+ editor.document.$.documentElement.scrollTop = scroll.y;
383
+ }
384
+ scroll = null;
385
+
386
+ saveEnabled = 1;
387
+ setTimeout( function()
388
+ {
389
+ saveSelection( true );
390
+ },
391
+ 0 );
392
+ });
393
+
394
+ body.on( 'keydown', disableSave );
395
+ body.on( 'keyup',
396
+ function()
397
+ {
398
+ saveEnabled = 1;
399
+ saveSelection();
400
+ });
401
+
402
+
403
+ // IE is the only to provide the "selectionchange"
404
+ // event.
405
+ doc.on( 'selectionchange', saveSelection );
406
+
407
+ function disableSave()
408
+ {
409
+ saveEnabled = 0;
410
+ }
411
+
412
+ function saveSelection( testIt )
413
+ {
414
+ if ( saveEnabled )
415
+ {
416
+ var doc = editor.document,
417
+ sel = editor.getSelection(),
418
+ nativeSel = sel && sel.getNative();
419
+
420
+ // There is a very specific case, when clicking
421
+ // inside a text selection. In that case, the
422
+ // selection collapses at the clicking point,
423
+ // but the selection object remains in an
424
+ // unknown state, making createRange return a
425
+ // range at the very start of the document. In
426
+ // such situation we have to test the range, to
427
+ // be sure it's valid.
428
+ if ( testIt && nativeSel && nativeSel.type == 'None' )
429
+ {
430
+ // The "InsertImage" command can be used to
431
+ // test whether the selection is good or not.
432
+ // If not, it's enough to give some time to
433
+ // IE to put things in order for us.
434
+ if ( !doc.$.queryCommandEnabled( 'InsertImage' ) )
435
+ {
436
+ CKEDITOR.tools.setTimeout( saveSelection, 50, this, true );
437
+ return;
438
+ }
439
+ }
440
+
441
+ // Avoid saving selection from within text input. (#5747)
442
+ var parentTag;
443
+ if ( nativeSel && nativeSel.type && nativeSel.type != 'Control'
444
+ && ( parentTag = nativeSel.createRange() )
445
+ && ( parentTag = parentTag.parentElement() )
446
+ && ( parentTag = parentTag.nodeName )
447
+ && parentTag.toLowerCase() in { input: 1, textarea : 1 } )
448
+ {
449
+ return;
450
+ }
451
+
452
+ savedRange = nativeSel && sel.getRanges()[ 0 ];
453
+
454
+ checkSelectionChangeTimeout.call( editor );
455
+ }
456
+ }
457
+ }
458
+ else
459
+ {
460
+ // In other browsers, we make the selection change
461
+ // check based on other events, like clicks or keys
462
+ // press.
463
+
464
+ doc.on( 'mouseup', checkSelectionChangeTimeout, editor );
465
+ doc.on( 'keyup', checkSelectionChangeTimeout, editor );
466
+ doc.on( 'selectionchange', checkSelectionChangeTimeout, editor );
467
+ }
468
+ });
469
+
470
+ // Clear the cached range path before unload. (#7174)
471
+ editor.on( 'contentDomUnload', editor.forceNextSelectionCheck, editor );
472
+
473
+ editor.addCommand( 'selectAll', selectAllCmd );
474
+ editor.ui.addButton( 'SelectAll',
475
+ {
476
+ label : editor.lang.selectAll,
477
+ command : 'selectAll'
478
+ });
479
+
480
+ editor.selectionChange = checkSelectionChangeTimeout;
481
+
482
+ // IE9 might cease to work if there's an object selection inside the iframe (#7639).
483
+ CKEDITOR.env.ie9Compat && editor.on( 'destroy', function()
484
+ {
485
+ var sel = editor.getSelection();
486
+ sel && sel.getNative().clear();
487
+ }, null, null, 9 );
488
+ }
489
+ });
490
+
491
+ /**
492
+ * Gets the current selection from the editing area when in WYSIWYG mode.
493
+ * @returns {CKEDITOR.dom.selection} A selection object or null if not in
494
+ * WYSIWYG mode or no selection is available.
495
+ * @example
496
+ * var selection = CKEDITOR.instances.editor1.<strong>getSelection()</strong>;
497
+ * alert( selection.getType() );
498
+ */
499
+ CKEDITOR.editor.prototype.getSelection = function()
500
+ {
501
+ return this.document && this.document.getSelection();
502
+ };
503
+
504
+ CKEDITOR.editor.prototype.forceNextSelectionCheck = function()
505
+ {
506
+ delete this._.selectionPreviousPath;
507
+ };
508
+
509
+ /**
510
+ * Gets the current selection from the document.
511
+ * @returns {CKEDITOR.dom.selection} A selection object.
512
+ * @example
513
+ * var selection = CKEDITOR.instances.editor1.document.<strong>getSelection()</strong>;
514
+ * alert( selection.getType() );
515
+ */
516
+ CKEDITOR.dom.document.prototype.getSelection = function()
517
+ {
518
+ var sel = new CKEDITOR.dom.selection( this );
519
+ return ( !sel || sel.isInvalid ) ? null : sel;
520
+ };
521
+
522
+ /**
523
+ * No selection.
524
+ * @constant
525
+ * @example
526
+ * if ( editor.getSelection().getType() == CKEDITOR.SELECTION_NONE )
527
+ * alert( 'Nothing is selected' );
528
+ */
529
+ CKEDITOR.SELECTION_NONE = 1;
530
+
531
+ /**
532
+ * A text or a collapsed selection.
533
+ * @constant
534
+ * @example
535
+ * if ( editor.getSelection().getType() == CKEDITOR.SELECTION_TEXT )
536
+ * alert( 'A text is selected' );
537
+ */
538
+ CKEDITOR.SELECTION_TEXT = 2;
539
+
540
+ /**
541
+ * Element selection.
542
+ * @constant
543
+ * @example
544
+ * if ( editor.getSelection().getType() == CKEDITOR.SELECTION_ELEMENT )
545
+ * alert( 'An element is selected' );
546
+ */
547
+ CKEDITOR.SELECTION_ELEMENT = 3;
548
+
549
+ /**
550
+ * Manipulates the selection in a DOM document.
551
+ * @constructor
552
+ * @param {CKEDITOR.dom.document} document The DOM document that contains the selection.
553
+ * @example
554
+ * var sel = new <strong>CKEDITOR.dom.selection( CKEDITOR.document )</strong>;
555
+ */
556
+ CKEDITOR.dom.selection = function( document )
557
+ {
558
+ var lockedSelection = document.getCustomData( 'cke_locked_selection' );
559
+
560
+ if ( lockedSelection )
561
+ return lockedSelection;
562
+
563
+ this.document = document;
564
+ this.isLocked = 0;
565
+ this._ =
566
+ {
567
+ cache : {}
568
+ };
569
+
570
+ /**
571
+ * IE BUG: The selection's document may be a different document than the
572
+ * editor document. Return null if that is the case.
573
+ */
574
+ if ( CKEDITOR.env.ie )
575
+ {
576
+ var range = this.getNative().createRange();
577
+ if ( !range
578
+ || ( range.item && range.item(0).ownerDocument != this.document.$ )
579
+ || ( range.parentElement && range.parentElement().ownerDocument != this.document.$ ) )
580
+ {
581
+ this.isInvalid = true;
582
+ }
583
+ }
584
+
585
+ return this;
586
+ };
587
+
588
+ var styleObjectElements =
589
+ {
590
+ img:1,hr:1,li:1,table:1,tr:1,td:1,th:1,embed:1,object:1,ol:1,ul:1,
591
+ a:1,input:1,form:1,select:1,textarea:1,button:1,fieldset:1,thead:1,tfoot:1
592
+ };
593
+
594
+ CKEDITOR.dom.selection.prototype =
595
+ {
596
+ /**
597
+ * Gets the native selection object from the browser.
598
+ * @function
599
+ * @returns {Object} The native browser selection object.
600
+ * @example
601
+ * var selection = editor.getSelection().<strong>getNative()</strong>;
602
+ */
603
+ getNative :
604
+ CKEDITOR.env.ie ?
605
+ function()
606
+ {
607
+ return this._.cache.nativeSel || ( this._.cache.nativeSel = this.document.$.selection );
608
+ }
609
+ :
610
+ function()
611
+ {
612
+ return this._.cache.nativeSel || ( this._.cache.nativeSel = this.document.getWindow().$.getSelection() );
613
+ },
614
+
615
+ /**
616
+ * Gets the type of the current selection. The following values are
617
+ * available:
618
+ * <ul>
619
+ * <li><code>{@link CKEDITOR.SELECTION_NONE}</code> (1): No selection.</li>
620
+ * <li><code>{@link CKEDITOR.SELECTION_TEXT}</code> (2): A text or a collapsed
621
+ * selection is selected.</li>
622
+ * <li><code>{@link CKEDITOR.SELECTION_ELEMENT}</code> (3): An element is
623
+ * selected.</li>
624
+ * </ul>
625
+ * @function
626
+ * @returns {Number} One of the following constant values:
627
+ * <code>{@link CKEDITOR.SELECTION_NONE}</code>, <code>{@link CKEDITOR.SELECTION_TEXT}</code>, or
628
+ * <code>{@link CKEDITOR.SELECTION_ELEMENT}</code>.
629
+ * @example
630
+ * if ( editor.getSelection().<strong>getType()</strong> == CKEDITOR.SELECTION_TEXT )
631
+ * alert( 'A text is selected' );
632
+ */
633
+ getType :
634
+ CKEDITOR.env.ie ?
635
+ function()
636
+ {
637
+ var cache = this._.cache;
638
+ if ( cache.type )
639
+ return cache.type;
640
+
641
+ var type = CKEDITOR.SELECTION_NONE;
642
+
643
+ try
644
+ {
645
+ var sel = this.getNative(),
646
+ ieType = sel.type;
647
+
648
+ if ( ieType == 'Text' )
649
+ type = CKEDITOR.SELECTION_TEXT;
650
+
651
+ if ( ieType == 'Control' )
652
+ type = CKEDITOR.SELECTION_ELEMENT;
653
+
654
+ // It is possible that we can still get a text range
655
+ // object even when type == 'None' is returned by IE.
656
+ // So we'd better check the object returned by
657
+ // createRange() rather than by looking at the type.
658
+ if ( sel.createRange().parentElement )
659
+ type = CKEDITOR.SELECTION_TEXT;
660
+ }
661
+ catch(e) {}
662
+
663
+ return ( cache.type = type );
664
+ }
665
+ :
666
+ function()
667
+ {
668
+ var cache = this._.cache;
669
+ if ( cache.type )
670
+ return cache.type;
671
+
672
+ var type = CKEDITOR.SELECTION_TEXT;
673
+
674
+ var sel = this.getNative();
675
+
676
+ if ( !sel )
677
+ type = CKEDITOR.SELECTION_NONE;
678
+ else if ( sel.rangeCount == 1 )
679
+ {
680
+ // Check if the actual selection is a control (IMG,
681
+ // TABLE, HR, etc...).
682
+
683
+ var range = sel.getRangeAt(0),
684
+ startContainer = range.startContainer;
685
+
686
+ if ( startContainer == range.endContainer
687
+ && startContainer.nodeType == 1
688
+ && ( range.endOffset - range.startOffset ) == 1
689
+ && styleObjectElements[ startContainer.childNodes[ range.startOffset ].nodeName.toLowerCase() ] )
690
+ {
691
+ type = CKEDITOR.SELECTION_ELEMENT;
692
+ }
693
+ }
694
+
695
+ return ( cache.type = type );
696
+ },
697
+
698
+ /**
699
+ * Retrieves the <code>{@link CKEDITOR.dom.range}</code> instances that represent the current selection.
700
+ * Note: Some browsers return multiple ranges even for a continuous selection. Firefox, for example, returns
701
+ * one range for each table cell when one or more table rows are selected.
702
+ * @function
703
+ * @param {Boolean} [onlyEditables] If set to <code>true</code>, this function retrives editable ranges only.
704
+ * @return {Array} Range instances that represent the current selection.
705
+ * @example
706
+ * var ranges = selection.<strong>getRanges()</strong>;
707
+ * alert( ranges.length );
708
+ */
709
+ getRanges : (function()
710
+ {
711
+ var func = CKEDITOR.env.ie ?
712
+ ( function()
713
+ {
714
+ function getNodeIndex( node ) { return new CKEDITOR.dom.node( node ).getIndex(); }
715
+
716
+ // Finds the container and offset for a specific boundary
717
+ // of an IE range.
718
+ var getBoundaryInformation = function( range, start )
719
+ {
720
+ // Creates a collapsed range at the requested boundary.
721
+ range = range.duplicate();
722
+ range.collapse( start );
723
+
724
+ // Gets the element that encloses the range entirely.
725
+ var parent = range.parentElement(),
726
+ doc = parent.ownerDocument;
727
+
728
+ // Empty parent element, e.g. <i>^</i>
729
+ if ( !parent.hasChildNodes() )
730
+ return { container : parent, offset : 0 };
731
+
732
+ var siblings = parent.children,
733
+ child,
734
+ sibling,
735
+ testRange = range.duplicate(),
736
+ startIndex = 0,
737
+ endIndex = siblings.length - 1,
738
+ index = -1,
739
+ position,
740
+ distance;
741
+
742
+ // Binary search over all element childs to test the range to see whether
743
+ // range is right on the boundary of one element.
744
+ while ( startIndex <= endIndex )
745
+ {
746
+ index = Math.floor( ( startIndex + endIndex ) / 2 );
747
+ child = siblings[ index ];
748
+ testRange.moveToElementText( child );
749
+ position = testRange.compareEndPoints( 'StartToStart', range );
750
+
751
+ if ( position > 0 )
752
+ endIndex = index - 1;
753
+ else if ( position < 0 )
754
+ startIndex = index + 1;
755
+ else
756
+ {
757
+ // IE9 report wrong measurement with compareEndPoints when range anchors between two BRs.
758
+ // e.g. <p>text<br />^<br /></p> (#7433)
759
+ if ( CKEDITOR.env.ie9Compat && child.tagName == 'BR' )
760
+ {
761
+ var bmId = 'cke_range_marker';
762
+ range.execCommand( 'CreateBookmark', false, bmId );
763
+ child = doc.getElementsByName( bmId )[ 0 ];
764
+ var offset = getNodeIndex( child );
765
+ parent.removeChild( child );
766
+ return { container : parent, offset : offset };
767
+ }
768
+ else
769
+ return { container : parent, offset : getNodeIndex( child ) };
770
+ }
771
+ }
772
+
773
+ // All childs are text nodes,
774
+ // or to the right hand of test range are all text nodes. (#6992)
775
+ if ( index == -1 || index == siblings.length - 1 && position < 0 )
776
+ {
777
+ // Adapt test range to embrace the entire parent contents.
778
+ testRange.moveToElementText( parent );
779
+ testRange.setEndPoint( 'StartToStart', range );
780
+
781
+ // IE report line break as CRLF with range.text but
782
+ // only LF with textnode.nodeValue, normalize them to avoid
783
+ // breaking character counting logic below. (#3949)
784
+ distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length;
785
+
786
+ siblings = parent.childNodes;
787
+
788
+ // Actual range anchor right beside test range at the boundary of text node.
789
+ if ( !distance )
790
+ {
791
+ child = siblings[ siblings.length - 1 ];
792
+
793
+ if ( child.nodeType == CKEDITOR.NODE_ELEMENT )
794
+ return { container : parent, offset : siblings.length };
795
+ else
796
+ return { container : child, offset : child.nodeValue.length };
797
+ }
798
+
799
+ // Start the measuring until distance overflows, meanwhile count the text nodes.
800
+ var i = siblings.length;
801
+ while ( distance > 0 )
802
+ distance -= siblings[ --i ].nodeValue.length;
803
+
804
+ return { container : siblings[ i ], offset : -distance };
805
+ }
806
+ // Test range was one offset beyond OR behind the anchored text node.
807
+ else
808
+ {
809
+ // Adapt one side of test range to the actual range
810
+ // for measuring the offset between them.
811
+ testRange.collapse( position > 0 ? true : false );
812
+ testRange.setEndPoint( position > 0 ? 'StartToStart' : 'EndToStart', range );
813
+
814
+ // IE report line break as CRLF with range.text but
815
+ // only LF with textnode.nodeValue, normalize them to avoid
816
+ // breaking character counting logic below. (#3949)
817
+ distance = testRange.text.replace( /(\r\n|\r)/g, '\n' ).length;
818
+
819
+ // Actual range anchor right beside test range at the inner boundary of text node.
820
+ if ( !distance )
821
+ return { container : parent, offset : getNodeIndex( child ) + ( position > 0 ? 0 : 1 ) };
822
+
823
+ // Start the measuring until distance overflows, meanwhile count the text nodes.
824
+ while ( distance > 0 )
825
+ {
826
+ try
827
+ {
828
+ sibling = child[ position > 0 ? 'previousSibling' : 'nextSibling' ];
829
+ distance -= sibling.nodeValue.length;
830
+ child = sibling;
831
+ }
832
+ // Measurement in IE could be somtimes wrong because of <select> element. (#4611)
833
+ catch( e )
834
+ {
835
+ return { container : parent, offset : getNodeIndex( child ) };
836
+ }
837
+ }
838
+
839
+ return { container : child, offset : position > 0 ? -distance : child.nodeValue.length + distance };
840
+ }
841
+ };
842
+
843
+ return function()
844
+ {
845
+ // IE doesn't have range support (in the W3C way), so we
846
+ // need to do some magic to transform selections into
847
+ // CKEDITOR.dom.range instances.
848
+
849
+ var sel = this.getNative(),
850
+ nativeRange = sel && sel.createRange(),
851
+ type = this.getType(),
852
+ range;
853
+
854
+ if ( !sel )
855
+ return [];
856
+
857
+ if ( type == CKEDITOR.SELECTION_TEXT )
858
+ {
859
+ range = new CKEDITOR.dom.range( this.document );
860
+
861
+ var boundaryInfo = getBoundaryInformation( nativeRange, true );
862
+ range.setStart( new CKEDITOR.dom.node( boundaryInfo.container ), boundaryInfo.offset );
863
+
864
+ boundaryInfo = getBoundaryInformation( nativeRange );
865
+ range.setEnd( new CKEDITOR.dom.node( boundaryInfo.container ), boundaryInfo.offset );
866
+
867
+ // Correct an invalid IE range case on empty list item. (#5850)
868
+ if ( range.endContainer.getPosition( range.startContainer ) & CKEDITOR.POSITION_PRECEDING
869
+ && range.endOffset <= range.startContainer.getIndex() )
870
+ {
871
+ range.collapse();
872
+ }
873
+
874
+ return [ range ];
875
+ }
876
+ else if ( type == CKEDITOR.SELECTION_ELEMENT )
877
+ {
878
+ var retval = [];
879
+
880
+ for ( var i = 0 ; i < nativeRange.length ; i++ )
881
+ {
882
+ var element = nativeRange.item( i ),
883
+ parentElement = element.parentNode,
884
+ j = 0;
885
+
886
+ range = new CKEDITOR.dom.range( this.document );
887
+
888
+ for (; j < parentElement.childNodes.length && parentElement.childNodes[j] != element ; j++ )
889
+ { /*jsl:pass*/ }
890
+
891
+ range.setStart( new CKEDITOR.dom.node( parentElement ), j );
892
+ range.setEnd( new CKEDITOR.dom.node( parentElement ), j + 1 );
893
+ retval.push( range );
894
+ }
895
+
896
+ return retval;
897
+ }
898
+
899
+ return [];
900
+ };
901
+ })()
902
+ :
903
+ function()
904
+ {
905
+
906
+ // On browsers implementing the W3C range, we simply
907
+ // tranform the native ranges in CKEDITOR.dom.range
908
+ // instances.
909
+
910
+ var ranges = [],
911
+ range,
912
+ doc = this.document,
913
+ sel = this.getNative();
914
+
915
+ if ( !sel )
916
+ return ranges;
917
+
918
+ // On WebKit, it may happen that we'll have no selection
919
+ // available. We normalize it here by replicating the
920
+ // behavior of other browsers.
921
+ if ( !sel.rangeCount )
922
+ {
923
+ range = new CKEDITOR.dom.range( doc );
924
+ range.moveToElementEditStart( doc.getBody() );
925
+ ranges.push( range );
926
+ }
927
+
928
+ for ( var i = 0 ; i < sel.rangeCount ; i++ )
929
+ {
930
+ var nativeRange = sel.getRangeAt( i );
931
+
932
+ range = new CKEDITOR.dom.range( doc );
933
+
934
+ range.setStart( new CKEDITOR.dom.node( nativeRange.startContainer ), nativeRange.startOffset );
935
+ range.setEnd( new CKEDITOR.dom.node( nativeRange.endContainer ), nativeRange.endOffset );
936
+ ranges.push( range );
937
+ }
938
+ return ranges;
939
+ };
940
+
941
+ return function( onlyEditables )
942
+ {
943
+ var cache = this._.cache;
944
+ if ( cache.ranges && !onlyEditables )
945
+ return cache.ranges;
946
+ else if ( !cache.ranges )
947
+ cache.ranges = new CKEDITOR.dom.rangeList( func.call( this ) );
948
+
949
+ // Split range into multiple by read-only nodes.
950
+ if ( onlyEditables )
951
+ {
952
+ var ranges = cache.ranges;
953
+ for ( var i = 0; i < ranges.length; i++ )
954
+ {
955
+ var range = ranges[ i ];
956
+
957
+ // Drop range spans inside one ready-only node.
958
+ var parent = range.getCommonAncestor();
959
+ if ( parent.isReadOnly() )
960
+ ranges.splice( i, 1 );
961
+
962
+ if ( range.collapsed )
963
+ continue;
964
+
965
+ // Range may start inside a non-editable element,
966
+ // replace the range start after it.
967
+ if ( range.startContainer.isReadOnly() )
968
+ {
969
+ var current = range.startContainer;
970
+ while( current )
971
+ {
972
+ if ( current.is( 'body' ) || !current.isReadOnly() )
973
+ break;
974
+
975
+ if ( current.type == CKEDITOR.NODE_ELEMENT
976
+ && current.getAttribute( 'contentEditable' ) == 'false' )
977
+ range.setStartAfter( current );
978
+
979
+ current = current.getParent();
980
+ }
981
+ }
982
+
983
+ var startContainer = range.startContainer,
984
+ endContainer = range.endContainer,
985
+ startOffset = range.startOffset,
986
+ endOffset = range.endOffset,
987
+ walkerRange = range.clone();
988
+
989
+ // Enlarge range start/end with text node to avoid walker
990
+ // being DOM destructive, it doesn't interfere our checking
991
+ // of elements below as well.
992
+ if ( startContainer && startContainer.type == CKEDITOR.NODE_TEXT )
993
+ {
994
+ if ( startOffset >= startContainer.getLength() )
995
+ walkerRange.setStartAfter( startContainer );
996
+ else
997
+ walkerRange.setStartBefore( startContainer );
998
+ }
999
+
1000
+ if ( endContainer && endContainer.type == CKEDITOR.NODE_TEXT )
1001
+ {
1002
+ if ( !endOffset )
1003
+ walkerRange.setEndBefore( endContainer );
1004
+ else
1005
+ walkerRange.setEndAfter( endContainer );
1006
+ }
1007
+
1008
+ // Looking for non-editable element inside the range.
1009
+ var walker = new CKEDITOR.dom.walker( walkerRange );
1010
+ walker.evaluator = function( node )
1011
+ {
1012
+ if ( node.type == CKEDITOR.NODE_ELEMENT
1013
+ && node.isReadOnly() )
1014
+ {
1015
+ var newRange = range.clone();
1016
+ range.setEndBefore( node );
1017
+
1018
+ // Drop collapsed range around read-only elements,
1019
+ // it make sure the range list empty when selecting
1020
+ // only non-editable elements.
1021
+ if ( range.collapsed )
1022
+ ranges.splice( i--, 1 );
1023
+
1024
+ // Avoid creating invalid range.
1025
+ if ( !( node.getPosition( walkerRange.endContainer ) & CKEDITOR.POSITION_CONTAINS ) )
1026
+ {
1027
+ newRange.setStartAfter( node );
1028
+ if ( !newRange.collapsed )
1029
+ ranges.splice( i + 1, 0, newRange );
1030
+ }
1031
+
1032
+ return true;
1033
+ }
1034
+
1035
+ return false;
1036
+ };
1037
+
1038
+ walker.next();
1039
+ }
1040
+ }
1041
+
1042
+ return cache.ranges;
1043
+ };
1044
+ })(),
1045
+
1046
+ /**
1047
+ * Gets the DOM element in which the selection starts.
1048
+ * @returns {CKEDITOR.dom.element} The element at the beginning of the
1049
+ * selection.
1050
+ * @example
1051
+ * var element = editor.getSelection().<strong>getStartElement()</strong>;
1052
+ * alert( element.getName() );
1053
+ */
1054
+ getStartElement : function()
1055
+ {
1056
+ var cache = this._.cache;
1057
+ if ( cache.startElement !== undefined )
1058
+ return cache.startElement;
1059
+
1060
+ var node,
1061
+ sel = this.getNative();
1062
+
1063
+ switch ( this.getType() )
1064
+ {
1065
+ case CKEDITOR.SELECTION_ELEMENT :
1066
+ return this.getSelectedElement();
1067
+
1068
+ case CKEDITOR.SELECTION_TEXT :
1069
+
1070
+ var range = this.getRanges()[0];
1071
+
1072
+ if ( range )
1073
+ {
1074
+ if ( !range.collapsed )
1075
+ {
1076
+ range.optimize();
1077
+
1078
+ // Decrease the range content to exclude particial
1079
+ // selected node on the start which doesn't have
1080
+ // visual impact. ( #3231 )
1081
+ while ( 1 )
1082
+ {
1083
+ var startContainer = range.startContainer,
1084
+ startOffset = range.startOffset;
1085
+ // Limit the fix only to non-block elements.(#3950)
1086
+ if ( startOffset == ( startContainer.getChildCount ?
1087
+ startContainer.getChildCount() : startContainer.getLength() )
1088
+ && !startContainer.isBlockBoundary() )
1089
+ range.setStartAfter( startContainer );
1090
+ else break;
1091
+ }
1092
+
1093
+ node = range.startContainer;
1094
+
1095
+ if ( node.type != CKEDITOR.NODE_ELEMENT )
1096
+ return node.getParent();
1097
+
1098
+ node = node.getChild( range.startOffset );
1099
+
1100
+ if ( !node || node.type != CKEDITOR.NODE_ELEMENT )
1101
+ node = range.startContainer;
1102
+ else
1103
+ {
1104
+ var child = node.getFirst();
1105
+ while ( child && child.type == CKEDITOR.NODE_ELEMENT )
1106
+ {
1107
+ node = child;
1108
+ child = child.getFirst();
1109
+ }
1110
+ }
1111
+ }
1112
+ else
1113
+ {
1114
+ node = range.startContainer;
1115
+ if ( node.type != CKEDITOR.NODE_ELEMENT )
1116
+ node = node.getParent();
1117
+ }
1118
+
1119
+ node = node.$;
1120
+ }
1121
+ }
1122
+
1123
+ return cache.startElement = ( node ? new CKEDITOR.dom.element( node ) : null );
1124
+ },
1125
+
1126
+ /**
1127
+ * Gets the currently selected element.
1128
+ * @returns {CKEDITOR.dom.element} The selected element. Null if no
1129
+ * selection is available or the selection type is not
1130
+ * <code>{@link CKEDITOR.SELECTION_ELEMENT}</code>.
1131
+ * @example
1132
+ * var element = editor.getSelection().<strong>getSelectedElement()</strong>;
1133
+ * alert( element.getName() );
1134
+ */
1135
+ getSelectedElement : function()
1136
+ {
1137
+ var cache = this._.cache;
1138
+ if ( cache.selectedElement !== undefined )
1139
+ return cache.selectedElement;
1140
+
1141
+ var self = this;
1142
+
1143
+ var node = CKEDITOR.tools.tryThese(
1144
+ // Is it native IE control type selection?
1145
+ function()
1146
+ {
1147
+ return self.getNative().createRange().item( 0 );
1148
+ },
1149
+ // If a table or list is fully selected.
1150
+ function()
1151
+ {
1152
+ var root,
1153
+ retval,
1154
+ range = self.getRanges()[ 0 ],
1155
+ ancestor = range.getCommonAncestor( 1, 1 ),
1156
+ tags = { table:1,ul:1,ol:1,dl:1 };
1157
+
1158
+ for ( var t in tags )
1159
+ {
1160
+ if ( root = ancestor.getAscendant( t, 1 ) )
1161
+ break;
1162
+ }
1163
+
1164
+ if ( root )
1165
+ {
1166
+ // Enlarging the start boundary.
1167
+ var testRange = new CKEDITOR.dom.range( this.document );
1168
+ testRange.setStartAt( root, CKEDITOR.POSITION_AFTER_START );
1169
+ testRange.setEnd( range.startContainer, range.startOffset );
1170
+
1171
+ var enlargeables = CKEDITOR.tools.extend( tags, CKEDITOR.dtd.$listItem, CKEDITOR.dtd.$tableContent ),
1172
+ walker = new CKEDITOR.dom.walker( testRange ),
1173
+ // Check the range is at the inner boundary of the structural element.
1174
+ guard = function( walker, isEnd )
1175
+ {
1176
+ return function( node, isWalkOut )
1177
+ {
1178
+ if ( node.type == CKEDITOR.NODE_TEXT && ( !CKEDITOR.tools.trim( node.getText() ) || node.getParent().data( 'cke-bookmark' ) ) )
1179
+ return true;
1180
+
1181
+ var tag;
1182
+ if ( node.type == CKEDITOR.NODE_ELEMENT )
1183
+ {
1184
+ tag = node.getName();
1185
+
1186
+ // Bypass bogus br at the end of block.
1187
+ if ( tag == 'br' && isEnd && node.equals( node.getParent().getBogus() ) )
1188
+ return true;
1189
+
1190
+ if ( isWalkOut && tag in enlargeables || tag in CKEDITOR.dtd.$removeEmpty )
1191
+ return true;
1192
+ }
1193
+
1194
+ walker.halted = 1;
1195
+ return false;
1196
+ };
1197
+ };
1198
+
1199
+ walker.guard = guard( walker );
1200
+
1201
+ if ( walker.checkBackward() && !walker.halted )
1202
+ {
1203
+ walker = new CKEDITOR.dom.walker( testRange );
1204
+ testRange.setStart( range.endContainer, range.endOffset );
1205
+ testRange.setEndAt( root, CKEDITOR.POSITION_BEFORE_END );
1206
+ walker.guard = guard( walker, 1 );
1207
+ if ( walker.checkForward() && !walker.halted )
1208
+ retval = root.$;
1209
+ }
1210
+ }
1211
+
1212
+ if ( !retval )
1213
+ throw 0;
1214
+
1215
+ return retval;
1216
+ },
1217
+ // Figure it out by checking if there's a single enclosed
1218
+ // node of the range.
1219
+ function()
1220
+ {
1221
+ var range = self.getRanges()[ 0 ],
1222
+ enclosed,
1223
+ selected;
1224
+
1225
+ // Check first any enclosed element, e.g. <ul>[<li><a href="#">item</a></li>]</ul>
1226
+ for ( var i = 2; i && !( ( enclosed = range.getEnclosedNode() )
1227
+ && ( enclosed.type == CKEDITOR.NODE_ELEMENT )
1228
+ && styleObjectElements[ enclosed.getName() ]
1229
+ && ( selected = enclosed ) ); i-- )
1230
+ {
1231
+ // Then check any deep wrapped element, e.g. [<b><i><img /></i></b>]
1232
+ range.shrink( CKEDITOR.SHRINK_ELEMENT );
1233
+ }
1234
+
1235
+ return selected.$;
1236
+ });
1237
+
1238
+ return cache.selectedElement = ( node ? new CKEDITOR.dom.element( node ) : null );
1239
+ },
1240
+
1241
+ /**
1242
+ * Retrieves the text contained within the range. An empty string is returned for non-text selection.
1243
+ * @returns {String} A string of text within the current selection.
1244
+ * @since 3.6.1
1245
+ * @example
1246
+ * var text = editor.getSelection().<strong>getSelectedText()</strong>;
1247
+ * alert( text );
1248
+ */
1249
+ getSelectedText : function()
1250
+ {
1251
+ var cache = this._.cache;
1252
+ if ( cache.selectedText !== undefined )
1253
+ return cache.selectedText;
1254
+
1255
+ var text = '',
1256
+ nativeSel = this.getNative();
1257
+ if ( this.getType() == CKEDITOR.SELECTION_TEXT )
1258
+ text = CKEDITOR.env.ie ? nativeSel.createRange().text : nativeSel.toString();
1259
+
1260
+ return ( cache.selectedText = text );
1261
+ },
1262
+
1263
+ /**
1264
+ * Locks the selection made in the editor in order to make it possible to
1265
+ * manipulate it without browser interference. A locked selection is
1266
+ * cached and remains unchanged until it is released with the <code>#unlock</code>
1267
+ * method.
1268
+ * @example
1269
+ * editor.getSelection().<strong>lock()</strong>;
1270
+ */
1271
+ lock : function()
1272
+ {
1273
+ // Call all cacheable function.
1274
+ this.getRanges();
1275
+ this.getStartElement();
1276
+ this.getSelectedElement();
1277
+ this.getSelectedText();
1278
+
1279
+ // The native selection is not available when locked.
1280
+ this._.cache.nativeSel = {};
1281
+
1282
+ this.isLocked = 1;
1283
+
1284
+ // Save this selection inside the DOM document.
1285
+ this.document.setCustomData( 'cke_locked_selection', this );
1286
+ },
1287
+
1288
+ /**
1289
+ * Unlocks the selection made in the editor and locked with the <code>#lock</code> method.
1290
+ * An unlocked selection is no longer cached and can be changed.
1291
+ * @param {Boolean} [restore] If set to <code>true</code>, the selection is restored back to the selection saved earlier by using the <code>#lock</code> method.
1292
+ * @example
1293
+ * editor.getSelection().<strong>unlock()</strong>;
1294
+ */
1295
+ unlock : function( restore )
1296
+ {
1297
+ var doc = this.document,
1298
+ lockedSelection = doc.getCustomData( 'cke_locked_selection' );
1299
+
1300
+ if ( lockedSelection )
1301
+ {
1302
+ doc.setCustomData( 'cke_locked_selection', null );
1303
+
1304
+ if ( restore )
1305
+ {
1306
+ var selectedElement = lockedSelection.getSelectedElement(),
1307
+ ranges = !selectedElement && lockedSelection.getRanges();
1308
+
1309
+ this.isLocked = 0;
1310
+ this.reset();
1311
+
1312
+ doc.getBody().focus();
1313
+
1314
+ if ( selectedElement )
1315
+ this.selectElement( selectedElement );
1316
+ else
1317
+ this.selectRanges( ranges );
1318
+ }
1319
+ }
1320
+
1321
+ if ( !lockedSelection || !restore )
1322
+ {
1323
+ this.isLocked = 0;
1324
+ this.reset();
1325
+ }
1326
+ },
1327
+
1328
+ /**
1329
+ * Clears the selection cache.
1330
+ * @example
1331
+ * editor.getSelection().<strong>reset()</strong>;
1332
+ */
1333
+ reset : function()
1334
+ {
1335
+ this._.cache = {};
1336
+ },
1337
+
1338
+ /**
1339
+ * Makes the current selection of type <code>{@link CKEDITOR.SELECTION_ELEMENT}</code> by enclosing the specified element.
1340
+ * @param {CKEDITOR.dom.element} element The element to enclose in the selection.
1341
+ * @example
1342
+ * var element = editor.document.getById( 'sampleElement' );
1343
+ * editor.getSelection.<strong>selectElement( element )</strong>;
1344
+ */
1345
+ selectElement : function( element )
1346
+ {
1347
+ if ( this.isLocked )
1348
+ {
1349
+ var range = new CKEDITOR.dom.range( this.document );
1350
+ range.setStartBefore( element );
1351
+ range.setEndAfter( element );
1352
+
1353
+ this._.cache.selectedElement = element;
1354
+ this._.cache.startElement = element;
1355
+ this._.cache.ranges = new CKEDITOR.dom.rangeList( range );
1356
+ this._.cache.type = CKEDITOR.SELECTION_ELEMENT;
1357
+
1358
+ return;
1359
+ }
1360
+
1361
+ range = new CKEDITOR.dom.range( element.getDocument() );
1362
+ range.setStartBefore( element );
1363
+ range.setEndAfter( element );
1364
+ range.select();
1365
+
1366
+ this.document.fire( 'selectionchange' );
1367
+ this.reset();
1368
+
1369
+ },
1370
+
1371
+ /**
1372
+ * Clears the original selection and adds the specified ranges
1373
+ * to the document selection.
1374
+ * @param {Array} ranges An array of <code>{@link CKEDITOR.dom.range}</code> instances representing ranges to be added to the document.
1375
+ * @example
1376
+ * var ranges = new CKEDITOR.dom.range( editor.document );
1377
+ * editor.getSelection().<strong>selectRanges( [ ranges ] )</strong>;
1378
+ */
1379
+ selectRanges : function( ranges )
1380
+ {
1381
+ if ( this.isLocked )
1382
+ {
1383
+ this._.cache.selectedElement = null;
1384
+ this._.cache.startElement = ranges[ 0 ] && ranges[ 0 ].getTouchedStartNode();
1385
+ this._.cache.ranges = new CKEDITOR.dom.rangeList( ranges );
1386
+ this._.cache.type = CKEDITOR.SELECTION_TEXT;
1387
+
1388
+ return;
1389
+ }
1390
+
1391
+ if ( CKEDITOR.env.ie )
1392
+ {
1393
+ if ( ranges.length > 1 )
1394
+ {
1395
+ // IE doesn't accept multiple ranges selection, so we join all into one.
1396
+ var last = ranges[ ranges.length -1 ] ;
1397
+ ranges[ 0 ].setEnd( last.endContainer, last.endOffset );
1398
+ ranges.length = 1;
1399
+ }
1400
+
1401
+ if ( ranges[ 0 ] )
1402
+ ranges[ 0 ].select();
1403
+
1404
+ this.reset();
1405
+ }
1406
+ else
1407
+ {
1408
+ var sel = this.getNative();
1409
+
1410
+ // getNative() returns null if iframe is "display:none" in FF. (#6577)
1411
+ if ( !sel )
1412
+ return;
1413
+
1414
+ if ( ranges.length )
1415
+ {
1416
+ sel.removeAllRanges();
1417
+ // Remove any existing filling char first.
1418
+ CKEDITOR.env.webkit && removeFillingChar( this.document );
1419
+ }
1420
+
1421
+ for ( var i = 0 ; i < ranges.length ; i++ )
1422
+ {
1423
+ // Joining sequential ranges introduced by
1424
+ // readonly elements protection.
1425
+ if ( i < ranges.length -1 )
1426
+ {
1427
+ var left = ranges[ i ], right = ranges[ i +1 ],
1428
+ between = left.clone();
1429
+ between.setStart( left.endContainer, left.endOffset );
1430
+ between.setEnd( right.startContainer, right.startOffset );
1431
+
1432
+ // Don't confused by Firefox adjancent multi-ranges
1433
+ // introduced by table cells selection.
1434
+ if ( !between.collapsed )
1435
+ {
1436
+ between.shrink( CKEDITOR.NODE_ELEMENT, true );
1437
+ var ancestor = between.getCommonAncestor(),
1438
+ enclosed = between.getEnclosedNode();
1439
+
1440
+ // The following cases has to be considered:
1441
+ // 1. <span contenteditable="false">[placeholder]</span>
1442
+ // 2. <input contenteditable="false" type="radio"/> (#6621)
1443
+ if ( ancestor.isReadOnly() || enclosed && enclosed.isReadOnly() )
1444
+ {
1445
+ right.setStart( left.startContainer, left.startOffset );
1446
+ ranges.splice( i--, 1 );
1447
+ continue;
1448
+ }
1449
+ }
1450
+ }
1451
+
1452
+ var range = ranges[ i ];
1453
+ var nativeRange = this.document.$.createRange();
1454
+ var startContainer = range.startContainer;
1455
+
1456
+ // In FF2, if we have a collapsed range, inside an empty
1457
+ // element, we must add something to it otherwise the caret
1458
+ // will not be visible.
1459
+ // In Opera instead, the selection will be moved out of the
1460
+ // element. (#4657)
1461
+ if ( range.collapsed &&
1462
+ ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.version < 10900 ) ) &&
1463
+ startContainer.type == CKEDITOR.NODE_ELEMENT &&
1464
+ !startContainer.getChildCount() )
1465
+ {
1466
+ startContainer.appendText( '' );
1467
+ }
1468
+
1469
+ if ( range.collapsed
1470
+ && CKEDITOR.env.webkit
1471
+ && rangeRequiresFix( range ) )
1472
+ {
1473
+ // Append a zero-width space so WebKit will not try to
1474
+ // move the selection by itself (#1272).
1475
+ var fillingChar = createFillingChar( this.document );
1476
+ range.insertNode( fillingChar ) ;
1477
+
1478
+ var next = fillingChar.getNext();
1479
+
1480
+ // If the filling char is followed by a <br>, whithout
1481
+ // having something before it, it'll not blink.
1482
+ // Let's remove it in this case.
1483
+ if ( next && !fillingChar.getPrevious() && next.type == CKEDITOR.NODE_ELEMENT && next.getName() == 'br' )
1484
+ {
1485
+ removeFillingChar( this.document );
1486
+ range.moveToPosition( next, CKEDITOR.POSITION_BEFORE_START );
1487
+ }
1488
+ else
1489
+ range.moveToPosition( fillingChar, CKEDITOR.POSITION_AFTER_END );
1490
+ }
1491
+
1492
+ nativeRange.setStart( range.startContainer.$, range.startOffset );
1493
+
1494
+ try
1495
+ {
1496
+ nativeRange.setEnd( range.endContainer.$, range.endOffset );
1497
+ }
1498
+ catch ( e )
1499
+ {
1500
+ // There is a bug in Firefox implementation (it would be too easy
1501
+ // otherwise). The new start can't be after the end (W3C says it can).
1502
+ // So, let's create a new range and collapse it to the desired point.
1503
+ if ( e.toString().indexOf( 'NS_ERROR_ILLEGAL_VALUE' ) >= 0 )
1504
+ {
1505
+ range.collapse( 1 );
1506
+ nativeRange.setEnd( range.endContainer.$, range.endOffset );
1507
+ }
1508
+ else
1509
+ throw e;
1510
+ }
1511
+
1512
+ // Select the range.
1513
+ sel.addRange( nativeRange );
1514
+ }
1515
+
1516
+ // Don't miss selection change event for non-IEs.
1517
+ this.document.fire( 'selectionchange' );
1518
+ this.reset();
1519
+ }
1520
+ },
1521
+
1522
+ /**
1523
+ * Creates a bookmark for each range of this selection (from <code>#getRanges</code>)
1524
+ * by calling the <code>{@link CKEDITOR.dom.range.prototype.createBookmark}</code> method,
1525
+ * with extra care taken to avoid interference among those ranges. The arguments
1526
+ * received are the same as with the underlying range method.
1527
+ * @returns {Array} Array of bookmarks for each range.
1528
+ * @example
1529
+ * var bookmarks = editor.getSelection().<strong>createBookmarks()</strong>;
1530
+ */
1531
+ createBookmarks : function( serializable )
1532
+ {
1533
+ return this.getRanges().createBookmarks( serializable );
1534
+ },
1535
+
1536
+ /**
1537
+ * Creates a bookmark for each range of this selection (from <code>#getRanges</code>)
1538
+ * by calling the <code>{@link CKEDITOR.dom.range.prototype.createBookmark2}</code> method,
1539
+ * with extra care taken to avoid interference among those ranges. The arguments
1540
+ * received are the same as with the underlying range method.
1541
+ * @returns {Array} Array of bookmarks for each range.
1542
+ * @example
1543
+ * var bookmarks = editor.getSelection().<strong>createBookmarks2()</strong>;
1544
+ */
1545
+ createBookmarks2 : function( normalized )
1546
+ {
1547
+ return this.getRanges().createBookmarks2( normalized );
1548
+ },
1549
+
1550
+ /**
1551
+ * Selects the virtual ranges denoted by the bookmarks by calling <code>#selectRanges</code>.
1552
+ * @param {Array} bookmarks The bookmarks representing ranges to be selected.
1553
+ * @returns {CKEDITOR.dom.selection} This selection object, after the ranges were selected.
1554
+ * @example
1555
+ * var bookmarks = editor.getSelection().createBookmarks();
1556
+ * editor.getSelection().<strong>selectBookmarks( bookmarks )</strong>;
1557
+ */
1558
+ selectBookmarks : function( bookmarks )
1559
+ {
1560
+ var ranges = [];
1561
+ for ( var i = 0 ; i < bookmarks.length ; i++ )
1562
+ {
1563
+ var range = new CKEDITOR.dom.range( this.document );
1564
+ range.moveToBookmark( bookmarks[i] );
1565
+ ranges.push( range );
1566
+ }
1567
+ this.selectRanges( ranges );
1568
+ return this;
1569
+ },
1570
+
1571
+ /**
1572
+ * Retrieves the common ancestor node of the first range and the last range.
1573
+ * @returns {CKEDITOR.dom.element} The common ancestor of the selection.
1574
+ * @example
1575
+ * var ancestor = editor.getSelection().<strong>getCommonAncestor()</strong>;
1576
+ */
1577
+ getCommonAncestor : function()
1578
+ {
1579
+ var ranges = this.getRanges(),
1580
+ startNode = ranges[ 0 ].startContainer,
1581
+ endNode = ranges[ ranges.length - 1 ].endContainer;
1582
+ return startNode.getCommonAncestor( endNode );
1583
+ },
1584
+
1585
+ /**
1586
+ * Moves the scrollbar to the starting position of the current selection.
1587
+ * @example
1588
+ * editor.getSelection().<strong>scrollIntoView()</strong>;
1589
+ */
1590
+ scrollIntoView : function()
1591
+ {
1592
+ // If we have split the block, adds a temporary span at the
1593
+ // range position and scroll relatively to it.
1594
+ var start = this.getStartElement();
1595
+ start.scrollIntoView();
1596
+ }
1597
+ };
1598
+ })();
1599
+
1600
+ ( function()
1601
+ {
1602
+ var notWhitespaces = CKEDITOR.dom.walker.whitespaces( true ),
1603
+ fillerTextRegex = /\ufeff|\u00a0/,
1604
+ nonCells = { table:1,tbody:1,tr:1 };
1605
+
1606
+ CKEDITOR.dom.range.prototype.select =
1607
+ CKEDITOR.env.ie ?
1608
+ // V2
1609
+ function( forceExpand )
1610
+ {
1611
+ var collapsed = this.collapsed,
1612
+ isStartMarkerAlone, dummySpan, ieRange;
1613
+
1614
+ // Try to make a object selection.
1615
+ var selected = this.getEnclosedNode();
1616
+ if ( selected )
1617
+ {
1618
+ try
1619
+ {
1620
+ ieRange = this.document.$.body.createControlRange();
1621
+ ieRange.addElement( selected.$ );
1622
+ ieRange.select();
1623
+ return;
1624
+ }
1625
+ catch( er ) {}
1626
+ }
1627
+
1628
+ // IE doesn't support selecting the entire table row/cell, move the selection into cells, e.g.
1629
+ // <table><tbody><tr>[<td>cell</b></td>... => <table><tbody><tr><td>[cell</td>...
1630
+ if ( this.startContainer.type == CKEDITOR.NODE_ELEMENT && this.startContainer.getName() in nonCells
1631
+ || this.endContainer.type == CKEDITOR.NODE_ELEMENT && this.endContainer.getName() in nonCells )
1632
+ {
1633
+ this.shrink( CKEDITOR.NODE_ELEMENT, true );
1634
+ }
1635
+
1636
+ var bookmark = this.createBookmark();
1637
+
1638
+ // Create marker tags for the start and end boundaries.
1639
+ var startNode = bookmark.startNode;
1640
+
1641
+ var endNode;
1642
+ if ( !collapsed )
1643
+ endNode = bookmark.endNode;
1644
+
1645
+ // Create the main range which will be used for the selection.
1646
+ ieRange = this.document.$.body.createTextRange();
1647
+
1648
+ // Position the range at the start boundary.
1649
+ ieRange.moveToElementText( startNode.$ );
1650
+ ieRange.moveStart( 'character', 1 );
1651
+
1652
+ if ( endNode )
1653
+ {
1654
+ // Create a tool range for the end.
1655
+ var ieRangeEnd = this.document.$.body.createTextRange();
1656
+
1657
+ // Position the tool range at the end.
1658
+ ieRangeEnd.moveToElementText( endNode.$ );
1659
+
1660
+ // Move the end boundary of the main range to match the tool range.
1661
+ ieRange.setEndPoint( 'EndToEnd', ieRangeEnd );
1662
+ ieRange.moveEnd( 'character', -1 );
1663
+ }
1664
+ else
1665
+ {
1666
+ // The isStartMarkerAlone logic comes from V2. It guarantees that the lines
1667
+ // will expand and that the cursor will be blinking on the right place.
1668
+ // Actually, we are using this flag just to avoid using this hack in all
1669
+ // situations, but just on those needed.
1670
+ var next = startNode.getNext( notWhitespaces );
1671
+ isStartMarkerAlone = ( !( next && next.getText && next.getText().match( fillerTextRegex ) ) // already a filler there?
1672
+ && ( forceExpand || !startNode.hasPrevious() || ( startNode.getPrevious().is && startNode.getPrevious().is( 'br' ) ) ) );
1673
+
1674
+ // Append a temporary <span>&#65279;</span> before the selection.
1675
+ // This is needed to avoid IE destroying selections inside empty
1676
+ // inline elements, like <b></b> (#253).
1677
+ // It is also needed when placing the selection right after an inline
1678
+ // element to avoid the selection moving inside of it.
1679
+ dummySpan = this.document.createElement( 'span' );
1680
+ dummySpan.setHtml( '&#65279;' ); // Zero Width No-Break Space (U+FEFF). See #1359.
1681
+ dummySpan.insertBefore( startNode );
1682
+
1683
+ if ( isStartMarkerAlone )
1684
+ {
1685
+ // To expand empty blocks or line spaces after <br>, we need
1686
+ // instead to have any char, which will be later deleted using the
1687
+ // selection.
1688
+ // \ufeff = Zero Width No-Break Space (U+FEFF). (#1359)
1689
+ this.document.createText( '\ufeff' ).insertBefore( startNode );
1690
+ }
1691
+ }
1692
+
1693
+ // Remove the markers (reset the position, because of the changes in the DOM tree).
1694
+ this.setStartBefore( startNode );
1695
+ startNode.remove();
1696
+
1697
+ if ( collapsed )
1698
+ {
1699
+ if ( isStartMarkerAlone )
1700
+ {
1701
+ // Move the selection start to include the temporary \ufeff.
1702
+ ieRange.moveStart( 'character', -1 );
1703
+
1704
+ ieRange.select();
1705
+
1706
+ // Remove our temporary stuff.
1707
+ this.document.$.selection.clear();
1708
+ }
1709
+ else
1710
+ ieRange.select();
1711
+
1712
+ this.moveToPosition( dummySpan, CKEDITOR.POSITION_BEFORE_START );
1713
+ dummySpan.remove();
1714
+ }
1715
+ else
1716
+ {
1717
+ this.setEndBefore( endNode );
1718
+ endNode.remove();
1719
+ ieRange.select();
1720
+ }
1721
+
1722
+ this.document.fire( 'selectionchange' );
1723
+ }
1724
+ :
1725
+ function()
1726
+ {
1727
+ this.document.getSelection().selectRanges( [ this ] );
1728
+ };
1729
+ } )();