narf 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (424) hide show
  1. data/ChangeLog +22 -0
  2. data/lib/web/htmltools/xmltree.rb +2 -2
  3. data/lib/web/htmltools/xpath.rb +1 -1
  4. data/narf.gemspec +1 -1
  5. metadata +2 -460
  6. data/InstalledFiles +0 -2227
  7. data/config.save +0 -12
  8. data/doc/apache_cgi.txt~ +0 -17
  9. data/doc/fastcgi.txt~ +0 -19
  10. data/doc/rdoc/classes/Web.html +0 -369
  11. data/doc/rdoc/classes/Web.src/M000002.html +0 -15
  12. data/doc/rdoc/classes/Web.src/M000003.html +0 -15
  13. data/doc/rdoc/classes/Web.src/M000004.html +0 -15
  14. data/doc/rdoc/classes/Web.src/M000005.html +0 -15
  15. data/doc/rdoc/classes/Web.src/M000006.html +0 -20
  16. data/doc/rdoc/classes/Web.src/M000007.html +0 -18
  17. data/doc/rdoc/classes/Web.src/M000008.html +0 -18
  18. data/doc/rdoc/classes/Web.src/M000009.html +0 -18
  19. data/doc/rdoc/classes/Web.src/M000010.html +0 -15
  20. data/doc/rdoc/classes/Web.src/M000011.html +0 -15
  21. data/doc/rdoc/classes/Web.src/M000012.html +0 -15
  22. data/doc/rdoc/classes/Web/CGD.html +0 -173
  23. data/doc/rdoc/classes/Web/CGD.src/M000037.html +0 -24
  24. data/doc/rdoc/classes/Web/CGD.src/M000038.html +0 -24
  25. data/doc/rdoc/classes/Web/CGD.src/M000039.html +0 -15
  26. data/doc/rdoc/classes/Web/CGD.src/M000040.html +0 -15
  27. data/doc/rdoc/classes/Web/CGD.src/M000041.html +0 -23
  28. data/doc/rdoc/classes/Web/CGI.html +0 -946
  29. data/doc/rdoc/classes/Web/CGI.src/M000051.html +0 -15
  30. data/doc/rdoc/classes/Web/CGI.src/M000052.html +0 -24
  31. data/doc/rdoc/classes/Web/CGI.src/M000053.html +0 -15
  32. data/doc/rdoc/classes/Web/CGI.src/M000054.html +0 -15
  33. data/doc/rdoc/classes/Web/CGI.src/M000055.html +0 -15
  34. data/doc/rdoc/classes/Web/CGI.src/M000056.html +0 -15
  35. data/doc/rdoc/classes/Web/CGI.src/M000057.html +0 -17
  36. data/doc/rdoc/classes/Web/CGI.src/M000058.html +0 -34
  37. data/doc/rdoc/classes/Web/CGI.src/M000059.html +0 -22
  38. data/doc/rdoc/classes/Web/CGI.src/M000060.html +0 -15
  39. data/doc/rdoc/classes/Web/CGI.src/M000061.html +0 -15
  40. data/doc/rdoc/classes/Web/CGI.src/M000062.html +0 -19
  41. data/doc/rdoc/classes/Web/CGI.src/M000063.html +0 -18
  42. data/doc/rdoc/classes/Web/CGI.src/M000064.html +0 -19
  43. data/doc/rdoc/classes/Web/CGI.src/M000065.html +0 -15
  44. data/doc/rdoc/classes/Web/CGI.src/M000066.html +0 -15
  45. data/doc/rdoc/classes/Web/CGI.src/M000067.html +0 -15
  46. data/doc/rdoc/classes/Web/CGI.src/M000068.html +0 -13
  47. data/doc/rdoc/classes/Web/CGI.src/M000069.html +0 -13
  48. data/doc/rdoc/classes/Web/CGI.src/M000070.html +0 -13
  49. data/doc/rdoc/classes/Web/CGI.src/M000071.html +0 -13
  50. data/doc/rdoc/classes/Web/CGI.src/M000072.html +0 -19
  51. data/doc/rdoc/classes/Web/CGI.src/M000073.html +0 -15
  52. data/doc/rdoc/classes/Web/CGI.src/M000074.html +0 -19
  53. data/doc/rdoc/classes/Web/CGI.src/M000075.html +0 -15
  54. data/doc/rdoc/classes/Web/CGI.src/M000076.html +0 -15
  55. data/doc/rdoc/classes/Web/CGI.src/M000077.html +0 -15
  56. data/doc/rdoc/classes/Web/CGI.src/M000078.html +0 -20
  57. data/doc/rdoc/classes/Web/CGI.src/M000079.html +0 -36
  58. data/doc/rdoc/classes/Web/CGI.src/M000080.html +0 -19
  59. data/doc/rdoc/classes/Web/CGI.src/M000081.html +0 -18
  60. data/doc/rdoc/classes/Web/CGI.src/M000082.html +0 -15
  61. data/doc/rdoc/classes/Web/CGI.src/M000083.html +0 -17
  62. data/doc/rdoc/classes/Web/CGI.src/M000084.html +0 -15
  63. data/doc/rdoc/classes/Web/CGI.src/M000085.html +0 -16
  64. data/doc/rdoc/classes/Web/CGI.src/M000086.html +0 -15
  65. data/doc/rdoc/classes/Web/CGI.src/M000087.html +0 -15
  66. data/doc/rdoc/classes/Web/CGI.src/M000088.html +0 -15
  67. data/doc/rdoc/classes/Web/CGI.src/M000089.html +0 -16
  68. data/doc/rdoc/classes/Web/CGI.src/M000090.html +0 -15
  69. data/doc/rdoc/classes/Web/CGI.src/M000091.html +0 -15
  70. data/doc/rdoc/classes/Web/CGI.src/M000092.html +0 -15
  71. data/doc/rdoc/classes/Web/CGI.src/M000093.html +0 -15
  72. data/doc/rdoc/classes/Web/CGI.src/M000094.html +0 -15
  73. data/doc/rdoc/classes/Web/CGI.src/M000095.html +0 -15
  74. data/doc/rdoc/classes/Web/CGI.src/M000096.html +0 -19
  75. data/doc/rdoc/classes/Web/CGI.src/M000097.html +0 -15
  76. data/doc/rdoc/classes/Web/CGI.src/M000098.html +0 -15
  77. data/doc/rdoc/classes/Web/CGI.src/M000099.html +0 -43
  78. data/doc/rdoc/classes/Web/CGI.src/M000100.html +0 -18
  79. data/doc/rdoc/classes/Web/CGI.src/M000101.html +0 -20
  80. data/doc/rdoc/classes/Web/CGI.src/M000102.html +0 -15
  81. data/doc/rdoc/classes/Web/CGI.src/M000103.html +0 -15
  82. data/doc/rdoc/classes/Web/CGI.src/M000104.html +0 -15
  83. data/doc/rdoc/classes/Web/CGI.src/M000105.html +0 -24
  84. data/doc/rdoc/classes/Web/CGI.src/M000106.html +0 -24
  85. data/doc/rdoc/classes/Web/CGI.src/M000107.html +0 -22
  86. data/doc/rdoc/classes/Web/CaseInsensitiveHash.html +0 -104
  87. data/doc/rdoc/classes/Web/CaseInsensitiveHash.src/M000118.html +0 -15
  88. data/doc/rdoc/classes/Web/CaseInsensitiveHash.src/M000119.html +0 -15
  89. data/doc/rdoc/classes/Web/CaseInsensitiveHash.src/M000120.html +0 -15
  90. data/doc/rdoc/classes/Web/Mime.html +0 -122
  91. data/doc/rdoc/classes/Web/Mime.src/M000118.html +0 -15
  92. data/doc/rdoc/classes/Web/Mime.src/M000119.html +0 -15
  93. data/doc/rdoc/classes/Web/Mime.src/M000120.html +0 -23
  94. data/doc/rdoc/classes/Web/Mime.src/M000121.html +0 -15
  95. data/doc/rdoc/classes/Web/Mime.src/M000122.html +0 -15
  96. data/doc/rdoc/classes/Web/Mime.src/M000123.html +0 -23
  97. data/doc/rdoc/classes/Web/Mime.src/M000124.html +0 -15
  98. data/doc/rdoc/classes/Web/Narflates.html +0 -134
  99. data/doc/rdoc/classes/Web/Parser.html +0 -219
  100. data/doc/rdoc/classes/Web/Parser.src/M000013.html +0 -21
  101. data/doc/rdoc/classes/Web/Parser.src/M000014.html +0 -19
  102. data/doc/rdoc/classes/Web/Parser.src/M000015.html +0 -21
  103. data/doc/rdoc/classes/Web/Parser.src/M000016.html +0 -15
  104. data/doc/rdoc/classes/Web/Parser.src/M000017.html +0 -30
  105. data/doc/rdoc/classes/Web/Parser.src/M000018.html +0 -15
  106. data/doc/rdoc/classes/Web/Parser.src/M000019.html +0 -19
  107. data/doc/rdoc/classes/Web/Parser.src/M000020.html +0 -27
  108. data/doc/rdoc/classes/Web/Parser.src/M000021.html +0 -15
  109. data/doc/rdoc/classes/Web/Parser.src/M000022.html +0 -16
  110. data/doc/rdoc/classes/Web/Parser.src/M000023.html +0 -18
  111. data/doc/rdoc/classes/Web/Session.html +0 -178
  112. data/doc/rdoc/classes/Web/Session.src/M000042.html +0 -20
  113. data/doc/rdoc/classes/Web/Session.src/M000043.html +0 -19
  114. data/doc/rdoc/classes/Web/Session.src/M000044.html +0 -21
  115. data/doc/rdoc/classes/Web/Session.src/M000045.html +0 -21
  116. data/doc/rdoc/classes/Web/Session.src/M000046.html +0 -15
  117. data/doc/rdoc/classes/Web/Session.src/M000047.html +0 -17
  118. data/doc/rdoc/classes/Web/Session.src/M000048.html +0 -15
  119. data/doc/rdoc/classes/Web/Session.src/M000049.html +0 -15
  120. data/doc/rdoc/classes/Web/Session.src/M000050.html +0 -16
  121. data/doc/rdoc/classes/Web/Testing.html +0 -474
  122. data/doc/rdoc/classes/Web/Testing.src/M000024.html +0 -15
  123. data/doc/rdoc/classes/Web/Testing.src/M000025.html +0 -25
  124. data/doc/rdoc/classes/Web/Testing.src/M000026.html +0 -15
  125. data/doc/rdoc/classes/Web/Testing.src/M000027.html +0 -25
  126. data/doc/rdoc/classes/Web/Testing.src/M000028.html +0 -57
  127. data/doc/rdoc/classes/Web/Testing.src/M000029.html +0 -15
  128. data/doc/rdoc/classes/Web/Testing.src/M000030.html +0 -15
  129. data/doc/rdoc/classes/Web/Testing.src/M000031.html +0 -15
  130. data/doc/rdoc/classes/Web/Testing.src/M000032.html +0 -15
  131. data/doc/rdoc/classes/Web/Testing.src/M000033.html +0 -15
  132. data/doc/rdoc/classes/Web/Testing.src/M000034.html +0 -15
  133. data/doc/rdoc/classes/Web/Testing.src/M000035.html +0 -15
  134. data/doc/rdoc/classes/Web/Testing.src/M000036.html +0 -18
  135. data/doc/rdoc/classes/Web/Upload.html +0 -160
  136. data/doc/rdoc/classes/Web/Upload.src/M000108.html +0 -25
  137. data/doc/rdoc/classes/Web/Upload.src/M000109.html +0 -18
  138. data/doc/rdoc/classes/Web/Upload.src/M000110.html +0 -16
  139. data/doc/rdoc/classes/Web/Upload.src/M000111.html +0 -16
  140. data/doc/rdoc/classes/Web/Wiki.html +0 -249
  141. data/doc/rdoc/classes/Web/Wiki.src/M000112.html +0 -25
  142. data/doc/rdoc/classes/Web/Wiki.src/M000113.html +0 -15
  143. data/doc/rdoc/classes/Web/Wiki.src/M000114.html +0 -26
  144. data/doc/rdoc/classes/Web/Wiki.src/M000115.html +0 -21
  145. data/doc/rdoc/classes/Web/Wiki.src/M000116.html +0 -18
  146. data/doc/rdoc/classes/Web/Wiki.src/M000117.html +0 -19
  147. data/doc/rdoc/created.rid +0 -1
  148. data/doc/rdoc/files/README.html +0 -230
  149. data/doc/rdoc/files/doc/apache_cgi_txt.html +0 -76
  150. data/doc/rdoc/files/doc/fastcgi_txt.html +0 -82
  151. data/doc/rdoc/files/doc/mod_ruby_txt.html +0 -62
  152. data/doc/rdoc/files/doc/webrick_txt.html +0 -79
  153. data/doc/rdoc/files/examples/examples_rdoc.html +0 -73
  154. data/doc/rdoc/files/lib/web/cgi_rb.html +0 -75
  155. data/doc/rdoc/files/lib/web/mime_rb.html +0 -67
  156. data/doc/rdoc/files/lib/web/parser_rb.html +0 -73
  157. data/doc/rdoc/files/lib/web/session_rb.html +0 -73
  158. data/doc/rdoc/files/lib/web/template_rb.html +0 -73
  159. data/doc/rdoc/files/lib/web/testing_rb.html +0 -67
  160. data/doc/rdoc/files/lib/web/upload_rb.html +0 -73
  161. data/doc/rdoc/files/lib/web/wiki_rb.html +0 -79
  162. data/doc/rdoc/files/lib/web_rb.html +0 -116
  163. data/doc/rdoc/files/lib/web_rb.src/M000001.html +0 -15
  164. data/doc/rdoc/fr_class_index.html +0 -47
  165. data/doc/rdoc/fr_file_index.html +0 -52
  166. data/doc/rdoc/fr_method_index.html +0 -158
  167. data/doc/rdoc/index.html +0 -22
  168. data/doc/rdoc/rdoc-style.css +0 -99
  169. data/examples/admin.rb~ +0 -5
  170. data/examples/cookbook.rdoc~ +0 -238
  171. data/examples/examples.rdoc~ +0 -17
  172. data/examples/hello.world.rb~ +0 -3
  173. data/examples/session.rb~ +0 -31
  174. data/examples/test/test.hello.world.rb~ +0 -9
  175. data/examples/test/test.session.rb~ +0 -37
  176. data/examples/wiki.rb~ +0 -5
  177. data/lib/web.rb~ +0 -290
  178. data/lib/web/#assertinclude.rb# +0 -110
  179. data/lib/web/assertinclude.rb~ +0 -110
  180. data/lib/web/cgi.rb~ +0 -640
  181. data/lib/web/htmlparser/html-parser.rb~ +0 -429
  182. data/lib/web/htmlparser/sgml-parser.rb~ +0 -332
  183. data/lib/web/htmltools/element.rb~ +0 -296
  184. data/lib/web/htmltools/stparser.rb~ +0 -276
  185. data/lib/web/htmltools/tags.rb~ +0 -286
  186. data/lib/web/htmltools/tree.rb~ +0 -139
  187. data/lib/web/htmltools/xmltree.rb~ +0 -160
  188. data/lib/web/htmltools/xpath.rb~ +0 -71
  189. data/lib/web/parser.rb~ +0 -288
  190. data/lib/web/request.rb~ +0 -238
  191. data/lib/web/runner.rb~ +0 -26
  192. data/lib/web/sapi/fastcgi.rb~ +0 -25
  193. data/lib/web/sapi/mod_ruby.rb~ +0 -46
  194. data/lib/web/sapi/webrick.rb~ +0 -89
  195. data/lib/web/session.rb~ +0 -75
  196. data/lib/web/tagparser.rb~ +0 -96
  197. data/lib/web/template.rb~ +0 -613
  198. data/lib/web/testing.rb~ +0 -546
  199. data/lib/web/unit/response.rb~ +0 -461
  200. data/lib/web/unit/ui/cui/testrunner.rb~ +0 -50
  201. data/lib/web/upload.rb~ +0 -262
  202. data/lib/web/wiki.rb~ +0 -517
  203. data/lib/web/wiki/linker.rb~ +0 -72
  204. data/lib/web/wiki/mime.rb~ +0 -68
  205. data/lib/web/wiki/page.rb~ +0 -192
  206. data/lib/web/wiki/resources/#edit.html# +0 -65
  207. data/lib/web/wiki/resources/admin.html~ +0 -13
  208. data/lib/web/wiki/resources/default-content_editor.html~ +0 -1
  209. data/lib/web/wiki/resources/edit.html~ +0 -2
  210. data/lib/web/wiki/resources/home.html~ +0 -10
  211. data/lib/web/wiki/resources/htmlarea/ChangeLog +0 -1185
  212. data/lib/web/wiki/resources/htmlarea/dialog.js +0 -72
  213. data/lib/web/wiki/resources/htmlarea/examples/2-areas.cgi +0 -16
  214. data/lib/web/wiki/resources/htmlarea/examples/2-areas.html +0 -158
  215. data/lib/web/wiki/resources/htmlarea/examples/context-menu.html +0 -95
  216. data/lib/web/wiki/resources/htmlarea/examples/core.html +0 -184
  217. data/lib/web/wiki/resources/htmlarea/examples/css.html +0 -88
  218. data/lib/web/wiki/resources/htmlarea/examples/custom.css +0 -29
  219. data/lib/web/wiki/resources/htmlarea/examples/full-page.html +0 -75
  220. data/lib/web/wiki/resources/htmlarea/examples/fully-loaded.html +0 -248
  221. data/lib/web/wiki/resources/htmlarea/examples/index.html +0 -40
  222. data/lib/web/wiki/resources/htmlarea/examples/spell-checker.html +0 -132
  223. data/lib/web/wiki/resources/htmlarea/examples/table-operations.html +0 -116
  224. data/lib/web/wiki/resources/htmlarea/examples/test.cgi +0 -21
  225. data/lib/web/wiki/resources/htmlarea/htmlarea.css +0 -180
  226. data/lib/web/wiki/resources/htmlarea/htmlarea.js +0 -2175
  227. data/lib/web/wiki/resources/htmlarea/images/ed_about.gif +0 -0
  228. data/lib/web/wiki/resources/htmlarea/images/ed_align_center.gif +0 -0
  229. data/lib/web/wiki/resources/htmlarea/images/ed_align_justify.gif +0 -0
  230. data/lib/web/wiki/resources/htmlarea/images/ed_align_left.gif +0 -0
  231. data/lib/web/wiki/resources/htmlarea/images/ed_align_right.gif +0 -0
  232. data/lib/web/wiki/resources/htmlarea/images/ed_blank.gif +0 -0
  233. data/lib/web/wiki/resources/htmlarea/images/ed_charmap.gif +0 -0
  234. data/lib/web/wiki/resources/htmlarea/images/ed_color_bg.gif +0 -0
  235. data/lib/web/wiki/resources/htmlarea/images/ed_color_fg.gif +0 -0
  236. data/lib/web/wiki/resources/htmlarea/images/ed_copy.gif +0 -0
  237. data/lib/web/wiki/resources/htmlarea/images/ed_custom.gif +0 -0
  238. data/lib/web/wiki/resources/htmlarea/images/ed_cut.gif +0 -0
  239. data/lib/web/wiki/resources/htmlarea/images/ed_delete.gif +0 -0
  240. data/lib/web/wiki/resources/htmlarea/images/ed_format_bold.gif +0 -0
  241. data/lib/web/wiki/resources/htmlarea/images/ed_format_italic.gif +0 -0
  242. data/lib/web/wiki/resources/htmlarea/images/ed_format_strike.gif +0 -0
  243. data/lib/web/wiki/resources/htmlarea/images/ed_format_sub.gif +0 -0
  244. data/lib/web/wiki/resources/htmlarea/images/ed_format_sup.gif +0 -0
  245. data/lib/web/wiki/resources/htmlarea/images/ed_format_underline.gif +0 -0
  246. data/lib/web/wiki/resources/htmlarea/images/ed_help.gif +0 -0
  247. data/lib/web/wiki/resources/htmlarea/images/ed_hr.gif +0 -0
  248. data/lib/web/wiki/resources/htmlarea/images/ed_html.gif +0 -0
  249. data/lib/web/wiki/resources/htmlarea/images/ed_image.gif +0 -0
  250. data/lib/web/wiki/resources/htmlarea/images/ed_indent_less.gif +0 -0
  251. data/lib/web/wiki/resources/htmlarea/images/ed_indent_more.gif +0 -0
  252. data/lib/web/wiki/resources/htmlarea/images/ed_left_to_right.gif +0 -0
  253. data/lib/web/wiki/resources/htmlarea/images/ed_link.gif +0 -0
  254. data/lib/web/wiki/resources/htmlarea/images/ed_list_bullet.gif +0 -0
  255. data/lib/web/wiki/resources/htmlarea/images/ed_list_num.gif +0 -0
  256. data/lib/web/wiki/resources/htmlarea/images/ed_paste.gif +0 -0
  257. data/lib/web/wiki/resources/htmlarea/images/ed_redo.gif +0 -0
  258. data/lib/web/wiki/resources/htmlarea/images/ed_right_to_left.gif +0 -0
  259. data/lib/web/wiki/resources/htmlarea/images/ed_save.gif +0 -0
  260. data/lib/web/wiki/resources/htmlarea/images/ed_show_border.gif +0 -0
  261. data/lib/web/wiki/resources/htmlarea/images/ed_splitcel.gif +0 -0
  262. data/lib/web/wiki/resources/htmlarea/images/ed_undo.gif +0 -0
  263. data/lib/web/wiki/resources/htmlarea/images/fullscreen_maximize.gif +0 -0
  264. data/lib/web/wiki/resources/htmlarea/images/fullscreen_minimize.gif +0 -0
  265. data/lib/web/wiki/resources/htmlarea/images/insert_table.gif +0 -0
  266. data/lib/web/wiki/resources/htmlarea/index.html +0 -199
  267. data/lib/web/wiki/resources/htmlarea/lang/b5.js +0 -36
  268. data/lib/web/wiki/resources/htmlarea/lang/cz.js +0 -63
  269. data/lib/web/wiki/resources/htmlarea/lang/da.js +0 -38
  270. data/lib/web/wiki/resources/htmlarea/lang/de.js +0 -54
  271. data/lib/web/wiki/resources/htmlarea/lang/ee.js +0 -63
  272. data/lib/web/wiki/resources/htmlarea/lang/el.js +0 -75
  273. data/lib/web/wiki/resources/htmlarea/lang/en.js +0 -88
  274. data/lib/web/wiki/resources/htmlarea/lang/es.js +0 -51
  275. data/lib/web/wiki/resources/htmlarea/lang/fi.js +0 -46
  276. data/lib/web/wiki/resources/htmlarea/lang/fr.js +0 -61
  277. data/lib/web/wiki/resources/htmlarea/lang/gb.js +0 -36
  278. data/lib/web/wiki/resources/htmlarea/lang/he.js +0 -63
  279. data/lib/web/wiki/resources/htmlarea/lang/hu.js +0 -63
  280. data/lib/web/wiki/resources/htmlarea/lang/it.js +0 -54
  281. data/lib/web/wiki/resources/htmlarea/lang/ja-euc.js +0 -37
  282. data/lib/web/wiki/resources/htmlarea/lang/ja-jis.js +0 -37
  283. data/lib/web/wiki/resources/htmlarea/lang/ja-sjis.js +0 -37
  284. data/lib/web/wiki/resources/htmlarea/lang/ja-utf8.js +0 -37
  285. data/lib/web/wiki/resources/htmlarea/lang/lt.js +0 -55
  286. data/lib/web/wiki/resources/htmlarea/lang/lv.js +0 -55
  287. data/lib/web/wiki/resources/htmlarea/lang/nb.js +0 -36
  288. data/lib/web/wiki/resources/htmlarea/lang/nl.js +0 -90
  289. data/lib/web/wiki/resources/htmlarea/lang/no.js +0 -79
  290. data/lib/web/wiki/resources/htmlarea/lang/pl.js +0 -36
  291. data/lib/web/wiki/resources/htmlarea/lang/pt_br.js +0 -37
  292. data/lib/web/wiki/resources/htmlarea/lang/ro.js +0 -80
  293. data/lib/web/wiki/resources/htmlarea/lang/ru.js +0 -63
  294. data/lib/web/wiki/resources/htmlarea/lang/se.js +0 -38
  295. data/lib/web/wiki/resources/htmlarea/lang/si.js +0 -63
  296. data/lib/web/wiki/resources/htmlarea/lang/vn.js +0 -51
  297. data/lib/web/wiki/resources/htmlarea/license.txt +0 -30
  298. data/lib/web/wiki/resources/htmlarea/plugins/CSS/css.js +0 -116
  299. data/lib/web/wiki/resources/htmlarea/plugins/CSS/lang/en.js +0 -2
  300. data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/context-menu.js +0 -416
  301. data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/lang/de.js +0 -59
  302. data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/lang/el.js +0 -57
  303. data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/lang/en.js +0 -66
  304. data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/lang/nl.js +0 -66
  305. data/lib/web/wiki/resources/htmlarea/plugins/ContextMenu/menu.css +0 -64
  306. data/lib/web/wiki/resources/htmlarea/plugins/FullPage/full-page.js +0 -143
  307. data/lib/web/wiki/resources/htmlarea/plugins/FullPage/img/docprop.gif +0 -0
  308. data/lib/web/wiki/resources/htmlarea/plugins/FullPage/lang/en.js +0 -25
  309. data/lib/web/wiki/resources/htmlarea/plugins/FullPage/lang/ro.js +0 -25
  310. data/lib/web/wiki/resources/htmlarea/plugins/FullPage/popups/docprop.html +0 -131
  311. data/lib/web/wiki/resources/htmlarea/plugins/FullPage/test.html +0 -89
  312. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/img/spell-check.gif +0 -0
  313. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/cz.js +0 -37
  314. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/da.js +0 -37
  315. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/de.js +0 -28
  316. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/en.js +0 -38
  317. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/hu.js +0 -37
  318. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/it.js +0 -28
  319. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/lang/ro.js +0 -37
  320. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/readme-tech.html +0 -114
  321. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-check-logic.cgi +0 -210
  322. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-check-style.css +0 -10
  323. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-check-ui.html +0 -122
  324. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-check-ui.js +0 -397
  325. data/lib/web/wiki/resources/htmlarea/plugins/SpellChecker/spell-checker.js +0 -79
  326. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-delete.gif +0 -0
  327. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-insert-after.gif +0 -0
  328. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-insert-before.gif +0 -0
  329. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-merge.gif +0 -0
  330. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-prop.gif +0 -0
  331. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/cell-split.gif +0 -0
  332. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/col-delete.gif +0 -0
  333. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/col-insert-after.gif +0 -0
  334. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/col-insert-before.gif +0 -0
  335. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/col-split.gif +0 -0
  336. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-delete.gif +0 -0
  337. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-insert-above.gif +0 -0
  338. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-insert-under.gif +0 -0
  339. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-prop.gif +0 -0
  340. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/row-split.gif +0 -0
  341. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/img/table-prop.gif +0 -0
  342. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/cz.js +0 -90
  343. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/da.js +0 -90
  344. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/de.js +0 -81
  345. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/el.js +0 -81
  346. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/en.js +0 -90
  347. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/fi.js +0 -66
  348. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/hu.js +0 -63
  349. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/it.js +0 -81
  350. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/nl.js +0 -90
  351. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/no.js +0 -91
  352. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/lang/ro.js +0 -90
  353. data/lib/web/wiki/resources/htmlarea/plugins/TableOperations/table-operations.js +0 -1160
  354. data/lib/web/wiki/resources/htmlarea/popupdiv.js +0 -369
  355. data/lib/web/wiki/resources/htmlarea/popups/about.html +0 -378
  356. data/lib/web/wiki/resources/htmlarea/popups/blank.html +0 -2
  357. data/lib/web/wiki/resources/htmlarea/popups/custom2.html +0 -35
  358. data/lib/web/wiki/resources/htmlarea/popups/editor_help.html +0 -16
  359. data/lib/web/wiki/resources/htmlarea/popups/fullscreen.html +0 -133
  360. data/lib/web/wiki/resources/htmlarea/popups/insert_image.html +0 -191
  361. data/lib/web/wiki/resources/htmlarea/popups/insert_table.html +0 -174
  362. data/lib/web/wiki/resources/htmlarea/popups/link.html +0 -142
  363. data/lib/web/wiki/resources/htmlarea/popups/old-fullscreen.html +0 -131
  364. data/lib/web/wiki/resources/htmlarea/popups/old_insert_image.html +0 -206
  365. data/lib/web/wiki/resources/htmlarea/popups/popup.js +0 -109
  366. data/lib/web/wiki/resources/htmlarea/popups/select_color.html +0 -347
  367. data/lib/web/wiki/resources/htmlarea/popupwin.js +0 -139
  368. data/lib/web/wiki/resources/htmlarea/reference.html +0 -523
  369. data/lib/web/wiki/resources/htmlarea/release-notes.html +0 -165
  370. data/lib/web/wiki/resources/illustration.html~ +0 -1
  371. data/lib/web/wiki/resources/index.html~ +0 -4
  372. data/lib/web/wiki/resources/more_news.html~ +0 -5
  373. data/lib/web/wiki/resources/more_news_rss_0.91.html +0 -23
  374. data/lib/web/wiki/resources/page_history.html~ +0 -19
  375. data/lib/web/wiki/resources/template.html~ +0 -13
  376. data/narf.gemspec~ +0 -40
  377. data/sapi/apache_cgi/INSTALL.txt~ +0 -9
  378. data/sapi/apache_cgi/README~ +0 -0
  379. data/sapi/fastcgi/INSTALL.txt~ +0 -17
  380. data/sapi/mod_ruby/INSTALL.txt~ +0 -5
  381. data/sapi/webrick/INSTALL.txt~ +0 -21
  382. data/sapi/webrick/run_webrick.rb~ +0 -16
  383. data/scripts/makedist.rb~ +0 -49
  384. data/test/mod_ruby_stub.rb~ +0 -38
  385. data/test/test.action.rb~ +0 -142
  386. data/test/test.assertinclude.rb~ +0 -109
  387. data/test/test.narf.cgi.rb~ +0 -105
  388. data/test/test.request.rb~ +0 -328
  389. data/test/test.response.rb~ +0 -556
  390. data/test/test.template.rb~ +0 -832
  391. data/test/test.web.test.rb~ +0 -461
  392. data/test/webunit/test_cookie.rb~ +0 -128
  393. data/test/webunit/test_form.rb~ +0 -43
  394. data/test/webunit/test_multipart.rb~ +0 -53
  395. data/test/webunit/test_params.rb~ +0 -211
  396. data/test/webunit/test_response.rb~ +0 -145
  397. data/test/webunit/test_site/assert.html~ +0 -1
  398. data/test/webunit/test_site/auth/index.html~ +0 -1
  399. data/test/webunit/test_site/badtags.html~ +0 -1
  400. data/test/webunit/test_site/cookie.cgi~ +0 -35
  401. data/test/webunit/test_site/document.xml~ +0 -1
  402. data/test/webunit/test_site/form.html~ +0 -1
  403. data/test/webunit/test_site/frame-0.html~ +0 -1
  404. data/test/webunit/test_site/frame-1.html~ +0 -1
  405. data/test/webunit/test_site/frame.html~ +0 -1
  406. data/test/webunit/test_site/image.html~ +0 -1
  407. data/test/webunit/test_site/include.cgi~ +0 -10
  408. data/test/webunit/test_site/jscript-0.html~ +0 -1
  409. data/test/webunit/test_site/jscript-1.html~ +0 -1
  410. data/test/webunit/test_site/jscript.html~ +0 -1
  411. data/test/webunit/test_site/link.html~ +0 -1
  412. data/test/webunit/test_site/multipart.cgi~ +0 -25
  413. data/test/webunit/test_site/multipart.html~ +0 -1
  414. data/test/webunit/test_site/params.html~ +0 -1
  415. data/test/webunit/test_site/redirect.cgi~ +0 -14
  416. data/test/webunit/test_site/response.html~ +0 -1
  417. data/test/webunit/test_site/simple.cgi~ +0 -17
  418. data/test/webunit/test_site/stock.cgi~ +0 -34
  419. data/test/webunit/test_site/table.html~ +0 -1
  420. data/test/webunit/test_site/test.cgi~ +0 -25
  421. data/test/wiki/test.history.rb~ +0 -254
  422. data/test/wiki/test.illustration_page.rb~ +0 -287
  423. data/test/wiki/test.tarpit.rb~ +0 -40
  424. data/test/wiki/test.wiki.rb~ +0 -295
@@ -1,2175 +0,0 @@
1
- // htmlArea v3.0 - Copyright (c) 2002-2004 interactivetools.com, inc.
2
- // This copyright notice MUST stay intact for use (see license.txt).
3
- //
4
- // Portions (c) dynarch.com, 2003-2004
5
- //
6
- // A free WYSIWYG editor replacement for <textarea> fields.
7
- // For full source code and docs, visit http://www.interactivetools.com/
8
- //
9
- // Version 3.0 developed by Mihai Bazon.
10
- // http://dynarch.com/mishoo
11
- //
12
- // $Id: htmlarea.js,v 1.59 2004/02/09 09:38:47 mishoo Exp $
13
-
14
- if (typeof _editor_url == "string") {
15
- // Leave exactly one backslash at the end of _editor_url
16
- _editor_url = _editor_url.replace(/\x2f*$/, '/');
17
- } else {
18
- alert("WARNING: _editor_url is not set! You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea', but it can be relative if you prefer. Further we will try to load the editor files correctly but we'll probably fail.");
19
- _editor_url = '';
20
- }
21
-
22
- // make sure we have a language
23
- if (typeof _editor_lang == "string") {
24
- _editor_lang = _editor_lang.toLowerCase();
25
- } else {
26
- _editor_lang = "en";
27
- }
28
-
29
- // Creates a new HTMLArea object. Tries to replace the textarea with the given
30
- // ID with it.
31
- function HTMLArea(textarea, config) {
32
- if (HTMLArea.checkSupportedBrowser()) {
33
- if (typeof config == "undefined") {
34
- this.config = new HTMLArea.Config();
35
- } else {
36
- this.config = config;
37
- }
38
- this._htmlArea = null;
39
- this._textArea = textarea;
40
- this._editMode = "wysiwyg";
41
- this.plugins = {};
42
- this._timerToolbar = null;
43
- this._timerUndo = null;
44
- this._undoQueue = new Array(this.config.undoSteps);
45
- this._undoPos = -1;
46
- this._customUndo = false;
47
- this._mdoc = document; // cache the document, we need it in plugins
48
- this.doctype = '';
49
- }
50
- };
51
-
52
- // load some scripts
53
- (function() {
54
- var scripts = HTMLArea._scripts = [ _editor_url + "htmlarea.js",
55
- _editor_url + "dialog.js",
56
- _editor_url + "popupwin.js",
57
- _editor_url + "lang/" + _editor_lang + ".js" ];
58
- var head = document.getElementsByTagName("head")[0];
59
- // start from 1, htmlarea.js is already loaded
60
- for (var i = 1; i < scripts.length; ++i) {
61
- var script = document.createElement("script");
62
- script.src = scripts[i];
63
- head.appendChild(script);
64
- }
65
- })();
66
-
67
- // cache some regexps
68
- HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig;
69
- HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
70
- HTMLArea.RE_head = /<head>((.|\n)*?)<\/head>/i;
71
- HTMLArea.RE_body = /<body>((.|\n)*?)<\/body>/i;
72
-
73
- HTMLArea.Config = function () {
74
- this.version = "3.0";
75
-
76
- this.width = "auto";
77
- this.height = "auto";
78
-
79
- // enable creation of a status bar?
80
- this.statusBar = true;
81
-
82
- // maximum size of the undo queue
83
- this.undoSteps = 20;
84
-
85
- // the time interval at which undo samples are taken
86
- this.undoTimeout = 500; // 1/2 sec.
87
-
88
- // the next parameter specifies whether the toolbar should be included
89
- // in the size or not.
90
- this.sizeIncludesToolbar = true;
91
-
92
- // if true then HTMLArea will retrieve the full HTML, starting with the
93
- // <HTML> tag.
94
- this.fullPage = false;
95
-
96
- // style included in the iframe document
97
- this.pageStyle = "";
98
-
99
- // set to true if you want Word code to be cleaned upon Paste
100
- this.killWordOnPaste = false;
101
-
102
- // BaseURL included in the iframe document
103
- this.baseURL = document.baseURI || document.URL;
104
- if (this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/))
105
- this.baseURL = RegExp.$1 + "/";
106
-
107
- // URL-s
108
- this.imgURL = "images/";
109
- this.popupURL = "popups/";
110
-
111
- /** CUSTOMIZING THE TOOLBAR
112
- * -------------------------
113
- *
114
- * It is recommended that you customize the toolbar contents in an
115
- * external file (i.e. the one calling HTMLArea) and leave this one
116
- * unchanged. That's because when we (InteractiveTools.com) release a
117
- * new official version, it's less likely that you will have problems
118
- * upgrading HTMLArea.
119
- */
120
- this.toolbar = [
121
- [ "fontname", "space",
122
- "fontsize", "space",
123
- "formatblock", "space",
124
- "bold", "italic", "underline", "strikethrough", "separator",
125
- "subscript", "superscript", "separator",
126
- "copy", "cut", "paste", "space", "undo", "redo" ],
127
-
128
- [ "justifyleft", "justifycenter", "justifyright", "justifyfull", "separator",
129
- "lefttoright", "righttoleft", "separator",
130
- "insertorderedlist", "insertunorderedlist", "outdent", "indent", "separator",
131
- "forecolor", "hilitecolor", "separator",
132
- "inserthorizontalrule", "createlink", "insertimage", "inserttable", "htmlmode", "separator",
133
- "popupeditor", "separator", "showhelp", "about" ]
134
- ];
135
-
136
- this.fontname = {
137
- "Arial": 'arial,helvetica,sans-serif',
138
- "Courier New": 'courier new,courier,monospace',
139
- "Georgia": 'georgia,times new roman,times,serif',
140
- "Tahoma": 'tahoma,arial,helvetica,sans-serif',
141
- "Times New Roman": 'times new roman,times,serif',
142
- "Verdana": 'verdana,arial,helvetica,sans-serif',
143
- "impact": 'impact',
144
- "WingDings": 'wingdings'
145
- };
146
-
147
- this.fontsize = {
148
- "1 (8 pt)": "1",
149
- "2 (10 pt)": "2",
150
- "3 (12 pt)": "3",
151
- "4 (14 pt)": "4",
152
- "5 (18 pt)": "5",
153
- "6 (24 pt)": "6",
154
- "7 (36 pt)": "7"
155
- };
156
-
157
- this.formatblock = {
158
- "Heading 1": "h1",
159
- "Heading 2": "h2",
160
- "Heading 3": "h3",
161
- "Heading 4": "h4",
162
- "Heading 5": "h5",
163
- "Heading 6": "h6",
164
- "Normal": "p",
165
- "Address": "address",
166
- "Formatted": "pre"
167
- };
168
-
169
- this.customSelects = {};
170
-
171
- function cut_copy_paste(e, cmd, obj) {
172
- e.execCommand(cmd);
173
- };
174
-
175
- // ADDING CUSTOM BUTTONS: please read below!
176
- // format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]"
177
- // - ID: unique ID for the button. If the button calls document.execCommand
178
- // it's wise to give it the same name as the called command.
179
- // - ACTION: function that gets called when the button is clicked.
180
- // it has the following prototype:
181
- // function(editor, buttonName)
182
- // - editor is the HTMLArea object that triggered the call
183
- // - buttonName is the ID of the clicked button
184
- // These 2 parameters makes it possible for you to use the same
185
- // handler for more HTMLArea objects or for more different buttons.
186
- // - ToolTip: default tooltip, for cases when it is not defined in the -lang- file (HTMLArea.I18N)
187
- // - Icon: path to an icon image file for the button (TODO: use one image for all buttons!)
188
- // - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.
189
- this.btnList = {
190
- bold: [ "Bold", "ed_format_bold.gif", false, function(e) {e.execCommand("bold");} ],
191
- italic: [ "Italic", "ed_format_italic.gif", false, function(e) {e.execCommand("italic");} ],
192
- underline: [ "Underline", "ed_format_underline.gif", false, function(e) {e.execCommand("underline");} ],
193
- strikethrough: [ "Strikethrough", "ed_format_strike.gif", false, function(e) {e.execCommand("strikethrough");} ],
194
- subscript: [ "Subscript", "ed_format_sub.gif", false, function(e) {e.execCommand("subscript");} ],
195
- superscript: [ "Superscript", "ed_format_sup.gif", false, function(e) {e.execCommand("superscript");} ],
196
- justifyleft: [ "Justify Left", "ed_align_left.gif", false, function(e) {e.execCommand("justifyleft");} ],
197
- justifycenter: [ "Justify Center", "ed_align_center.gif", false, function(e) {e.execCommand("justifycenter");} ],
198
- justifyright: [ "Justify Right", "ed_align_right.gif", false, function(e) {e.execCommand("justifyright");} ],
199
- justifyfull: [ "Justify Full", "ed_align_justify.gif", false, function(e) {e.execCommand("justifyfull");} ],
200
- insertorderedlist: [ "Ordered List", "ed_list_num.gif", false, function(e) {e.execCommand("insertorderedlist");} ],
201
- insertunorderedlist: [ "Bulleted List", "ed_list_bullet.gif", false, function(e) {e.execCommand("insertunorderedlist");} ],
202
- outdent: [ "Decrease Indent", "ed_indent_less.gif", false, function(e) {e.execCommand("outdent");} ],
203
- indent: [ "Increase Indent", "ed_indent_more.gif", false, function(e) {e.execCommand("indent");} ],
204
- forecolor: [ "Font Color", "ed_color_fg.gif", false, function(e) {e.execCommand("forecolor");} ],
205
- hilitecolor: [ "Background Color", "ed_color_bg.gif", false, function(e) {e.execCommand("hilitecolor");} ],
206
- inserthorizontalrule: [ "Horizontal Rule", "ed_hr.gif", false, function(e) {e.execCommand("inserthorizontalrule");} ],
207
- createlink: [ "Insert Web Link", "ed_link.gif", false, function(e) {e.execCommand("createlink", true);} ],
208
- insertimage: [ "Insert/Modify Image", "ed_image.gif", false, function(e) {e.execCommand("insertimage");} ],
209
- inserttable: [ "Insert Table", "insert_table.gif", false, function(e) {e.execCommand("inserttable");} ],
210
- htmlmode: [ "Toggle HTML Source", "ed_html.gif", true, function(e) {e.execCommand("htmlmode");} ],
211
- popupeditor: [ "Enlarge Editor", "fullscreen_maximize.gif", true, function(e) {e.execCommand("popupeditor");} ],
212
- about: [ "About this editor", "ed_about.gif", true, function(e) {e.execCommand("about");} ],
213
- showhelp: [ "Help using editor", "ed_help.gif", true, function(e) {e.execCommand("showhelp");} ],
214
- undo: [ "Undoes your last action", "ed_undo.gif", false, function(e) {e.execCommand("undo");} ],
215
- redo: [ "Redoes your last action", "ed_redo.gif", false, function(e) {e.execCommand("redo");} ],
216
- cut: [ "Cut selection", "ed_cut.gif", false, cut_copy_paste ],
217
- copy: [ "Copy selection", "ed_copy.gif", false, cut_copy_paste ],
218
- paste: [ "Paste from clipboard", "ed_paste.gif", false, cut_copy_paste ],
219
- lefttoright: [ "Direction left to right", "ed_left_to_right.gif", false, function(e) {e.execCommand("lefttoright");} ],
220
- righttoleft: [ "Direction right to left", "ed_right_to_left.gif", false, function(e) {e.execCommand("righttoleft");} ]
221
- };
222
- /* ADDING CUSTOM BUTTONS
223
- * ---------------------
224
- *
225
- * It is recommended that you add the custom buttons in an external
226
- * file and leave this one unchanged. That's because when we
227
- * (InteractiveTools.com) release a new official version, it's less
228
- * likely that you will have problems upgrading HTMLArea.
229
- *
230
- * Example on how to add a custom button when you construct the HTMLArea:
231
- *
232
- * var editor = new HTMLArea("your_text_area_id");
233
- * var cfg = editor.config; // this is the default configuration
234
- * cfg.btnList["my-hilite"] =
235
- * [ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action
236
- * "Highlight selection", // tooltip
237
- * "my_hilite.gif", // image
238
- * false // disabled in text mode
239
- * ];
240
- * cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
241
- *
242
- * An alternate (also more convenient and recommended) way to
243
- * accomplish this is to use the registerButton function below.
244
- */
245
- // initialize tooltips from the I18N module and generate correct image path
246
- for (var i in this.btnList) {
247
- var btn = this.btnList[i];
248
- btn[1] = _editor_url + this.imgURL + btn[1];
249
- if (typeof HTMLArea.I18N.tooltips[i] != "undefined") {
250
- btn[0] = HTMLArea.I18N.tooltips[i];
251
- }
252
- }
253
- };
254
-
255
- /** Helper function: register a new button with the configuration. It can be
256
- * called with all 5 arguments, or with only one (first one). When called with
257
- * only one argument it must be an object with the following properties: id,
258
- * tooltip, image, textMode, action. Examples:
259
- *
260
- * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...});
261
- * 2. config.registerButton({
262
- * id : "my-hilite", // the ID of your button
263
- * tooltip : "Hilite text", // the tooltip
264
- * image : "my-hilite.gif", // image to be displayed in the toolbar
265
- * textMode : false, // disabled in text mode
266
- * action : function(editor) { // called when the button is clicked
267
- * editor.surroundHTML('<span class="hilite">', '</span>');
268
- * },
269
- * context : "p" // will be disabled if outside a <p> element
270
- * });
271
- */
272
- HTMLArea.Config.prototype.registerButton = function(id, tooltip, image, textMode, action, context) {
273
- var the_id;
274
- if (typeof id == "string") {
275
- the_id = id;
276
- } else if (typeof id == "object") {
277
- the_id = id.id;
278
- } else {
279
- alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");
280
- return false;
281
- }
282
- // check for existing id
283
- if (typeof this.customSelects[the_id] != "undefined") {
284
- // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
285
- }
286
- if (typeof this.btnList[the_id] != "undefined") {
287
- // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
288
- }
289
- switch (typeof id) {
290
- case "string": this.btnList[id] = [ tooltip, image, textMode, action, context ]; break;
291
- case "object": this.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action, id.context ]; break;
292
- }
293
- };
294
-
295
- /** The following helper function registers a dropdown box with the editor
296
- * configuration. You still have to add it to the toolbar, same as with the
297
- * buttons. Call it like this:
298
- *
299
- * FIXME: add example
300
- */
301
- HTMLArea.Config.prototype.registerDropdown = function(object) {
302
- // check for existing id
303
- if (typeof this.customSelects[object.id] != "undefined") {
304
- // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
305
- }
306
- if (typeof this.btnList[object.id] != "undefined") {
307
- // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
308
- }
309
- this.customSelects[object.id] = object;
310
- };
311
-
312
- /** Call this function to remove some buttons/drop-down boxes from the toolbar.
313
- * Pass as the only parameter a string containing button/drop-down names
314
- * delimited by spaces. Note that the string should also begin with a space
315
- * and end with a space. Example:
316
- *
317
- * config.hideSomeButtons(" fontname fontsize textindicator ");
318
- *
319
- * It's useful because it's easier to remove stuff from the defaul toolbar than
320
- * create a brand new toolbar ;-)
321
- */
322
- HTMLArea.Config.prototype.hideSomeButtons = function(remove) {
323
- var toolbar = this.toolbar;
324
- for (var i in toolbar) {
325
- var line = toolbar[i];
326
- for (var j = line.length; --j >= 0; ) {
327
- if (remove.indexOf(" " + line[j] + " ") >= 0) {
328
- var len = 1;
329
- if (/separator|space/.test(line[j + 1])) {
330
- len = 2;
331
- }
332
- line.splice(j, len);
333
- }
334
- }
335
- }
336
- };
337
-
338
- /** Helper function: replace all TEXTAREA-s in the document with HTMLArea-s. */
339
- HTMLArea.replaceAll = function(config) {
340
- var tas = document.getElementsByTagName("textarea");
341
- for (var i = tas.length; i > 0; (new HTMLArea(tas[--i], config)).generate());
342
- };
343
-
344
- /** Helper function: replaces the TEXTAREA with the given ID with HTMLArea. */
345
- HTMLArea.replace = function(id, config) {
346
- var ta = HTMLArea.getElementById("textarea", id);
347
- return ta ? (new HTMLArea(ta, config)).generate() : null;
348
- };
349
-
350
- // Creates the toolbar and appends it to the _htmlarea
351
- HTMLArea.prototype._createToolbar = function () {
352
- var editor = this; // to access this in nested functions
353
-
354
- var toolbar = document.createElement("div");
355
- this._toolbar = toolbar;
356
- toolbar.className = "toolbar";
357
- toolbar.unselectable = "1";
358
- var tb_row = null;
359
- var tb_objects = new Object();
360
- this._toolbarObjects = tb_objects;
361
-
362
- // creates a new line in the toolbar
363
- function newLine() {
364
- var table = document.createElement("table");
365
- table.border = "0px";
366
- table.cellSpacing = "0px";
367
- table.cellPadding = "0px";
368
- toolbar.appendChild(table);
369
- // TBODY is required for IE, otherwise you don't see anything
370
- // in the TABLE.
371
- var tb_body = document.createElement("tbody");
372
- table.appendChild(tb_body);
373
- tb_row = document.createElement("tr");
374
- tb_body.appendChild(tb_row);
375
- }; // END of function: newLine
376
- // init first line
377
- newLine();
378
-
379
- // updates the state of a toolbar element. This function is member of
380
- // a toolbar element object (unnamed objects created by createButton or
381
- // createSelect functions below).
382
- function setButtonStatus(id, newval) {
383
- var oldval = this[id];
384
- var el = this.element;
385
- if (oldval != newval) {
386
- switch (id) {
387
- case "enabled":
388
- if (newval) {
389
- HTMLArea._removeClass(el, "buttonDisabled");
390
- el.disabled = false;
391
- } else {
392
- HTMLArea._addClass(el, "buttonDisabled");
393
- el.disabled = true;
394
- }
395
- break;
396
- case "active":
397
- if (newval) {
398
- HTMLArea._addClass(el, "buttonPressed");
399
- } else {
400
- HTMLArea._removeClass(el, "buttonPressed");
401
- }
402
- break;
403
- }
404
- this[id] = newval;
405
- }
406
- }; // END of function: setButtonStatus
407
-
408
- // this function will handle creation of combo boxes. Receives as
409
- // parameter the name of a button as defined in the toolBar config.
410
- // This function is called from createButton, above, if the given "txt"
411
- // doesn't match a button.
412
- function createSelect(txt) {
413
- var options = null;
414
- var el = null;
415
- var cmd = null;
416
- var customSelects = editor.config.customSelects;
417
- var context = null;
418
- switch (txt) {
419
- case "fontsize":
420
- case "fontname":
421
- case "formatblock":
422
- // the following line retrieves the correct
423
- // configuration option because the variable name
424
- // inside the Config object is named the same as the
425
- // button/select in the toolbar. For instance, if txt
426
- // == "formatblock" we retrieve config.formatblock (or
427
- // a different way to write it in JS is
428
- // config["formatblock"].
429
- options = editor.config[txt];
430
- cmd = txt;
431
- break;
432
- default:
433
- // try to fetch it from the list of registered selects
434
- cmd = txt;
435
- var dropdown = customSelects[cmd];
436
- if (typeof dropdown != "undefined") {
437
- options = dropdown.options;
438
- context = dropdown.context;
439
- } else {
440
- alert("ERROR [createSelect]:\nCan't find the requested dropdown definition");
441
- }
442
- break;
443
- }
444
- if (options) {
445
- el = document.createElement("select");
446
- var obj = {
447
- name : txt, // field name
448
- element : el, // the UI element (SELECT)
449
- enabled : true, // is it enabled?
450
- text : false, // enabled in text mode?
451
- cmd : cmd, // command ID
452
- state : setButtonStatus, // for changing state
453
- context : context
454
- };
455
- tb_objects[txt] = obj;
456
- for (var i in options) {
457
- var op = document.createElement("option");
458
- op.appendChild(document.createTextNode(i));
459
- op.value = options[i];
460
- el.appendChild(op);
461
- }
462
- HTMLArea._addEvent(el, "change", function () {
463
- editor._comboSelected(el, txt);
464
- });
465
- }
466
- return el;
467
- }; // END of function: createSelect
468
-
469
- // appends a new button to toolbar
470
- function createButton(txt) {
471
- // the element that will be created
472
- var el = null;
473
- var btn = null;
474
- switch (txt) {
475
- case "separator":
476
- el = document.createElement("div");
477
- el.className = "separator";
478
- break;
479
- case "space":
480
- el = document.createElement("div");
481
- el.className = "space";
482
- break;
483
- case "linebreak":
484
- newLine();
485
- return false;
486
- case "textindicator":
487
- el = document.createElement("div");
488
- el.appendChild(document.createTextNode("A"));
489
- el.className = "indicator";
490
- el.title = HTMLArea.I18N.tooltips.textindicator;
491
- var obj = {
492
- name : txt, // the button name (i.e. 'bold')
493
- element : el, // the UI element (DIV)
494
- enabled : true, // is it enabled?
495
- active : false, // is it pressed?
496
- text : false, // enabled in text mode?
497
- cmd : "textindicator", // the command ID
498
- state : setButtonStatus // for changing state
499
- };
500
- tb_objects[txt] = obj;
501
- break;
502
- default:
503
- btn = editor.config.btnList[txt];
504
- }
505
- if (!el && btn) {
506
- el = document.createElement("div");
507
- el.title = btn[0];
508
- el.className = "button";
509
- // let's just pretend we have a button object, and
510
- // assign all the needed information to it.
511
- var obj = {
512
- name : txt, // the button name (i.e. 'bold')
513
- element : el, // the UI element (DIV)
514
- enabled : true, // is it enabled?
515
- active : false, // is it pressed?
516
- text : btn[2], // enabled in text mode?
517
- cmd : btn[3], // the command ID
518
- state : setButtonStatus, // for changing state
519
- context : btn[4] || null // enabled in a certain context?
520
- };
521
- tb_objects[txt] = obj;
522
- // handlers to emulate nice flat toolbar buttons
523
- HTMLArea._addEvent(el, "mouseover", function () {
524
- if (obj.enabled) {
525
- HTMLArea._addClass(el, "buttonHover");
526
- }
527
- });
528
- HTMLArea._addEvent(el, "mouseout", function () {
529
- if (obj.enabled) with (HTMLArea) {
530
- _removeClass(el, "buttonHover");
531
- _removeClass(el, "buttonActive");
532
- (obj.active) && _addClass(el, "buttonPressed");
533
- }
534
- });
535
- HTMLArea._addEvent(el, "mousedown", function (ev) {
536
- if (obj.enabled) with (HTMLArea) {
537
- _addClass(el, "buttonActive");
538
- _removeClass(el, "buttonPressed");
539
- _stopEvent(is_ie ? window.event : ev);
540
- }
541
- });
542
- // when clicked, do the following:
543
- HTMLArea._addEvent(el, "click", function (ev) {
544
- if (obj.enabled) with (HTMLArea) {
545
- _removeClass(el, "buttonActive");
546
- _removeClass(el, "buttonHover");
547
- obj.cmd(editor, obj.name, obj);
548
- _stopEvent(is_ie ? window.event : ev);
549
- }
550
- });
551
- var img = document.createElement("img");
552
- img.src = btn[1];
553
- img.style.width = "18px";
554
- img.style.height = "18px";
555
- el.appendChild(img);
556
- } else if (!el) {
557
- el = createSelect(txt);
558
- }
559
- if (el) {
560
- var tb_cell = document.createElement("td");
561
- tb_row.appendChild(tb_cell);
562
- tb_cell.appendChild(el);
563
- } else {
564
- alert("FIXME: Unknown toolbar item: " + txt);
565
- }
566
- return el;
567
- };
568
-
569
- var first = true;
570
- for (var i in this.config.toolbar) {
571
- if (!first) {
572
- createButton("linebreak");
573
- } else {
574
- first = false;
575
- }
576
- var group = this.config.toolbar[i];
577
- for (var j in group) {
578
- var code = group[j];
579
- if (/^([IT])\[(.*?)\]/.test(code)) {
580
- // special case, create text label
581
- var l7ed = RegExp.$1 == "I"; // localized?
582
- var label = RegExp.$2;
583
- if (l7ed) {
584
- label = HTMLArea.I18N.custom[label];
585
- }
586
- var tb_cell = document.createElement("td");
587
- tb_row.appendChild(tb_cell);
588
- tb_cell.className = "label";
589
- tb_cell.innerHTML = label;
590
- } else {
591
- createButton(code);
592
- }
593
- }
594
- }
595
-
596
- this._htmlArea.appendChild(toolbar);
597
- };
598
-
599
- HTMLArea.prototype._createStatusBar = function() {
600
- var statusbar = document.createElement("div");
601
- statusbar.className = "statusBar";
602
- this._htmlArea.appendChild(statusbar);
603
- this._statusBar = statusbar;
604
- // statusbar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
605
- // creates a holder for the path view
606
- div = document.createElement("span");
607
- div.className = "statusBarTree";
608
- div.innerHTML = HTMLArea.I18N.msg["Path"] + ": ";
609
- this._statusBarTree = div;
610
- this._statusBar.appendChild(div);
611
- if (!this.config.statusBar) {
612
- // disable it...
613
- statusbar.style.display = "none";
614
- }
615
- };
616
-
617
- // Creates the HTMLArea object and replaces the textarea with it.
618
- HTMLArea.prototype.generate = function () {
619
- var editor = this; // we'll need "this" in some nested functions
620
- // get the textarea
621
- var textarea = this._textArea;
622
- if (typeof textarea == "string") {
623
- // it's not element but ID
624
- this._textArea = textarea = HTMLArea.getElementById("textarea", textarea);
625
- }
626
- this._ta_size = {
627
- w: textarea.offsetWidth,
628
- h: textarea.offsetHeight
629
- };
630
- textarea.style.display = "none";
631
-
632
- // create the editor framework
633
- var htmlarea = document.createElement("div");
634
- htmlarea.className = "htmlarea";
635
- this._htmlArea = htmlarea;
636
-
637
- // insert the editor before the textarea.
638
- textarea.parentNode.insertBefore(htmlarea, textarea);
639
-
640
- if (textarea.form) {
641
- // we have a form, on submit get the HTMLArea content and
642
- // update original textarea.
643
- var f = textarea.form;
644
- if (typeof f.onsubmit == "function") {
645
- var funcref = f.onsubmit;
646
- if (typeof f.__msh_prevOnSubmit == "undefined") {
647
- f.__msh_prevOnSubmit = [];
648
- }
649
- f.__msh_prevOnSubmit.push(funcref);
650
- }
651
- f.onsubmit = function() {
652
- editor._textArea.value = editor.getHTML();
653
- var a = this.__msh_prevOnSubmit;
654
- // call previous submit methods if they were there.
655
- if (typeof a != "undefined") {
656
- for (var i in a) {
657
- a[i]();
658
- }
659
- }
660
- };
661
- }
662
-
663
- // add a handler for the "back/forward" case -- on body.unload we save
664
- // the HTML content into the original textarea.
665
- window.onunload = function() {
666
- editor._textArea.value = editor.getHTML();
667
- };
668
-
669
- // creates & appends the toolbar
670
- this._createToolbar();
671
-
672
- // create the IFRAME
673
- var iframe = document.createElement("iframe");
674
- htmlarea.appendChild(iframe);
675
-
676
- this._iframe = iframe;
677
-
678
- // creates & appends the status bar, if the case
679
- this._createStatusBar();
680
-
681
- // remove the default border as it keeps us from computing correctly
682
- // the sizes. (somebody tell me why doesn't this work in IE)
683
-
684
- if (!HTMLArea.is_ie) {
685
- iframe.style.borderWidth = "1px";
686
- // iframe.frameBorder = "1";
687
- // iframe.marginHeight = "0";
688
- // iframe.marginWidth = "0";
689
- }
690
-
691
- // size the IFRAME according to user's prefs or initial textarea
692
- var height = (this.config.height == "auto" ? (this._ta_size.h + "px") : this.config.height);
693
- height = parseInt(height);
694
- var width = (this.config.width == "auto" ? (this._ta_size.w + "px") : this.config.width);
695
- width = parseInt(width);
696
-
697
- if (!HTMLArea.is_ie) {
698
- height -= 2;
699
- width -= 2;
700
- }
701
-
702
- iframe.style.width = width + "px";
703
- if (this.config.sizeIncludesToolbar) {
704
- // substract toolbar height
705
- height -= this._toolbar.offsetHeight;
706
- height -= this._statusBar.offsetHeight;
707
- }
708
- if (height < 0) {
709
- height = 0;
710
- }
711
- iframe.style.height = height + "px";
712
-
713
- // the editor including the toolbar now have the same size as the
714
- // original textarea.. which means that we need to reduce that a bit.
715
- textarea.style.width = iframe.style.width;
716
- textarea.style.height = iframe.style.height;
717
-
718
- // IMPORTANT: we have to allow Mozilla a short time to recognize the
719
- // new frame. Otherwise we get a stupid exception.
720
- function initIframe() {
721
- var doc = editor._iframe.contentWindow.document;
722
- if (!doc) {
723
- // Try again..
724
- // FIXME: don't know what else to do here. Normally
725
- // we'll never reach this point.
726
- if (HTMLArea.is_gecko) {
727
- setTimeout(initIframe, 100);
728
- return false;
729
- } else {
730
- alert("ERROR: IFRAME can't be initialized.");
731
- }
732
- }
733
- if (HTMLArea.is_gecko) {
734
- // enable editable mode for Mozilla
735
- doc.designMode = "on";
736
- }
737
- editor._doc = doc;
738
- if (!editor.config.fullPage) {
739
- doc.open();
740
- var html = "<html>\n";
741
- html += "<head>\n";
742
- if (editor.config.baseURL)
743
- html += '<base href="' + editor.config.baseURL + '" />';
744
- html += "<style> html,body { border: 0px; } " +
745
- editor.config.pageStyle + "</style>\n";
746
- html += "</head>\n";
747
- html += "<body>\n";
748
- html += editor._textArea.value;
749
- html += "</body>\n";
750
- html += "</html>";
751
- doc.write(html);
752
- doc.close();
753
- } else {
754
- var html = editor._textArea.value;
755
- if (html.match(HTMLArea.RE_doctype)) {
756
- editor.setDoctype(RegExp.$1);
757
- html = html.replace(HTMLArea.RE_doctype, "");
758
- }
759
- doc.open();
760
- doc.write(html);
761
- doc.close();
762
- }
763
-
764
- if (HTMLArea.is_ie) {
765
- // enable editable mode for IE. For some reason this
766
- // doesn't work if done in the same place as for Gecko
767
- // (above).
768
- doc.body.contentEditable = true;
769
- }
770
-
771
- editor.focusEditor();
772
- // intercept some events; for updating the toolbar & keyboard handlers
773
- HTMLArea._addEvents
774
- (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"],
775
- function (event) {
776
- return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event);
777
- });
778
-
779
- // check if any plugins have registered refresh handlers
780
- for (var i in editor.plugins) {
781
- var plugin = editor.plugins[i].instance;
782
- if (typeof plugin.onGenerate == "function")
783
- plugin.onGenerate();
784
- }
785
-
786
- setTimeout(function() {
787
- editor.updateToolbar();
788
- }, 250);
789
-
790
- if (typeof editor.onGenerate == "function")
791
- editor.onGenerate();
792
- };
793
- setTimeout(initIframe, 100);
794
- };
795
-
796
- // Switches editor mode; parameter can be "textmode" or "wysiwyg". If no
797
- // parameter was passed this function toggles between modes.
798
- HTMLArea.prototype.setMode = function(mode) {
799
- if (typeof mode == "undefined") {
800
- mode = ((this._editMode == "textmode") ? "wysiwyg" : "textmode");
801
- }
802
- switch (mode) {
803
- case "textmode":
804
- this._textArea.value = this.getHTML();
805
- this._iframe.style.display = "none";
806
- this._textArea.style.display = "block";
807
- if (this.config.statusBar) {
808
- this._statusBar.innerHTML = HTMLArea.I18N.msg["TEXT_MODE"];
809
- }
810
- break;
811
- case "wysiwyg":
812
- if (HTMLArea.is_gecko) {
813
- // disable design mode before changing innerHTML
814
- try {
815
- this._doc.designMode = "off";
816
- } catch(e) {};
817
- }
818
- if (!this.config.fullPage)
819
- this._doc.body.innerHTML = this.getHTML();
820
- else
821
- this.setFullHTML(this.getHTML());
822
- this._iframe.style.display = "block";
823
- this._textArea.style.display = "none";
824
- if (HTMLArea.is_gecko) {
825
- // we need to refresh that info for Moz-1.3a
826
- try {
827
- this._doc.designMode = "on";
828
- } catch(e) {};
829
- }
830
- if (this.config.statusBar) {
831
- this._statusBar.innerHTML = '';
832
- this._statusBar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
833
- this._statusBar.appendChild(this._statusBarTree);
834
- }
835
- break;
836
- default:
837
- alert("Mode <" + mode + "> not defined!");
838
- return false;
839
- }
840
- this._editMode = mode;
841
- this.focusEditor();
842
- };
843
-
844
- HTMLArea.prototype.setFullHTML = function(html) {
845
- var save_multiline = RegExp.multiline;
846
- RegExp.multiline = true;
847
- if (html.match(HTMLArea.RE_doctype)) {
848
- this.setDoctype(RegExp.$1);
849
- html = html.replace(HTMLArea.RE_doctype, "");
850
- }
851
- RegExp.multiline = save_multiline;
852
- if (!HTMLArea.is_ie) {
853
- if (html.match(HTMLArea.RE_head))
854
- this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
855
- if (html.match(HTMLArea.RE_body))
856
- this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
857
- } else {
858
- var html_re = /<html>((.|\n)*?)<\/html>/i;
859
- html = html.replace(html_re, "$1");
860
- this._doc.open();
861
- this._doc.write(html);
862
- this._doc.close();
863
- this._doc.body.contentEditable = true;
864
- return true;
865
- }
866
- };
867
-
868
- /***************************************************
869
- * Category: PLUGINS
870
- ***************************************************/
871
-
872
- // this is the variant of the function above where the plugin arguments are
873
- // already packed in an array. Externally, it should be only used in the
874
- // full-screen editor code, in order to initialize plugins with the same
875
- // parameters as in the opener window.
876
- HTMLArea.prototype.registerPlugin2 = function(plugin, args) {
877
- if (typeof plugin == "string")
878
- plugin = eval(plugin);
879
- var obj = new plugin(this, args);
880
- if (obj) {
881
- var clone = {};
882
- var info = plugin._pluginInfo;
883
- for (var i in info)
884
- clone[i] = info[i];
885
- clone.instance = obj;
886
- clone.args = args;
887
- this.plugins[plugin._pluginInfo.name] = clone;
888
- } else
889
- alert("Can't register plugin " + plugin.toString() + ".");
890
- };
891
-
892
- // Create the specified plugin and register it with this HTMLArea
893
- HTMLArea.prototype.registerPlugin = function() {
894
- var plugin = arguments[0];
895
- var args = [];
896
- for (var i = 1; i < arguments.length; ++i)
897
- args.push(arguments[i]);
898
- this.registerPlugin2(plugin, args);
899
- };
900
-
901
- // static function that loads the required plugin and lang file, based on the
902
- // language loaded already for HTMLArea. You better make sure that the plugin
903
- // _has_ that language, otherwise shit might happen ;-)
904
- HTMLArea.loadPlugin = function(pluginName) {
905
- var dir = _editor_url + "plugins/" + pluginName;
906
- var plugin = pluginName.replace(/([a-z])([A-Z])([a-z])/g,
907
- function (str, l1, l2, l3) {
908
- return l1 + "-" + l2.toLowerCase() + l3;
909
- }).toLowerCase() + ".js";
910
- var plugin_file = dir + "/" + plugin;
911
- var plugin_lang = dir + "/lang/" + HTMLArea.I18N.lang + ".js";
912
- HTMLArea._scripts.push(plugin_file, plugin_lang);
913
- document.write("<script type='text/javascript' src='" + plugin_file + "'></script>");
914
- document.write("<script type='text/javascript' src='" + plugin_lang + "'></script>");
915
- };
916
-
917
- HTMLArea.loadStyle = function(style, plugin) {
918
- var url = _editor_url || '';
919
- if (typeof plugin != "undefined") {
920
- url += "plugins/" + plugin + "/";
921
- }
922
- url += style;
923
- document.write("<style type='text/css'>@import url(" + url + ");</style>");
924
- };
925
- HTMLArea.loadStyle("htmlarea.css");
926
-
927
- /***************************************************
928
- * Category: EDITOR UTILITIES
929
- ***************************************************/
930
-
931
- // The following function is a slight variation of the word cleaner code posted
932
- // by Weeezl (user @ InteractiveTools forums).
933
- HTMLArea.prototype._wordClean = function() {
934
- var D = this.getInnerHTML();
935
- if (D.indexOf('class=Mso') >= 0) {
936
-
937
- // make one line
938
- D = D.replace(/\r\n/g, ' ').
939
- replace(/\n/g, ' ').
940
- replace(/\r/g, ' ').
941
- replace(/\&nbsp\;/g,' ');
942
-
943
- // keep tags, strip attributes
944
- D = D.replace(/ class=[^\s|>]*/gi,'').
945
- //replace(/<p [^>]*TEXT-ALIGN: justify[^>]*>/gi,'<p align="justify">').
946
- replace(/ style=\"[^>]*\"/gi,'').
947
- replace(/ align=[^\s|>]*/gi,'');
948
-
949
- //clean up tags
950
- D = D.replace(/<b [^>]*>/gi,'<b>').
951
- replace(/<i [^>]*>/gi,'<i>').
952
- replace(/<li [^>]*>/gi,'<li>').
953
- replace(/<ul [^>]*>/gi,'<ul>');
954
-
955
- // replace outdated tags
956
- D = D.replace(/<b>/gi,'<strong>').
957
- replace(/<\/b>/gi,'</strong>');
958
-
959
- // mozilla doesn't like <em> tags
960
- D = D.replace(/<em>/gi,'<i>').
961
- replace(/<\/em>/gi,'</i>');
962
-
963
- // kill unwanted tags
964
- D = D.replace(/<\?xml:[^>]*>/g, ''). // Word xml
965
- replace(/<\/?st1:[^>]*>/g,''). // Word SmartTags
966
- replace(/<\/?[a-z]\:[^>]*>/g,''). // All other funny Word non-HTML stuff
967
- replace(/<\/?font[^>]*>/gi,''). // Disable if you want to keep font formatting
968
- replace(/<\/?span[^>]*>/gi,' ').
969
- replace(/<\/?div[^>]*>/gi,' ').
970
- replace(/<\/?pre[^>]*>/gi,' ').
971
- replace(/<\/?h[1-6][^>]*>/gi,' ');
972
-
973
- //remove empty tags
974
- //D = D.replace(/<strong><\/strong>/gi,'').
975
- //replace(/<i><\/i>/gi,'').
976
- //replace(/<P[^>]*><\/P>/gi,'');
977
-
978
- // nuke double tags
979
- oldlen = D.length + 1;
980
- while(oldlen > D.length) {
981
- oldlen = D.length;
982
- // join us now and free the tags, we'll be free hackers, we'll be free... ;-)
983
- D = D.replace(/<([a-z][a-z]*)> *<\/\1>/gi,' ').
984
- replace(/<([a-z][a-z]*)> *<([a-z][^>]*)> *<\/\1>/gi,'<$2>');
985
- }
986
- D = D.replace(/<([a-z][a-z]*)><\1>/gi,'<$1>').
987
- replace(/<\/([a-z][a-z]*)><\/\1>/gi,'<\/$1>');
988
-
989
- // nuke double spaces
990
- D = D.replace(/ */gi,' ');
991
-
992
- this.setHTML(D);
993
- this.updateToolbar();
994
- }
995
- };
996
-
997
- HTMLArea.prototype.forceRedraw = function() {
998
- this._doc.body.style.visibility = "hidden";
999
- this._doc.body.style.visibility = "visible";
1000
- // this._doc.body.innerHTML = this.getInnerHTML();
1001
- };
1002
-
1003
- // focuses the iframe window. returns a reference to the editor document.
1004
- HTMLArea.prototype.focusEditor = function() {
1005
- switch (this._editMode) {
1006
- case "wysiwyg" : this._iframe.contentWindow.focus(); break;
1007
- case "textmode": this._textArea.focus(); break;
1008
- default : alert("ERROR: mode " + this._editMode + " is not defined");
1009
- }
1010
- return this._doc;
1011
- };
1012
-
1013
- // takes a snapshot of the current text (for undo)
1014
- HTMLArea.prototype._undoTakeSnapshot = function() {
1015
- ++this._undoPos;
1016
- if (this._undoPos >= this.config.undoSteps) {
1017
- // remove the first element
1018
- this._undoQueue.shift();
1019
- --this._undoPos;
1020
- }
1021
- // use the fasted method (getInnerHTML);
1022
- var take = true;
1023
- var txt = this.getInnerHTML();
1024
- if (this._undoPos > 0)
1025
- take = (this._undoQueue[this._undoPos - 1] != txt);
1026
- if (take) {
1027
- this._undoQueue[this._undoPos] = txt;
1028
- } else {
1029
- this._undoPos--;
1030
- }
1031
- };
1032
-
1033
- HTMLArea.prototype.undo = function() {
1034
- if (this._undoPos > 0) {
1035
- var txt = this._undoQueue[--this._undoPos];
1036
- if (txt) this.setHTML(txt);
1037
- else ++this._undoPos;
1038
- }
1039
- };
1040
-
1041
- HTMLArea.prototype.redo = function() {
1042
- if (this._undoPos < this._undoQueue.length - 1) {
1043
- var txt = this._undoQueue[++this._undoPos];
1044
- if (txt) this.setHTML(txt);
1045
- else --this._undoPos;
1046
- }
1047
- };
1048
-
1049
- // updates enabled/disable/active state of the toolbar elements
1050
- HTMLArea.prototype.updateToolbar = function(noStatus) {
1051
- var doc = this._doc;
1052
- var text = (this._editMode == "textmode");
1053
- var ancestors = null;
1054
- if (!text) {
1055
- ancestors = this.getAllAncestors();
1056
- if (this.config.statusBar && !noStatus) {
1057
- this._statusBarTree.innerHTML = HTMLArea.I18N.msg["Path"] + ": "; // clear
1058
- for (var i = ancestors.length; --i >= 0;) {
1059
- var el = ancestors[i];
1060
- if (!el) {
1061
- // hell knows why we get here; this
1062
- // could be a classic example of why
1063
- // it's good to check for conditions
1064
- // that are impossible to happen ;-)
1065
- continue;
1066
- }
1067
- var a = document.createElement("a");
1068
- a.href = "#";
1069
- a.el = el;
1070
- a.editor = this;
1071
- a.onclick = function() {
1072
- this.blur();
1073
- this.editor.selectNodeContents(this.el);
1074
- this.editor.updateToolbar(true);
1075
- return false;
1076
- };
1077
- a.oncontextmenu = function() {
1078
- // TODO: add context menu here
1079
- this.blur();
1080
- var info = "Inline style:\n\n";
1081
- info += this.el.style.cssText.split(/;\s*/).join(";\n");
1082
- alert(info);
1083
- return false;
1084
- };
1085
- var txt = el.tagName.toLowerCase();
1086
- a.title = el.style.cssText;
1087
- if (el.id) {
1088
- txt += "#" + el.id;
1089
- }
1090
- if (el.className) {
1091
- txt += "." + el.className;
1092
- }
1093
- a.appendChild(document.createTextNode(txt));
1094
- this._statusBarTree.appendChild(a);
1095
- if (i != 0) {
1096
- this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(0xbb)));
1097
- }
1098
- }
1099
- }
1100
- }
1101
- for (var i in this._toolbarObjects) {
1102
- var btn = this._toolbarObjects[i];
1103
- var cmd = i;
1104
- var inContext = true;
1105
- if (btn.context && !text) {
1106
- inContext = false;
1107
- var context = btn.context;
1108
- var attrs = [];
1109
- if (/(.*)\[(.*?)\]/.test(context)) {
1110
- context = RegExp.$1;
1111
- attrs = RegExp.$2.split(",");
1112
- }
1113
- context = context.toLowerCase();
1114
- var match = (context == "*");
1115
- for (var k in ancestors) {
1116
- if (!ancestors[k]) {
1117
- // the impossible really happens.
1118
- continue;
1119
- }
1120
- if (match || (ancestors[k].tagName.toLowerCase() == context)) {
1121
- inContext = true;
1122
- for (var ka in attrs) {
1123
- if (!eval("ancestors[k]." + attrs[ka])) {
1124
- inContext = false;
1125
- break;
1126
- }
1127
- }
1128
- if (inContext) {
1129
- break;
1130
- }
1131
- }
1132
- }
1133
- }
1134
- btn.state("enabled", (!text || btn.text) && inContext);
1135
- if (typeof cmd == "function") {
1136
- continue;
1137
- }
1138
- // look-it-up in the custom dropdown boxes
1139
- var dropdown = this.config.customSelects[cmd];
1140
- if ((!text || btn.text) && (typeof dropdown != "undefined")) {
1141
- dropdown.refresh(this);
1142
- continue;
1143
- }
1144
- switch (cmd) {
1145
- case "fontname":
1146
- case "fontsize":
1147
- case "formatblock":
1148
- if (!text) try {
1149
- var value = ("" + doc.queryCommandValue(cmd)).toLowerCase();
1150
- if (!value) {
1151
- // FIXME: what do we do here?
1152
- break;
1153
- }
1154
- // HACK -- retrieve the config option for this
1155
- // combo box. We rely on the fact that the
1156
- // variable in config has the same name as
1157
- // button name in the toolbar.
1158
- var options = this.config[cmd];
1159
- var k = 0;
1160
- // btn.element.selectedIndex = 0;
1161
- for (var j in options) {
1162
- // FIXME: the following line is scary.
1163
- if ((j.toLowerCase() == value) ||
1164
- (options[j].substr(0, value.length).toLowerCase() == value)) {
1165
- btn.element.selectedIndex = k;
1166
- break;
1167
- }
1168
- ++k;
1169
- }
1170
- } catch(e) {};
1171
- break;
1172
- case "textindicator":
1173
- if (!text) {
1174
- try {with (btn.element.style) {
1175
- backgroundColor = HTMLArea._makeColor(
1176
- doc.queryCommandValue(HTMLArea.is_ie ? "backcolor" : "hilitecolor"));
1177
- if (/transparent/i.test(backgroundColor)) {
1178
- // Mozilla
1179
- backgroundColor = HTMLArea._makeColor(doc.queryCommandValue("backcolor"));
1180
- }
1181
- color = HTMLArea._makeColor(doc.queryCommandValue("forecolor"));
1182
- fontFamily = doc.queryCommandValue("fontname");
1183
- fontWeight = doc.queryCommandState("bold") ? "bold" : "normal";
1184
- fontStyle = doc.queryCommandState("italic") ? "italic" : "normal";
1185
- }} catch (e) {
1186
- // alert(e + "\n\n" + cmd);
1187
- }
1188
- }
1189
- break;
1190
- case "htmlmode": btn.state("active", text); break;
1191
- case "lefttoright":
1192
- case "righttoleft":
1193
- var el = this.getParentElement();
1194
- while (el && !HTMLArea.isBlockElement(el))
1195
- el = el.parentNode;
1196
- if (el)
1197
- btn.state("active", (el.style.direction == ((cmd == "righttoleft") ? "rtl" : "ltr")));
1198
- break;
1199
- default:
1200
- try {
1201
- btn.state("active", (!text && doc.queryCommandState(cmd)));
1202
- } catch (e) {}
1203
- }
1204
- }
1205
- // take undo snapshots
1206
- if (this._customUndo && !this._timerUndo) {
1207
- this._undoTakeSnapshot();
1208
- var editor = this;
1209
- this._timerUndo = setTimeout(function() {
1210
- editor._timerUndo = null;
1211
- }, this.config.undoTimeout);
1212
- }
1213
- // check if any plugins have registered refresh handlers
1214
- for (var i in this.plugins) {
1215
- var plugin = this.plugins[i].instance;
1216
- if (typeof plugin.onUpdateToolbar == "function")
1217
- plugin.onUpdateToolbar();
1218
- }
1219
- };
1220
-
1221
- /** Returns a node after which we can insert other nodes, in the current
1222
- * selection. The selection is removed. It splits a text node, if needed.
1223
- */
1224
- HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
1225
- if (!HTMLArea.is_ie) {
1226
- var sel = this._getSelection();
1227
- var range = this._createRange(sel);
1228
- // remove the current selection
1229
- sel.removeAllRanges();
1230
- range.deleteContents();
1231
- var node = range.startContainer;
1232
- var pos = range.startOffset;
1233
- switch (node.nodeType) {
1234
- case 3: // Node.TEXT_NODE
1235
- // we have to split it at the caret position.
1236
- if (toBeInserted.nodeType == 3) {
1237
- // do optimized insertion
1238
- node.insertData(pos, toBeInserted.data);
1239
- range = this._createRange();
1240
- range.setEnd(node, pos + toBeInserted.length);
1241
- range.setStart(node, pos + toBeInserted.length);
1242
- sel.addRange(range);
1243
- } else {
1244
- node = node.splitText(pos);
1245
- var selnode = toBeInserted;
1246
- if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
1247
- selnode = selnode.firstChild;
1248
- }
1249
- node.parentNode.insertBefore(toBeInserted, node);
1250
- this.selectNodeContents(selnode);
1251
- this.updateToolbar();
1252
- }
1253
- break;
1254
- case 1: // Node.ELEMENT_NODE
1255
- var selnode = toBeInserted;
1256
- if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
1257
- selnode = selnode.firstChild;
1258
- }
1259
- node.insertBefore(toBeInserted, node.childNodes[pos]);
1260
- this.selectNodeContents(selnode);
1261
- this.updateToolbar();
1262
- break;
1263
- }
1264
- } else {
1265
- return null; // this function not yet used for IE <FIXME>
1266
- }
1267
- };
1268
-
1269
- // Returns the deepest node that contains both endpoints of the selection.
1270
- HTMLArea.prototype.getParentElement = function() {
1271
- var sel = this._getSelection();
1272
- var range = this._createRange(sel);
1273
- if (HTMLArea.is_ie) {
1274
- switch (sel.type) {
1275
- case "Text":
1276
- case "None":
1277
- // It seems that even for selection of type "None",
1278
- // there _is_ a parent element and it's value is not
1279
- // only correct, but very important to us. MSIE is
1280
- // certainly the buggiest browser in the world and I
1281
- // wonder, God, how can Earth stand it?
1282
- return range.parentElement();
1283
- case "Control":
1284
- return range.item(0);
1285
- default:
1286
- return this._doc.body;
1287
- }
1288
- } else try {
1289
- var p = range.commonAncestorContainer;
1290
- if (!range.collapsed && range.startContainer == range.endContainer &&
1291
- range.startOffset - range.endOffset <= 1 && range.startContainer.hasChildNodes())
1292
- p = range.startContainer.childNodes[range.startOffset];
1293
- /*
1294
- alert(range.startContainer + ":" + range.startOffset + "\n" +
1295
- range.endContainer + ":" + range.endOffset);
1296
- */
1297
- while (p.nodeType == 3) {
1298
- p = p.parentNode;
1299
- }
1300
- return p;
1301
- } catch (e) {
1302
- return null;
1303
- }
1304
- };
1305
-
1306
- // Returns an array with all the ancestor nodes of the selection.
1307
- HTMLArea.prototype.getAllAncestors = function() {
1308
- var p = this.getParentElement();
1309
- var a = [];
1310
- while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
1311
- a.push(p);
1312
- p = p.parentNode;
1313
- }
1314
- a.push(this._doc.body);
1315
- return a;
1316
- };
1317
-
1318
- // Selects the contents inside the given node
1319
- HTMLArea.prototype.selectNodeContents = function(node, pos) {
1320
- this.focusEditor();
1321
- this.forceRedraw();
1322
- var range;
1323
- var collapsed = (typeof pos != "undefined");
1324
- if (HTMLArea.is_ie) {
1325
- range = this._doc.body.createTextRange();
1326
- range.moveToElementText(node);
1327
- (collapsed) && range.collapse(pos);
1328
- range.select();
1329
- } else {
1330
- var sel = this._getSelection();
1331
- range = this._doc.createRange();
1332
- range.selectNodeContents(node);
1333
- (collapsed) && range.collapse(pos);
1334
- sel.removeAllRanges();
1335
- sel.addRange(range);
1336
- }
1337
- };
1338
-
1339
- /** Call this function to insert HTML code at the current position. It deletes
1340
- * the selection, if any.
1341
- */
1342
- HTMLArea.prototype.insertHTML = function(html) {
1343
- var sel = this._getSelection();
1344
- var range = this._createRange(sel);
1345
- if (HTMLArea.is_ie) {
1346
- range.pasteHTML(html);
1347
- } else {
1348
- // construct a new document fragment with the given HTML
1349
- var fragment = this._doc.createDocumentFragment();
1350
- var div = this._doc.createElement("div");
1351
- div.innerHTML = html;
1352
- while (div.firstChild) {
1353
- // the following call also removes the node from div
1354
- fragment.appendChild(div.firstChild);
1355
- }
1356
- // this also removes the selection
1357
- var node = this.insertNodeAtSelection(fragment);
1358
- }
1359
- };
1360
-
1361
- /**
1362
- * Call this function to surround the existing HTML code in the selection with
1363
- * your tags. FIXME: buggy! This function will be deprecated "soon".
1364
- */
1365
- HTMLArea.prototype.surroundHTML = function(startTag, endTag) {
1366
- var html = this.getSelectedHTML();
1367
- // the following also deletes the selection
1368
- this.insertHTML(startTag + html + endTag);
1369
- };
1370
-
1371
- /// Retrieve the selected block
1372
- HTMLArea.prototype.getSelectedHTML = function() {
1373
- var sel = this._getSelection();
1374
- var range = this._createRange(sel);
1375
- var existing = null;
1376
- if (HTMLArea.is_ie) {
1377
- existing = range.htmlText;
1378
- } else {
1379
- existing = HTMLArea.getHTML(range.cloneContents(), false, this);
1380
- }
1381
- return existing;
1382
- };
1383
-
1384
- /// Return true if we have some selection
1385
- HTMLArea.prototype.hasSelectedText = function() {
1386
- // FIXME: come _on_ mishoo, you can do better than this ;-)
1387
- return this.getSelectedHTML() != '';
1388
- };
1389
-
1390
- HTMLArea.prototype._createLink = function(link) {
1391
- var editor = this;
1392
- var outparam = null;
1393
- if (typeof link == "undefined") {
1394
- link = this.getParentElement();
1395
- if (link && !/^a$/i.test(link.tagName))
1396
- link = null;
1397
- }
1398
- if (link) outparam = {
1399
- f_href : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"),
1400
- f_title : link.title,
1401
- f_target : link.target
1402
- };
1403
- this._popupDialog("link.html", function(param) {
1404
- if (!param)
1405
- return false;
1406
- var a = link;
1407
- if (!a) {
1408
- editor._doc.execCommand("createlink", false, param.f_href);
1409
- a = editor.getParentElement();
1410
- var sel = editor._getSelection();
1411
- var range = editor._createRange(sel);
1412
- if (!HTMLArea.is_ie) {
1413
- a = range.startContainer;
1414
- if (!/^a$/i.test(a.tagName))
1415
- a = a.nextSibling;
1416
- }
1417
- } else a.href = param.f_href.trim();
1418
- if (!/^a$/i.test(a.tagName))
1419
- return false;
1420
- a.target = param.f_target.trim();
1421
- a.title = param.f_title.trim();
1422
- editor.selectNodeContents(a);
1423
- editor.updateToolbar();
1424
- }, outparam);
1425
- };
1426
-
1427
- // Called when the user clicks on "InsertImage" button. If an image is already
1428
- // there, it will just modify it's properties.
1429
- HTMLArea.prototype._insertImage = function(image) {
1430
- var editor = this; // for nested functions
1431
- var outparam = null;
1432
- if (typeof image == "undefined") {
1433
- image = this.getParentElement();
1434
- if (image && !/^img$/i.test(image.tagName))
1435
- image = null;
1436
- }
1437
- if (image) outparam = {
1438
- f_url : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image.getAttribute("src"),
1439
- f_alt : image.alt,
1440
- f_border : image.border,
1441
- f_align : image.align,
1442
- f_vert : image.vspace,
1443
- f_horiz : image.hspace
1444
- };
1445
- this._popupDialog("insert_image.html", function(param) {
1446
- if (!param) { // user must have pressed Cancel
1447
- return false;
1448
- }
1449
- var img = image;
1450
- if (!img) {
1451
- var sel = editor._getSelection();
1452
- var range = editor._createRange(sel);
1453
- editor._doc.execCommand("insertimage", false, param.f_url);
1454
- if (HTMLArea.is_ie) {
1455
- img = range.parentElement();
1456
- // wonder if this works...
1457
- if (img.tagName.toLowerCase() != "img") {
1458
- img = img.previousSibling;
1459
- }
1460
- } else {
1461
- img = range.startContainer.previousSibling;
1462
- }
1463
- } else {
1464
- img.src = param.f_url;
1465
- }
1466
- for (field in param) {
1467
- var value = param[field];
1468
- switch (field) {
1469
- case "f_alt" : img.alt = value; break;
1470
- case "f_border" : img.border = parseInt(value || "0"); break;
1471
- case "f_align" : img.align = value; break;
1472
- case "f_vert" : img.vspace = parseInt(value || "0"); break;
1473
- case "f_horiz" : img.hspace = parseInt(value || "0"); break;
1474
- }
1475
- }
1476
- }, outparam);
1477
- };
1478
-
1479
- // Called when the user clicks the Insert Table button
1480
- HTMLArea.prototype._insertTable = function() {
1481
- var sel = this._getSelection();
1482
- var range = this._createRange(sel);
1483
- var editor = this; // for nested functions
1484
- this._popupDialog("insert_table.html", function(param) {
1485
- if (!param) { // user must have pressed Cancel
1486
- return false;
1487
- }
1488
- var doc = editor._doc;
1489
- // create the table element
1490
- var table = doc.createElement("table");
1491
- // assign the given arguments
1492
- for (var field in param) {
1493
- var value = param[field];
1494
- if (!value) {
1495
- continue;
1496
- }
1497
- switch (field) {
1498
- case "f_width" : table.style.width = value + param["f_unit"]; break;
1499
- case "f_align" : table.align = value; break;
1500
- case "f_border" : table.border = parseInt(value); break;
1501
- case "f_spacing" : table.cellspacing = parseInt(value); break;
1502
- case "f_padding" : table.cellpadding = parseInt(value); break;
1503
- }
1504
- }
1505
- var tbody = doc.createElement("tbody");
1506
- table.appendChild(tbody);
1507
- for (var i = 0; i < param["f_rows"]; ++i) {
1508
- var tr = doc.createElement("tr");
1509
- tbody.appendChild(tr);
1510
- for (var j = 0; j < param["f_cols"]; ++j) {
1511
- var td = doc.createElement("td");
1512
- tr.appendChild(td);
1513
- // Mozilla likes to see something inside the cell.
1514
- (HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
1515
- }
1516
- }
1517
- if (HTMLArea.is_ie) {
1518
- range.pasteHTML(table.outerHTML);
1519
- } else {
1520
- // insert the table
1521
- editor.insertNodeAtSelection(table);
1522
- }
1523
- return true;
1524
- }, null);
1525
- };
1526
-
1527
- /***************************************************
1528
- * Category: EVENT HANDLERS
1529
- ***************************************************/
1530
-
1531
- // el is reference to the SELECT object
1532
- // txt is the name of the select field, as in config.toolbar
1533
- HTMLArea.prototype._comboSelected = function(el, txt) {
1534
- this.focusEditor();
1535
- var value = el.options[el.selectedIndex].value;
1536
- switch (txt) {
1537
- case "fontname":
1538
- case "fontsize": this.execCommand(txt, false, value); break;
1539
- case "formatblock":
1540
- (HTMLArea.is_ie) && (value = "<" + value + ">");
1541
- this.execCommand(txt, false, value);
1542
- break;
1543
- default:
1544
- // try to look it up in the registered dropdowns
1545
- var dropdown = this.config.customSelects[txt];
1546
- if (typeof dropdown != "undefined") {
1547
- dropdown.action(this);
1548
- } else {
1549
- alert("FIXME: combo box " + txt + " not implemented");
1550
- }
1551
- }
1552
- };
1553
-
1554
- // the execCommand function (intercepts some commands and replaces them with
1555
- // our own implementation)
1556
- HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
1557
- var editor = this; // for nested functions
1558
- this.focusEditor();
1559
- cmdID = cmdID.toLowerCase();
1560
- switch (cmdID) {
1561
- case "htmlmode" : this.setMode(); break;
1562
- case "hilitecolor":
1563
- (HTMLArea.is_ie) && (cmdID = "backcolor");
1564
- case "forecolor":
1565
- this._popupDialog("select_color.html", function(color) {
1566
- if (color) { // selection not canceled
1567
- editor._doc.execCommand(cmdID, false, "#" + color);
1568
- }
1569
- }, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)));
1570
- break;
1571
- case "createlink":
1572
- this._createLink();
1573
- break;
1574
- case "popupeditor":
1575
- // this object will be passed to the newly opened window
1576
- HTMLArea._object = this;
1577
- if (HTMLArea.is_ie) {
1578
- //if (confirm(HTMLArea.I18N.msg["IE-sucks-full-screen"]))
1579
- {
1580
- window.open(this.popupURL("fullscreen.html"), "ha_fullscreen",
1581
- "toolbar=no,location=no,directories=no,status=no,menubar=no," +
1582
- "scrollbars=no,resizable=yes,width=640,height=480");
1583
- }
1584
- } else {
1585
- window.open(this.popupURL("fullscreen.html"), "ha_fullscreen",
1586
- "toolbar=no,menubar=no,personalbar=no,width=640,height=480," +
1587
- "scrollbars=no,resizable=yes");
1588
- }
1589
- break;
1590
- case "undo":
1591
- case "redo":
1592
- if (this._customUndo)
1593
- this[cmdID]();
1594
- else
1595
- this._doc.execCommand(cmdID, UI, param);
1596
- break;
1597
- case "inserttable": this._insertTable(); break;
1598
- case "insertimage": this._insertImage(); break;
1599
- case "about" : this._popupDialog("about.html", null, this); break;
1600
- case "showhelp" : window.open(_editor_url + "reference.html", "ha_help"); break;
1601
-
1602
- case "killword": this._wordClean(); break;
1603
-
1604
- case "cut":
1605
- case "copy":
1606
- case "paste":
1607
- try {
1608
- if (this.config.killWordOnPaste)
1609
- this._wordClean();
1610
- this._doc.execCommand(cmdID, UI, param);
1611
- } catch (e) {
1612
- if (HTMLArea.is_gecko) {
1613
- if (confirm("Unprivileged scripts cannot access Cut/Copy/Paste programatically " +
1614
- "for security reasons. Click OK to see a technical note at mozilla.org " +
1615
- "which shows you how to allow a script to access the clipboard."))
1616
- window.open("http://mozilla.org/editor/midasdemo/securityprefs.html");
1617
- }
1618
- }
1619
- break;
1620
- case "lefttoright":
1621
- case "righttoleft":
1622
- var dir = (cmdID == "righttoleft") ? "rtl" : "ltr";
1623
- var el = this.getParentElement();
1624
- while (el && !HTMLArea.isBlockElement(el))
1625
- el = el.parentNode;
1626
- if (el) {
1627
- if (el.style.direction == dir)
1628
- el.style.direction = "";
1629
- else
1630
- el.style.direction = dir;
1631
- }
1632
- break;
1633
- default: this._doc.execCommand(cmdID, UI, param);
1634
- }
1635
- this.updateToolbar();
1636
- return false;
1637
- };
1638
-
1639
- /** A generic event handler for things that happen in the IFRAME's document.
1640
- * This function also handles key bindings. */
1641
- HTMLArea.prototype._editorEvent = function(ev) {
1642
- var editor = this;
1643
- var keyEvent = (HTMLArea.is_ie && ev.type == "keydown") || (ev.type == "keypress");
1644
- if (keyEvent) {
1645
- for (var i in editor.plugins) {
1646
- var plugin = editor.plugins[i].instance;
1647
- if (typeof plugin.onKeyPress == "function") plugin.onKeyPress(ev);
1648
- }
1649
- }
1650
- if (keyEvent && ev.ctrlKey) {
1651
- var sel = null;
1652
- var range = null;
1653
- var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
1654
- var cmd = null;
1655
- var value = null;
1656
- switch (key) {
1657
- case 'a':
1658
- if (!HTMLArea.is_ie) {
1659
- // KEY select all
1660
- sel = this._getSelection();
1661
- sel.removeAllRanges();
1662
- range = this._createRange();
1663
- range.selectNodeContents(this._doc.body);
1664
- sel.addRange(range);
1665
- HTMLArea._stopEvent(ev);
1666
- }
1667
- break;
1668
-
1669
- // simple key commands follow
1670
-
1671
- case 'b': cmd = "bold"; break;
1672
- case 'i': cmd = "italic"; break;
1673
- case 'u': cmd = "underline"; break;
1674
- case 's': cmd = "strikethrough"; break;
1675
- case 'l': cmd = "justifyleft"; break;
1676
- case 'e': cmd = "justifycenter"; break;
1677
- case 'r': cmd = "justifyright"; break;
1678
- case 'j': cmd = "justifyfull"; break;
1679
- case 'z': cmd = "undo"; break;
1680
- case 'y': cmd = "redo"; break;
1681
- case 'v': cmd = "paste"; break;
1682
-
1683
- case '0': cmd = "killword"; break;
1684
-
1685
- // headings
1686
- case '1':
1687
- case '2':
1688
- case '3':
1689
- case '4':
1690
- case '5':
1691
- case '6':
1692
- cmd = "formatblock";
1693
- value = "h" + key;
1694
- if (HTMLArea.is_ie) {
1695
- value = "<" + value + ">";
1696
- }
1697
- break;
1698
- }
1699
- if (cmd) {
1700
- // execute simple command
1701
- this.execCommand(cmd, false, value);
1702
- HTMLArea._stopEvent(ev);
1703
- }
1704
- }
1705
- /*
1706
- else if (keyEvent) {
1707
- // other keys here
1708
- switch (ev.keyCode) {
1709
- case 13: // KEY enter
1710
- // if (HTMLArea.is_ie) {
1711
- this.insertHTML("<br />");
1712
- HTMLArea._stopEvent(ev);
1713
- // }
1714
- break;
1715
- }
1716
- }
1717
- */
1718
- // update the toolbar state after some time
1719
- if (editor._timerToolbar) {
1720
- clearTimeout(editor._timerToolbar);
1721
- }
1722
- editor._timerToolbar = setTimeout(function() {
1723
- editor.updateToolbar();
1724
- editor._timerToolbar = null;
1725
- }, 50);
1726
- };
1727
-
1728
- // retrieve the HTML
1729
- HTMLArea.prototype.getHTML = function() {
1730
- switch (this._editMode) {
1731
- case "wysiwyg" :
1732
- if (!this.config.fullPage) {
1733
- return HTMLArea.getHTML(this._doc.body, false, this);
1734
- } else
1735
- return this.doctype + "\n" + HTMLArea.getHTML(this._doc.documentElement, true, this);
1736
- case "textmode" : return this._textArea.value;
1737
- default : alert("Mode <" + mode + "> not defined!");
1738
- }
1739
- return false;
1740
- };
1741
-
1742
- // retrieve the HTML (fastest version, but uses innerHTML)
1743
- HTMLArea.prototype.getInnerHTML = function() {
1744
- switch (this._editMode) {
1745
- case "wysiwyg" :
1746
- if (!this.config.fullPage)
1747
- return this._doc.body.innerHTML;
1748
- else
1749
- return this.doctype + "\n" + this._doc.documentElement.innerHTML;
1750
- case "textmode" : return this._textArea.value;
1751
- default : alert("Mode <" + mode + "> not defined!");
1752
- }
1753
- return false;
1754
- };
1755
-
1756
- // completely change the HTML inside
1757
- HTMLArea.prototype.setHTML = function(html) {
1758
- switch (this._editMode) {
1759
- case "wysiwyg" :
1760
- if (!this.config.fullPage)
1761
- this._doc.body.innerHTML = html;
1762
- else
1763
- // this._doc.documentElement.innerHTML = html;
1764
- this._doc.body.innerHTML = html;
1765
- break;
1766
- case "textmode" : this._textArea.value = html; break;
1767
- default : alert("Mode <" + mode + "> not defined!");
1768
- }
1769
- return false;
1770
- };
1771
-
1772
- // sets the given doctype (useful when config.fullPage is true)
1773
- HTMLArea.prototype.setDoctype = function(doctype) {
1774
- this.doctype = doctype;
1775
- };
1776
-
1777
- /***************************************************
1778
- * Category: UTILITY FUNCTIONS
1779
- ***************************************************/
1780
-
1781
- // browser identification
1782
-
1783
- HTMLArea.agt = navigator.userAgent.toLowerCase();
1784
- HTMLArea.is_ie = ((HTMLArea.agt.indexOf("msie") != -1) && (HTMLArea.agt.indexOf("opera") == -1));
1785
- HTMLArea.is_opera = (HTMLArea.agt.indexOf("opera") != -1);
1786
- HTMLArea.is_mac = (HTMLArea.agt.indexOf("mac") != -1);
1787
- HTMLArea.is_mac_ie = (HTMLArea.is_ie && HTMLArea.is_mac);
1788
- HTMLArea.is_win_ie = (HTMLArea.is_ie && !HTMLArea.is_mac);
1789
- HTMLArea.is_gecko = (navigator.product == "Gecko");
1790
-
1791
- // variable used to pass the object to the popup editor window.
1792
- HTMLArea._object = null;
1793
-
1794
- // function that returns a clone of the given object
1795
- HTMLArea.cloneObject = function(obj) {
1796
- var newObj = new Object;
1797
-
1798
- // check for array objects
1799
- if (obj.constructor.toString().indexOf("function Array(") == 1) {
1800
- newObj = obj.constructor();
1801
- }
1802
-
1803
- // check for function objects (as usual, IE is fucked up)
1804
- if (obj.constructor.toString().indexOf("function Function(") == 1) {
1805
- newObj = obj; // just copy reference to it
1806
- } else for (var n in obj) {
1807
- var node = obj[n];
1808
- if (typeof node == 'object') { newObj[n] = HTMLArea.cloneObject(node); }
1809
- else { newObj[n] = node; }
1810
- }
1811
-
1812
- return newObj;
1813
- };
1814
-
1815
- // FIXME!!! this should return false for IE < 5.5
1816
- HTMLArea.checkSupportedBrowser = function() {
1817
- if (HTMLArea.is_gecko) {
1818
- if (navigator.productSub < 20021201) {
1819
- alert("You need at least Mozilla-1.3 Alpha.\n" +
1820
- "Sorry, your Gecko is not supported.");
1821
- return false;
1822
- }
1823
- if (navigator.productSub < 20030210) {
1824
- alert("Mozilla < 1.3 Beta is not supported!\n" +
1825
- "I'll try, though, but it might not work.");
1826
- }
1827
- }
1828
- return HTMLArea.is_gecko || HTMLArea.is_ie;
1829
- };
1830
-
1831
- // selection & ranges
1832
-
1833
- // returns the current selection object
1834
- HTMLArea.prototype._getSelection = function() {
1835
- if (HTMLArea.is_ie) {
1836
- return this._doc.selection;
1837
- } else {
1838
- return this._iframe.contentWindow.getSelection();
1839
- }
1840
- };
1841
-
1842
- // returns a range for the current selection
1843
- HTMLArea.prototype._createRange = function(sel) {
1844
- if (HTMLArea.is_ie) {
1845
- return sel.createRange();
1846
- } else {
1847
- this.focusEditor();
1848
- if (typeof sel != "undefined") {
1849
- try {
1850
- return sel.getRangeAt(0);
1851
- } catch(e) {
1852
- return this._doc.createRange();
1853
- }
1854
- } else {
1855
- return this._doc.createRange();
1856
- }
1857
- }
1858
- };
1859
-
1860
- // event handling
1861
-
1862
- HTMLArea._addEvent = function(el, evname, func) {
1863
- if (HTMLArea.is_ie) {
1864
- el.attachEvent("on" + evname, func);
1865
- } else {
1866
- el.addEventListener(evname, func, true);
1867
- }
1868
- };
1869
-
1870
- HTMLArea._addEvents = function(el, evs, func) {
1871
- for (var i in evs) {
1872
- HTMLArea._addEvent(el, evs[i], func);
1873
- }
1874
- };
1875
-
1876
- HTMLArea._removeEvent = function(el, evname, func) {
1877
- if (HTMLArea.is_ie) {
1878
- el.detachEvent("on" + evname, func);
1879
- } else {
1880
- el.removeEventListener(evname, func, true);
1881
- }
1882
- };
1883
-
1884
- HTMLArea._removeEvents = function(el, evs, func) {
1885
- for (var i in evs) {
1886
- HTMLArea._removeEvent(el, evs[i], func);
1887
- }
1888
- };
1889
-
1890
- HTMLArea._stopEvent = function(ev) {
1891
- if (HTMLArea.is_ie) {
1892
- ev.cancelBubble = true;
1893
- ev.returnValue = false;
1894
- } else {
1895
- ev.preventDefault();
1896
- ev.stopPropagation();
1897
- }
1898
- };
1899
-
1900
- HTMLArea._removeClass = function(el, className) {
1901
- if (!(el && el.className)) {
1902
- return;
1903
- }
1904
- var cls = el.className.split(" ");
1905
- var ar = new Array();
1906
- for (var i = cls.length; i > 0;) {
1907
- if (cls[--i] != className) {
1908
- ar[ar.length] = cls[i];
1909
- }
1910
- }
1911
- el.className = ar.join(" ");
1912
- };
1913
-
1914
- HTMLArea._addClass = function(el, className) {
1915
- // remove the class first, if already there
1916
- HTMLArea._removeClass(el, className);
1917
- el.className += " " + className;
1918
- };
1919
-
1920
- HTMLArea._hasClass = function(el, className) {
1921
- if (!(el && el.className)) {
1922
- return false;
1923
- }
1924
- var cls = el.className.split(" ");
1925
- for (var i = cls.length; i > 0;) {
1926
- if (cls[--i] == className) {
1927
- return true;
1928
- }
1929
- }
1930
- return false;
1931
- };
1932
-
1933
- HTMLArea.isBlockElement = function(el) {
1934
- var blockTags = " body form textarea fieldset ul ol dl li div " +
1935
- "p h1 h2 h3 h4 h5 h6 quote pre table thead " +
1936
- "tbody tfoot tr td iframe address ";
1937
- return (blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
1938
- };
1939
-
1940
- HTMLArea.needsClosingTag = function(el) {
1941
- var closingTags = " head script style div span tr td tbody table em strong font a title ";
1942
- return (closingTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
1943
- };
1944
-
1945
- // performs HTML encoding of some given string
1946
- HTMLArea.htmlEncode = function(str) {
1947
- // we don't need regexp for that, but.. so be it for now.
1948
- str = str.replace(/&/ig, "&amp;");
1949
- str = str.replace(/</ig, "&lt;");
1950
- str = str.replace(/>/ig, "&gt;");
1951
- str = str.replace(/\x22/ig, "&quot;");
1952
- // \x22 means '"' -- we use hex reprezentation so that we don't disturb
1953
- // JS compressors (well, at least mine fails.. ;)
1954
- return str;
1955
- };
1956
-
1957
- // Retrieves the HTML code from the given node. This is a replacement for
1958
- // getting innerHTML, using standard DOM calls.
1959
- HTMLArea.getHTML = function(root, outputRoot, editor) {
1960
- var html = "";
1961
- switch (root.nodeType) {
1962
- case 1: // Node.ELEMENT_NODE
1963
- case 11: // Node.DOCUMENT_FRAGMENT_NODE
1964
- var closed;
1965
- var i;
1966
- var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
1967
- if (HTMLArea.is_ie && root_tag == "head") {
1968
- if (outputRoot)
1969
- html += "<head>";
1970
- // lowercasize
1971
- var save_multiline = RegExp.multiline;
1972
- RegExp.multiline = true;
1973
- var txt = root.innerHTML.replace(HTMLArea.RE_tagName, function(str, p1, p2) {
1974
- return p1 + p2.toLowerCase();
1975
- });
1976
- RegExp.multiline = save_multiline;
1977
- html += txt;
1978
- if (outputRoot)
1979
- html += "</head>";
1980
- break;
1981
- } else if (outputRoot) {
1982
- closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root)));
1983
- html = "<" + root.tagName.toLowerCase();
1984
- var attrs = root.attributes;
1985
- for (i = 0; i < attrs.length; ++i) {
1986
- var a = attrs.item(i);
1987
- if (!a.specified) {
1988
- continue;
1989
- }
1990
- var name = a.nodeName.toLowerCase();
1991
- if (/_moz|contenteditable|_msh/.test(name)) {
1992
- // avoid certain attributes
1993
- continue;
1994
- }
1995
- var value;
1996
- if (name != "style") {
1997
- // IE5.5 reports 25 when cellSpacing is
1998
- // 1; other values might be doomed too.
1999
- // For this reason we extract the
2000
- // values directly from the root node.
2001
- // I'm starting to HATE JavaScript
2002
- // development. Browser differences
2003
- // suck.
2004
- //
2005
- // Using Gecko the values of href and src are converted to absolute links
2006
- // unless we get them using nodeValue()
2007
- if (typeof root[a.nodeName] != "undefined" && name != "href" && name != "src") {
2008
- value = root[a.nodeName];
2009
- } else {
2010
- value = a.nodeValue;
2011
- // IE seems not willing to return the original values - it converts to absolute
2012
- // links using a.nodeValue, a.value, a.stringValue, root.getAttribute("href")
2013
- // So we have to strip the baseurl manually -/
2014
- if (HTMLArea.is_ie && (name == "href" || name == "src")) {
2015
- value = editor.stripBaseURL(value);
2016
- }
2017
- }
2018
- } else { // IE fails to put style in attributes list
2019
- // FIXME: cssText reported by IE is UPPERCASE
2020
- value = root.style.cssText;
2021
- }
2022
- if (/(_moz|^$)/.test(value)) {
2023
- // Mozilla reports some special tags
2024
- // here; we don't need them.
2025
- continue;
2026
- }
2027
- html += " " + name + '="' + value + '"';
2028
- }
2029
- html += closed ? " />" : ">";
2030
- }
2031
- for (i = root.firstChild; i; i = i.nextSibling) {
2032
- html += HTMLArea.getHTML(i, true, editor);
2033
- }
2034
- if (outputRoot && !closed) {
2035
- html += "</" + root.tagName.toLowerCase() + ">";
2036
- }
2037
- break;
2038
- case 3: // Node.TEXT_NODE
2039
- // If a text node is alone in an element and all spaces, replace it with an non breaking one
2040
- // This partially undoes the damage done by moz, which translates '&nbsp;'s into spaces in the data element
2041
- if ( !root.previousSibling && !root.nextSibling && root.data.match(/^\s*$/i) ) html = '&nbsp;';
2042
- else html = HTMLArea.htmlEncode(root.data);
2043
- break;
2044
- case 8: // Node.COMMENT_NODE
2045
- html = "<!--" + root.data + "-->";
2046
- break; // skip comments, for now.
2047
- }
2048
- return html;
2049
- };
2050
-
2051
- HTMLArea.prototype.stripBaseURL = function(string) {
2052
- var baseurl = this.config.baseURL;
2053
-
2054
- // strip to last directory in case baseurl points to a file
2055
- baseurl = baseurl.replace(/[^\/]+$/, '');
2056
- var basere = new RegExp(baseurl);
2057
- string = string.replace(basere, "");
2058
-
2059
- // strip host-part of URL which is added by MSIE to links relative to server root
2060
- baseurl = baseurl.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1');
2061
- basere = new RegExp(baseurl);
2062
- return string.replace(basere, "");
2063
- };
2064
-
2065
- String.prototype.trim = function() {
2066
- a = this.replace(/^\s+/, '');
2067
- return a.replace(/\s+$/, '');
2068
- };
2069
-
2070
- // creates a rgb-style color from a number
2071
- HTMLArea._makeColor = function(v) {
2072
- if (typeof v != "number") {
2073
- // already in rgb (hopefully); IE doesn't get here.
2074
- return v;
2075
- }
2076
- // IE sends number; convert to rgb.
2077
- var r = v & 0xFF;
2078
- var g = (v >> 8) & 0xFF;
2079
- var b = (v >> 16) & 0xFF;
2080
- return "rgb(" + r + "," + g + "," + b + ")";
2081
- };
2082
-
2083
- // returns hexadecimal color representation from a number or a rgb-style color.
2084
- HTMLArea._colorToRgb = function(v) {
2085
- if (!v)
2086
- return '';
2087
-
2088
- // returns the hex representation of one byte (2 digits)
2089
- function hex(d) {
2090
- return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
2091
- };
2092
-
2093
- if (typeof v == "number") {
2094
- // we're talking to IE here
2095
- var r = v & 0xFF;
2096
- var g = (v >> 8) & 0xFF;
2097
- var b = (v >> 16) & 0xFF;
2098
- return "#" + hex(r) + hex(g) + hex(b);
2099
- }
2100
-
2101
- if (v.substr(0, 3) == "rgb") {
2102
- // in rgb(...) form -- Mozilla
2103
- var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
2104
- if (v.match(re)) {
2105
- var r = parseInt(RegExp.$1);
2106
- var g = parseInt(RegExp.$2);
2107
- var b = parseInt(RegExp.$3);
2108
- return "#" + hex(r) + hex(g) + hex(b);
2109
- }
2110
- // doesn't match RE?! maybe uses percentages or float numbers
2111
- // -- FIXME: not yet implemented.
2112
- return null;
2113
- }
2114
-
2115
- if (v.substr(0, 1) == "#") {
2116
- // already hex rgb (hopefully :D )
2117
- return v;
2118
- }
2119
-
2120
- // if everything else fails ;)
2121
- return null;
2122
- };
2123
-
2124
- // modal dialogs for Mozilla (for IE we're using the showModalDialog() call).
2125
-
2126
- // receives an URL to the popup dialog and a function that receives one value;
2127
- // this function will get called after the dialog is closed, with the return
2128
- // value of the dialog.
2129
- HTMLArea.prototype._popupDialog = function(url, action, init) {
2130
- Dialog(this.popupURL(url), action, init);
2131
- };
2132
-
2133
- // paths
2134
-
2135
- HTMLArea.prototype.imgURL = function(file, plugin) {
2136
- if (typeof plugin == "undefined")
2137
- return _editor_url + file;
2138
- else
2139
- return _editor_url + "plugins/" + plugin + "/img/" + file;
2140
- };
2141
-
2142
- HTMLArea.prototype.popupURL = function(file) {
2143
- var url = "";
2144
- if (file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
2145
- var plugin = RegExp.$1;
2146
- var popup = RegExp.$2;
2147
- if (!/\.html$/.test(popup))
2148
- popup += ".html";
2149
- url = _editor_url + "plugins/" + plugin + "/popups/" + popup;
2150
- } else
2151
- url = _editor_url + this.config.popupURL + file;
2152
- return url;
2153
- };
2154
-
2155
- /**
2156
- * FIX: Internet Explorer returns an item having the _name_ equal to the given
2157
- * id, even if it's not having any id. This way it can return a different form
2158
- * field even if it's not a textarea. This workarounds the problem by
2159
- * specifically looking to search only elements having a certain tag name.
2160
- */
2161
- HTMLArea.getElementById = function(tag, id) {
2162
- var el, i, objs = document.getElementsByTagName(tag);
2163
- for (i = objs.length; --i >= 0 && (el = objs[i]);)
2164
- if (el.id == id)
2165
- return el;
2166
- return null;
2167
- };
2168
-
2169
-
2170
-
2171
- // EOF
2172
- // Local variables: //
2173
- // c-basic-offset:8 //
2174
- // indent-tabs-mode:t //
2175
- // End: //