gnuside-aloha-rails 0.23.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (826) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +18 -0
  3. data/README.md +48 -0
  4. data/Rakefile +69 -0
  5. data/app/assets/javascripts/aloha.js +3 -0
  6. data/app/assets/javascripts/aloha/preinit.js.erb +1 -0
  7. data/lib/aloha-rails.rb +1 -0
  8. data/lib/aloha/rails.rb +2 -0
  9. data/lib/aloha/rails/engine.rb +9 -0
  10. data/lib/aloha/rails/version.rb +7 -0
  11. data/lib/tasks/aloha-assets.rake +9 -0
  12. data/vendor/assets/javascripts/aloha/css/aloha.scss +31 -0
  13. data/vendor/assets/javascripts/aloha/img/arrow-down.png +0 -0
  14. data/vendor/assets/javascripts/aloha/img/arrow-left.png +0 -0
  15. data/vendor/assets/javascripts/aloha/img/arrow.png +0 -0
  16. data/vendor/assets/javascripts/aloha/img/base-multi.png +0 -0
  17. data/vendor/assets/javascripts/aloha/img/base.png +0 -0
  18. data/vendor/assets/javascripts/aloha/img/bg.png +0 -0
  19. data/vendor/assets/javascripts/aloha/img/breadcrumb-divider.png +0 -0
  20. data/vendor/assets/javascripts/aloha/img/gentics-logo.png +0 -0
  21. data/vendor/assets/javascripts/aloha/img/grabhandle.png +0 -0
  22. data/vendor/assets/javascripts/aloha/img/maximize.png +0 -0
  23. data/vendor/assets/javascripts/aloha/img/multisplit-base.jpg +0 -0
  24. data/vendor/assets/javascripts/aloha/img/multisplit-close.gif +0 -0
  25. data/vendor/assets/javascripts/aloha/img/multisplit-open.gif +0 -0
  26. data/vendor/assets/javascripts/aloha/img/pin.png +0 -0
  27. data/vendor/assets/javascripts/aloha/img/removeformat.png +0 -0
  28. data/vendor/assets/javascripts/aloha/img/text_indent.png +0 -0
  29. data/vendor/assets/javascripts/aloha/img/text_indent_remove.png +0 -0
  30. data/vendor/assets/javascripts/aloha/lib/aloha-jquery-noconflict.js +14 -0
  31. data/vendor/assets/javascripts/aloha/lib/aloha.js +595 -0
  32. data/vendor/assets/javascripts/aloha/lib/aloha/block-jump.js +153 -0
  33. data/vendor/assets/javascripts/aloha/lib/aloha/command.js +287 -0
  34. data/vendor/assets/javascripts/aloha/lib/aloha/console.js +347 -0
  35. data/vendor/assets/javascripts/aloha/lib/aloha/contenthandlermanager.js +104 -0
  36. data/vendor/assets/javascripts/aloha/lib/aloha/copypaste.js +108 -0
  37. data/vendor/assets/javascripts/aloha/lib/aloha/core.js +623 -0
  38. data/vendor/assets/javascripts/aloha/lib/aloha/ecma5shims.js +326 -0
  39. data/vendor/assets/javascripts/aloha/lib/aloha/editable.js +1042 -0
  40. data/vendor/assets/javascripts/aloha/lib/aloha/engine.js +8646 -0
  41. data/vendor/assets/javascripts/aloha/lib/aloha/ephemera.js +492 -0
  42. data/vendor/assets/javascripts/aloha/lib/aloha/ierange-m2.js +29 -0
  43. data/vendor/assets/javascripts/aloha/lib/aloha/jquery.aloha.js +542 -0
  44. data/vendor/assets/javascripts/aloha/lib/aloha/markup.js +1276 -0
  45. data/vendor/assets/javascripts/aloha/lib/aloha/nls/ca/i18n.js +11 -0
  46. data/vendor/assets/javascripts/aloha/lib/aloha/nls/de/i18n.js +11 -0
  47. data/vendor/assets/javascripts/aloha/lib/aloha/nls/i18n.js +20 -0
  48. data/vendor/assets/javascripts/aloha/lib/aloha/nls/mk/i18n.js +11 -0
  49. data/vendor/assets/javascripts/aloha/lib/aloha/nls/pt-br/i18n.js +11 -0
  50. data/vendor/assets/javascripts/aloha/lib/aloha/nls/ru/i18n.js +11 -0
  51. data/vendor/assets/javascripts/aloha/lib/aloha/nls/uk/i18n.js +11 -0
  52. data/vendor/assets/javascripts/aloha/lib/aloha/nls/zh-hans/i18n.js +11 -0
  53. data/vendor/assets/javascripts/aloha/lib/aloha/observable.js +113 -0
  54. data/vendor/assets/javascripts/aloha/lib/aloha/plugin.js +281 -0
  55. data/vendor/assets/javascripts/aloha/lib/aloha/pluginmanager.js +203 -0
  56. data/vendor/assets/javascripts/aloha/lib/aloha/rangy-core.js +30 -0
  57. data/vendor/assets/javascripts/aloha/lib/aloha/registry.js +137 -0
  58. data/vendor/assets/javascripts/aloha/lib/aloha/repository.js +255 -0
  59. data/vendor/assets/javascripts/aloha/lib/aloha/repositorymanager.js +742 -0
  60. data/vendor/assets/javascripts/aloha/lib/aloha/repositoryobjects.js +162 -0
  61. data/vendor/assets/javascripts/aloha/lib/aloha/selection.js +2402 -0
  62. data/vendor/assets/javascripts/aloha/lib/aloha/sidebar.js +1045 -0
  63. data/vendor/assets/javascripts/aloha/lib/aloha/state-override.js +147 -0
  64. data/vendor/assets/javascripts/aloha/lib/css.js +455 -0
  65. data/vendor/assets/javascripts/aloha/lib/i18n.js +192 -0
  66. data/vendor/assets/javascripts/aloha/lib/require.js +2053 -0
  67. data/vendor/assets/javascripts/aloha/lib/text.js +288 -0
  68. data/vendor/assets/javascripts/aloha/lib/util/arrays.js +287 -0
  69. data/vendor/assets/javascripts/aloha/lib/util/boundary-markers.js +86 -0
  70. data/vendor/assets/javascripts/aloha/lib/util/browser.js +32 -0
  71. data/vendor/assets/javascripts/aloha/lib/util/class.js +78 -0
  72. data/vendor/assets/javascripts/aloha/lib/util/dom.js +1888 -0
  73. data/vendor/assets/javascripts/aloha/lib/util/dom2.js +908 -0
  74. data/vendor/assets/javascripts/aloha/lib/util/functions.js +62 -0
  75. data/vendor/assets/javascripts/aloha/lib/util/html.js +311 -0
  76. data/vendor/assets/javascripts/aloha/lib/util/json2.js +464 -0
  77. data/vendor/assets/javascripts/aloha/lib/util/keys.js +65 -0
  78. data/vendor/assets/javascripts/aloha/lib/util/lang.js +89 -0
  79. data/vendor/assets/javascripts/aloha/lib/util/maps.js +130 -0
  80. data/vendor/assets/javascripts/aloha/lib/util/misc.js +51 -0
  81. data/vendor/assets/javascripts/aloha/lib/util/position.js +176 -0
  82. data/vendor/assets/javascripts/aloha/lib/util/range-context.js +776 -0
  83. data/vendor/assets/javascripts/aloha/lib/util/range.js +917 -0
  84. data/vendor/assets/javascripts/aloha/lib/util/strings.js +122 -0
  85. data/vendor/assets/javascripts/aloha/lib/util/trees.js +336 -0
  86. data/vendor/assets/javascripts/aloha/lib/vendor/3rdparty.txt +70 -0
  87. data/vendor/assets/javascripts/aloha/lib/vendor/amplify.store.js +298 -0
  88. data/vendor/assets/javascripts/aloha/lib/vendor/class.js +76 -0
  89. data/vendor/assets/javascripts/aloha/lib/vendor/grid.locale.de.js +138 -0
  90. data/vendor/assets/javascripts/aloha/lib/vendor/grid.locale.en.js +133 -0
  91. data/vendor/assets/javascripts/aloha/lib/vendor/ierange-m2.js +508 -0
  92. data/vendor/assets/javascripts/aloha/lib/vendor/jquery-1.7.2.js +9421 -0
  93. data/vendor/assets/javascripts/aloha/lib/vendor/jquery-ui-1.9.0.custom-aloha.js +14711 -0
  94. data/vendor/assets/javascripts/aloha/lib/vendor/jquery.jqgrid.js +474 -0
  95. data/vendor/assets/javascripts/aloha/lib/vendor/jquery.jstree.js +4549 -0
  96. data/vendor/assets/javascripts/aloha/lib/vendor/jquery.layout-1.3.0-rc30.7.js +5924 -0
  97. data/vendor/assets/javascripts/aloha/lib/vendor/pubsub/js/pubsub-unminified.js +187 -0
  98. data/vendor/assets/javascripts/aloha/lib/vendor/pubsub/js/pubsub.js +2 -0
  99. data/vendor/assets/javascripts/aloha/lib/vendor/rangy-core.js +3295 -0
  100. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/css/jstree.css +88 -0
  101. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/css/repository-browser.css +744 -0
  102. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/arrow-000-medium.png +0 -0
  103. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/arrow-180.png +0 -0
  104. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/arrow-315-medium.png +0 -0
  105. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/arrow-stop-180.png +0 -0
  106. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/arrow-stop.png +0 -0
  107. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/arrow.png +0 -0
  108. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/control-stop-square-small.png +0 -0
  109. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/folder-horizontal-open.png +0 -0
  110. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/folder-open.png +0 -0
  111. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/magnifier-left.png +0 -0
  112. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/page.png +0 -0
  113. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/picture.png +0 -0
  114. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/sort-alphabet-descending.png +0 -0
  115. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/sort-alphabet.png +0 -0
  116. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/img/throbber.gif +0 -0
  117. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/js/repository-browser-unminified.js +1450 -0
  118. data/vendor/assets/javascripts/aloha/lib/vendor/repository-browser/js/repository-browser.js +32 -0
  119. data/vendor/assets/javascripts/aloha/lib/vendor/sanitize.js +278 -0
  120. data/vendor/assets/javascripts/aloha/plugins/common/abbr/css/abbr.css +1 -0
  121. data/vendor/assets/javascripts/aloha/plugins/common/abbr/img/remabbr.png +0 -0
  122. data/vendor/assets/javascripts/aloha/plugins/common/abbr/lib/abbr-plugin.js +304 -0
  123. data/vendor/assets/javascripts/aloha/plugins/common/abbr/nls/ca/i18n.js +6 -0
  124. data/vendor/assets/javascripts/aloha/plugins/common/abbr/nls/de/i18n.js +6 -0
  125. data/vendor/assets/javascripts/aloha/plugins/common/abbr/nls/i18n.js +15 -0
  126. data/vendor/assets/javascripts/aloha/plugins/common/abbr/nls/mk/i18n.js +6 -0
  127. data/vendor/assets/javascripts/aloha/plugins/common/abbr/nls/pt-br/i18n.js +6 -0
  128. data/vendor/assets/javascripts/aloha/plugins/common/abbr/nls/ru/i18n.js +6 -0
  129. data/vendor/assets/javascripts/aloha/plugins/common/abbr/nls/uk/i18n.js +6 -0
  130. data/vendor/assets/javascripts/aloha/plugins/common/abbr/nls/zh-hans/i18n.js +6 -0
  131. data/vendor/assets/javascripts/aloha/plugins/common/abbr/package.json +1 -0
  132. data/vendor/assets/javascripts/aloha/plugins/common/align/LICENSE +166 -0
  133. data/vendor/assets/javascripts/aloha/plugins/common/align/README +12 -0
  134. data/vendor/assets/javascripts/aloha/plugins/common/align/css/align.css +31 -0
  135. data/vendor/assets/javascripts/aloha/plugins/common/align/img/align.png +0 -0
  136. data/vendor/assets/javascripts/aloha/plugins/common/align/lib/align-plugin.js +465 -0
  137. data/vendor/assets/javascripts/aloha/plugins/common/align/nls/ca/i18n.js +6 -0
  138. data/vendor/assets/javascripts/aloha/plugins/common/align/nls/de/i18n.js +9 -0
  139. data/vendor/assets/javascripts/aloha/plugins/common/align/nls/i18n.js +18 -0
  140. data/vendor/assets/javascripts/aloha/plugins/common/align/nls/mk/i18n.js +6 -0
  141. data/vendor/assets/javascripts/aloha/plugins/common/align/nls/pt-br/i18n.js +6 -0
  142. data/vendor/assets/javascripts/aloha/plugins/common/align/nls/ru/i18n.js +6 -0
  143. data/vendor/assets/javascripts/aloha/plugins/common/align/nls/uk/i18n.js +6 -0
  144. data/vendor/assets/javascripts/aloha/plugins/common/align/nls/zh-hans/i18n.js +6 -0
  145. data/vendor/assets/javascripts/aloha/plugins/common/align/package.json +2 -0
  146. data/vendor/assets/javascripts/aloha/plugins/common/block/README +0 -0
  147. data/vendor/assets/javascripts/aloha/plugins/common/block/css/block.css +110 -0
  148. data/vendor/assets/javascripts/aloha/plugins/common/block/img/toolbar-draghandle.gif +0 -0
  149. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/block-plugin.js +347 -0
  150. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/block.js +1277 -0
  151. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/blockcontenthandler.js +118 -0
  152. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/blockmanager.js +621 -0
  153. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/editor.js +331 -0
  154. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/editormanager.js +55 -0
  155. data/vendor/assets/javascripts/aloha/plugins/common/block/lib/sidebarattributeeditor.js +126 -0
  156. data/vendor/assets/javascripts/aloha/plugins/common/block/nls/ca/i18n.js +3 -0
  157. data/vendor/assets/javascripts/aloha/plugins/common/block/nls/de/i18n.js +3 -0
  158. data/vendor/assets/javascripts/aloha/plugins/common/block/nls/i18n.js +12 -0
  159. data/vendor/assets/javascripts/aloha/plugins/common/block/nls/mk/i18n.js +3 -0
  160. data/vendor/assets/javascripts/aloha/plugins/common/block/nls/pt-br/i18n.js +3 -0
  161. data/vendor/assets/javascripts/aloha/plugins/common/block/nls/ru/i18n.js +3 -0
  162. data/vendor/assets/javascripts/aloha/plugins/common/block/nls/uk/i18n.js +3 -0
  163. data/vendor/assets/javascripts/aloha/plugins/common/block/nls/zh-hans/i18n.js +3 -0
  164. data/vendor/assets/javascripts/aloha/plugins/common/block/package.json +11 -0
  165. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/css/characterpicker.css +44 -0
  166. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/img/icon.png +0 -0
  167. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/lib/characterpicker-plugin.js +466 -0
  168. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/nls/ca/i18n.js +3 -0
  169. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/nls/de/i18n.js +3 -0
  170. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/nls/i18n.js +12 -0
  171. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/nls/mk/i18n.js +3 -0
  172. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/nls/pt-br/i18n.js +3 -0
  173. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/nls/ru/i18n.js +3 -0
  174. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/nls/uk/i18n.js +3 -0
  175. data/vendor/assets/javascripts/aloha/plugins/common/characterpicker/nls/zh-hans/i18n.js +3 -0
  176. data/vendor/assets/javascripts/aloha/plugins/common/commands/css/abbr.css +0 -0
  177. data/vendor/assets/javascripts/aloha/plugins/common/commands/lib/commands-plugin.js +33 -0
  178. data/vendor/assets/javascripts/aloha/plugins/common/commands/lib/inserthtml.js +126 -0
  179. data/vendor/assets/javascripts/aloha/plugins/common/commands/package.json +1 -0
  180. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/README.md +0 -0
  181. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/blockelementcontenthandler.js +144 -0
  182. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/contenthandler-plugin.js +65 -0
  183. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/contenthandler-utils.js +58 -0
  184. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/genericcontenthandler.js +359 -0
  185. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/oembedcontenthandler.js +461 -0
  186. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/sanitizecontenthandler.js +186 -0
  187. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/lib/wordcontenthandler.js +461 -0
  188. data/vendor/assets/javascripts/aloha/plugins/common/contenthandler/package.json +1 -0
  189. data/vendor/assets/javascripts/aloha/plugins/common/dom-to-xhtml/lib/dom-to-xhtml-plugin.js +74 -0
  190. data/vendor/assets/javascripts/aloha/plugins/common/dom-to-xhtml/lib/dom-to-xhtml.js +415 -0
  191. data/vendor/assets/javascripts/aloha/plugins/common/format/img/em.png +0 -0
  192. data/vendor/assets/javascripts/aloha/plugins/common/format/img/strong.png +0 -0
  193. data/vendor/assets/javascripts/aloha/plugins/common/format/lib/format-plugin.js +594 -0
  194. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/ca/i18n.js +52 -0
  195. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/de/i18n.js +52 -0
  196. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/i18n.js +61 -0
  197. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/mk/i18n.js +52 -0
  198. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/pt-br/i18n.js +52 -0
  199. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/ru/i18n.js +52 -0
  200. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/uk/i18n.js +52 -0
  201. data/vendor/assets/javascripts/aloha/plugins/common/format/nls/zh-hans/i18n.js +52 -0
  202. data/vendor/assets/javascripts/aloha/plugins/common/highlighteditables/css/highlighteditables.css +14 -0
  203. data/vendor/assets/javascripts/aloha/plugins/common/highlighteditables/lib/highlighteditables-plugin.js +100 -0
  204. data/vendor/assets/javascripts/aloha/plugins/common/highlighteditables/package.json +1 -0
  205. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/css/horizontalruler.css +3 -0
  206. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/img/icon.png +0 -0
  207. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/lib/horizontalruler-plugin.js +95 -0
  208. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/nls/ca/i18n.js +3 -0
  209. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/nls/de/i18n.js +3 -0
  210. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/nls/i18n.js +12 -0
  211. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/nls/mk/i18n.js +3 -0
  212. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/nls/pt-br/i18n.js +3 -0
  213. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/nls/ru/i18n.js +3 -0
  214. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/nls/uk/i18n.js +3 -0
  215. data/vendor/assets/javascripts/aloha/plugins/common/horizontalruler/nls/zh-hans/i18n.js +3 -0
  216. data/vendor/assets/javascripts/aloha/plugins/common/image/README.md +66 -0
  217. data/vendor/assets/javascripts/aloha/plugins/common/image/css/image.css +133 -0
  218. data/vendor/assets/javascripts/aloha/plugins/common/image/img/blank.jpg +0 -0
  219. data/vendor/assets/javascripts/aloha/plugins/common/image/img/crop-buttons.gif +0 -0
  220. data/vendor/assets/javascripts/aloha/plugins/common/image/img/cropnresize.png +0 -0
  221. data/vendor/assets/javascripts/aloha/plugins/common/image/img/handle-sw.png +0 -0
  222. data/vendor/assets/javascripts/aloha/plugins/common/image/img/image-align-left.png +0 -0
  223. data/vendor/assets/javascripts/aloha/plugins/common/image/img/image-align-none.png +0 -0
  224. data/vendor/assets/javascripts/aloha/plugins/common/image/img/image-align-right.png +0 -0
  225. data/vendor/assets/javascripts/aloha/plugins/common/image/img/image-border.png +0 -0
  226. data/vendor/assets/javascripts/aloha/plugins/common/image/img/image-title.png +0 -0
  227. data/vendor/assets/javascripts/aloha/plugins/common/image/img/image.gif +0 -0
  228. data/vendor/assets/javascripts/aloha/plugins/common/image/img/padding-decrease.gif +0 -0
  229. data/vendor/assets/javascripts/aloha/plugins/common/image/img/padding-increase.gif +0 -0
  230. data/vendor/assets/javascripts/aloha/plugins/common/image/img/page.png +0 -0
  231. data/vendor/assets/javascripts/aloha/plugins/common/image/img/size-decrease.gif +0 -0
  232. data/vendor/assets/javascripts/aloha/plugins/common/image/img/size-increase.gif +0 -0
  233. data/vendor/assets/javascripts/aloha/plugins/common/image/lib/image-floatingMenu.js +308 -0
  234. data/vendor/assets/javascripts/aloha/plugins/common/image/lib/image-plugin-actions.js +0 -0
  235. data/vendor/assets/javascripts/aloha/plugins/common/image/lib/image-plugin.js +1341 -0
  236. data/vendor/assets/javascripts/aloha/plugins/common/image/nls/ca/i18n.js +32 -0
  237. data/vendor/assets/javascripts/aloha/plugins/common/image/nls/de/i18n.js +32 -0
  238. data/vendor/assets/javascripts/aloha/plugins/common/image/nls/i18n.js +41 -0
  239. data/vendor/assets/javascripts/aloha/plugins/common/image/nls/mk/i18n.js +32 -0
  240. data/vendor/assets/javascripts/aloha/plugins/common/image/nls/pt-br/i18n.js +32 -0
  241. data/vendor/assets/javascripts/aloha/plugins/common/image/nls/ru/i18n.js +32 -0
  242. data/vendor/assets/javascripts/aloha/plugins/common/image/nls/uk/i18n.js +32 -0
  243. data/vendor/assets/javascripts/aloha/plugins/common/image/nls/zh-hans/i18n.js +32 -0
  244. data/vendor/assets/javascripts/aloha/plugins/common/image/package.json +1 -0
  245. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/jcrop/jcrop.gif +0 -0
  246. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/jcrop/jquery.jcrop.css +46 -0
  247. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/jcrop/jquery.jcrop.min.js +165 -0
  248. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/mousewheel/mousewheel.js +85 -0
  249. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  250. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  251. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  252. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  253. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  254. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  255. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  256. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  257. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  258. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  259. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  260. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  261. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  262. data/vendor/assets/javascripts/aloha/plugins/common/image/vendor/ui/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  263. data/vendor/assets/javascripts/aloha/plugins/common/link/css/link.css +52 -0
  264. data/vendor/assets/javascripts/aloha/plugins/common/link/extra/delicious.js +264 -0
  265. data/vendor/assets/javascripts/aloha/plugins/common/link/extra/linklist.js +247 -0
  266. data/vendor/assets/javascripts/aloha/plugins/common/link/extra/slowlinklist.js +247 -0
  267. data/vendor/assets/javascripts/aloha/plugins/common/link/lib/link-plugin.js +958 -0
  268. data/vendor/assets/javascripts/aloha/plugins/common/link/nls/ca/i18n.js +14 -0
  269. data/vendor/assets/javascripts/aloha/plugins/common/link/nls/de/i18n.js +14 -0
  270. data/vendor/assets/javascripts/aloha/plugins/common/link/nls/i18n.js +23 -0
  271. data/vendor/assets/javascripts/aloha/plugins/common/link/nls/mk/i18n.js +14 -0
  272. data/vendor/assets/javascripts/aloha/plugins/common/link/nls/pt-br/i18n.js +14 -0
  273. data/vendor/assets/javascripts/aloha/plugins/common/link/nls/ru/i18n.js +14 -0
  274. data/vendor/assets/javascripts/aloha/plugins/common/link/nls/uk/i18n.js +14 -0
  275. data/vendor/assets/javascripts/aloha/plugins/common/link/nls/zh-hans/i18n.js +14 -0
  276. data/vendor/assets/javascripts/aloha/plugins/common/list/lib/list-plugin.js +878 -0
  277. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/ca/i18n.js +7 -0
  278. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/de/i18n.js +7 -0
  279. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/i18n.js +16 -0
  280. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/mk/i18n.js +7 -0
  281. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/pt-br/i18n.js +7 -0
  282. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/ru/i18n.js +7 -0
  283. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/uk/i18n.js +7 -0
  284. data/vendor/assets/javascripts/aloha/plugins/common/list/nls/zh-hans/i18n.js +7 -0
  285. data/vendor/assets/javascripts/aloha/plugins/common/list/package.json +1 -0
  286. data/vendor/assets/javascripts/aloha/plugins/common/paste/lib/paste-plugin.js +457 -0
  287. data/vendor/assets/javascripts/aloha/plugins/common/paste/package.json +8 -0
  288. data/vendor/assets/javascripts/aloha/plugins/common/table/css/table.css +125 -0
  289. data/vendor/assets/javascripts/aloha/plugins/common/table/img/down.cur +0 -0
  290. data/vendor/assets/javascripts/aloha/plugins/common/table/img/left.cur +0 -0
  291. data/vendor/assets/javascripts/aloha/plugins/common/table/img/table_layout.png +0 -0
  292. data/vendor/assets/javascripts/aloha/plugins/common/table/img/wai-green.png +0 -0
  293. data/vendor/assets/javascripts/aloha/plugins/common/table/img/wai-red.png +0 -0
  294. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-cell.js +542 -0
  295. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-create-layer.js +213 -0
  296. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-plugin-utils.js +494 -0
  297. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-plugin.js +1596 -0
  298. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table-selection.js +468 -0
  299. data/vendor/assets/javascripts/aloha/plugins/common/table/lib/table.js +2110 -0
  300. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/ca/i18n.js +28 -0
  301. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/de/i18n.js +29 -0
  302. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/i18n.js +38 -0
  303. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/mk/i18n.js +28 -0
  304. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/pt-br/i18n.js +28 -0
  305. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/ru/i18n.js +28 -0
  306. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/uk/i18n.js +28 -0
  307. data/vendor/assets/javascripts/aloha/plugins/common/table/nls/zh-hans/i18n.js +28 -0
  308. data/vendor/assets/javascripts/aloha/plugins/common/table/package.json +1 -0
  309. data/vendor/assets/javascripts/aloha/plugins/common/ui/css/jquery-ui-1.9m6.css +430 -0
  310. data/vendor/assets/javascripts/aloha/plugins/common/ui/css/ui.css +689 -0
  311. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/blockquote.png +0 -0
  312. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/character-picker.png +0 -0
  313. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/em.png +0 -0
  314. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/format-block.png +0 -0
  315. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/format-inline.png +0 -0
  316. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/indent.png +0 -0
  317. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/jqueryui/ui-icons_222222_256x240.png +0 -0
  318. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/justify.png +0 -0
  319. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/language-annotation.png +0 -0
  320. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview.png +0 -0
  321. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/anchor.png +0 -0
  322. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/blockquote.png +0 -0
  323. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/caption.png +0 -0
  324. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/cite.png +0 -0
  325. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/dd.png +0 -0
  326. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/div.png +0 -0
  327. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/dl.png +0 -0
  328. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/dt.png +0 -0
  329. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/h1.png +0 -0
  330. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/h2.png +0 -0
  331. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/h3.png +0 -0
  332. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/h4.png +0 -0
  333. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/h5.png +0 -0
  334. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/h6.png +0 -0
  335. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/p.png +0 -0
  336. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/pre.png +0 -0
  337. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/q.png +0 -0
  338. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/table.png +0 -0
  339. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/td.png +0 -0
  340. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/metaview/th.png +0 -0
  341. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/multisplit-close.gif +0 -0
  342. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/multisplit-open.gif +0 -0
  343. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/outdent.png +0 -0
  344. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/quote.png +0 -0
  345. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/removeformat.png +0 -0
  346. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/strong.png +0 -0
  347. data/vendor/assets/javascripts/aloha/plugins/common/ui/img/tree.png +0 -0
  348. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/arena.js +11 -0
  349. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/autocomplete.js +70 -0
  350. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/button.js +114 -0
  351. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/component.js +121 -0
  352. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/container.js +210 -0
  353. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/context.js +53 -0
  354. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/dialog.js +215 -0
  355. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/floating.js +405 -0
  356. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/menuButton.js +169 -0
  357. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/multiSplit.js +237 -0
  358. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/port-helper-attribute-field.js +440 -0
  359. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/port-helper-multi-split.js +71 -0
  360. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/scopes.js +187 -0
  361. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/settings.js +202 -0
  362. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/subguarded.js +183 -0
  363. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/surface.js +106 -0
  364. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/tab.js +316 -0
  365. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/text.js +33 -0
  366. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/toggleButton.js +57 -0
  367. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/toolbar.js +251 -0
  368. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/ui-plugin.js +169 -0
  369. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/ui.js +181 -0
  370. data/vendor/assets/javascripts/aloha/plugins/common/ui/lib/utils.js +104 -0
  371. data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/ca/i18n.js +46 -0
  372. data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/de/i18n.js +48 -0
  373. data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/i18n.js +75 -0
  374. data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/mk/i18n.js +46 -0
  375. data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/pt-br/i18n.js +46 -0
  376. data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/ru/i18n.js +46 -0
  377. data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/uk/i18n.js +46 -0
  378. data/vendor/assets/javascripts/aloha/plugins/common/ui/nls/zh-hans/i18n.js +46 -0
  379. data/vendor/assets/javascripts/aloha/plugins/common/ui/vendor/jquery-ui-autocomplete-html.js +42 -0
  380. data/vendor/assets/javascripts/aloha/plugins/common/undo/lib/undo-plugin.js +165 -0
  381. data/vendor/assets/javascripts/aloha/plugins/common/undo/package.json +7 -0
  382. data/vendor/assets/javascripts/aloha/plugins/common/undo/vendor/diff_match_patch_uncompressed.js +2155 -0
  383. data/vendor/assets/javascripts/aloha/plugins/common/undo/vendor/undo.js +121 -0
  384. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/README +0 -0
  385. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/css/attributes.css +12 -0
  386. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/lib/attributes-plugin.js +237 -0
  387. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/nls/ca/i18n.js +5 -0
  388. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/nls/de/i18n.js +5 -0
  389. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/nls/i18n.js +14 -0
  390. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/nls/mk/i18n.js +5 -0
  391. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/nls/pt-br/i18n.js +5 -0
  392. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/nls/ru/i18n.js +5 -0
  393. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/nls/uk/i18n.js +5 -0
  394. data/vendor/assets/javascripts/aloha/plugins/extra/attributes/nls/zh-hans/i18n.js +5 -0
  395. data/vendor/assets/javascripts/aloha/plugins/extra/captioned-image/css/captioned-image.css +15 -0
  396. data/vendor/assets/javascripts/aloha/plugins/extra/captioned-image/lib/captioned-image-plugin.js +555 -0
  397. data/vendor/assets/javascripts/aloha/plugins/extra/cite/README +0 -0
  398. data/vendor/assets/javascripts/aloha/plugins/extra/cite/css/cite.css +39 -0
  399. data/vendor/assets/javascripts/aloha/plugins/extra/cite/img/blockquote.png +0 -0
  400. data/vendor/assets/javascripts/aloha/plugins/extra/cite/img/icon_cite.png +0 -0
  401. data/vendor/assets/javascripts/aloha/plugins/extra/cite/lib/cite-plugin.js +614 -0
  402. data/vendor/assets/javascripts/aloha/plugins/extra/cite/nls/ca/i18n.js +4 -0
  403. data/vendor/assets/javascripts/aloha/plugins/extra/cite/nls/de/i18n.js +4 -0
  404. data/vendor/assets/javascripts/aloha/plugins/extra/cite/nls/i18n.js +13 -0
  405. data/vendor/assets/javascripts/aloha/plugins/extra/cite/nls/mk/i18n.js +4 -0
  406. data/vendor/assets/javascripts/aloha/plugins/extra/cite/nls/pt-br/i18n.js +4 -0
  407. data/vendor/assets/javascripts/aloha/plugins/extra/cite/nls/ru/i18n.js +4 -0
  408. data/vendor/assets/javascripts/aloha/plugins/extra/cite/nls/uk/i18n.js +4 -0
  409. data/vendor/assets/javascripts/aloha/plugins/extra/cite/nls/zh-hans/i18n.js +4 -0
  410. data/vendor/assets/javascripts/aloha/plugins/extra/cite/package.json +1 -0
  411. data/vendor/assets/javascripts/aloha/plugins/extra/comments/img/add-icon.png +0 -0
  412. data/vendor/assets/javascripts/aloha/plugins/extra/comments/img/add.png +0 -0
  413. data/vendor/assets/javascripts/aloha/plugins/extra/comments/img/comments.png +0 -0
  414. data/vendor/assets/javascripts/aloha/plugins/extra/comments/img/hr.png +0 -0
  415. data/vendor/assets/javascripts/aloha/plugins/extra/comments/img/textbox.png +0 -0
  416. data/vendor/assets/javascripts/aloha/plugins/extra/comments/lib/comments-plugin.js +692 -0
  417. data/vendor/assets/javascripts/aloha/plugins/extra/comments/lib/comments.css +442 -0
  418. data/vendor/assets/javascripts/aloha/plugins/extra/comments/package.json +1 -0
  419. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/README.md +5 -0
  420. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/TODO.md +2 -0
  421. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/img/cross.png +0 -0
  422. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/img/hourglass.png +0 -0
  423. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/img/loading.gif +0 -0
  424. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/img/page.png +0 -0
  425. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/img/tick.png +0 -0
  426. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/lib/draganddropfiles-plugin.js +4 -0
  427. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/lib/dragndropfiles.css +110 -0
  428. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/lib/dragndropfiles.js +363 -0
  429. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/lib/dropfilesrepository.js +365 -0
  430. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/nls/ca/i18n.js +3 -0
  431. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/nls/de/i18n.js +3 -0
  432. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/nls/i18n.js +12 -0
  433. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/nls/mk/i18n.js +3 -0
  434. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/nls/pt-br/i18n.js +3 -0
  435. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/nls/ru/i18n.js +3 -0
  436. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/nls/uk/i18n.js +3 -0
  437. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/nls/zh-hans/i18n.js +3 -0
  438. data/vendor/assets/javascripts/aloha/plugins/extra/draganddropfiles/package.json +1 -0
  439. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/README.md +1 -0
  440. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/css/formatless.css +7 -0
  441. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/img/button.png +0 -0
  442. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/lib/formatlesshandler.js +97 -0
  443. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/lib/formatlesspaste-plugin.js +230 -0
  444. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/nls/ca/i18n.js +3 -0
  445. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/nls/de/i18n.js +3 -0
  446. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/nls/i18n.js +12 -0
  447. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/nls/mk/i18n.js +3 -0
  448. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/nls/pt-br/i18n.js +3 -0
  449. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/nls/ru/i18n.js +3 -0
  450. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/nls/uk/i18n.js +3 -0
  451. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/nls/zh-hans/i18n.js +3 -0
  452. data/vendor/assets/javascripts/aloha/plugins/extra/formatlesspaste/package.json +8 -0
  453. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/README +0 -0
  454. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/css/headerids.css +8 -0
  455. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/lib/headerids-plugin.js +254 -0
  456. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/nls/ca/i18n.js +6 -0
  457. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/nls/de/i18n.js +6 -0
  458. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/nls/i18n.js +15 -0
  459. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/nls/mk/i18n.js +6 -0
  460. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/nls/pt-br/i18n.js +6 -0
  461. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/nls/ru/i18n.js +6 -0
  462. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/nls/uk/i18n.js +6 -0
  463. data/vendor/assets/javascripts/aloha/plugins/extra/headerids/nls/zh-hans/i18n.js +6 -0
  464. data/vendor/assets/javascripts/aloha/plugins/extra/hints/README.md +12 -0
  465. data/vendor/assets/javascripts/aloha/plugins/extra/hints/css/hints.css +29 -0
  466. data/vendor/assets/javascripts/aloha/plugins/extra/hints/lib/hints-plugin.js +97 -0
  467. data/vendor/assets/javascripts/aloha/plugins/extra/hints/package.json +9 -0
  468. data/vendor/assets/javascripts/aloha/plugins/extra/hints/vendor/tipsy.js +242 -0
  469. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/README +0 -0
  470. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/lib/imagebrowser-plugin.js +160 -0
  471. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/nls/ca/i18n.js +6 -0
  472. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/nls/de/i18n.js +6 -0
  473. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/nls/i18n.js +15 -0
  474. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/nls/mk/i18n.js +6 -0
  475. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/nls/pt-br/i18n.js +6 -0
  476. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/nls/ru/i18n.js +6 -0
  477. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/nls/uk/i18n.js +6 -0
  478. data/vendor/assets/javascripts/aloha/plugins/extra/imagebrowser/nls/zh-hans/i18n.js +6 -0
  479. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/README +0 -0
  480. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ad.png +0 -0
  481. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ae.png +0 -0
  482. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/af.png +0 -0
  483. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ag.png +0 -0
  484. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ai.png +0 -0
  485. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/al.png +0 -0
  486. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/am.png +0 -0
  487. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/an.png +0 -0
  488. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ao.png +0 -0
  489. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ar.png +0 -0
  490. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/as.png +0 -0
  491. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/at.png +0 -0
  492. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/au.png +0 -0
  493. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/aw.png +0 -0
  494. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ax.png +0 -0
  495. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/az.png +0 -0
  496. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ba.png +0 -0
  497. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bb.png +0 -0
  498. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bd.png +0 -0
  499. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/be.png +0 -0
  500. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bf.png +0 -0
  501. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bg.png +0 -0
  502. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bh.png +0 -0
  503. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bi.png +0 -0
  504. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bj.png +0 -0
  505. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bm.png +0 -0
  506. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bn.png +0 -0
  507. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bo.png +0 -0
  508. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/br.png +0 -0
  509. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bs.png +0 -0
  510. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bt.png +0 -0
  511. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bv.png +0 -0
  512. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bw.png +0 -0
  513. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/by.png +0 -0
  514. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/bz.png +0 -0
  515. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ca.png +0 -0
  516. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/catalonia.png +0 -0
  517. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cc.png +0 -0
  518. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cd.png +0 -0
  519. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cf.png +0 -0
  520. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cg.png +0 -0
  521. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ch.png +0 -0
  522. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ci.png +0 -0
  523. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ck.png +0 -0
  524. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cl.png +0 -0
  525. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cm.png +0 -0
  526. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cn.png +0 -0
  527. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/co.png +0 -0
  528. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cr.png +0 -0
  529. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cs.png +0 -0
  530. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cu.png +0 -0
  531. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cv.png +0 -0
  532. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cx.png +0 -0
  533. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cy.png +0 -0
  534. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/cz.png +0 -0
  535. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/de.png +0 -0
  536. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/dj.png +0 -0
  537. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/dk.png +0 -0
  538. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/dm.png +0 -0
  539. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/do.png +0 -0
  540. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/dz.png +0 -0
  541. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ec.png +0 -0
  542. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ee.png +0 -0
  543. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/eg.png +0 -0
  544. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/eh.png +0 -0
  545. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/en.png +0 -0
  546. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/er.png +0 -0
  547. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/es.png +0 -0
  548. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/et.png +0 -0
  549. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/europeanunion.png +0 -0
  550. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/fam.png +0 -0
  551. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/fi.png +0 -0
  552. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/fj.png +0 -0
  553. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/fk.png +0 -0
  554. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/fm.png +0 -0
  555. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/fo.png +0 -0
  556. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/fr.png +0 -0
  557. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ga.png +0 -0
  558. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gb.png +0 -0
  559. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gd.png +0 -0
  560. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ge.png +0 -0
  561. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gf.png +0 -0
  562. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gh.png +0 -0
  563. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gi.png +0 -0
  564. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gl.png +0 -0
  565. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gm.png +0 -0
  566. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gn.png +0 -0
  567. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gp.png +0 -0
  568. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gq.png +0 -0
  569. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gr.png +0 -0
  570. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gs.png +0 -0
  571. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gt.png +0 -0
  572. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gu.png +0 -0
  573. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gw.png +0 -0
  574. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/gy.png +0 -0
  575. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/hk.png +0 -0
  576. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/hm.png +0 -0
  577. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/hn.png +0 -0
  578. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/hr.png +0 -0
  579. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ht.png +0 -0
  580. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/hu.png +0 -0
  581. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/id.png +0 -0
  582. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ie.png +0 -0
  583. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/il.png +0 -0
  584. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/in.png +0 -0
  585. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/io.png +0 -0
  586. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/iq.png +0 -0
  587. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ir.png +0 -0
  588. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/is.png +0 -0
  589. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/it.png +0 -0
  590. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/jm.png +0 -0
  591. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/jo.png +0 -0
  592. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/jp.png +0 -0
  593. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ke.png +0 -0
  594. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/kg.png +0 -0
  595. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/kh.png +0 -0
  596. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ki.png +0 -0
  597. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/km.png +0 -0
  598. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/kn.png +0 -0
  599. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/kp.png +0 -0
  600. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/kr.png +0 -0
  601. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/kw.png +0 -0
  602. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ky.png +0 -0
  603. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/kz.png +0 -0
  604. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/la.png +0 -0
  605. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/lb.png +0 -0
  606. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/lc.png +0 -0
  607. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/li.png +0 -0
  608. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/lk.png +0 -0
  609. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/lr.png +0 -0
  610. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ls.png +0 -0
  611. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/lt.png +0 -0
  612. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/lu.png +0 -0
  613. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/lv.png +0 -0
  614. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ly.png +0 -0
  615. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ma.png +0 -0
  616. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mc.png +0 -0
  617. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/md.png +0 -0
  618. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/me.png +0 -0
  619. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mg.png +0 -0
  620. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mh.png +0 -0
  621. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mk.png +0 -0
  622. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ml.png +0 -0
  623. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mm.png +0 -0
  624. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mn.png +0 -0
  625. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mo.png +0 -0
  626. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mp.png +0 -0
  627. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mq.png +0 -0
  628. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mr.png +0 -0
  629. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ms.png +0 -0
  630. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mt.png +0 -0
  631. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mu.png +0 -0
  632. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mv.png +0 -0
  633. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mw.png +0 -0
  634. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mx.png +0 -0
  635. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/my.png +0 -0
  636. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/mz.png +0 -0
  637. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/na.png +0 -0
  638. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/nc.png +0 -0
  639. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ne.png +0 -0
  640. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/nf.png +0 -0
  641. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ng.png +0 -0
  642. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ni.png +0 -0
  643. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/nl.png +0 -0
  644. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/no.png +0 -0
  645. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/np.png +0 -0
  646. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/nr.png +0 -0
  647. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/nu.png +0 -0
  648. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/nz.png +0 -0
  649. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/om.png +0 -0
  650. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pa.png +0 -0
  651. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pe.png +0 -0
  652. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pf.png +0 -0
  653. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pg.png +0 -0
  654. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ph.png +0 -0
  655. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pk.png +0 -0
  656. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pl.png +0 -0
  657. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pm.png +0 -0
  658. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pn.png +0 -0
  659. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pr.png +0 -0
  660. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ps.png +0 -0
  661. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pt.png +0 -0
  662. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/pw.png +0 -0
  663. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/py.png +0 -0
  664. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/qa.png +0 -0
  665. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/re.png +0 -0
  666. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ro.png +0 -0
  667. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/rs.png +0 -0
  668. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ru.png +0 -0
  669. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/rw.png +0 -0
  670. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sa.png +0 -0
  671. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sb.png +0 -0
  672. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sc.png +0 -0
  673. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/scotland.png +0 -0
  674. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sd.png +0 -0
  675. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/se.png +0 -0
  676. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sg.png +0 -0
  677. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sh.png +0 -0
  678. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/si.png +0 -0
  679. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sj.png +0 -0
  680. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sk.png +0 -0
  681. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sl.png +0 -0
  682. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sm.png +0 -0
  683. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sn.png +0 -0
  684. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/so.png +0 -0
  685. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sr.png +0 -0
  686. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/st.png +0 -0
  687. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sv.png +0 -0
  688. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sy.png +0 -0
  689. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/sz.png +0 -0
  690. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tc.png +0 -0
  691. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/td.png +0 -0
  692. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tf.png +0 -0
  693. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tg.png +0 -0
  694. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/th.png +0 -0
  695. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tj.png +0 -0
  696. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tk.png +0 -0
  697. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tl.png +0 -0
  698. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tm.png +0 -0
  699. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tn.png +0 -0
  700. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/to.png +0 -0
  701. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tr.png +0 -0
  702. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tt.png +0 -0
  703. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tv.png +0 -0
  704. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tw.png +0 -0
  705. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/tz.png +0 -0
  706. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ua.png +0 -0
  707. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ug.png +0 -0
  708. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/um.png +0 -0
  709. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/us.png +0 -0
  710. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/uy.png +0 -0
  711. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/uz.png +0 -0
  712. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/va.png +0 -0
  713. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/vc.png +0 -0
  714. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ve.png +0 -0
  715. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/vg.png +0 -0
  716. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/vi.png +0 -0
  717. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/vn.png +0 -0
  718. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/vu.png +0 -0
  719. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/wales.png +0 -0
  720. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/wf.png +0 -0
  721. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ws.png +0 -0
  722. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/ye.png +0 -0
  723. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/yt.png +0 -0
  724. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/za.png +0 -0
  725. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/zm.png +0 -0
  726. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/img/flags/zw.png +0 -0
  727. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/lib/linkbrowser-plugin.js +161 -0
  728. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/nls/ca/i18n.js +6 -0
  729. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/nls/de/i18n.js +6 -0
  730. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/nls/i18n.js +15 -0
  731. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/nls/mk/i18n.js +6 -0
  732. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/nls/pt-br/i18n.js +6 -0
  733. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/nls/ru/i18n.js +6 -0
  734. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/nls/uk/i18n.js +6 -0
  735. data/vendor/assets/javascripts/aloha/plugins/extra/linkbrowser/nls/zh-hans/i18n.js +6 -0
  736. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/nls/ca/i18n.js +28 -0
  737. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/nls/de/i18n.js +28 -0
  738. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/nls/i18n.js +37 -0
  739. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/nls/mk/i18n.js +28 -0
  740. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/nls/pt-br/i18n.js +28 -0
  741. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/nls/ru/i18n.js +28 -0
  742. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/nls/uk/i18n.js +28 -0
  743. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/nls/zh-hans/i18n.js +28 -0
  744. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/package.json +1 -0
  745. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/proxy.php.example +244 -0
  746. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/src/linkchecker.css +14 -0
  747. data/vendor/assets/javascripts/aloha/plugins/extra/linkchecker/src/linkchecker.js +269 -0
  748. data/vendor/assets/javascripts/aloha/plugins/extra/listenforcer/lib/listenforcer-plugin.js +190 -0
  749. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/README +0 -0
  750. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/css/metaview.css +78 -0
  751. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/anchor.png +0 -0
  752. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/blockquote.png +0 -0
  753. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/button.png +0 -0
  754. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/caption.png +0 -0
  755. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/cite.png +0 -0
  756. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/dd.png +0 -0
  757. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/div.png +0 -0
  758. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/dl.png +0 -0
  759. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/dt.png +0 -0
  760. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/h1.png +0 -0
  761. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/h2.png +0 -0
  762. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/h3.png +0 -0
  763. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/h4.png +0 -0
  764. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/h5.png +0 -0
  765. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/h6.png +0 -0
  766. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/hr.png +0 -0
  767. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/icon_cite.png +0 -0
  768. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/p.png +0 -0
  769. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/pre.png +0 -0
  770. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/table.png +0 -0
  771. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/td.png +0 -0
  772. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/img/th.png +0 -0
  773. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/lib/metaview-plugin.js +185 -0
  774. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/nls/ca/i18n.js +3 -0
  775. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/nls/de/i18n.js +3 -0
  776. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/nls/i18n.js +12 -0
  777. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/nls/mk/i18n.js +3 -0
  778. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/nls/pt-br/i18n.js +3 -0
  779. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/nls/ru/i18n.js +3 -0
  780. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/nls/uk/i18n.js +3 -0
  781. data/vendor/assets/javascripts/aloha/plugins/extra/metaview/nls/zh-hans/i18n.js +3 -0
  782. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/README +0 -0
  783. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/css/numerated-headers.css +7 -0
  784. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/img/headers.png +0 -0
  785. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/lib/numerated-headers-plugin.js +421 -0
  786. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/ca/i18n.js +5 -0
  787. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/de/i18n.js +6 -0
  788. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/i18n.js +15 -0
  789. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/mk/i18n.js +5 -0
  790. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/pt-br/i18n.js +5 -0
  791. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/ru/i18n.js +5 -0
  792. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/uk/i18n.js +5 -0
  793. data/vendor/assets/javascripts/aloha/plugins/extra/numerated-headers/nls/zh-hans/i18n.js +5 -0
  794. data/vendor/assets/javascripts/aloha/plugins/extra/profiler/css/profiler.css +34 -0
  795. data/vendor/assets/javascripts/aloha/plugins/extra/profiler/lib/profiler-plugin.js +304 -0
  796. data/vendor/assets/javascripts/aloha/plugins/extra/ribbon/README.md +8 -0
  797. data/vendor/assets/javascripts/aloha/plugins/extra/ribbon/css/ribbon.css +54 -0
  798. data/vendor/assets/javascripts/aloha/plugins/extra/ribbon/img/fade-in.png +0 -0
  799. data/vendor/assets/javascripts/aloha/plugins/extra/ribbon/img/fade-out.png +0 -0
  800. data/vendor/assets/javascripts/aloha/plugins/extra/ribbon/lib/ribbon-plugin.js +144 -0
  801. data/vendor/assets/javascripts/aloha/plugins/extra/ribbon/package.json +1 -0
  802. data/vendor/assets/javascripts/aloha/plugins/extra/sourceview/css/sourceview.css +18 -0
  803. data/vendor/assets/javascripts/aloha/plugins/extra/sourceview/lib/sourceview-plugin.js +252 -0
  804. data/vendor/assets/javascripts/aloha/plugins/extra/sourceview/vendor/htmlbeautifier.js +468 -0
  805. data/vendor/assets/javascripts/aloha/plugins/extra/textcolor/css/textcolor.css +65 -0
  806. data/vendor/assets/javascripts/aloha/plugins/extra/textcolor/img/icon.png +0 -0
  807. data/vendor/assets/javascripts/aloha/plugins/extra/textcolor/lib/textcolor-plugin.js +420 -0
  808. data/vendor/assets/javascripts/aloha/plugins/extra/textcolor/nls/de/i18n.js +3 -0
  809. data/vendor/assets/javascripts/aloha/plugins/extra/textcolor/nls/i18n.js +6 -0
  810. data/vendor/assets/javascripts/aloha/plugins/extra/toc/lib/toc-plugin.js +399 -0
  811. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/ca/i18n.js +3 -0
  812. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/de/i18n.js +3 -0
  813. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/i18n.js +12 -0
  814. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/mk/i18n.js +3 -0
  815. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/pt-br/i18n.js +3 -0
  816. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/ru/i18n.js +3 -0
  817. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/uk/i18n.js +3 -0
  818. data/vendor/assets/javascripts/aloha/plugins/extra/toc/nls/zh-hans/i18n.js +3 -0
  819. data/vendor/assets/javascripts/aloha/plugins/extra/toc/package.json +1 -0
  820. data/vendor/assets/javascripts/aloha/plugins/extra/validation/lib/validation-plugin.js +277 -0
  821. data/vendor/assets/stylesheets/aloha-common-extra.css +24 -0
  822. data/vendor/assets/stylesheets/aloha-core.css +19 -0
  823. data/vendor/assets/stylesheets/aloha-reset.css +24 -0
  824. data/vendor/assets/stylesheets/aloha-sidebar.css +296 -0
  825. data/vendor/assets/stylesheets/aloha.css +31 -0
  826. metadata +898 -0
@@ -0,0 +1,187 @@
1
+ /*!
2
+ * Aloha Editor
3
+ * Author & Copyright (c) 2012 Gentics Software GmbH
4
+ * aloha-sales@gentics.com
5
+ * Licensed under the terms of http://www.aloha-editor.com/license.html
6
+ *
7
+ * @overview Provides methods to broker publish/subscribe facilities.
8
+ */
9
+ define('PubSub', [], function () {
10
+ 'use strict';
11
+
12
+ /**
13
+ * A hash of channel names mapped to an array of ids of subscriptions that
14
+ * are listening on that channel.
15
+ *
16
+ * @type {Object<String, Array.<Number>>}
17
+ */
18
+ var channels = {};
19
+
20
+ /**
21
+ * A hash of subscription tuples (channel, callback), mapped against unique
22
+ * ids assigned to each subscription.
23
+ * As subscriptions are removed from this object via `unsub()' this object
24
+ * will become a sparse array.
25
+ *
26
+ * @type {Object<Number, Object>}
27
+ */
28
+ var subscriptions = {};
29
+
30
+ /**
31
+ * The last used subscription id. This values is only used and modified in
32
+ * `sub().'
33
+ *
34
+ * @type {number}
35
+ */
36
+ var sid = 0;
37
+
38
+ /**
39
+ * Returns the channel to which a subscription matching the given sid is
40
+ * listening on.
41
+ *
42
+ * @param {Number} sid Id of subscription.
43
+ * @return {Array.<Object>} sid Id of subscription.
44
+ */
45
+ function getSubscriptionChannel(sid) {
46
+ return subscriptions[sid] && channels[subscriptions[sid].channel];
47
+ }
48
+
49
+ /**
50
+ * Publishes a message `message' on the given channel.
51
+ * All callbacks that have sub()scribed to listen on this channel will be
52
+ * invoked and receive `message' as their only argument.
53
+ *
54
+ * @private
55
+ * @param {String} channel Name of channel to publish the message on.
56
+ * @param {*} message Variable to pass to all callbacks listening on the
57
+ * given channel.
58
+ * @return {Number} The number of subscribed callbacks that were invoked.
59
+ */
60
+ function pub(channel, message) {
61
+ if (!channels[channel]) {
62
+ return 0;
63
+ }
64
+
65
+ if (!message) {
66
+ message = {};
67
+ } else if (typeof message !== 'object') {
68
+ message = {
69
+ data: message
70
+ };
71
+ }
72
+
73
+ message.channel = channel;
74
+
75
+ // Clone a immutable snapshot of the subscription ids that we can
76
+ // safetly iterate over.
77
+ var sids = channels[channel].slice();
78
+
79
+ // NB: It is necessary to read the size of the `sids' array on each
80
+ // iteration, in case the size changes (via unsubscription) between
81
+ // iterations.
82
+ var i;
83
+ for (i = 0; i < sids.length; ++i) {
84
+ subscriptions[sids[i]].callback(message);
85
+ }
86
+
87
+ return i;
88
+ }
89
+
90
+ var PubSub = {
91
+
92
+ /**
93
+ * Subscribes a callback function to a channel. Whenever this channel
94
+ * publishes, this function will be invoked. The return value is an id
95
+ * which identifies this subscription (a channel, and callback tuple).
96
+ * This id can be used to unsubscribe this subscription from the given
97
+ * channel.
98
+ *
99
+ * @param {String} channel Name of channel to listen on.
100
+ * @param {Function(Object)} callback Function to be invoked when
101
+ * messages are published on the
102
+ * given channel.
103
+ * @return {Number} Positive integer representing the sid of this
104
+ * subscription, that can be used with unsub() if
105
+ * subscription succeeds. Otherwise the return value
106
+ * is -1;
107
+ */
108
+ sub: function (channel, callback) {
109
+ if (typeof callback !== 'function') {
110
+ return -1;
111
+ }
112
+
113
+ var subscriptionIds = channels[channel];
114
+
115
+ if (!subscriptionIds) {
116
+ subscriptionIds = channels[channel] = [];
117
+ }
118
+
119
+ subscriptionIds.push(++sid);
120
+ subscriptions[sid] = {
121
+ channel : channel,
122
+ callback : callback
123
+ };
124
+
125
+ return sid;
126
+ },
127
+
128
+ /**
129
+ * Unsubscribes callback using an sid which was returned by sub() when
130
+ * the callback was subscribed. Returns true if a subscription for
131
+ * this sid was found and removed, otherwise returns false.
132
+ *
133
+ * @param {Number} sid Id of subscription.
134
+ * @return {Boolean} True if a a subscription matching this sid was
135
+ * removed.
136
+ */
137
+ unsub: function (sid) {
138
+ if (-1 === sid || !subscriptions[sid]) {
139
+ return false;
140
+ }
141
+
142
+ var subscriptionIds = getSubscriptionChannel(sid);
143
+
144
+ // assert(typeof subscriptionIds === 'array')
145
+
146
+ delete subscriptions[sid];
147
+ var j = subscriptionIds.length;
148
+
149
+ while (j) {
150
+ if (subscriptionIds[--j] === sid) {
151
+ subscriptionIds.splice(j, 1);
152
+ return true;
153
+ }
154
+ }
155
+
156
+ return false;
157
+ },
158
+
159
+ /**
160
+ * Publishes a message `message' on all channels that can be derived
161
+ * from the given channel name.
162
+ *
163
+ * @param {String} channel Name of channel to publish the message on.
164
+ * @param {*} message Variable to pass to all callbacks listening on
165
+ * the given channel.
166
+ * @return {Number} The number of subscribed callbacks that were
167
+ * invoked.
168
+ */
169
+ pub: function (channel, message) {
170
+ var segments = channel.split('.');
171
+ var i;
172
+ var len = segments.length;
173
+ var channelName = '';
174
+ var tally = 0;
175
+
176
+ for (i = 0; i < len; ++i) {
177
+ channelName += (0 === i ? '' : '.') + segments[i];
178
+ tally += pub(channelName, message);
179
+ }
180
+
181
+ return tally;
182
+ }
183
+
184
+ };
185
+
186
+ return PubSub;
187
+ });
@@ -0,0 +1,2 @@
1
+ define("PubSub",[],function(){var g={},e={},h=0;return{sub:function(a,d){if(typeof d!=="function")return-1;var c=g[a];c||(c=g[a]=[]);c.push(++h);e[h]={channel:a,callback:d};return h},unsub:function(a){if(-1===a||!e[a])return!1;var d=e[a]&&g[e[a].channel];delete e[a];for(var c=d.length;c;)if(d[--c]===a)return d.splice(c,1),!0;return!1},pub:function(a,d){var c=a.split("."),i,h=c.length,k="",l=0;for(i=0;i<h;++i){k+=(0===i?"":".")+c[i];var b;var f=k;b=d;if(g[f]){b?typeof b!=="object"&&(b={data:b}):b=
2
+ {};b.channel=f;for(var f=g[f].slice(),j=void 0,j=0;j<f.length;++j)e[f[j]].callback(b);b=j}else b=0;l+=b}return l}}});
@@ -0,0 +1,3295 @@
1
+ /**
2
+ * @license Rangy, a cross-browser JavaScript range and selection library
3
+ * http://code.google.com/p/rangy/
4
+ *
5
+ * Copyright 2011, Tim Down
6
+ * Licensed under the MIT license.
7
+ * Version: 1.2.1
8
+ * Build date: 8 October 2011
9
+ */
10
+ (function () {
11
+ var rangy = (function () {
12
+
13
+
14
+ var OBJECT = "object",
15
+ FUNCTION = "function",
16
+ UNDEFINED = "undefined";
17
+
18
+ var domRangeProperties = ["startContainer", "startOffset", "endContainer", "endOffset", "collapsed", "commonAncestorContainer", "START_TO_START", "START_TO_END", "END_TO_START", "END_TO_END"];
19
+
20
+ var domRangeMethods = ["setStart", "setStartBefore", "setStartAfter", "setEnd", "setEndBefore", "setEndAfter", "collapse", "selectNode", "selectNodeContents", "compareBoundaryPoints", "deleteContents", "extractContents", "cloneContents", "insertNode", "surroundContents", "cloneRange", "toString", "detach"];
21
+
22
+ var textRangeProperties = ["boundingHeight", "boundingLeft", "boundingTop", "boundingWidth", "htmlText", "text"];
23
+
24
+ // Subset of TextRange's full set of methods that we're interested in
25
+ var textRangeMethods = ["collapse", "compareEndPoints", "duplicate", "getBookmark", "moveToBookmark", "moveToElementText", "parentElement", "pasteHTML", "select", "setEndPoint", "getBoundingClientRect"];
26
+
27
+ /*----------------------------------------------------------------------------------------------------------------*/
28
+
29
+ // Trio of functions taken from Peter Michaux's article:
30
+ // http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
31
+ function isHostMethod(o, p) {
32
+ var t = typeof o[p];
33
+ return t == FUNCTION || ( !! (t == OBJECT && o[p])) || t == "unknown";
34
+ }
35
+
36
+ function isHostObject(o, p) {
37
+ return !!(typeof o[p] == OBJECT && o[p]);
38
+ }
39
+
40
+ function isHostProperty(o, p) {
41
+ return typeof o[p] != UNDEFINED;
42
+ }
43
+
44
+ // Creates a convenience function to save verbose repeated calls to tests functions
45
+ function createMultiplePropertyTest(testFunc) {
46
+ return function (o, props) {
47
+ var i = props.length;
48
+ while (i--) {
49
+ if (!testFunc(o, props[i])) {
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ };
55
+ }
56
+
57
+ // Next trio of functions are a convenience to save verbose repeated calls to previous two functions
58
+ var areHostMethods = createMultiplePropertyTest(isHostMethod);
59
+ var areHostObjects = createMultiplePropertyTest(isHostObject);
60
+ var areHostProperties = createMultiplePropertyTest(isHostProperty);
61
+
62
+ function isTextRange(range) {
63
+ return range && areHostMethods(range, textRangeMethods) && areHostProperties(range, textRangeProperties);
64
+ }
65
+
66
+ var api = {
67
+ version: "1.2.1",
68
+ initialized: false,
69
+ supported: true,
70
+
71
+ util: {
72
+ isHostMethod: isHostMethod,
73
+ isHostObject: isHostObject,
74
+ isHostProperty: isHostProperty,
75
+ areHostMethods: areHostMethods,
76
+ areHostObjects: areHostObjects,
77
+ areHostProperties: areHostProperties,
78
+ isTextRange: isTextRange
79
+ },
80
+
81
+ features: {},
82
+
83
+ modules: {},
84
+ config: {
85
+ alertOnWarn: false,
86
+ // Note: this was set to true, see issue https://github.com/alohaeditor/Aloha-Editor/issues/474
87
+ preferTextRange: true
88
+ }
89
+ };
90
+
91
+ function fail(reason) {
92
+ window.alert("Rangy not supported in your browser. Reason: " + reason);
93
+ api.initialized = true;
94
+ api.supported = false;
95
+ }
96
+
97
+ api.fail = fail;
98
+
99
+ function warn(msg) {
100
+ var warningMessage = "Rangy warning: " + msg;
101
+ if (api.config.alertOnWarn) {
102
+ window.alert(warningMessage);
103
+ } else if (typeof window.console != UNDEFINED && typeof window.console.log != UNDEFINED) {
104
+ window.console.log(warningMessage);
105
+ }
106
+ }
107
+
108
+ api.warn = warn;
109
+
110
+ if ({}.hasOwnProperty) {
111
+ api.util.extend = function (o, props) {
112
+ for (var i in props) {
113
+ if (props.hasOwnProperty(i)) {
114
+ o[i] = props[i];
115
+ }
116
+ }
117
+ };
118
+ } else {
119
+ fail("hasOwnProperty not supported");
120
+ }
121
+
122
+ var initListeners = [];
123
+ var moduleInitializers = [];
124
+
125
+ // Initialization
126
+ function init() {
127
+ if (api.initialized) {
128
+ return;
129
+ }
130
+ var testRange;
131
+ var implementsDomRange = false,
132
+ implementsTextRange = false;
133
+
134
+ // First, perform basic feature tests
135
+
136
+ if (isHostMethod(document, "createRange")) {
137
+ testRange = document.createRange();
138
+ if (areHostMethods(testRange, domRangeMethods) && areHostProperties(testRange, domRangeProperties)) {
139
+ implementsDomRange = true;
140
+ }
141
+ testRange.detach();
142
+ }
143
+
144
+ var body = isHostObject(document, "body") ? document.body : document.getElementsByTagName("body")[0];
145
+
146
+ if (body && isHostMethod(body, "createTextRange")) {
147
+ testRange = body.createTextRange();
148
+ if (isTextRange(testRange)) {
149
+ implementsTextRange = true;
150
+ }
151
+ }
152
+
153
+ if (!implementsDomRange && !implementsTextRange) {
154
+ fail("Neither Range nor TextRange are implemented");
155
+ }
156
+
157
+ api.initialized = true;
158
+ api.features = {
159
+ implementsDomRange: implementsDomRange,
160
+ implementsTextRange: implementsTextRange
161
+ };
162
+
163
+ // Initialize modules and call init listeners
164
+ var allListeners = moduleInitializers.concat(initListeners);
165
+ for (var i = 0, len = allListeners.length; i < len; ++i) {
166
+ try {
167
+ allListeners[i](api);
168
+ } catch (ex) {
169
+ if (isHostObject(window, "console") && isHostMethod(window.console, "log")) {
170
+ window.console.log("Init listener threw an exception. Continuing.", ex);
171
+ }
172
+
173
+ }
174
+ }
175
+ }
176
+
177
+ // Allow external scripts to initialize this library in case it's loaded after the document has loaded
178
+ api.init = init;
179
+
180
+ // Execute listener immediately if already initialized
181
+ api.addInitListener = function (listener) {
182
+ if (api.initialized) {
183
+ listener(api);
184
+ } else {
185
+ initListeners.push(listener);
186
+ }
187
+ };
188
+
189
+ var createMissingNativeApiListeners = [];
190
+
191
+ api.addCreateMissingNativeApiListener = function (listener) {
192
+ createMissingNativeApiListeners.push(listener);
193
+ };
194
+
195
+ function createMissingNativeApi(win) {
196
+ win = win || window;
197
+ init();
198
+
199
+ // Notify listeners
200
+ for (var i = 0, len = createMissingNativeApiListeners.length; i < len; ++i) {
201
+ createMissingNativeApiListeners[i](win);
202
+ }
203
+ }
204
+
205
+ api.createMissingNativeApi = createMissingNativeApi;
206
+
207
+ /**
208
+ * @constructor
209
+ */
210
+ function Module(name) {
211
+ this.name = name;
212
+ this.initialized = false;
213
+ this.supported = false;
214
+ }
215
+
216
+ Module.prototype.fail = function (reason) {
217
+ this.initialized = true;
218
+ this.supported = false;
219
+
220
+ throw new Error("Module '" + this.name + "' failed to load: " + reason);
221
+ };
222
+
223
+ Module.prototype.warn = function (msg) {
224
+ api.warn("Module " + this.name + ": " + msg);
225
+ };
226
+
227
+ Module.prototype.createError = function (msg) {
228
+ return new Error("Error in Rangy " + this.name + " module: " + msg);
229
+ };
230
+
231
+ api.createModule = function (name, initFunc) {
232
+ var module = new Module(name);
233
+ api.modules[name] = module;
234
+
235
+ moduleInitializers.push(function (api) {
236
+ initFunc(api, module);
237
+ module.initialized = true;
238
+ module.supported = true;
239
+ });
240
+ };
241
+
242
+ api.requireModules = function (modules) {
243
+ for (var i = 0, len = modules.length, module, moduleName; i < len; ++i) {
244
+ moduleName = modules[i];
245
+ module = api.modules[moduleName];
246
+ if (!module || !(module instanceof Module)) {
247
+ throw new Error("Module '" + moduleName + "' not found");
248
+ }
249
+ if (!module.supported) {
250
+ throw new Error("Module '" + moduleName + "' not supported");
251
+ }
252
+ }
253
+ };
254
+
255
+ /*----------------------------------------------------------------------------------------------------------------*/
256
+
257
+ // Wait for document to load before running tests
258
+
259
+ var docReady = false;
260
+
261
+ var loadHandler = function (e) {
262
+
263
+ if (!docReady) {
264
+ docReady = true;
265
+ if (!api.initialized) {
266
+ init();
267
+ }
268
+ }
269
+ };
270
+
271
+ // Test whether we have window and document objects that we will need
272
+ if (typeof window == UNDEFINED) {
273
+ fail("No window found");
274
+ return;
275
+ }
276
+ if (typeof document == UNDEFINED) {
277
+ fail("No document found");
278
+ return;
279
+ }
280
+
281
+ if (isHostMethod(document, "addEventListener")) {
282
+ document.addEventListener("DOMContentLoaded", loadHandler, false);
283
+ }
284
+
285
+ // Add a fallback in case the DOMContentLoaded event isn't supported
286
+ if (isHostMethod(window, "addEventListener")) {
287
+ window.addEventListener("load", loadHandler, false);
288
+ } else if (isHostMethod(window, "attachEvent")) {
289
+ window.attachEvent("onload", loadHandler);
290
+ } else {
291
+ fail("Window does not have required addEventListener or attachEvent method");
292
+ }
293
+
294
+ return api;
295
+ })();
296
+ rangy.createModule("DomUtil", function (api, module) {
297
+
298
+ var UNDEF = "undefined";
299
+ var util = api.util;
300
+
301
+ // Perform feature tests
302
+ if (!util.areHostMethods(document, ["createDocumentFragment", "createElement", "createTextNode"])) {
303
+ module.fail("document missing a Node creation method");
304
+ }
305
+
306
+ if (!util.isHostMethod(document, "getElementsByTagName")) {
307
+ module.fail("document missing getElementsByTagName method");
308
+ }
309
+
310
+ var el = document.createElement("div");
311
+ if (!util.areHostMethods(el, ["insertBefore", "appendChild", "cloneNode"] || !util.areHostObjects(el, ["previousSibling", "nextSibling", "childNodes", "parentNode"]))) {
312
+ module.fail("Incomplete Element implementation");
313
+ }
314
+
315
+ // innerHTML is required for Range's createContextualFragment method
316
+ if (!util.isHostProperty(el, "innerHTML")) {
317
+ module.fail("Element is missing innerHTML property");
318
+ }
319
+
320
+ var textNode = document.createTextNode("test");
321
+ if (!util.areHostMethods(textNode, ["splitText", "deleteData", "insertData", "appendData", "cloneNode"] || !util.areHostObjects(el, ["previousSibling", "nextSibling", "childNodes", "parentNode"]) || !util.areHostProperties(textNode, ["data"]))) {
322
+ module.fail("Incomplete Text Node implementation");
323
+ }
324
+
325
+ /*----------------------------------------------------------------------------------------------------------------*/
326
+
327
+ // Removed use of indexOf because of a bizarre bug in Opera that is thrown in one of the Acid3 tests. I haven't been
328
+ // able to replicate it outside of the test. The bug is that indexOf returns -1 when called on an Array that
329
+ // contains just the document as a single element and the value searched for is the document.
330
+ var arrayContains =
331
+ /*Array.prototype.indexOf ?
332
+ function(arr, val) {
333
+ return arr.indexOf(val) > -1;
334
+ }:*/
335
+
336
+ function (arr, val) {
337
+ var i = arr.length;
338
+ while (i--) {
339
+ if (arr[i] === val) {
340
+ return true;
341
+ }
342
+ }
343
+ return false;
344
+ };
345
+
346
+ // Opera 11 puts HTML elements in the null namespace, it seems, and IE 7 has undefined namespaceURI
347
+ function isHtmlNamespace(node) {
348
+ var ns;
349
+ return typeof node.namespaceURI == UNDEF || ((ns = node.namespaceURI) === null || ns == "http://www.w3.org/1999/xhtml");
350
+ }
351
+
352
+ function parentElement(node) {
353
+ var parent = node.parentNode;
354
+ return (parent.nodeType == 1) ? parent : null;
355
+ }
356
+
357
+ function getNodeIndex(node) {
358
+ var i = 0;
359
+ while ((node = node.previousSibling)) {
360
+ i++;
361
+ }
362
+ return i;
363
+ }
364
+
365
+ function getNodeLength(node) {
366
+ var childNodes;
367
+ return isCharacterDataNode(node) ? node.length : ((childNodes = node.childNodes) ? childNodes.length : 0);
368
+ }
369
+
370
+ function getCommonAncestor(node1, node2) {
371
+ var ancestors = [],
372
+ n;
373
+ for (n = node1; n; n = n.parentNode) {
374
+ ancestors.push(n);
375
+ }
376
+
377
+ for (n = node2; n; n = n.parentNode) {
378
+ if (arrayContains(ancestors, n)) {
379
+ return n;
380
+ }
381
+ }
382
+
383
+ return null;
384
+ }
385
+
386
+ function isAncestorOf(ancestor, descendant, selfIsAncestor) {
387
+ var n = selfIsAncestor ? descendant : descendant.parentNode;
388
+ while (n) {
389
+ if (n === ancestor) {
390
+ return true;
391
+ } else {
392
+ n = n.parentNode;
393
+ }
394
+ }
395
+ return false;
396
+ }
397
+
398
+ function getClosestAncestorIn(node, ancestor, selfIsAncestor) {
399
+ var p, n = selfIsAncestor ? node : node.parentNode;
400
+ while (n) {
401
+ p = n.parentNode;
402
+ if (p === ancestor) {
403
+ return n;
404
+ }
405
+ n = p;
406
+ }
407
+ return null;
408
+ }
409
+
410
+ function isCharacterDataNode(node) {
411
+ var t = node.nodeType;
412
+ return t == 3 || t == 4 || t == 8; // Text, CDataSection or Comment
413
+ }
414
+
415
+ function insertAfter(node, precedingNode) {
416
+ var nextNode = precedingNode.nextSibling,
417
+ parent = precedingNode.parentNode;
418
+ if (nextNode) {
419
+ parent.insertBefore(node, nextNode);
420
+ } else {
421
+ parent.appendChild(node);
422
+ }
423
+ return node;
424
+ }
425
+
426
+ // Note that we cannot use splitText() because it is bugridden in IE 9.
427
+ function splitDataNode(node, index) {
428
+ var newNode = node.cloneNode(false);
429
+ newNode.deleteData(0, index);
430
+ node.deleteData(index, node.length - index);
431
+ insertAfter(newNode, node);
432
+ return newNode;
433
+ }
434
+
435
+ function getDocument(node) {
436
+ if (node.nodeType == 9) {
437
+ return node;
438
+ } else if (typeof node.ownerDocument != UNDEF) {
439
+ return node.ownerDocument;
440
+ } else if (typeof node.document != UNDEF) {
441
+ return node.document;
442
+ } else if (node.parentNode) {
443
+ return getDocument(node.parentNode);
444
+ } else {
445
+ throw new Error("getDocument: no document found for node");
446
+ }
447
+ }
448
+
449
+ function getWindow(node) {
450
+ var doc = getDocument(node);
451
+ if (typeof doc.defaultView != UNDEF) {
452
+ return doc.defaultView;
453
+ } else if (typeof doc.parentWindow != UNDEF) {
454
+ return doc.parentWindow;
455
+ } else {
456
+ throw new Error("Cannot get a window object for node");
457
+ }
458
+ }
459
+
460
+ function getIframeDocument(iframeEl) {
461
+ if (typeof iframeEl.contentDocument != UNDEF) {
462
+ return iframeEl.contentDocument;
463
+ } else if (typeof iframeEl.contentWindow != UNDEF) {
464
+ return iframeEl.contentWindow.document;
465
+ } else {
466
+ throw new Error("getIframeWindow: No Document object found for iframe element");
467
+ }
468
+ }
469
+
470
+ function getIframeWindow(iframeEl) {
471
+ if (typeof iframeEl.contentWindow != UNDEF) {
472
+ return iframeEl.contentWindow;
473
+ } else if (typeof iframeEl.contentDocument != UNDEF) {
474
+ return iframeEl.contentDocument.defaultView;
475
+ } else {
476
+ throw new Error("getIframeWindow: No Window object found for iframe element");
477
+ }
478
+ }
479
+
480
+ function getBody(doc) {
481
+ return util.isHostObject(doc, "body") ? doc.body : doc.getElementsByTagName("body")[0];
482
+ }
483
+
484
+ function getRootContainer(node) {
485
+ var parent;
486
+ while ((parent = node.parentNode)) {
487
+ node = parent;
488
+ }
489
+ return node;
490
+ }
491
+
492
+ /**
493
+ * This is a very ugly workaround for an IE9 issue Before comparing DOM
494
+ * elements "normalize" them. There are cases, where anchorNode and
495
+ * focusNode in a nativeselection point to DOM elements with same
496
+ * parentNode, same previousSibling and same nextSibling, but the nodes
497
+ * themselves are not the same
498
+ * If such nodes are compared in the comparePoints method, an error occurs.
499
+ * To fix this, we move to the previousSibling/nextSibling/parentNode and back, to hopefully get
500
+ * the "correct" node in the DOM
501
+ * @param node node to fix
502
+ * @return normalized node
503
+ */
504
+ function fixNode(node) {
505
+ if (!node) {
506
+ return;
507
+ }
508
+ if (node.previousSibling) {
509
+ return node.previousSibling.nextSibling;
510
+ } else if (node.nextSibling) {
511
+ return node.nextSibling.previousSibling;
512
+ } else if (node.parentNode) {
513
+ return node.parentNode.firstChild;
514
+ } else {
515
+ return node;
516
+ }
517
+ }
518
+
519
+ function comparePoints(nodeA, offsetA, nodeB, offsetB) {
520
+ // fix the nodes before comparing them
521
+ nodeA = fixNode(nodeA);
522
+ nodeB = fixNode(nodeB);
523
+ // See http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Comparing
524
+ var nodeC, root, childA, childB, n;
525
+ if (nodeA == nodeB) {
526
+
527
+ // Case 1: nodes are the same
528
+ return offsetA === offsetB ? 0 : (offsetA < offsetB) ? -1 : 1;
529
+ } else if ((nodeC = getClosestAncestorIn(nodeB, nodeA, true))) {
530
+
531
+ // Case 2: node C (container B or an ancestor) is a child node of A
532
+ return offsetA <= getNodeIndex(nodeC) ? -1 : 1;
533
+ } else if ((nodeC = getClosestAncestorIn(nodeA, nodeB, true))) {
534
+
535
+ // Case 3: node C (container A or an ancestor) is a child node of B
536
+ return getNodeIndex(nodeC) < offsetB ? -1 : 1;
537
+ } else {
538
+
539
+ // Case 4: containers are siblings or descendants of siblings
540
+ root = getCommonAncestor(nodeA, nodeB);
541
+ childA = (nodeA === root) ? root : getClosestAncestorIn(nodeA, root, true);
542
+ childB = (nodeB === root) ? root : getClosestAncestorIn(nodeB, root, true);
543
+
544
+ if (childA === childB) {
545
+ // This shouldn't be possible
546
+
547
+ throw new Error("comparePoints got to case 4 and childA and childB are the same!");
548
+ } else {
549
+ n = root.firstChild;
550
+ while (n) {
551
+ if (n === childA) {
552
+ return -1;
553
+ } else if (n === childB) {
554
+ return 1;
555
+ }
556
+ n = n.nextSibling;
557
+ }
558
+ throw new Error("Should not be here!");
559
+ }
560
+ }
561
+ }
562
+
563
+ function fragmentFromNodeChildren(node) {
564
+ var fragment = getDocument(node).createDocumentFragment(),
565
+ child;
566
+ while ((child = node.firstChild)) {
567
+ fragment.appendChild(child);
568
+ }
569
+ return fragment;
570
+ }
571
+
572
+ function inspectNode(node) {
573
+ if (!node) {
574
+ return "[No node]";
575
+ }
576
+ if (isCharacterDataNode(node)) {
577
+ return '"' + node.data + '"';
578
+ } else if (node.nodeType == 1) {
579
+ var idAttr = node.id ? ' id="' + node.id + '"' : "";
580
+ return "<" + node.nodeName + idAttr + ">[" + node.childNodes.length + "]";
581
+ } else {
582
+ return node.nodeName;
583
+ }
584
+ }
585
+
586
+ /**
587
+ * @constructor
588
+ */
589
+ function NodeIterator(root) {
590
+ this.root = root;
591
+ this._next = root;
592
+ }
593
+
594
+ NodeIterator.prototype = {
595
+ _current: null,
596
+
597
+ hasNext: function () {
598
+ return !!this._next;
599
+ },
600
+
601
+ next: function () {
602
+ var n = this._current = this._next;
603
+ var child, next;
604
+ if (this._current) {
605
+ child = n.firstChild;
606
+ if (child) {
607
+ this._next = child;
608
+ } else {
609
+ next = null;
610
+ while ((n !== this.root) && !(next = n.nextSibling)) {
611
+ n = n.parentNode;
612
+ }
613
+ this._next = next;
614
+ }
615
+ }
616
+ return this._current;
617
+ },
618
+
619
+ detach: function () {
620
+ this._current = this._next = this.root = null;
621
+ }
622
+ };
623
+
624
+ function createIterator(root) {
625
+ return new NodeIterator(root);
626
+ }
627
+
628
+ /**
629
+ * @constructor
630
+ */
631
+ function DomPosition(node, offset) {
632
+ this.node = node;
633
+ this.offset = offset;
634
+ }
635
+
636
+ DomPosition.prototype = {
637
+ equals: function (pos) {
638
+ return this.node === pos.node & this.offset == pos.offset;
639
+ },
640
+
641
+ inspect: function () {
642
+ return "[DomPosition(" + inspectNode(this.node) + ":" + this.offset + ")]";
643
+ }
644
+ };
645
+
646
+ /**
647
+ * @constructor
648
+ */
649
+ function DOMException(codeName) {
650
+ this.code = this[codeName];
651
+ this.codeName = codeName;
652
+ this.message = "DOMException: " + this.codeName;
653
+ }
654
+
655
+ DOMException.prototype = {
656
+ INDEX_SIZE_ERR: 1,
657
+ HIERARCHY_REQUEST_ERR: 3,
658
+ WRONG_DOCUMENT_ERR: 4,
659
+ NO_MODIFICATION_ALLOWED_ERR: 7,
660
+ NOT_FOUND_ERR: 8,
661
+ NOT_SUPPORTED_ERR: 9,
662
+ INVALID_STATE_ERR: 11
663
+ };
664
+
665
+ DOMException.prototype.toString = function () {
666
+ return this.message;
667
+ };
668
+
669
+ api.dom = {
670
+ arrayContains: arrayContains,
671
+ isHtmlNamespace: isHtmlNamespace,
672
+ parentElement: parentElement,
673
+ getNodeIndex: getNodeIndex,
674
+ getNodeLength: getNodeLength,
675
+ getCommonAncestor: getCommonAncestor,
676
+ isAncestorOf: isAncestorOf,
677
+ getClosestAncestorIn: getClosestAncestorIn,
678
+ isCharacterDataNode: isCharacterDataNode,
679
+ insertAfter: insertAfter,
680
+ splitDataNode: splitDataNode,
681
+ getDocument: getDocument,
682
+ getWindow: getWindow,
683
+ getIframeWindow: getIframeWindow,
684
+ getIframeDocument: getIframeDocument,
685
+ getBody: getBody,
686
+ getRootContainer: getRootContainer,
687
+ comparePoints: comparePoints,
688
+ inspectNode: inspectNode,
689
+ fragmentFromNodeChildren: fragmentFromNodeChildren,
690
+ createIterator: createIterator,
691
+ DomPosition: DomPosition
692
+ };
693
+
694
+ api.DOMException = DOMException;
695
+ });
696
+ rangy.createModule("DomRange", function (api, module) {
697
+ api.requireModules(["DomUtil"]);
698
+
699
+
700
+ var dom = api.dom;
701
+ var DomPosition = dom.DomPosition;
702
+ var DOMException = api.DOMException;
703
+
704
+ /*----------------------------------------------------------------------------------------------------------------*/
705
+
706
+ // Utility functions
707
+
708
+ function isNonTextPartiallySelected(node, range) {
709
+ return (node.nodeType != 3) && (dom.isAncestorOf(node, range.startContainer, true) || dom.isAncestorOf(node, range.endContainer, true));
710
+ }
711
+
712
+ function getRangeDocument(range) {
713
+ return dom.getDocument(range.startContainer);
714
+ }
715
+
716
+ function dispatchEvent(range, type, args) {
717
+ var listeners = range._listeners[type];
718
+ if (listeners) {
719
+ for (var i = 0, len = listeners.length; i < len; ++i) {
720
+ listeners[i].call(range, {
721
+ target: range,
722
+ args: args
723
+ });
724
+ }
725
+ }
726
+ }
727
+
728
+ function getBoundaryBeforeNode(node) {
729
+ return new DomPosition(node.parentNode, dom.getNodeIndex(node));
730
+ }
731
+
732
+ function getBoundaryAfterNode(node) {
733
+ return new DomPosition(node.parentNode, dom.getNodeIndex(node) + 1);
734
+ }
735
+
736
+ function insertNodeAtPosition(node, n, o) {
737
+ var firstNodeInserted = node.nodeType == 11 ? node.firstChild : node;
738
+ if (dom.isCharacterDataNode(n)) {
739
+ if (o == n.length) {
740
+ dom.insertAfter(node, n);
741
+ } else {
742
+ n.parentNode.insertBefore(node, o == 0 ? n : dom.splitDataNode(n, o));
743
+ }
744
+ } else if (o >= n.childNodes.length) {
745
+ n.appendChild(node);
746
+ } else {
747
+ n.insertBefore(node, n.childNodes[o]);
748
+ }
749
+ return firstNodeInserted;
750
+ }
751
+
752
+ function cloneSubtree(iterator) {
753
+ var partiallySelected;
754
+ for (var node, frag = getRangeDocument(iterator.range).createDocumentFragment(), subIterator; node = iterator.next();) {
755
+ partiallySelected = iterator.isPartiallySelectedSubtree();
756
+
757
+ node = node.cloneNode(!partiallySelected);
758
+ if (partiallySelected) {
759
+ subIterator = iterator.getSubtreeIterator();
760
+ node.appendChild(cloneSubtree(subIterator));
761
+ subIterator.detach(true);
762
+ }
763
+
764
+ if (node.nodeType == 10) { // DocumentType
765
+ throw new DOMException("HIERARCHY_REQUEST_ERR");
766
+ }
767
+ frag.appendChild(node);
768
+ }
769
+ return frag;
770
+ }
771
+
772
+ function iterateSubtree(rangeIterator, func, iteratorState) {
773
+ var it, n;
774
+ iteratorState = iteratorState || {
775
+ stop: false
776
+ };
777
+ for (var node, subRangeIterator; node = rangeIterator.next();) {
778
+ //log.debug("iterateSubtree, partially selected: " + rangeIterator.isPartiallySelectedSubtree(), nodeToString(node));
779
+ if (rangeIterator.isPartiallySelectedSubtree()) {
780
+ // The node is partially selected by the Range, so we can use a new RangeIterator on the portion of the
781
+ // node selected by the Range.
782
+ if (func(node) === false) {
783
+ iteratorState.stop = true;
784
+ return;
785
+ } else {
786
+ subRangeIterator = rangeIterator.getSubtreeIterator();
787
+ iterateSubtree(subRangeIterator, func, iteratorState);
788
+ subRangeIterator.detach(true);
789
+ if (iteratorState.stop) {
790
+ return;
791
+ }
792
+ }
793
+ } else {
794
+ // The whole node is selected, so we can use efficient DOM iteration to iterate over the node and its
795
+ // descendant
796
+ it = dom.createIterator(node);
797
+ while ((n = it.next())) {
798
+ if (func(n) === false) {
799
+ iteratorState.stop = true;
800
+ return;
801
+ }
802
+ }
803
+ }
804
+ }
805
+ }
806
+
807
+ function deleteSubtree(iterator) {
808
+ var subIterator;
809
+ while (iterator.next()) {
810
+ if (iterator.isPartiallySelectedSubtree()) {
811
+ subIterator = iterator.getSubtreeIterator();
812
+ deleteSubtree(subIterator);
813
+ subIterator.detach(true);
814
+ } else {
815
+ iterator.remove();
816
+ }
817
+ }
818
+ }
819
+
820
+ function extractSubtree(iterator) {
821
+
822
+ for (var node, frag = getRangeDocument(iterator.range).createDocumentFragment(), subIterator; node = iterator.next();) {
823
+
824
+
825
+ if (iterator.isPartiallySelectedSubtree()) {
826
+ node = node.cloneNode(false);
827
+ subIterator = iterator.getSubtreeIterator();
828
+ node.appendChild(extractSubtree(subIterator));
829
+ subIterator.detach(true);
830
+ } else {
831
+ iterator.remove();
832
+ }
833
+ if (node.nodeType == 10) { // DocumentType
834
+ throw new DOMException("HIERARCHY_REQUEST_ERR");
835
+ }
836
+ frag.appendChild(node);
837
+ }
838
+ return frag;
839
+ }
840
+
841
+ function getNodesInRange(range, nodeTypes, filter) {
842
+ //log.info("getNodesInRange, " + nodeTypes.join(","));
843
+ var filterNodeTypes = !! (nodeTypes && nodeTypes.length),
844
+ regex;
845
+ var filterExists = !! filter;
846
+ if (filterNodeTypes) {
847
+ regex = new RegExp("^(" + nodeTypes.join("|") + ")$");
848
+ }
849
+
850
+ var nodes = [];
851
+ iterateSubtree(new RangeIterator(range, false), function (node) {
852
+ if ((!filterNodeTypes || regex.test(node.nodeType)) && (!filterExists || filter(node))) {
853
+ nodes.push(node);
854
+ }
855
+ });
856
+ return nodes;
857
+ }
858
+
859
+ function inspect(range) {
860
+ var name = (typeof range.getName == "undefined") ? "Range" : range.getName();
861
+ return "[" + name + "(" + dom.inspectNode(range.startContainer) + ":" + range.startOffset + ", " + dom.inspectNode(range.endContainer) + ":" + range.endOffset + ")]";
862
+ }
863
+
864
+ /*----------------------------------------------------------------------------------------------------------------*/
865
+
866
+ // RangeIterator code partially borrows from IERange by Tim Ryan (http://github.com/timcameronryan/IERange)
867
+
868
+ /**
869
+ * @constructor
870
+ */
871
+ function RangeIterator(range, clonePartiallySelectedTextNodes) {
872
+ this.range = range;
873
+ this.clonePartiallySelectedTextNodes = clonePartiallySelectedTextNodes;
874
+
875
+
876
+
877
+ if (!range.collapsed) {
878
+ this.sc = range.startContainer;
879
+ this.so = range.startOffset;
880
+ this.ec = range.endContainer;
881
+ this.eo = range.endOffset;
882
+ var root = range.commonAncestorContainer;
883
+
884
+ if (this.sc === this.ec && dom.isCharacterDataNode(this.sc)) {
885
+ this.isSingleCharacterDataNode = true;
886
+ this._first = this._last = this._next = this.sc;
887
+ } else {
888
+ this._first = this._next = (this.sc === root && !dom.isCharacterDataNode(this.sc)) ? this.sc.childNodes[this.so] : dom.getClosestAncestorIn(this.sc, root, true);
889
+ this._last = (this.ec === root && !dom.isCharacterDataNode(this.ec)) ? this.ec.childNodes[this.eo - 1] : dom.getClosestAncestorIn(this.ec, root, true);
890
+ }
891
+
892
+ }
893
+ }
894
+
895
+ RangeIterator.prototype = {
896
+ _current: null,
897
+ _next: null,
898
+ _first: null,
899
+ _last: null,
900
+ isSingleCharacterDataNode: false,
901
+
902
+ reset: function () {
903
+ this._current = null;
904
+ this._next = this._first;
905
+ },
906
+
907
+ hasNext: function () {
908
+ return !!this._next;
909
+ },
910
+
911
+ next: function () {
912
+ // Move to next node
913
+ var current = this._current = this._next;
914
+ if (current) {
915
+ this._next = (current !== this._last) ? current.nextSibling : null;
916
+
917
+ // Check for partially selected text nodes
918
+ if (dom.isCharacterDataNode(current) && this.clonePartiallySelectedTextNodes) {
919
+ if (current === this.ec) {
920
+
921
+ (current = current.cloneNode(true)).deleteData(this.eo, current.length - this.eo);
922
+ }
923
+ if (this._current === this.sc) {
924
+
925
+ (current = current.cloneNode(true)).deleteData(0, this.so);
926
+ }
927
+ }
928
+ }
929
+
930
+ return current;
931
+ },
932
+
933
+ remove: function () {
934
+ var current = this._current,
935
+ start, end;
936
+
937
+ if (dom.isCharacterDataNode(current) && (current === this.sc || current === this.ec)) {
938
+ start = (current === this.sc) ? this.so : 0;
939
+ end = (current === this.ec) ? this.eo : current.length;
940
+ if (start != end) {
941
+ current.deleteData(start, end - start);
942
+ }
943
+ } else {
944
+ if (current.parentNode) {
945
+ current.parentNode.removeChild(current);
946
+ } else {
947
+
948
+ }
949
+ }
950
+ },
951
+
952
+ // Checks if the current node is partially selected
953
+ isPartiallySelectedSubtree: function () {
954
+ var current = this._current;
955
+ return isNonTextPartiallySelected(current, this.range);
956
+ },
957
+
958
+ getSubtreeIterator: function () {
959
+ var subRange;
960
+ if (this.isSingleCharacterDataNode) {
961
+ subRange = this.range.cloneRange();
962
+ subRange.collapse();
963
+ } else {
964
+ subRange = new Range(getRangeDocument(this.range));
965
+ var current = this._current;
966
+ var startContainer = current,
967
+ startOffset = 0,
968
+ endContainer = current,
969
+ endOffset = dom.getNodeLength(current);
970
+
971
+ if (dom.isAncestorOf(current, this.sc, true)) {
972
+ startContainer = this.sc;
973
+ startOffset = this.so;
974
+ }
975
+ if (dom.isAncestorOf(current, this.ec, true)) {
976
+ endContainer = this.ec;
977
+ endOffset = this.eo;
978
+ }
979
+
980
+ updateBoundaries(subRange, startContainer, startOffset, endContainer, endOffset);
981
+ }
982
+ return new RangeIterator(subRange, this.clonePartiallySelectedTextNodes);
983
+ },
984
+
985
+ detach: function (detachRange) {
986
+ if (detachRange) {
987
+ this.range.detach();
988
+ }
989
+ this.range = this._current = this._next = this._first = this._last = this.sc = this.so = this.ec = this.eo = null;
990
+ }
991
+ };
992
+
993
+ /*----------------------------------------------------------------------------------------------------------------*/
994
+
995
+ // Exceptions
996
+
997
+ /**
998
+ * @constructor
999
+ */
1000
+ function RangeException(codeName) {
1001
+ this.code = this[codeName];
1002
+ this.codeName = codeName;
1003
+ this.message = "RangeException: " + this.codeName;
1004
+ }
1005
+
1006
+ RangeException.prototype = {
1007
+ BAD_BOUNDARYPOINTS_ERR: 1,
1008
+ INVALID_NODE_TYPE_ERR: 2
1009
+ };
1010
+
1011
+ RangeException.prototype.toString = function () {
1012
+ return this.message;
1013
+ };
1014
+
1015
+ /*----------------------------------------------------------------------------------------------------------------*/
1016
+
1017
+ /**
1018
+ * Currently iterates through all nodes in the range on creation until I think of a decent way to do it
1019
+ * TODO: Look into making this a proper iterator, not requiring preloading everything first
1020
+ * @constructor
1021
+ */
1022
+ function RangeNodeIterator(range, nodeTypes, filter) {
1023
+ this.nodes = getNodesInRange(range, nodeTypes, filter);
1024
+ this._next = this.nodes[0];
1025
+ this._position = 0;
1026
+ }
1027
+
1028
+ RangeNodeIterator.prototype = {
1029
+ _current: null,
1030
+
1031
+ hasNext: function () {
1032
+ return !!this._next;
1033
+ },
1034
+
1035
+ next: function () {
1036
+ this._current = this._next;
1037
+ this._next = this.nodes[++this._position];
1038
+ return this._current;
1039
+ },
1040
+
1041
+ detach: function () {
1042
+ this._current = this._next = this.nodes = null;
1043
+ }
1044
+ };
1045
+
1046
+ var beforeAfterNodeTypes = [1, 3, 4, 5, 7, 8, 10];
1047
+ var rootContainerNodeTypes = [2, 9, 11];
1048
+ var readonlyNodeTypes = [5, 6, 10, 12];
1049
+ var insertableNodeTypes = [1, 3, 4, 5, 7, 8, 10, 11];
1050
+ var surroundNodeTypes = [1, 3, 4, 5, 7, 8];
1051
+
1052
+ function createAncestorFinder(nodeTypes) {
1053
+ return function (node, selfIsAncestor) {
1054
+ var t, n = selfIsAncestor ? node : node.parentNode;
1055
+ while (n) {
1056
+ t = n.nodeType;
1057
+ if (dom.arrayContains(nodeTypes, t)) {
1058
+ return n;
1059
+ }
1060
+ n = n.parentNode;
1061
+ }
1062
+ return null;
1063
+ };
1064
+ }
1065
+
1066
+ var getRootContainer = dom.getRootContainer;
1067
+ var getDocumentOrFragmentContainer = createAncestorFinder([9, 11]);
1068
+ var getReadonlyAncestor = createAncestorFinder(readonlyNodeTypes);
1069
+ var getDocTypeNotationEntityAncestor = createAncestorFinder([6, 10, 12]);
1070
+
1071
+ function assertNoDocTypeNotationEntityAncestor(node, allowSelf) {
1072
+ if (getDocTypeNotationEntityAncestor(node, allowSelf)) {
1073
+ throw new RangeException("INVALID_NODE_TYPE_ERR");
1074
+ }
1075
+ }
1076
+
1077
+ function assertNotDetached(range) {
1078
+ if (!range.startContainer) {
1079
+ throw new DOMException("INVALID_STATE_ERR");
1080
+ }
1081
+ }
1082
+
1083
+ function assertValidNodeType(node, invalidTypes) {
1084
+ if (!dom.arrayContains(invalidTypes, node.nodeType)) {
1085
+ throw new RangeException("INVALID_NODE_TYPE_ERR");
1086
+ }
1087
+ }
1088
+
1089
+ function assertValidOffset(node, offset) {
1090
+ if (offset < 0 || offset > (dom.isCharacterDataNode(node) ? node.length : node.childNodes.length)) {
1091
+ throw new DOMException("INDEX_SIZE_ERR");
1092
+ }
1093
+ }
1094
+
1095
+ function assertSameDocumentOrFragment(node1, node2) {
1096
+ if (getDocumentOrFragmentContainer(node1, true) !== getDocumentOrFragmentContainer(node2, true)) {
1097
+ throw new DOMException("WRONG_DOCUMENT_ERR");
1098
+ }
1099
+ }
1100
+
1101
+ function assertNodeNotReadOnly(node) {
1102
+ if (getReadonlyAncestor(node, true)) {
1103
+ throw new DOMException("NO_MODIFICATION_ALLOWED_ERR");
1104
+ }
1105
+ }
1106
+
1107
+ function assertNode(node, codeName) {
1108
+ if (!node) {
1109
+ throw new DOMException(codeName);
1110
+ }
1111
+ }
1112
+
1113
+ function isOrphan(node) {
1114
+ return !dom.arrayContains(rootContainerNodeTypes, node.nodeType) && !getDocumentOrFragmentContainer(node, true);
1115
+ }
1116
+
1117
+ function isValidOffset(node, offset) {
1118
+ return offset <= (dom.isCharacterDataNode(node) ? node.length : node.childNodes.length);
1119
+ }
1120
+
1121
+ function assertRangeValid(range) {
1122
+ assertNotDetached(range);
1123
+ if (isOrphan(range.startContainer) || isOrphan(range.endContainer) || !isValidOffset(range.startContainer, range.startOffset) || !isValidOffset(range.endContainer, range.endOffset)) {
1124
+ throw new Error("Range error: Range is no longer valid after DOM mutation (" + range.inspect() + ")");
1125
+ }
1126
+ }
1127
+
1128
+ /*----------------------------------------------------------------------------------------------------------------*/
1129
+
1130
+ // Test the browser's innerHTML support to decide how to implement createContextualFragment
1131
+ var styleEl = document.createElement("style");
1132
+ var htmlParsingConforms = false;
1133
+ try {
1134
+ styleEl.innerHTML = "<b>x</b>";
1135
+ htmlParsingConforms = (styleEl.firstChild.nodeType == 3); // Opera incorrectly creates an element node
1136
+ } catch (e) {
1137
+ // IE 6 and 7 throw
1138
+ }
1139
+
1140
+ api.features.htmlParsingConforms = htmlParsingConforms;
1141
+
1142
+ var createContextualFragment = htmlParsingConforms ?
1143
+
1144
+ // Implementation as per HTML parsing spec, trusting in the browser's implementation of innerHTML. See
1145
+ // discussion and base code for this implementation at issue 67.
1146
+ // Spec: http://html5.org/specs/dom-parsing.html#extensions-to-the-range-interface
1147
+ // Thanks to Aleks Williams.
1148
+ function (fragmentStr) {
1149
+ // "Let node the context object's start's node."
1150
+ var node = this.startContainer;
1151
+ var doc = dom.getDocument(node);
1152
+
1153
+ // "If the context object's start's node is null, raise an INVALID_STATE_ERR
1154
+ // exception and abort these steps."
1155
+ if (!node) {
1156
+ throw new DOMException("INVALID_STATE_ERR");
1157
+ }
1158
+
1159
+ // "Let element be as follows, depending on node's interface:"
1160
+ // Document, Document Fragment: null
1161
+ var el = null;
1162
+
1163
+ // "Element: node"
1164
+ if (node.nodeType == 1) {
1165
+ el = node;
1166
+
1167
+ // "Text, Comment: node's parentElement"
1168
+ } else if (dom.isCharacterDataNode(node)) {
1169
+ el = dom.parentElement(node);
1170
+ }
1171
+
1172
+ // "If either element is null or element's ownerDocument is an HTML document
1173
+ // and element's local name is "html" and element's namespace is the HTML
1174
+ // namespace"
1175
+ if (el === null || (
1176
+ el.nodeName == "HTML" && dom.isHtmlNamespace(dom.getDocument(el).documentElement) && dom.isHtmlNamespace(el))) {
1177
+
1178
+ // "let element be a new Element with "body" as its local name and the HTML
1179
+ // namespace as its namespace.""
1180
+ el = doc.createElement("body");
1181
+ } else {
1182
+ el = el.cloneNode(false);
1183
+ }
1184
+
1185
+ // "If the node's document is an HTML document: Invoke the HTML fragment parsing algorithm."
1186
+ // "If the node's document is an XML document: Invoke the XML fragment parsing algorithm."
1187
+ // "In either case, the algorithm must be invoked with fragment as the input
1188
+ // and element as the context element."
1189
+ el.innerHTML = fragmentStr;
1190
+
1191
+ // "If this raises an exception, then abort these steps. Otherwise, let new
1192
+ // children be the nodes returned."
1193
+
1194
+ // "Let fragment be a new DocumentFragment."
1195
+ // "Append all new children to fragment."
1196
+ // "Return fragment."
1197
+ return dom.fragmentFromNodeChildren(el);
1198
+ } :
1199
+
1200
+ // In this case, innerHTML cannot be trusted, so fall back to a simpler, non-conformant implementation that
1201
+ // previous versions of Rangy used (with the exception of using a body element rather than a div)
1202
+ function (fragmentStr) {
1203
+ assertNotDetached(this);
1204
+ var doc = getRangeDocument(this);
1205
+ var el = doc.createElement("body");
1206
+ el.innerHTML = fragmentStr;
1207
+
1208
+ return dom.fragmentFromNodeChildren(el);
1209
+ };
1210
+
1211
+ /*----------------------------------------------------------------------------------------------------------------*/
1212
+
1213
+ var rangeProperties = ["startContainer", "startOffset", "endContainer", "endOffset", "collapsed", "commonAncestorContainer"];
1214
+
1215
+ var s2s = 0,
1216
+ s2e = 1,
1217
+ e2e = 2,
1218
+ e2s = 3;
1219
+ var n_b = 0,
1220
+ n_a = 1,
1221
+ n_b_a = 2,
1222
+ n_i = 3;
1223
+
1224
+ function RangePrototype() {}
1225
+
1226
+ RangePrototype.prototype = {
1227
+ attachListener: function (type, listener) {
1228
+ this._listeners[type].push(listener);
1229
+ },
1230
+
1231
+ compareBoundaryPoints: function (how, range) {
1232
+ assertRangeValid(this);
1233
+ assertSameDocumentOrFragment(this.startContainer, range.startContainer);
1234
+
1235
+ var nodeA, offsetA, nodeB, offsetB;
1236
+ var prefixA = (how == e2s || how == s2s) ? "start" : "end";
1237
+ var prefixB = (how == s2e || how == s2s) ? "start" : "end";
1238
+ nodeA = this[prefixA + "Container"];
1239
+ offsetA = this[prefixA + "Offset"];
1240
+ nodeB = range[prefixB + "Container"];
1241
+ offsetB = range[prefixB + "Offset"];
1242
+ return dom.comparePoints(nodeA, offsetA, nodeB, offsetB);
1243
+ },
1244
+
1245
+ insertNode: function (node) {
1246
+ assertRangeValid(this);
1247
+ assertValidNodeType(node, insertableNodeTypes);
1248
+ assertNodeNotReadOnly(this.startContainer);
1249
+
1250
+ if (dom.isAncestorOf(node, this.startContainer, true)) {
1251
+ throw new DOMException("HIERARCHY_REQUEST_ERR");
1252
+ }
1253
+
1254
+ // No check for whether the container of the start of the Range is of a type that does not allow
1255
+ // children of the type of node: the browser's DOM implementation should do this for us when we attempt
1256
+ // to add the node
1257
+
1258
+ var firstNodeInserted = insertNodeAtPosition(node, this.startContainer, this.startOffset);
1259
+ this.setStartBefore(firstNodeInserted);
1260
+ },
1261
+
1262
+ cloneContents: function () {
1263
+ assertRangeValid(this);
1264
+
1265
+ var clone, frag;
1266
+ if (this.collapsed) {
1267
+ return getRangeDocument(this).createDocumentFragment();
1268
+ } else {
1269
+ if (this.startContainer === this.endContainer && dom.isCharacterDataNode(this.startContainer)) {
1270
+ clone = this.startContainer.cloneNode(true);
1271
+ clone.data = clone.data.slice(this.startOffset, this.endOffset);
1272
+ frag = getRangeDocument(this).createDocumentFragment();
1273
+ frag.appendChild(clone);
1274
+ return frag;
1275
+ } else {
1276
+ var iterator = new RangeIterator(this, true);
1277
+ clone = cloneSubtree(iterator);
1278
+ iterator.detach();
1279
+ }
1280
+ return clone;
1281
+ }
1282
+ },
1283
+
1284
+ canSurroundContents: function () {
1285
+ assertRangeValid(this);
1286
+ assertNodeNotReadOnly(this.startContainer);
1287
+ assertNodeNotReadOnly(this.endContainer);
1288
+
1289
+ // Check if the contents can be surrounded. Specifically, this means whether the range partially selects
1290
+ // no non-text nodes.
1291
+ var iterator = new RangeIterator(this, true);
1292
+ var boundariesInvalid = (iterator._first && (isNonTextPartiallySelected(iterator._first, this)) || (iterator._last && isNonTextPartiallySelected(iterator._last, this)));
1293
+ iterator.detach();
1294
+ return !boundariesInvalid;
1295
+ },
1296
+
1297
+ surroundContents: function (node) {
1298
+ assertValidNodeType(node, surroundNodeTypes);
1299
+
1300
+ if (!this.canSurroundContents()) {
1301
+ throw new RangeException("BAD_BOUNDARYPOINTS_ERR");
1302
+ }
1303
+
1304
+ // Extract the contents
1305
+ var content = this.extractContents();
1306
+
1307
+ // Clear the children of the node
1308
+ if (node.hasChildNodes()) {
1309
+ while (node.lastChild) {
1310
+ node.removeChild(node.lastChild);
1311
+ }
1312
+ }
1313
+
1314
+ // Insert the new node and add the extracted contents
1315
+ insertNodeAtPosition(node, this.startContainer, this.startOffset);
1316
+ node.appendChild(content);
1317
+
1318
+ this.selectNode(node);
1319
+ },
1320
+
1321
+ cloneRange: function () {
1322
+ assertRangeValid(this);
1323
+ var range = new Range(getRangeDocument(this));
1324
+ var i = rangeProperties.length,
1325
+ prop;
1326
+ while (i--) {
1327
+ prop = rangeProperties[i];
1328
+ range[prop] = this[prop];
1329
+ }
1330
+ return range;
1331
+ },
1332
+
1333
+ toString: function () {
1334
+ assertRangeValid(this);
1335
+ var sc = this.startContainer;
1336
+ if (sc === this.endContainer && dom.isCharacterDataNode(sc)) {
1337
+ return (sc.nodeType == 3 || sc.nodeType == 4) ? sc.data.slice(this.startOffset, this.endOffset) : "";
1338
+ } else {
1339
+ var textBits = [],
1340
+ iterator = new RangeIterator(this, true);
1341
+
1342
+ iterateSubtree(iterator, function (node) {
1343
+ // Accept only text or CDATA nodes, not comments
1344
+
1345
+ if (node.nodeType == 3 || node.nodeType == 4) {
1346
+ textBits.push(node.data);
1347
+ }
1348
+ });
1349
+ iterator.detach();
1350
+ return textBits.join("");
1351
+ }
1352
+ },
1353
+
1354
+ // The methods below are all non-standard. The following batch were introduced by Mozilla but have since
1355
+ // been removed from Mozilla.
1356
+
1357
+ compareNode: function (node) {
1358
+ assertRangeValid(this);
1359
+
1360
+ var parent = node.parentNode;
1361
+ var nodeIndex = dom.getNodeIndex(node);
1362
+
1363
+ if (!parent) {
1364
+ throw new DOMException("NOT_FOUND_ERR");
1365
+ }
1366
+
1367
+ var startComparison = this.comparePoint(parent, nodeIndex),
1368
+ endComparison = this.comparePoint(parent, nodeIndex + 1);
1369
+
1370
+ if (startComparison < 0) { // Node starts before
1371
+ return (endComparison > 0) ? n_b_a : n_b;
1372
+ } else {
1373
+ return (endComparison > 0) ? n_a : n_i;
1374
+ }
1375
+ },
1376
+
1377
+ comparePoint: function (node, offset) {
1378
+ assertRangeValid(this);
1379
+ assertNode(node, "HIERARCHY_REQUEST_ERR");
1380
+ assertSameDocumentOrFragment(node, this.startContainer);
1381
+
1382
+ if (dom.comparePoints(node, offset, this.startContainer, this.startOffset) < 0) {
1383
+ return -1;
1384
+ } else if (dom.comparePoints(node, offset, this.endContainer, this.endOffset) > 0) {
1385
+ return 1;
1386
+ }
1387
+ return 0;
1388
+ },
1389
+
1390
+ createContextualFragment: createContextualFragment,
1391
+
1392
+ toHtml: function () {
1393
+ assertRangeValid(this);
1394
+ var container = getRangeDocument(this).createElement("div");
1395
+ container.appendChild(this.cloneContents());
1396
+ return container.innerHTML;
1397
+ },
1398
+
1399
+ // touchingIsIntersecting determines whether this method considers a node that borders a range intersects
1400
+ // with it (as in WebKit) or not (as in Gecko pre-1.9, and the default)
1401
+ intersectsNode: function (node, touchingIsIntersecting) {
1402
+ assertRangeValid(this);
1403
+ assertNode(node, "NOT_FOUND_ERR");
1404
+ if (dom.getDocument(node) !== getRangeDocument(this)) {
1405
+ return false;
1406
+ }
1407
+
1408
+ var parent = node.parentNode,
1409
+ offset = dom.getNodeIndex(node);
1410
+ assertNode(parent, "NOT_FOUND_ERR");
1411
+
1412
+ var startComparison = dom.comparePoints(parent, offset, this.endContainer, this.endOffset),
1413
+ endComparison = dom.comparePoints(parent, offset + 1, this.startContainer, this.startOffset);
1414
+
1415
+ return touchingIsIntersecting ? startComparison <= 0 && endComparison >= 0 : startComparison < 0 && endComparison > 0;
1416
+ },
1417
+
1418
+
1419
+ isPointInRange: function (node, offset) {
1420
+ assertRangeValid(this);
1421
+ assertNode(node, "HIERARCHY_REQUEST_ERR");
1422
+ assertSameDocumentOrFragment(node, this.startContainer);
1423
+
1424
+ return (dom.comparePoints(node, offset, this.startContainer, this.startOffset) >= 0) && (dom.comparePoints(node, offset, this.endContainer, this.endOffset) <= 0);
1425
+ },
1426
+
1427
+ // The methods below are non-standard and invented by me.
1428
+
1429
+ // Sharing a boundary start-to-end or end-to-start does not count as intersection.
1430
+ intersectsRange: function (range, touchingIsIntersecting) {
1431
+ assertRangeValid(this);
1432
+
1433
+ if (getRangeDocument(range) != getRangeDocument(this)) {
1434
+ throw new DOMException("WRONG_DOCUMENT_ERR");
1435
+ }
1436
+
1437
+ var startComparison = dom.comparePoints(this.startContainer, this.startOffset, range.endContainer, range.endOffset),
1438
+ endComparison = dom.comparePoints(this.endContainer, this.endOffset, range.startContainer, range.startOffset);
1439
+
1440
+ return touchingIsIntersecting ? startComparison <= 0 && endComparison >= 0 : startComparison < 0 && endComparison > 0;
1441
+ },
1442
+
1443
+ intersection: function (range) {
1444
+ if (this.intersectsRange(range)) {
1445
+ var startComparison = dom.comparePoints(this.startContainer, this.startOffset, range.startContainer, range.startOffset),
1446
+ endComparison = dom.comparePoints(this.endContainer, this.endOffset, range.endContainer, range.endOffset);
1447
+
1448
+ var intersectionRange = this.cloneRange();
1449
+
1450
+ if (startComparison == -1) {
1451
+ intersectionRange.setStart(range.startContainer, range.startOffset);
1452
+ }
1453
+ if (endComparison == 1) {
1454
+ intersectionRange.setEnd(range.endContainer, range.endOffset);
1455
+ }
1456
+ return intersectionRange;
1457
+ }
1458
+ return null;
1459
+ },
1460
+
1461
+ union: function (range) {
1462
+ if (this.intersectsRange(range, true)) {
1463
+ var unionRange = this.cloneRange();
1464
+ if (dom.comparePoints(range.startContainer, range.startOffset, this.startContainer, this.startOffset) == -1) {
1465
+ unionRange.setStart(range.startContainer, range.startOffset);
1466
+ }
1467
+ if (dom.comparePoints(range.endContainer, range.endOffset, this.endContainer, this.endOffset) == 1) {
1468
+ unionRange.setEnd(range.endContainer, range.endOffset);
1469
+ }
1470
+ return unionRange;
1471
+ } else {
1472
+ throw new RangeException("Ranges do not intersect");
1473
+ }
1474
+ },
1475
+
1476
+ containsNode: function (node, allowPartial) {
1477
+ if (allowPartial) {
1478
+ return this.intersectsNode(node, false);
1479
+ } else {
1480
+ return this.compareNode(node) == n_i;
1481
+ }
1482
+ },
1483
+
1484
+ containsNodeContents: function (node) {
1485
+ return this.comparePoint(node, 0) >= 0 && this.comparePoint(node, dom.getNodeLength(node)) <= 0;
1486
+ },
1487
+
1488
+ containsRange: function (range) {
1489
+ return this.intersection(range).equals(range);
1490
+ },
1491
+
1492
+ containsNodeText: function (node) {
1493
+ var nodeRange = this.cloneRange();
1494
+ nodeRange.selectNode(node);
1495
+ var textNodes = nodeRange.getNodes([3]);
1496
+ if (textNodes.length > 0) {
1497
+ nodeRange.setStart(textNodes[0], 0);
1498
+ var lastTextNode = textNodes.pop();
1499
+ nodeRange.setEnd(lastTextNode, lastTextNode.length);
1500
+ var contains = this.containsRange(nodeRange);
1501
+ nodeRange.detach();
1502
+ return contains;
1503
+ } else {
1504
+ return this.containsNodeContents(node);
1505
+ }
1506
+ },
1507
+
1508
+ createNodeIterator: function (nodeTypes, filter) {
1509
+ assertRangeValid(this);
1510
+ return new RangeNodeIterator(this, nodeTypes, filter);
1511
+ },
1512
+
1513
+ getNodes: function (nodeTypes, filter) {
1514
+ assertRangeValid(this);
1515
+ return getNodesInRange(this, nodeTypes, filter);
1516
+ },
1517
+
1518
+ getDocument: function () {
1519
+ return getRangeDocument(this);
1520
+ },
1521
+
1522
+ collapseBefore: function (node) {
1523
+ assertNotDetached(this);
1524
+
1525
+ this.setEndBefore(node);
1526
+ this.collapse(false);
1527
+ },
1528
+
1529
+ collapseAfter: function (node) {
1530
+ assertNotDetached(this);
1531
+
1532
+ this.setStartAfter(node);
1533
+ this.collapse(true);
1534
+ },
1535
+
1536
+ getName: function () {
1537
+ return "DomRange";
1538
+ },
1539
+
1540
+ equals: function (range) {
1541
+ return Range.rangesEqual(this, range);
1542
+ },
1543
+
1544
+ inspect: function () {
1545
+ return inspect(this);
1546
+ }
1547
+ };
1548
+
1549
+ function copyComparisonConstantsToObject(obj) {
1550
+ obj.START_TO_START = s2s;
1551
+ obj.START_TO_END = s2e;
1552
+ obj.END_TO_END = e2e;
1553
+ obj.END_TO_START = e2s;
1554
+
1555
+ obj.NODE_BEFORE = n_b;
1556
+ obj.NODE_AFTER = n_a;
1557
+ obj.NODE_BEFORE_AND_AFTER = n_b_a;
1558
+ obj.NODE_INSIDE = n_i;
1559
+ }
1560
+
1561
+ function copyComparisonConstants(constructor) {
1562
+ copyComparisonConstantsToObject(constructor);
1563
+ copyComparisonConstantsToObject(constructor.prototype);
1564
+ }
1565
+
1566
+ function createRangeContentRemover(remover, boundaryUpdater) {
1567
+ return function () {
1568
+ assertRangeValid(this);
1569
+
1570
+ var sc = this.startContainer,
1571
+ so = this.startOffset,
1572
+ root = this.commonAncestorContainer;
1573
+
1574
+ var iterator = new RangeIterator(this, true);
1575
+
1576
+ // Work out where to position the range after content removal
1577
+ var node, boundary;
1578
+ if (sc !== root) {
1579
+ node = dom.getClosestAncestorIn(sc, root, true);
1580
+ boundary = getBoundaryAfterNode(node);
1581
+ sc = boundary.node;
1582
+ so = boundary.offset;
1583
+ }
1584
+
1585
+ // Check none of the range is read-only
1586
+ iterateSubtree(iterator, assertNodeNotReadOnly);
1587
+
1588
+ iterator.reset();
1589
+
1590
+ // Remove the content
1591
+ var returnValue = remover(iterator);
1592
+ iterator.detach();
1593
+
1594
+ // Move to the new position
1595
+ boundaryUpdater(this, sc, so, sc, so);
1596
+
1597
+ return returnValue;
1598
+ };
1599
+ }
1600
+
1601
+ function createPrototypeRange(constructor, boundaryUpdater, detacher) {
1602
+ function createBeforeAfterNodeSetter(isBefore, isStart) {
1603
+ return function (node) {
1604
+ assertNotDetached(this);
1605
+ assertValidNodeType(node, beforeAfterNodeTypes);
1606
+ assertValidNodeType(getRootContainer(node), rootContainerNodeTypes);
1607
+
1608
+ var boundary = (isBefore ? getBoundaryBeforeNode : getBoundaryAfterNode)(node);
1609
+ (isStart ? setRangeStart : setRangeEnd)(this, boundary.node, boundary.offset);
1610
+ };
1611
+ }
1612
+
1613
+ function setRangeStart(range, node, offset) {
1614
+ var ec = range.endContainer,
1615
+ eo = range.endOffset;
1616
+ if (node !== range.startContainer || offset !== this.startOffset) {
1617
+ // Check the root containers of the range and the new boundary, and also check whether the new boundary
1618
+ // is after the current end. In either case, collapse the range to the new position
1619
+ if (getRootContainer(node) != getRootContainer(ec) || dom.comparePoints(node, offset, ec, eo) == 1) {
1620
+ ec = node;
1621
+ eo = offset;
1622
+ }
1623
+ boundaryUpdater(range, node, offset, ec, eo);
1624
+ }
1625
+ }
1626
+
1627
+ function setRangeEnd(range, node, offset) {
1628
+ var sc = range.startContainer,
1629
+ so = range.startOffset;
1630
+ if (node !== range.endContainer || offset !== this.endOffset) {
1631
+ // Check the root containers of the range and the new boundary, and also check whether the new boundary
1632
+ // is after the current end. In either case, collapse the range to the new position
1633
+ if (getRootContainer(node) != getRootContainer(sc) || dom.comparePoints(node, offset, sc, so) == -1) {
1634
+ sc = node;
1635
+ so = offset;
1636
+ }
1637
+ boundaryUpdater(range, sc, so, node, offset);
1638
+ }
1639
+ }
1640
+
1641
+ function setRangeStartAndEnd(range, node, offset) {
1642
+ if (node !== range.startContainer || offset !== this.startOffset || node !== range.endContainer || offset !== this.endOffset) {
1643
+ boundaryUpdater(range, node, offset, node, offset);
1644
+ }
1645
+ }
1646
+
1647
+ constructor.prototype = new RangePrototype();
1648
+
1649
+ api.util.extend(constructor.prototype, {
1650
+ setStart: function (node, offset) {
1651
+ assertNotDetached(this);
1652
+ assertNoDocTypeNotationEntityAncestor(node, true);
1653
+ assertValidOffset(node, offset);
1654
+
1655
+ setRangeStart(this, node, offset);
1656
+ },
1657
+
1658
+ setEnd: function (node, offset) {
1659
+ assertNotDetached(this);
1660
+ assertNoDocTypeNotationEntityAncestor(node, true);
1661
+ assertValidOffset(node, offset);
1662
+
1663
+ setRangeEnd(this, node, offset);
1664
+ },
1665
+
1666
+ setStartBefore: createBeforeAfterNodeSetter(true, true),
1667
+ setStartAfter: createBeforeAfterNodeSetter(false, true),
1668
+ setEndBefore: createBeforeAfterNodeSetter(true, false),
1669
+ setEndAfter: createBeforeAfterNodeSetter(false, false),
1670
+
1671
+ collapse: function (isStart) {
1672
+ assertRangeValid(this);
1673
+ if (isStart) {
1674
+ boundaryUpdater(this, this.startContainer, this.startOffset, this.startContainer, this.startOffset);
1675
+ } else {
1676
+ boundaryUpdater(this, this.endContainer, this.endOffset, this.endContainer, this.endOffset);
1677
+ }
1678
+ },
1679
+
1680
+ selectNodeContents: function (node) {
1681
+ // This doesn't seem well specified: the spec talks only about selecting the node's contents, which
1682
+ // could be taken to mean only its children. However, browsers implement this the same as selectNode for
1683
+ // text nodes, so I shall do likewise
1684
+ assertNotDetached(this);
1685
+ assertNoDocTypeNotationEntityAncestor(node, true);
1686
+
1687
+ boundaryUpdater(this, node, 0, node, dom.getNodeLength(node));
1688
+ },
1689
+
1690
+ selectNode: function (node) {
1691
+ assertNotDetached(this);
1692
+ assertNoDocTypeNotationEntityAncestor(node, false);
1693
+ assertValidNodeType(node, beforeAfterNodeTypes);
1694
+
1695
+ var start = getBoundaryBeforeNode(node),
1696
+ end = getBoundaryAfterNode(node);
1697
+ boundaryUpdater(this, start.node, start.offset, end.node, end.offset);
1698
+ },
1699
+
1700
+ extractContents: createRangeContentRemover(extractSubtree, boundaryUpdater),
1701
+
1702
+ deleteContents: createRangeContentRemover(deleteSubtree, boundaryUpdater),
1703
+
1704
+ canSurroundContents: function () {
1705
+ assertRangeValid(this);
1706
+ assertNodeNotReadOnly(this.startContainer);
1707
+ assertNodeNotReadOnly(this.endContainer);
1708
+
1709
+ // Check if the contents can be surrounded. Specifically, this means whether the range partially selects
1710
+ // no non-text nodes.
1711
+ var iterator = new RangeIterator(this, true);
1712
+ var boundariesInvalid = (iterator._first && (isNonTextPartiallySelected(iterator._first, this)) || (iterator._last && isNonTextPartiallySelected(iterator._last, this)));
1713
+ iterator.detach();
1714
+ return !boundariesInvalid;
1715
+ },
1716
+
1717
+ detach: function () {
1718
+ detacher(this);
1719
+ },
1720
+
1721
+ splitBoundaries: function () {
1722
+ assertRangeValid(this);
1723
+
1724
+
1725
+ var sc = this.startContainer,
1726
+ so = this.startOffset,
1727
+ ec = this.endContainer,
1728
+ eo = this.endOffset;
1729
+ var startEndSame = (sc === ec);
1730
+
1731
+ if (dom.isCharacterDataNode(ec) && eo > 0 && eo < ec.length) {
1732
+ dom.splitDataNode(ec, eo);
1733
+
1734
+ }
1735
+
1736
+ if (dom.isCharacterDataNode(sc) && so > 0 && so < sc.length) {
1737
+
1738
+ sc = dom.splitDataNode(sc, so);
1739
+ if (startEndSame) {
1740
+ eo -= so;
1741
+ ec = sc;
1742
+ } else if (ec == sc.parentNode && eo >= dom.getNodeIndex(sc)) {
1743
+ eo++;
1744
+ }
1745
+ so = 0;
1746
+
1747
+ }
1748
+ boundaryUpdater(this, sc, so, ec, eo);
1749
+ },
1750
+
1751
+ normalizeBoundaries: function () {
1752
+ assertRangeValid(this);
1753
+
1754
+ var sc = this.startContainer,
1755
+ so = this.startOffset,
1756
+ ec = this.endContainer,
1757
+ eo = this.endOffset;
1758
+
1759
+ var mergeForward = function (node) {
1760
+ var sibling = node.nextSibling;
1761
+ if (sibling && sibling.nodeType == node.nodeType) {
1762
+ ec = node;
1763
+ eo = node.length;
1764
+ node.appendData(sibling.data);
1765
+ sibling.parentNode.removeChild(sibling);
1766
+ }
1767
+ };
1768
+
1769
+ var mergeBackward = function (node) {
1770
+ var sibling = node.previousSibling;
1771
+ if (sibling && sibling.nodeType == node.nodeType) {
1772
+ sc = node;
1773
+ var nodeLength = node.length;
1774
+ so = sibling.length;
1775
+ node.insertData(0, sibling.data);
1776
+ sibling.parentNode.removeChild(sibling);
1777
+ if (sc == ec) {
1778
+ eo += so;
1779
+ ec = sc;
1780
+ } else if (ec == node.parentNode) {
1781
+ var nodeIndex = dom.getNodeIndex(node);
1782
+ if (eo == nodeIndex) {
1783
+ ec = node;
1784
+ eo = nodeLength;
1785
+ } else if (eo > nodeIndex) {
1786
+ eo--;
1787
+ }
1788
+ }
1789
+ }
1790
+ };
1791
+
1792
+ var normalizeStart = true;
1793
+
1794
+ if (dom.isCharacterDataNode(ec)) {
1795
+ if (ec.length == eo) {
1796
+ mergeForward(ec);
1797
+ }
1798
+ } else {
1799
+ if (eo > 0) {
1800
+ var endNode = ec.childNodes[eo - 1];
1801
+ if (endNode && dom.isCharacterDataNode(endNode)) {
1802
+ mergeForward(endNode);
1803
+ }
1804
+ }
1805
+ normalizeStart = !this.collapsed;
1806
+ }
1807
+
1808
+ if (normalizeStart) {
1809
+ if (dom.isCharacterDataNode(sc)) {
1810
+ if (so == 0) {
1811
+ mergeBackward(sc);
1812
+ }
1813
+ } else {
1814
+ if (so < sc.childNodes.length) {
1815
+ var startNode = sc.childNodes[so];
1816
+ if (startNode && dom.isCharacterDataNode(startNode)) {
1817
+ mergeBackward(startNode);
1818
+ }
1819
+ }
1820
+ }
1821
+ } else {
1822
+ sc = ec;
1823
+ so = eo;
1824
+ }
1825
+
1826
+ boundaryUpdater(this, sc, so, ec, eo);
1827
+ },
1828
+
1829
+ collapseToPoint: function (node, offset) {
1830
+ assertNotDetached(this);
1831
+
1832
+ assertNoDocTypeNotationEntityAncestor(node, true);
1833
+ assertValidOffset(node, offset);
1834
+
1835
+ setRangeStartAndEnd(this, node, offset);
1836
+ }
1837
+ });
1838
+
1839
+ copyComparisonConstants(constructor);
1840
+ }
1841
+
1842
+ /*----------------------------------------------------------------------------------------------------------------*/
1843
+
1844
+ // Updates commonAncestorContainer and collapsed after boundary change
1845
+ function updateCollapsedAndCommonAncestor(range) {
1846
+ range.collapsed = (range.startContainer === range.endContainer && range.startOffset === range.endOffset);
1847
+ range.commonAncestorContainer = range.collapsed ? range.startContainer : dom.getCommonAncestor(range.startContainer, range.endContainer);
1848
+ }
1849
+
1850
+ function updateBoundaries(range, startContainer, startOffset, endContainer, endOffset) {
1851
+ var startMoved = (range.startContainer !== startContainer || range.startOffset !== startOffset);
1852
+ var endMoved = (range.endContainer !== endContainer || range.endOffset !== endOffset);
1853
+
1854
+ range.startContainer = startContainer;
1855
+ range.startOffset = startOffset;
1856
+ range.endContainer = endContainer;
1857
+ range.endOffset = endOffset;
1858
+
1859
+ updateCollapsedAndCommonAncestor(range);
1860
+ dispatchEvent(range, "boundarychange", {
1861
+ startMoved: startMoved,
1862
+ endMoved: endMoved
1863
+ });
1864
+ }
1865
+
1866
+ function detach(range) {
1867
+ assertNotDetached(range);
1868
+ range.startContainer = range.startOffset = range.endContainer = range.endOffset = null;
1869
+ range.collapsed = range.commonAncestorContainer = null;
1870
+ dispatchEvent(range, "detach", null);
1871
+ range._listeners = null;
1872
+ }
1873
+
1874
+ /**
1875
+ * @constructor
1876
+ */
1877
+ function Range(doc) {
1878
+ this.startContainer = doc;
1879
+ this.startOffset = 0;
1880
+ this.endContainer = doc;
1881
+ this.endOffset = 0;
1882
+ this._listeners = {
1883
+ boundarychange: [],
1884
+ detach: []
1885
+ };
1886
+ updateCollapsedAndCommonAncestor(this);
1887
+ }
1888
+
1889
+ createPrototypeRange(Range, updateBoundaries, detach);
1890
+
1891
+ api.rangePrototype = RangePrototype.prototype;
1892
+
1893
+ Range.rangeProperties = rangeProperties;
1894
+ Range.RangeIterator = RangeIterator;
1895
+ Range.copyComparisonConstants = copyComparisonConstants;
1896
+ Range.createPrototypeRange = createPrototypeRange;
1897
+ Range.inspect = inspect;
1898
+ Range.getRangeDocument = getRangeDocument;
1899
+ Range.rangesEqual = function (r1, r2) {
1900
+ return r1.startContainer === r2.startContainer && r1.startOffset === r2.startOffset && r1.endContainer === r2.endContainer && r1.endOffset === r2.endOffset;
1901
+ };
1902
+
1903
+ api.DomRange = Range;
1904
+ api.RangeException = RangeException;
1905
+ });
1906
+ rangy.createModule("WrappedRange", function (api, module) {
1907
+ api.requireModules(["DomUtil", "DomRange"]);
1908
+
1909
+ /**
1910
+ * @constructor
1911
+ */
1912
+ var WrappedRange;
1913
+ var dom = api.dom;
1914
+ var DomPosition = dom.DomPosition;
1915
+ var DomRange = api.DomRange;
1916
+
1917
+
1918
+
1919
+ /*----------------------------------------------------------------------------------------------------------------*/
1920
+
1921
+ /*
1922
+ This is a workaround for a bug where IE returns the wrong container element from the TextRange's parentElement()
1923
+ method. For example, in the following (where pipes denote the selection boundaries):
1924
+
1925
+ <ul id="ul"><li id="a">| a </li><li id="b"> b |</li></ul>
1926
+
1927
+ var range = document.selection.createRange();
1928
+ alert(range.parentElement().id); // Should alert "ul" but alerts "b"
1929
+
1930
+ This method returns the common ancestor node of the following:
1931
+ - the parentElement() of the textRange
1932
+ - the parentElement() of the textRange after calling collapse(true)
1933
+ - the parentElement() of the textRange after calling collapse(false)
1934
+ */
1935
+ function getTextRangeContainerElement(textRange) {
1936
+ var parentEl = textRange.parentElement();
1937
+
1938
+ var range = textRange.duplicate();
1939
+ range.collapse(true);
1940
+ var startEl = range.parentElement();
1941
+ range = textRange.duplicate();
1942
+ range.collapse(false);
1943
+ var endEl = range.parentElement();
1944
+ var startEndContainer = (startEl == endEl) ? startEl : dom.getCommonAncestor(startEl, endEl);
1945
+
1946
+ return startEndContainer == parentEl ? startEndContainer : dom.getCommonAncestor(parentEl, startEndContainer);
1947
+ }
1948
+
1949
+ function textRangeIsCollapsed(textRange) {
1950
+ return textRange.compareEndPoints("StartToEnd", textRange) == 0;
1951
+ }
1952
+
1953
+ // Gets the boundary of a TextRange expressed as a node and an offset within that node. This function started out as
1954
+ // an improved version of code found in Tim Cameron Ryan's IERange (http://code.google.com/p/ierange/) but has
1955
+ // grown, fixing problems with line breaks in preformatted text, adding workaround for IE TextRange bugs, handling
1956
+ // for inputs and images, plus optimizations.
1957
+ function getTextRangeBoundaryPosition(textRange, wholeRangeContainerElement, isStart, isCollapsed) {
1958
+ var workingRange = textRange.duplicate();
1959
+
1960
+ workingRange.collapse(isStart);
1961
+ var containerElement = workingRange.parentElement();
1962
+
1963
+ // Sometimes collapsing a TextRange that's at the start of a text node can move it into the previous node, so
1964
+ // check for that
1965
+ // TODO: Find out when. Workaround for wholeRangeContainerElement may break this
1966
+ if (!dom.isAncestorOf(wholeRangeContainerElement, containerElement, true)) {
1967
+ containerElement = wholeRangeContainerElement;
1968
+
1969
+ }
1970
+
1971
+
1972
+
1973
+ // Deal with nodes that cannot "contain rich HTML markup". In practice, this means form inputs, images and
1974
+ // similar. See http://msdn.microsoft.com/en-us/library/aa703950%28VS.85%29.aspx
1975
+ if (!containerElement.canHaveHTML) {
1976
+ return new DomPosition(containerElement.parentNode, dom.getNodeIndex(containerElement));
1977
+ }
1978
+
1979
+ var workingNode = dom.getDocument(containerElement).createElement("span");
1980
+
1981
+ // Workaround for HTML5 Shiv's insane violation of
1982
+ // document.createElement(). See Rangy issue 104 and HTML 5 Shiv issue
1983
+ // 64: https://github.com/aFarkas/html5shiv/issues/64
1984
+ if (workingNode.parentNode) {
1985
+ workingNode.parentNode.removeChild(workingNode);
1986
+ }
1987
+
1988
+ var comparison, workingComparisonType = isStart ? "StartToStart" : "StartToEnd";
1989
+ var previousNode, nextNode, boundaryPosition, boundaryNode;
1990
+
1991
+ // Move the working range through the container's children, starting at the end and working backwards, until the
1992
+ // working range reaches or goes past the boundary we're interested in
1993
+ do {
1994
+ containerElement.insertBefore(workingNode, workingNode.previousSibling);
1995
+ workingRange.moveToElementText(workingNode);
1996
+ } while ((comparison = workingRange.compareEndPoints(workingComparisonType, textRange)) > 0 && workingNode.previousSibling);
1997
+
1998
+ // We've now reached or gone past the boundary of the text range we're interested in
1999
+ // so have identified the node we want
2000
+ boundaryNode = workingNode.nextSibling;
2001
+
2002
+ if (comparison == -1 && boundaryNode && dom.isCharacterDataNode(boundaryNode)) {
2003
+ // This is a character data node (text, comment, cdata). The working range is collapsed at the start of the
2004
+ // node containing the text range's boundary, so we move the end of the working range to the boundary point
2005
+ // and measure the length of its text to get the boundary's offset within the node.
2006
+ workingRange.setEndPoint(isStart ? "EndToStart" : "EndToEnd", textRange);
2007
+
2008
+
2009
+ var offset;
2010
+
2011
+ if (/[\r\n]/.test(boundaryNode.data)) {
2012
+ /*
2013
+ For the particular case of a boundary within a text node containing line breaks (within a <pre> element,
2014
+ for example), we need a slightly complicated approach to get the boundary's offset in IE. The facts:
2015
+
2016
+ - Each line break is represented as \r in the text node's data/nodeValue properties
2017
+ - Each line break is represented as \r\n in the TextRange's 'text' property
2018
+ - The 'text' property of the TextRange does not contain trailing line breaks
2019
+
2020
+ To get round the problem presented by the final fact above, we can use the fact that TextRange's
2021
+ moveStart() and moveEnd() methods return the actual number of characters moved, which is not necessarily
2022
+ the same as the number of characters it was instructed to move. The simplest approach is to use this to
2023
+ store the characters moved when moving both the start and end of the range to the start of the document
2024
+ body and subtracting the start offset from the end offset (the "move-negative-gazillion" method).
2025
+ However, this is extremely slow when the document is large and the range is near the end of it. Clearly
2026
+ doing the mirror image (i.e. moving the range boundaries to the end of the document) has the same
2027
+ problem.
2028
+
2029
+ Another approach that works is to use moveStart() to move the start boundary of the range up to the end
2030
+ boundary one character at a time and incrementing a counter with the value returned by the moveStart()
2031
+ call. However, the check for whether the start boundary has reached the end boundary is expensive, so
2032
+ this method is slow (although unlike "move-negative-gazillion" is largely unaffected by the location of
2033
+ the range within the document).
2034
+
2035
+ The method below is a hybrid of the two methods above. It uses the fact that a string containing the
2036
+ TextRange's 'text' property with each \r\n converted to a single \r character cannot be longer than the
2037
+ text of the TextRange, so the start of the range is moved that length initially and then a character at
2038
+ a time to make up for any trailing line breaks not contained in the 'text' property. This has good
2039
+ performance in most situations compared to the previous two methods.
2040
+ */
2041
+ var tempRange = workingRange.duplicate();
2042
+ var rangeLength = tempRange.text.replace(/\r\n/g, "\r").length;
2043
+
2044
+ offset = tempRange.moveStart("character", rangeLength);
2045
+ while ((comparison = tempRange.compareEndPoints("StartToEnd", tempRange)) == -1) {
2046
+ offset++;
2047
+ tempRange.moveStart("character", 1);
2048
+ }
2049
+ } else {
2050
+ // IE7 sometimes has weird workingranges that apparently do not start in the workingNode any more, but in
2051
+ // some kind of phantom paragraph, that cannot be found in the DOM.
2052
+ // in such situations, the workingRange.text no longer is a substring at the start of the boundaryNode.data
2053
+ // If we find such a situation, we skip all characters at the start of the workingRange.data, that are not
2054
+ // at the start of the boundaryNode.data.
2055
+ // Before comparing, we have to replace all nbsp with normal spaces
2056
+ var wrText = workingRange.text.replace(/\u00a0/g, " ");
2057
+ var bnText = boundaryNode.data.replace(/\u00a0/g, " ");
2058
+ if (bnText.indexOf(wrText) !== 0) {
2059
+ while (wrText.length > 0 && bnText.indexOf(wrText) !== 0) {
2060
+ wrText = wrText.substr(1);
2061
+ }
2062
+ offset = wrText.length;
2063
+ } else {
2064
+ offset = workingRange.text.length;
2065
+ }
2066
+ }
2067
+ boundaryPosition = new DomPosition(boundaryNode, offset);
2068
+ } else {
2069
+
2070
+
2071
+ // If the boundary immediately follows a character data node and this is the end boundary, we should favour
2072
+ // a position within that, and likewise for a start boundary preceding a character data node
2073
+ previousNode = (isCollapsed || !isStart) && workingNode.previousSibling;
2074
+ nextNode = (isCollapsed || isStart) && workingNode.nextSibling;
2075
+
2076
+
2077
+
2078
+ if (nextNode && dom.isCharacterDataNode(nextNode)) {
2079
+ boundaryPosition = new DomPosition(nextNode, 0);
2080
+ } else if (previousNode && dom.isCharacterDataNode(previousNode)) {
2081
+ boundaryPosition = new DomPosition(previousNode, previousNode.length);
2082
+ } else {
2083
+ boundaryPosition = new DomPosition(containerElement, dom.getNodeIndex(workingNode));
2084
+ }
2085
+ }
2086
+
2087
+ // Clean up
2088
+ workingNode.parentNode.removeChild(workingNode);
2089
+
2090
+ return boundaryPosition;
2091
+ }
2092
+
2093
+ // Returns a TextRange representing the boundary of a TextRange expressed as a node and an offset within that node.
2094
+ // This function started out as an optimized version of code found in Tim Cameron Ryan's IERange
2095
+ // (http://code.google.com/p/ierange/)
2096
+ function createBoundaryTextRange(boundaryPosition, isStart) {
2097
+ var boundaryNode, boundaryParent, boundaryOffset = boundaryPosition.offset;
2098
+ var doc = dom.getDocument(boundaryPosition.node);
2099
+ var workingNode, childNodes, workingRange = doc.body.createTextRange();
2100
+ var nodeIsDataNode = dom.isCharacterDataNode(boundaryPosition.node);
2101
+
2102
+ if (nodeIsDataNode) {
2103
+ boundaryNode = boundaryPosition.node;
2104
+ boundaryParent = boundaryNode.parentNode;
2105
+ } else {
2106
+ childNodes = boundaryPosition.node.childNodes;
2107
+ boundaryNode = (boundaryOffset < childNodes.length) ? childNodes[boundaryOffset] : null;
2108
+ boundaryParent = boundaryPosition.node;
2109
+ }
2110
+
2111
+ // Position the range immediately before the node containing the boundary
2112
+ workingNode = doc.createElement("span");
2113
+
2114
+ // Making the working element non-empty element persuades IE to consider the TextRange boundary to be within the
2115
+ // element rather than immediately before or after it, which is what we want
2116
+ workingNode.innerHTML = "&#feff;";
2117
+
2118
+ // insertBefore is supposed to work like appendChild if the second parameter is null. However, a bug report
2119
+ // for IERange suggests that it can crash the browser: http://code.google.com/p/ierange/issues/detail?id=12
2120
+ if (boundaryNode) {
2121
+ boundaryParent.insertBefore(workingNode, boundaryNode);
2122
+ } else {
2123
+ boundaryParent.appendChild(workingNode);
2124
+ }
2125
+
2126
+ try {
2127
+ workingRange.moveToElementText(workingNode);
2128
+ workingRange.collapse(!isStart);
2129
+ } catch (err) {
2130
+ // @todo window.console.log('problem with moveToElementText');
2131
+ //return false;
2132
+ }
2133
+
2134
+ // Clean up
2135
+ boundaryParent.removeChild(workingNode);
2136
+
2137
+ // Move the working range to the text offset, if required
2138
+ if (nodeIsDataNode) {
2139
+ workingRange[isStart ? "moveStart" : "moveEnd"]("character", boundaryOffset);
2140
+ }
2141
+
2142
+ return workingRange;
2143
+ }
2144
+
2145
+ /*----------------------------------------------------------------------------------------------------------------*/
2146
+
2147
+ if (api.features.implementsDomRange && (!api.features.implementsTextRange || !api.config.preferTextRange)) {
2148
+ // This is a wrapper around the browser's native DOM Range. It has two aims:
2149
+ // - Provide workarounds for specific browser bugs
2150
+ // - provide convenient extensions, which are inherited from Rangy's DomRange
2151
+
2152
+ (function () {
2153
+ var rangeProto;
2154
+ var rangeProperties = DomRange.rangeProperties;
2155
+ var canSetRangeStartAfterEnd;
2156
+
2157
+ function updateRangeProperties(range) {
2158
+ var i = rangeProperties.length,
2159
+ prop;
2160
+ while (i--) {
2161
+ prop = rangeProperties[i];
2162
+ range[prop] = range.nativeRange[prop];
2163
+ }
2164
+ }
2165
+
2166
+ function updateNativeRange(range, startContainer, startOffset, endContainer, endOffset) {
2167
+ var startMoved = (range.startContainer !== startContainer || range.startOffset != startOffset);
2168
+ var endMoved = (range.endContainer !== endContainer || range.endOffset != endOffset);
2169
+
2170
+ // Always set both boundaries for the benefit of IE9 (see issue 35)
2171
+ if (startMoved || endMoved) {
2172
+ range.setEnd(endContainer, endOffset);
2173
+ range.setStart(startContainer, startOffset);
2174
+ }
2175
+ }
2176
+
2177
+ function detach(range) {
2178
+ range.nativeRange.detach();
2179
+ range.detached = true;
2180
+ var i = rangeProperties.length,
2181
+ prop;
2182
+ while (i--) {
2183
+ prop = rangeProperties[i];
2184
+ range[prop] = null;
2185
+ }
2186
+ }
2187
+
2188
+ var createBeforeAfterNodeSetter;
2189
+
2190
+ WrappedRange = function (range) {
2191
+ if (!range) {
2192
+ throw new Error("Range must be specified");
2193
+ }
2194
+ this.nativeRange = range;
2195
+ updateRangeProperties(this);
2196
+ };
2197
+
2198
+ DomRange.createPrototypeRange(WrappedRange, updateNativeRange, detach);
2199
+
2200
+ rangeProto = WrappedRange.prototype;
2201
+
2202
+ rangeProto.selectNode = function (node) {
2203
+ this.nativeRange.selectNode(node);
2204
+ updateRangeProperties(this);
2205
+ };
2206
+
2207
+ rangeProto.deleteContents = function () {
2208
+ this.nativeRange.deleteContents();
2209
+ updateRangeProperties(this);
2210
+ };
2211
+
2212
+ rangeProto.extractContents = function () {
2213
+ var frag = this.nativeRange.extractContents();
2214
+ updateRangeProperties(this);
2215
+ return frag;
2216
+ };
2217
+
2218
+ rangeProto.cloneContents = function () {
2219
+ return this.nativeRange.cloneContents();
2220
+ };
2221
+
2222
+ // TODO: Until I can find a way to programmatically trigger the Firefox bug (apparently long-standing, still
2223
+ // present in 3.6.8) that throws "Index or size is negative or greater than the allowed amount" for
2224
+ // insertNode in some circumstances, all browsers will have to use the Rangy's own implementation of
2225
+ // insertNode, which works but is almost certainly slower than the native implementation.
2226
+ /*
2227
+ rangeProto.insertNode = function(node) {
2228
+ this.nativeRange.insertNode(node);
2229
+ updateRangeProperties(this);
2230
+ };
2231
+ */
2232
+
2233
+ rangeProto.surroundContents = function (node) {
2234
+ this.nativeRange.surroundContents(node);
2235
+ updateRangeProperties(this);
2236
+ };
2237
+
2238
+ rangeProto.collapse = function (isStart) {
2239
+ this.nativeRange.collapse(isStart);
2240
+ updateRangeProperties(this);
2241
+ };
2242
+
2243
+ rangeProto.cloneRange = function () {
2244
+ return new WrappedRange(this.nativeRange.cloneRange());
2245
+ };
2246
+
2247
+ rangeProto.refresh = function () {
2248
+ updateRangeProperties(this);
2249
+ };
2250
+
2251
+ rangeProto.toString = function () {
2252
+ return this.nativeRange.toString();
2253
+ };
2254
+
2255
+ // Create test range and node for feature detection
2256
+
2257
+ var testTextNode = document.createTextNode("test");
2258
+ dom.getBody(document).appendChild(testTextNode);
2259
+ var range = document.createRange();
2260
+
2261
+ /*--------------------------------------------------------------------------------------------------------*/
2262
+
2263
+ // Test for Firefox 2 bug that prevents moving the start of a Range to a point after its current end and
2264
+ // correct for it
2265
+
2266
+ range.setStart(testTextNode, 0);
2267
+ range.setEnd(testTextNode, 0);
2268
+
2269
+ try {
2270
+ range.setStart(testTextNode, 1);
2271
+ canSetRangeStartAfterEnd = true;
2272
+
2273
+ rangeProto.setStart = function (node, offset) {
2274
+ this.nativeRange.setStart(node, offset);
2275
+ updateRangeProperties(this);
2276
+ };
2277
+
2278
+ rangeProto.setEnd = function (node, offset) {
2279
+ this.nativeRange.setEnd(node, offset);
2280
+ updateRangeProperties(this);
2281
+ };
2282
+
2283
+ createBeforeAfterNodeSetter = function (name) {
2284
+ return function (node) {
2285
+ this.nativeRange[name](node);
2286
+ updateRangeProperties(this);
2287
+ };
2288
+ };
2289
+
2290
+ } catch (ex) {
2291
+
2292
+
2293
+ canSetRangeStartAfterEnd = false;
2294
+
2295
+ rangeProto.setStart = function (node, offset) {
2296
+ try {
2297
+ this.nativeRange.setStart(node, offset);
2298
+ } catch (ex) {
2299
+ this.nativeRange.setEnd(node, offset);
2300
+ this.nativeRange.setStart(node, offset);
2301
+ }
2302
+ updateRangeProperties(this);
2303
+ };
2304
+
2305
+ rangeProto.setEnd = function (node, offset) {
2306
+ try {
2307
+ this.nativeRange.setEnd(node, offset);
2308
+ } catch (ex) {
2309
+ this.nativeRange.setStart(node, offset);
2310
+ this.nativeRange.setEnd(node, offset);
2311
+ }
2312
+ updateRangeProperties(this);
2313
+ };
2314
+
2315
+ createBeforeAfterNodeSetter = function (name, oppositeName) {
2316
+ return function (node) {
2317
+ try {
2318
+ this.nativeRange[name](node);
2319
+ } catch (ex) {
2320
+ this.nativeRange[oppositeName](node);
2321
+ this.nativeRange[name](node);
2322
+ }
2323
+ updateRangeProperties(this);
2324
+ };
2325
+ };
2326
+ }
2327
+
2328
+ rangeProto.setStartBefore = createBeforeAfterNodeSetter("setStartBefore", "setEndBefore");
2329
+ rangeProto.setStartAfter = createBeforeAfterNodeSetter("setStartAfter", "setEndAfter");
2330
+ rangeProto.setEndBefore = createBeforeAfterNodeSetter("setEndBefore", "setStartBefore");
2331
+ rangeProto.setEndAfter = createBeforeAfterNodeSetter("setEndAfter", "setStartAfter");
2332
+
2333
+ /*--------------------------------------------------------------------------------------------------------*/
2334
+
2335
+ // Test for and correct Firefox 2 behaviour with selectNodeContents on text nodes: it collapses the range to
2336
+ // the 0th character of the text node
2337
+ range.selectNodeContents(testTextNode);
2338
+ if (range.startContainer == testTextNode && range.endContainer == testTextNode && range.startOffset == 0 && range.endOffset == testTextNode.length) {
2339
+ rangeProto.selectNodeContents = function (node) {
2340
+ this.nativeRange.selectNodeContents(node);
2341
+ updateRangeProperties(this);
2342
+ };
2343
+ } else {
2344
+ rangeProto.selectNodeContents = function (node) {
2345
+ this.setStart(node, 0);
2346
+ this.setEnd(node, DomRange.getEndOffset(node));
2347
+ };
2348
+ }
2349
+
2350
+ /*--------------------------------------------------------------------------------------------------------*/
2351
+
2352
+ // Test for WebKit bug that has the beahviour of compareBoundaryPoints round the wrong way for constants
2353
+ // START_TO_END and END_TO_START: https://bugs.webkit.org/show_bug.cgi?id=20738
2354
+
2355
+ range.selectNodeContents(testTextNode);
2356
+ range.setEnd(testTextNode, 3);
2357
+
2358
+ var range2 = document.createRange();
2359
+ range2.selectNodeContents(testTextNode);
2360
+ range2.setEnd(testTextNode, 4);
2361
+ range2.setStart(testTextNode, 2);
2362
+
2363
+ if (range.compareBoundaryPoints(range.START_TO_END, range2) == -1 & range.compareBoundaryPoints(range.END_TO_START, range2) == 1) {
2364
+ // This is the wrong way round, so correct for it
2365
+
2366
+
2367
+ rangeProto.compareBoundaryPoints = function (type, range) {
2368
+ range = range.nativeRange || range;
2369
+ if (type == range.START_TO_END) {
2370
+ type = range.END_TO_START;
2371
+ } else if (type == range.END_TO_START) {
2372
+ type = range.START_TO_END;
2373
+ }
2374
+ return this.nativeRange.compareBoundaryPoints(type, range);
2375
+ };
2376
+ } else {
2377
+ rangeProto.compareBoundaryPoints = function (type, range) {
2378
+ return this.nativeRange.compareBoundaryPoints(type, range.nativeRange || range);
2379
+ };
2380
+ }
2381
+
2382
+ /*--------------------------------------------------------------------------------------------------------*/
2383
+
2384
+ // Test for existence of createContextualFragment and delegate to it if it exists
2385
+ if (api.util.isHostMethod(range, "createContextualFragment")) {
2386
+ rangeProto.createContextualFragment = function (fragmentStr) {
2387
+ return this.nativeRange.createContextualFragment(fragmentStr);
2388
+ };
2389
+ }
2390
+
2391
+ /*--------------------------------------------------------------------------------------------------------*/
2392
+
2393
+ // Clean up
2394
+ dom.getBody(document).removeChild(testTextNode);
2395
+ range.detach();
2396
+ range2.detach();
2397
+ })();
2398
+
2399
+ api.createNativeRange = function (doc) {
2400
+ doc = doc || document;
2401
+ return doc.createRange();
2402
+ };
2403
+ } else if (api.features.implementsTextRange) {
2404
+ // This is a wrapper around a TextRange, providing full DOM Range functionality using rangy's DomRange as a
2405
+ // prototype
2406
+
2407
+ WrappedRange = function (textRange) {
2408
+ this.textRange = textRange;
2409
+ this.refresh();
2410
+ };
2411
+
2412
+ WrappedRange.prototype = new DomRange(document);
2413
+
2414
+ WrappedRange.prototype.refresh = function () {
2415
+ var start, end;
2416
+
2417
+ // TextRange's parentElement() method cannot be trusted. getTextRangeContainerElement() works around that.
2418
+ var rangeContainerElement = getTextRangeContainerElement(this.textRange);
2419
+
2420
+ if (textRangeIsCollapsed(this.textRange)) {
2421
+ end = start = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, true, true);
2422
+ } else {
2423
+
2424
+ start = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, true, false);
2425
+ end = getTextRangeBoundaryPosition(this.textRange, rangeContainerElement, false, false);
2426
+ }
2427
+
2428
+ this.setStart(start.node, start.offset);
2429
+ this.setEnd(end.node, end.offset);
2430
+ };
2431
+
2432
+ DomRange.copyComparisonConstants(WrappedRange);
2433
+
2434
+ // Add WrappedRange as the Range property of the global object to allow expression like Range.END_TO_END to work
2435
+ var globalObj = (function () {
2436
+ return this;
2437
+ })();
2438
+ if (typeof globalObj.Range == "undefined") {
2439
+ globalObj.Range = WrappedRange;
2440
+ }
2441
+
2442
+ api.createNativeRange = function (doc) {
2443
+ doc = doc || document;
2444
+ return doc.body.createTextRange();
2445
+ };
2446
+ }
2447
+
2448
+ if (api.features.implementsTextRange) {
2449
+ WrappedRange.rangeToTextRange = function (range) {
2450
+ if (range.collapsed) {
2451
+ var tr = createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
2452
+ return tr;
2453
+ //return createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
2454
+ } else {
2455
+ var startRange = createBoundaryTextRange(new DomPosition(range.startContainer, range.startOffset), true);
2456
+ var endRange = createBoundaryTextRange(new DomPosition(range.endContainer, range.endOffset), false);
2457
+ var textRange = dom.getDocument(range.startContainer).body.createTextRange();
2458
+ textRange.setEndPoint("StartToStart", startRange);
2459
+ textRange.setEndPoint("EndToEnd", endRange);
2460
+ return textRange;
2461
+ }
2462
+ };
2463
+ }
2464
+
2465
+ WrappedRange.prototype.getName = function () {
2466
+ return "WrappedRange";
2467
+ };
2468
+
2469
+ api.WrappedRange = WrappedRange;
2470
+
2471
+ api.createRange = function (doc) {
2472
+ doc = doc || document;
2473
+ return new WrappedRange(api.createNativeRange(doc));
2474
+ };
2475
+
2476
+ api.createRangyRange = function (doc) {
2477
+ doc = doc || document;
2478
+ return new DomRange(doc);
2479
+ };
2480
+
2481
+ api.createIframeRange = function (iframeEl) {
2482
+ return api.createRange(dom.getIframeDocument(iframeEl));
2483
+ };
2484
+
2485
+ api.createIframeRangyRange = function (iframeEl) {
2486
+ return api.createRangyRange(dom.getIframeDocument(iframeEl));
2487
+ };
2488
+
2489
+ api.addCreateMissingNativeApiListener(function (win) {
2490
+ var doc = win.document;
2491
+ if (typeof doc.createRange == "undefined") {
2492
+ doc.createRange = function () {
2493
+ return api.createRange(this);
2494
+ };
2495
+ }
2496
+ doc = win = null;
2497
+ });
2498
+ });
2499
+ rangy.createModule("WrappedSelection", function (api, module) {
2500
+ // This will create a selection object wrapper that follows the Selection object found in the WHATWG draft DOM Range
2501
+ // spec (http://html5.org/specs/dom-range.html)
2502
+
2503
+ api.requireModules(["DomUtil", "DomRange", "WrappedRange"]);
2504
+
2505
+ api.config.checkSelectionRanges = true;
2506
+
2507
+ var BOOLEAN = "boolean",
2508
+ windowPropertyName = "_rangySelection",
2509
+ dom = api.dom,
2510
+ util = api.util,
2511
+ DomRange = api.DomRange,
2512
+ WrappedRange = api.WrappedRange,
2513
+ DOMException = api.DOMException,
2514
+ DomPosition = dom.DomPosition,
2515
+ getSelection,
2516
+ selectionIsCollapsed,
2517
+ CONTROL = "Control";
2518
+
2519
+
2520
+
2521
+ function getWinSelection(winParam) {
2522
+ return (winParam || window).getSelection();
2523
+ }
2524
+
2525
+ function getDocSelection(winParam) {
2526
+ return (winParam || window).document.selection;
2527
+ }
2528
+
2529
+ // Test for the Range/TextRange and Selection features required
2530
+ // Test for ability to retrieve selection
2531
+ var implementsWinGetSelection = api.util.isHostMethod(window, "getSelection"),
2532
+ implementsDocSelection = api.util.isHostObject(document, "selection");
2533
+
2534
+ var useDocumentSelection = implementsDocSelection && (!implementsWinGetSelection || api.config.preferTextRange);
2535
+
2536
+ if (useDocumentSelection) {
2537
+ getSelection = getDocSelection;
2538
+ api.isSelectionValid = function (winParam) {
2539
+ var doc = (winParam || window).document,
2540
+ nativeSel = doc.selection;
2541
+
2542
+ // Check whether the selection TextRange is actually contained within the correct document
2543
+ return (nativeSel.type != "None" || dom.getDocument(nativeSel.createRange().parentElement()) == doc);
2544
+ };
2545
+ } else if (implementsWinGetSelection) {
2546
+ getSelection = getWinSelection;
2547
+ api.isSelectionValid = function () {
2548
+ return true;
2549
+ };
2550
+ } else {
2551
+ module.fail("Neither document.selection or window.getSelection() detected.");
2552
+ }
2553
+
2554
+ api.getNativeSelection = getSelection;
2555
+
2556
+ var testSelection = getSelection();
2557
+ var testRange = api.createNativeRange(document);
2558
+ var body = dom.getBody(document);
2559
+
2560
+ // Obtaining a range from a selection
2561
+ var selectionHasAnchorAndFocus = util.areHostObjects(testSelection, ["anchorNode", "focusNode"] && util.areHostProperties(testSelection, ["anchorOffset", "focusOffset"]));
2562
+ api.features.selectionHasAnchorAndFocus = selectionHasAnchorAndFocus;
2563
+
2564
+ // Test for existence of native selection extend() method
2565
+ var selectionHasExtend = util.isHostMethod(testSelection, "extend");
2566
+ api.features.selectionHasExtend = selectionHasExtend;
2567
+
2568
+ // Test if rangeCount exists
2569
+ var selectionHasRangeCount = (typeof testSelection.rangeCount == "number");
2570
+ api.features.selectionHasRangeCount = selectionHasRangeCount;
2571
+
2572
+ var selectionSupportsMultipleRanges = false;
2573
+ var collapsedNonEditableSelectionsSupported = true;
2574
+
2575
+ if (util.areHostMethods(testSelection, ["addRange", "getRangeAt", "removeAllRanges"]) && typeof testSelection.rangeCount == "number" && api.features.implementsDomRange) {
2576
+
2577
+ (function () {
2578
+ var iframe = document.createElement("iframe");
2579
+ body.appendChild(iframe);
2580
+
2581
+ var iframeDoc = dom.getIframeDocument(iframe);
2582
+ iframeDoc.open();
2583
+ iframeDoc.write("<html><head></head><body>12</body></html>");
2584
+ iframeDoc.close();
2585
+
2586
+ var sel = dom.getIframeWindow(iframe).getSelection();
2587
+ var docEl = iframeDoc.documentElement;
2588
+ var iframeBody = docEl.lastChild,
2589
+ textNode = iframeBody.firstChild;
2590
+
2591
+ // Test whether the native selection will allow a collapsed selection within a non-editable element
2592
+ var r1 = iframeDoc.createRange();
2593
+ r1.setStart(textNode, 1);
2594
+ r1.collapse(true);
2595
+ sel.addRange(r1);
2596
+ collapsedNonEditableSelectionsSupported = (sel.rangeCount == 1);
2597
+ sel.removeAllRanges();
2598
+
2599
+ // Test whether the native selection is capable of supporting multiple ranges
2600
+ var r2 = r1.cloneRange();
2601
+ r1.setStart(textNode, 0);
2602
+ r2.setEnd(textNode, 2);
2603
+ sel.addRange(r1);
2604
+ sel.addRange(r2);
2605
+
2606
+ selectionSupportsMultipleRanges = (sel.rangeCount == 2);
2607
+
2608
+ // Clean up
2609
+ r1.detach();
2610
+ r2.detach();
2611
+
2612
+ body.removeChild(iframe);
2613
+ })();
2614
+ }
2615
+
2616
+ api.features.selectionSupportsMultipleRanges = selectionSupportsMultipleRanges;
2617
+ api.features.collapsedNonEditableSelectionsSupported = collapsedNonEditableSelectionsSupported;
2618
+
2619
+ // ControlRanges
2620
+ var implementsControlRange = false,
2621
+ testControlRange;
2622
+
2623
+ if (body && util.isHostMethod(body, "createControlRange")) {
2624
+ testControlRange = body.createControlRange();
2625
+ if (util.areHostProperties(testControlRange, ["item", "add"])) {
2626
+ implementsControlRange = true;
2627
+ }
2628
+ }
2629
+ api.features.implementsControlRange = implementsControlRange;
2630
+
2631
+ // Selection collapsedness
2632
+ if (selectionHasAnchorAndFocus) {
2633
+ selectionIsCollapsed = function (sel) {
2634
+ return sel.anchorNode === sel.focusNode && sel.anchorOffset === sel.focusOffset;
2635
+ };
2636
+ } else {
2637
+ selectionIsCollapsed = function (sel) {
2638
+ return sel.rangeCount ? sel.getRangeAt(sel.rangeCount - 1).collapsed : false;
2639
+ };
2640
+ }
2641
+
2642
+ function updateAnchorAndFocusFromRange(sel, range, backwards) {
2643
+ var anchorPrefix = backwards ? "end" : "start",
2644
+ focusPrefix = backwards ? "start" : "end";
2645
+ sel.anchorNode = range[anchorPrefix + "Container"];
2646
+ sel.anchorOffset = range[anchorPrefix + "Offset"];
2647
+ sel.focusNode = range[focusPrefix + "Container"];
2648
+ sel.focusOffset = range[focusPrefix + "Offset"];
2649
+ }
2650
+
2651
+ function updateAnchorAndFocusFromNativeSelection(sel) {
2652
+ var nativeSel = sel.nativeSelection;
2653
+ sel.anchorNode = nativeSel.anchorNode;
2654
+ sel.anchorOffset = nativeSel.anchorOffset;
2655
+ sel.focusNode = nativeSel.focusNode;
2656
+ sel.focusOffset = nativeSel.focusOffset;
2657
+ }
2658
+
2659
+ function updateEmptySelection(sel) {
2660
+ sel.anchorNode = sel.focusNode = null;
2661
+ sel.anchorOffset = sel.focusOffset = 0;
2662
+ sel.rangeCount = 0;
2663
+ sel.isCollapsed = true;
2664
+ sel._ranges.length = 0;
2665
+ }
2666
+
2667
+ function getNativeRange(range) {
2668
+ var nativeRange;
2669
+ if (range instanceof DomRange) {
2670
+ nativeRange = range._selectionNativeRange;
2671
+ if (!nativeRange) {
2672
+ nativeRange = api.createNativeRange(dom.getDocument(range.startContainer));
2673
+ nativeRange.setEnd(range.endContainer, range.endOffset);
2674
+ nativeRange.setStart(range.startContainer, range.startOffset);
2675
+ range._selectionNativeRange = nativeRange;
2676
+ range.attachListener("detach", function () {
2677
+
2678
+ this._selectionNativeRange = null;
2679
+ });
2680
+ }
2681
+ } else if (range instanceof WrappedRange) {
2682
+ nativeRange = range.nativeRange;
2683
+ } else if (api.features.implementsDomRange && (range instanceof dom.getWindow(range.startContainer).Range)) {
2684
+ nativeRange = range;
2685
+ }
2686
+ return nativeRange;
2687
+ }
2688
+
2689
+ function rangeContainsSingleElement(rangeNodes) {
2690
+ if (!rangeNodes.length || rangeNodes[0].nodeType != 1) {
2691
+ return false;
2692
+ }
2693
+ for (var i = 1, len = rangeNodes.length; i < len; ++i) {
2694
+ if (!dom.isAncestorOf(rangeNodes[0], rangeNodes[i])) {
2695
+ return false;
2696
+ }
2697
+ }
2698
+ return true;
2699
+ }
2700
+
2701
+ function getSingleElementFromRange(range) {
2702
+ var nodes = range.getNodes();
2703
+ if (!rangeContainsSingleElement(nodes)) {
2704
+ throw new Error("getSingleElementFromRange: range " + range.inspect() + " did not consist of a single element");
2705
+ }
2706
+ return nodes[0];
2707
+ }
2708
+
2709
+ function isTextRange(range) {
2710
+ return !!range && typeof range.text != "undefined";
2711
+ }
2712
+
2713
+ function updateFromTextRange(sel, range) {
2714
+ // Create a Range from the selected TextRange
2715
+ var wrappedRange = new WrappedRange(range);
2716
+ sel._ranges = [wrappedRange];
2717
+
2718
+ updateAnchorAndFocusFromRange(sel, wrappedRange, false);
2719
+ sel.rangeCount = 1;
2720
+ sel.isCollapsed = wrappedRange.collapsed;
2721
+ }
2722
+
2723
+ function updateControlSelection(sel) {
2724
+ // Update the wrapped selection based on what's now in the native selection
2725
+ sel._ranges.length = 0;
2726
+ if (sel.docSelection.type == "None") {
2727
+ updateEmptySelection(sel);
2728
+ } else {
2729
+ var controlRange = sel.docSelection.createRange();
2730
+ if (isTextRange(controlRange)) {
2731
+ // This case (where the selection type is "Control" and calling createRange() on the selection returns
2732
+ // a TextRange) can happen in IE 9. It happens, for example, when all elements in the selected
2733
+ // ControlRange have been removed from the ControlRange and removed from the document.
2734
+ updateFromTextRange(sel, controlRange);
2735
+ } else {
2736
+ sel.rangeCount = controlRange.length;
2737
+ var range, doc = dom.getDocument(controlRange.item(0));
2738
+ for (var i = 0; i < sel.rangeCount; ++i) {
2739
+ range = api.createRange(doc);
2740
+ range.selectNode(controlRange.item(i));
2741
+ sel._ranges.push(range);
2742
+ }
2743
+ sel.isCollapsed = sel.rangeCount == 1 && sel._ranges[0].collapsed;
2744
+ updateAnchorAndFocusFromRange(sel, sel._ranges[sel.rangeCount - 1], false);
2745
+ }
2746
+ }
2747
+ }
2748
+
2749
+ function addRangeToControlSelection(sel, range) {
2750
+ var controlRange = sel.docSelection.createRange();
2751
+ var rangeElement = getSingleElementFromRange(range);
2752
+
2753
+ // Create a new ControlRange containing all the elements in the selected ControlRange plus the element
2754
+ // contained by the supplied range
2755
+ var doc = dom.getDocument(controlRange.item(0));
2756
+ var newControlRange = dom.getBody(doc).createControlRange();
2757
+ for (var i = 0, len = controlRange.length; i < len; ++i) {
2758
+ newControlRange.add(controlRange.item(i));
2759
+ }
2760
+ try {
2761
+ newControlRange.add(rangeElement);
2762
+ } catch (ex) {
2763
+ throw new Error("addRange(): Element within the specified Range could not be added to control selection (does it have layout?)");
2764
+ }
2765
+ newControlRange.select();
2766
+
2767
+ // Update the wrapped selection based on what's now in the native selection
2768
+ updateControlSelection(sel);
2769
+ }
2770
+
2771
+ var getSelectionRangeAt;
2772
+
2773
+ if (util.isHostMethod(testSelection, "getRangeAt")) {
2774
+ getSelectionRangeAt = function (sel, index) {
2775
+ try {
2776
+ return sel.getRangeAt(index);
2777
+ } catch (ex) {
2778
+ return null;
2779
+ }
2780
+ };
2781
+ } else if (selectionHasAnchorAndFocus) {
2782
+ getSelectionRangeAt = function (sel) {
2783
+ var doc = dom.getDocument(sel.anchorNode);
2784
+ var range = api.createRange(doc);
2785
+ range.setStart(sel.anchorNode, sel.anchorOffset);
2786
+ range.setEnd(sel.focusNode, sel.focusOffset);
2787
+
2788
+ // Handle the case when the selection was selected backwards (from the end to the start in the
2789
+ // document)
2790
+ if (range.collapsed !== this.isCollapsed) {
2791
+ range.setStart(sel.focusNode, sel.focusOffset);
2792
+ range.setEnd(sel.anchorNode, sel.anchorOffset);
2793
+ }
2794
+
2795
+ return range;
2796
+ };
2797
+ }
2798
+
2799
+ /**
2800
+ * @constructor
2801
+ */
2802
+ function WrappedSelection(selection, docSelection, win) {
2803
+ this.nativeSelection = selection;
2804
+ this.docSelection = docSelection;
2805
+ this._ranges = [];
2806
+ this.win = win;
2807
+ this.refresh();
2808
+ }
2809
+
2810
+ api.getSelection = function (win) {
2811
+ win = win || window;
2812
+ var sel = win[windowPropertyName];
2813
+ var nativeSel = getSelection(win),
2814
+ docSel = implementsDocSelection ? getDocSelection(win) : null;
2815
+ if (sel) {
2816
+ sel.nativeSelection = nativeSel;
2817
+ sel.docSelection = docSel;
2818
+ sel.refresh(win);
2819
+ } else {
2820
+ sel = new WrappedSelection(nativeSel, docSel, win);
2821
+ win[windowPropertyName] = sel;
2822
+ }
2823
+ return sel;
2824
+ };
2825
+
2826
+ api.getIframeSelection = function (iframeEl) {
2827
+ return api.getSelection(dom.getIframeWindow(iframeEl));
2828
+ };
2829
+
2830
+ var selProto = WrappedSelection.prototype;
2831
+
2832
+ function createControlSelection(sel, ranges) {
2833
+ // Ensure that the selection becomes of type "Control"
2834
+ var doc = dom.getDocument(ranges[0].startContainer);
2835
+ var controlRange = dom.getBody(doc).createControlRange();
2836
+ for (var i = 0, el; i < rangeCount; ++i) {
2837
+ el = getSingleElementFromRange(ranges[i]);
2838
+ try {
2839
+ controlRange.add(el);
2840
+ } catch (ex) {
2841
+ throw new Error("setRanges(): Element within the one of the specified Ranges could not be added to control selection (does it have layout?)");
2842
+ }
2843
+ }
2844
+ controlRange.select();
2845
+
2846
+ // Update the wrapped selection based on what's now in the native selection
2847
+ updateControlSelection(sel);
2848
+ }
2849
+
2850
+ // Selecting a range
2851
+ if (!useDocumentSelection && selectionHasAnchorAndFocus && util.areHostMethods(testSelection, ["removeAllRanges", "addRange"])) {
2852
+ selProto.removeAllRanges = function () {
2853
+ this.nativeSelection.removeAllRanges();
2854
+ updateEmptySelection(this);
2855
+ };
2856
+
2857
+ var addRangeBackwards = function (sel, range) {
2858
+ var doc = DomRange.getRangeDocument(range);
2859
+ var endRange = api.createRange(doc);
2860
+ endRange.collapseToPoint(range.endContainer, range.endOffset);
2861
+ sel.nativeSelection.addRange(getNativeRange(endRange));
2862
+ sel.nativeSelection.extend(range.startContainer, range.startOffset);
2863
+ sel.refresh();
2864
+ };
2865
+
2866
+ if (selectionHasRangeCount) {
2867
+ selProto.addRange = function (range, backwards) {
2868
+ if (implementsControlRange && implementsDocSelection && this.docSelection.type == CONTROL) {
2869
+ addRangeToControlSelection(this, range);
2870
+ } else {
2871
+ if (backwards && selectionHasExtend) {
2872
+ addRangeBackwards(this, range);
2873
+ } else {
2874
+ var previousRangeCount;
2875
+ if (selectionSupportsMultipleRanges) {
2876
+ previousRangeCount = this.rangeCount;
2877
+ } else {
2878
+ this.removeAllRanges();
2879
+ previousRangeCount = 0;
2880
+ }
2881
+ this.nativeSelection.addRange(getNativeRange(range));
2882
+
2883
+ // Check whether adding the range was successful
2884
+ this.rangeCount = this.nativeSelection.rangeCount;
2885
+
2886
+ if (this.rangeCount == previousRangeCount + 1) {
2887
+ // The range was added successfully
2888
+
2889
+ // Check whether the range that we added to the selection is reflected in the last range extracted from
2890
+ // the selection
2891
+ if (api.config.checkSelectionRanges) {
2892
+ var nativeRange = getSelectionRangeAt(this.nativeSelection, this.rangeCount - 1);
2893
+ if (nativeRange && !DomRange.rangesEqual(nativeRange, range)) {
2894
+ // Happens in WebKit with, for example, a selection placed at the start of a text node
2895
+ range = new WrappedRange(nativeRange);
2896
+ }
2897
+ }
2898
+ this._ranges[this.rangeCount - 1] = range;
2899
+ updateAnchorAndFocusFromRange(this, range, selectionIsBackwards(this.nativeSelection));
2900
+ this.isCollapsed = selectionIsCollapsed(this);
2901
+ } else {
2902
+ // The range was not added successfully. The simplest thing is to refresh
2903
+ this.refresh();
2904
+ }
2905
+ }
2906
+ }
2907
+ };
2908
+ } else {
2909
+ selProto.addRange = function (range, backwards) {
2910
+ if (backwards && selectionHasExtend) {
2911
+ addRangeBackwards(this, range);
2912
+ } else {
2913
+ this.nativeSelection.addRange(getNativeRange(range));
2914
+ this.refresh();
2915
+ }
2916
+ };
2917
+ }
2918
+
2919
+ selProto.setRanges = function (ranges) {
2920
+ if (implementsControlRange && ranges.length > 1) {
2921
+ createControlSelection(this, ranges);
2922
+ } else {
2923
+ this.removeAllRanges();
2924
+ for (var i = 0, len = ranges.length; i < len; ++i) {
2925
+ this.addRange(ranges[i]);
2926
+ }
2927
+ }
2928
+ };
2929
+ } else if (util.isHostMethod(testSelection, "empty") && util.isHostMethod(testRange, "select") && implementsControlRange && useDocumentSelection) {
2930
+
2931
+ selProto.removeAllRanges = function () {
2932
+ // Added try/catch as fix for issue #21
2933
+ try {
2934
+
2935
+ var isNativeIE7 = (jQuery.browser.msie && jQuery.browser.version < 8 && (typeof document.documentMode === 'undefined'));
2936
+ if (!isNativeIE7) {
2937
+ this.docSelection.empty();
2938
+ }
2939
+
2940
+ // Check for empty() not working (issue #24)
2941
+ if (this.docSelection.type != "None") {
2942
+
2943
+ if (isNativeIE7) {
2944
+ this.docSelection.empty();
2945
+ }
2946
+
2947
+ // removed workaround of rangy-core implementation
2948
+ // for IE to fix issue with strange selection of
2949
+ // hole body in some selection change cases
2950
+ }
2951
+
2952
+ } catch (ex) {}
2953
+ updateEmptySelection(this);
2954
+ };
2955
+
2956
+ selProto.addRange = function (range) {
2957
+ if (this.docSelection.type == CONTROL) {
2958
+ addRangeToControlSelection(this, range);
2959
+ } else {
2960
+ try {
2961
+ WrappedRange.rangeToTextRange(range).select();
2962
+ this._ranges[0] = range;
2963
+ this.rangeCount = 1;
2964
+ this.isCollapsed = this._ranges[0].collapsed;
2965
+ updateAnchorAndFocusFromRange(this, range, false);
2966
+ } catch (e) {
2967
+ // @todo
2968
+ // window.console.log('problem at addRange');
2969
+ }
2970
+ }
2971
+ };
2972
+
2973
+ selProto.setRanges = function (ranges) {
2974
+ this.removeAllRanges();
2975
+ var rangeCount = ranges.length;
2976
+ if (rangeCount > 1) {
2977
+ createControlSelection(this, ranges);
2978
+ } else if (rangeCount) {
2979
+ this.addRange(ranges[0]);
2980
+ }
2981
+ };
2982
+ } else {
2983
+ module.fail("No means of selecting a Range or TextRange was found");
2984
+ return false;
2985
+ }
2986
+
2987
+ selProto.getRangeAt = function (index) {
2988
+ if (index < 0 || index >= this.rangeCount) {
2989
+ throw new DOMException("INDEX_SIZE_ERR");
2990
+ } else {
2991
+ return this._ranges[index];
2992
+ }
2993
+ };
2994
+
2995
+ var refreshSelection;
2996
+
2997
+ if (useDocumentSelection) {
2998
+ refreshSelection = function (sel) {
2999
+ var range;
3000
+ if (api.isSelectionValid(sel.win)) {
3001
+ range = sel.docSelection.createRange();
3002
+ } else {
3003
+ range = dom.getBody(sel.win.document).createTextRange();
3004
+ range.collapse(true);
3005
+ }
3006
+
3007
+
3008
+ if (sel.docSelection.type == CONTROL) {
3009
+ updateControlSelection(sel);
3010
+ } else if (isTextRange(range)) {
3011
+ updateFromTextRange(sel, range);
3012
+ } else {
3013
+ updateEmptySelection(sel);
3014
+ }
3015
+ };
3016
+ } else if (util.isHostMethod(testSelection, "getRangeAt") && typeof testSelection.rangeCount == "number") {
3017
+ refreshSelection = function (sel) {
3018
+ if (implementsControlRange && implementsDocSelection && sel.docSelection.type == CONTROL) {
3019
+ updateControlSelection(sel);
3020
+ } else {
3021
+ sel._ranges.length = sel.rangeCount = sel.nativeSelection.rangeCount;
3022
+ if (sel.rangeCount) {
3023
+ for (var i = 0, len = sel.rangeCount; i < len; ++i) {
3024
+ sel._ranges[i] = new api.WrappedRange(sel.nativeSelection.getRangeAt(i));
3025
+ }
3026
+ updateAnchorAndFocusFromRange(sel, sel._ranges[sel.rangeCount - 1], selectionIsBackwards(sel.nativeSelection));
3027
+ sel.isCollapsed = selectionIsCollapsed(sel);
3028
+ } else {
3029
+ updateEmptySelection(sel);
3030
+ }
3031
+ }
3032
+ };
3033
+ } else if (selectionHasAnchorAndFocus && typeof testSelection.isCollapsed == BOOLEAN && typeof testRange.collapsed == BOOLEAN && api.features.implementsDomRange) {
3034
+ refreshSelection = function (sel) {
3035
+ var range, nativeSel = sel.nativeSelection;
3036
+ if (nativeSel.anchorNode) {
3037
+ range = getSelectionRangeAt(nativeSel, 0);
3038
+ sel._ranges = [range];
3039
+ sel.rangeCount = 1;
3040
+ updateAnchorAndFocusFromNativeSelection(sel);
3041
+ sel.isCollapsed = selectionIsCollapsed(sel);
3042
+ } else {
3043
+ updateEmptySelection(sel);
3044
+ }
3045
+ };
3046
+ } else {
3047
+ module.fail("No means of obtaining a Range or TextRange from the user's selection was found");
3048
+ return false;
3049
+ }
3050
+
3051
+ selProto.refresh = function (checkForChanges) {
3052
+ var oldRanges = checkForChanges ? this._ranges.slice(0) : null;
3053
+ refreshSelection(this);
3054
+ if (checkForChanges) {
3055
+ var i = oldRanges.length;
3056
+ if (i != this._ranges.length) {
3057
+ return false;
3058
+ }
3059
+ while (i--) {
3060
+ if (!DomRange.rangesEqual(oldRanges[i], this._ranges[i])) {
3061
+ return false;
3062
+ }
3063
+ }
3064
+ return true;
3065
+ }
3066
+ };
3067
+
3068
+ // Removal of a single range
3069
+ var removeRangeManually = function (sel, range) {
3070
+ var ranges = sel.getAllRanges(),
3071
+ removed = false;
3072
+ sel.removeAllRanges();
3073
+ for (var i = 0, len = ranges.length; i < len; ++i) {
3074
+ if (removed || range !== ranges[i]) {
3075
+ sel.addRange(ranges[i]);
3076
+ } else {
3077
+ // According to the draft WHATWG Range spec, the same range may be added to the selection multiple
3078
+ // times. removeRange should only remove the first instance, so the following ensures only the first
3079
+ // instance is removed
3080
+ removed = true;
3081
+ }
3082
+ }
3083
+ if (!sel.rangeCount) {
3084
+ updateEmptySelection(sel);
3085
+ }
3086
+ };
3087
+
3088
+ if (implementsControlRange) {
3089
+ selProto.removeRange = function (range) {
3090
+ if (this.docSelection.type == CONTROL) {
3091
+ var controlRange = this.docSelection.createRange();
3092
+ var rangeElement = getSingleElementFromRange(range);
3093
+
3094
+ // Create a new ControlRange containing all the elements in the selected ControlRange minus the
3095
+ // element contained by the supplied range
3096
+ var doc = dom.getDocument(controlRange.item(0));
3097
+ var newControlRange = dom.getBody(doc).createControlRange();
3098
+ var el, removed = false;
3099
+ for (var i = 0, len = controlRange.length; i < len; ++i) {
3100
+ el = controlRange.item(i);
3101
+ if (el !== rangeElement || removed) {
3102
+ newControlRange.add(controlRange.item(i));
3103
+ } else {
3104
+ removed = true;
3105
+ }
3106
+ }
3107
+ newControlRange.select();
3108
+
3109
+ // Update the wrapped selection based on what's now in the native selection
3110
+ updateControlSelection(this);
3111
+ } else {
3112
+ removeRangeManually(this, range);
3113
+ }
3114
+ };
3115
+ } else {
3116
+ selProto.removeRange = function (range) {
3117
+ removeRangeManually(this, range);
3118
+ };
3119
+ }
3120
+
3121
+ // Detecting if a selection is backwards
3122
+ var selectionIsBackwards;
3123
+ if (!useDocumentSelection && selectionHasAnchorAndFocus && api.features.implementsDomRange) {
3124
+ selectionIsBackwards = function (sel) {
3125
+ var backwards = false;
3126
+ if (sel.anchorNode) {
3127
+ backwards = (dom.comparePoints(sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset) == 1);
3128
+ }
3129
+ return backwards;
3130
+ };
3131
+
3132
+ selProto.isBackwards = function () {
3133
+ return selectionIsBackwards(this);
3134
+ };
3135
+ } else {
3136
+ selectionIsBackwards = selProto.isBackwards = function () {
3137
+ return false;
3138
+ };
3139
+ }
3140
+
3141
+ // Selection text
3142
+ // This is conformant to the new WHATWG DOM Range draft spec but differs from WebKit and Mozilla's implementation
3143
+ selProto.toString = function () {
3144
+
3145
+ var rangeTexts = [];
3146
+ for (var i = 0, len = this.rangeCount; i < len; ++i) {
3147
+ rangeTexts[i] = "" + this._ranges[i];
3148
+ }
3149
+ return rangeTexts.join("");
3150
+ };
3151
+
3152
+ function assertNodeInSameDocument(sel, node) {
3153
+ if (sel.anchorNode && (dom.getDocument(sel.anchorNode) !== dom.getDocument(node))) {
3154
+ throw new DOMException("WRONG_DOCUMENT_ERR");
3155
+ }
3156
+ }
3157
+
3158
+ // No current browsers conform fully to the HTML 5 draft spec for this method, so Rangy's own method is always used
3159
+ selProto.collapse = function (node, offset) {
3160
+ assertNodeInSameDocument(this, node);
3161
+ var range = api.createRange(dom.getDocument(node));
3162
+ range.collapseToPoint(node, offset);
3163
+ this.removeAllRanges();
3164
+ this.addRange(range);
3165
+ this.isCollapsed = true;
3166
+ };
3167
+
3168
+ selProto.collapseToStart = function () {
3169
+ if (this.rangeCount) {
3170
+ var range = this._ranges[0];
3171
+ this.collapse(range.startContainer, range.startOffset);
3172
+ } else {
3173
+ throw new DOMException("INVALID_STATE_ERR");
3174
+ }
3175
+ };
3176
+
3177
+ selProto.collapseToEnd = function () {
3178
+ if (this.rangeCount) {
3179
+ var range = this._ranges[this.rangeCount - 1];
3180
+ this.collapse(range.endContainer, range.endOffset);
3181
+ } else {
3182
+ throw new DOMException("INVALID_STATE_ERR");
3183
+ }
3184
+ };
3185
+
3186
+ // The HTML 5 spec is very specific on how selectAllChildren should be implemented so the native implementation is
3187
+ // never used by Rangy.
3188
+ selProto.selectAllChildren = function (node) {
3189
+ assertNodeInSameDocument(this, node);
3190
+ var range = api.createRange(dom.getDocument(node));
3191
+ range.selectNodeContents(node);
3192
+ this.removeAllRanges();
3193
+ this.addRange(range);
3194
+ };
3195
+
3196
+ selProto.deleteFromDocument = function () {
3197
+ // Sepcial behaviour required for Control selections
3198
+ if (implementsControlRange && implementsDocSelection && this.docSelection.type == CONTROL) {
3199
+ var controlRange = this.docSelection.createRange();
3200
+ var element;
3201
+ while (controlRange.length) {
3202
+ element = controlRange.item(0);
3203
+ controlRange.remove(element);
3204
+ element.parentNode.removeChild(element);
3205
+ }
3206
+ this.refresh();
3207
+ } else if (this.rangeCount) {
3208
+ var ranges = this.getAllRanges();
3209
+ this.removeAllRanges();
3210
+ for (var i = 0, len = ranges.length; i < len; ++i) {
3211
+ ranges[i].deleteContents();
3212
+ }
3213
+ // The HTML5 spec says nothing about what the selection should contain after calling deleteContents on each
3214
+ // range. Firefox moves the selection to where the final selected range was, so we emulate that
3215
+ this.addRange(ranges[len - 1]);
3216
+ }
3217
+ };
3218
+
3219
+ // The following are non-standard extensions
3220
+ selProto.getAllRanges = function () {
3221
+ return this._ranges.slice(0);
3222
+ };
3223
+
3224
+ selProto.setSingleRange = function (range) {
3225
+ this.setRanges([range]);
3226
+ };
3227
+
3228
+ selProto.containsNode = function (node, allowPartial) {
3229
+ for (var i = 0, len = this._ranges.length; i < len; ++i) {
3230
+ if (this._ranges[i].containsNode(node, allowPartial)) {
3231
+ return true;
3232
+ }
3233
+ }
3234
+ return false;
3235
+ };
3236
+
3237
+ selProto.toHtml = function () {
3238
+ var html = "";
3239
+ if (this.rangeCount) {
3240
+ var container = DomRange.getRangeDocument(this._ranges[0]).createElement("div");
3241
+ for (var i = 0, len = this._ranges.length; i < len; ++i) {
3242
+ container.appendChild(this._ranges[i].cloneContents());
3243
+ }
3244
+ html = container.innerHTML;
3245
+ }
3246
+ return html;
3247
+ };
3248
+
3249
+ function inspect(sel) {
3250
+ var rangeInspects = [];
3251
+ var anchor = new DomPosition(sel.anchorNode, sel.anchorOffset);
3252
+ var focus = new DomPosition(sel.focusNode, sel.focusOffset);
3253
+ var name = (typeof sel.getName == "function") ? sel.getName() : "Selection";
3254
+
3255
+ if (typeof sel.rangeCount != "undefined") {
3256
+ for (var i = 0, len = sel.rangeCount; i < len; ++i) {
3257
+ rangeInspects[i] = DomRange.inspect(sel.getRangeAt(i));
3258
+ }
3259
+ }
3260
+ return "[" + name + "(Ranges: " + rangeInspects.join(", ") + ")(anchor: " + anchor.inspect() + ", focus: " + focus.inspect() + "]";
3261
+
3262
+ }
3263
+
3264
+ selProto.getName = function () {
3265
+ return "WrappedSelection";
3266
+ };
3267
+
3268
+ selProto.inspect = function () {
3269
+ return inspect(this);
3270
+ };
3271
+
3272
+ selProto.detach = function () {
3273
+ this.win[windowPropertyName] = null;
3274
+ this.win = this.anchorNode = this.focusNode = null;
3275
+ };
3276
+
3277
+ WrappedSelection.inspect = inspect;
3278
+
3279
+ api.Selection = WrappedSelection;
3280
+
3281
+ api.selectionPrototype = selProto;
3282
+
3283
+ api.addCreateMissingNativeApiListener(function (win) {
3284
+ if (typeof win.getSelection == "undefined") {
3285
+ win.getSelection = function () {
3286
+ return api.getSelection(this);
3287
+ };
3288
+ }
3289
+ win = null;
3290
+ });
3291
+ });
3292
+
3293
+ // TODO we should avoid populating the global namespace
3294
+ window.rangy = rangy;
3295
+ }());