zena 1.2.7 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (407) hide show
  1. data/History.txt +80 -25
  2. data/Rakefile +2 -2
  3. data/app/controllers/columns_controller.rb +2 -2
  4. data/app/controllers/nodes_controller.rb +22 -29
  5. data/app/controllers/user_sessions_controller.rb +35 -10
  6. data/app/controllers/users_controller.rb +2 -2
  7. data/app/controllers/versions_controller.rb +2 -2
  8. data/app/models/group.rb +15 -1
  9. data/app/models/node.rb +109 -8
  10. data/app/models/role.rb +4 -0
  11. data/app/models/site.rb +64 -58
  12. data/app/models/template.rb +1 -1
  13. data/app/models/user.rb +135 -29
  14. data/app/models/user_session.rb +0 -1
  15. data/app/models/virtual_class.rb +11 -6
  16. data/app/views/columns/_form.html.erb +3 -1
  17. data/app/views/columns/_li.html.erb +1 -1
  18. data/app/views/columns/create.rjs +1 -1
  19. data/app/views/groups/_form.rhtml +16 -13
  20. data/app/views/relations/_form.erb +18 -6
  21. data/app/views/sites/_form.erb +12 -6
  22. data/app/views/users/_form.rhtml +23 -8
  23. data/app/views/users/_li.rhtml +14 -3
  24. data/app/views/users/index.rhtml +1 -1
  25. data/app/views/virtual_classes/_form.erb +12 -2
  26. data/app/views/zafu/default/Node-+login.zafu +8 -1
  27. data/app/views/zafu/default/Node-+search.zafu +1 -1
  28. data/bricks/acls/lib/bricks/acls.rb +1 -0
  29. data/bricks/acls/zena/migrate/20130903150356_longer_names_for_acl.rb +9 -0
  30. data/bricks/acls/zena/test/integration/acl_integration_test.rb +2 -2
  31. data/bricks/currency/lib/bricks/currency.rb +120 -0
  32. data/bricks/currency/zena/test/unit/currency_test.rb +43 -0
  33. data/bricks/fs_skin/lib/bricks/fs_skin.rb +1 -1
  34. data/bricks/fs_skin/zena/skins/blog/Node-+search.zafu +1 -1
  35. data/bricks/fs_skin/zena/skins/blog/Node.zafu +1 -1
  36. data/bricks/fs_skin/zena/test/unit/fs_skin_view_test.rb +35 -0
  37. data/bricks/pdf/lib/bricks/pdf.rb +1 -1
  38. data/bricks/sphinx/lib/bricks/sphinx.rb +2 -0
  39. data/bricks/sphinx/zena/init.rb +14 -0
  40. data/bricks/tags/zena/test/zafu/tags.yml +5 -1
  41. data/bricks/worker/lib/bricks/worker.rb +3 -2
  42. data/bricks/zena/zena/migrate/20130829093753_add_versioned_flag_to_column.rb +10 -0
  43. data/bricks/zena/zena/migrate/20130903084909_count_login_attempts.rb +11 -0
  44. data/bricks/zena/zena/migrate/20131104153126_index_fullpath.rb +10 -0
  45. data/bricks/zena/zena/migrate/20131104210011_rebuild_fullpath_after_change.rb +10 -0
  46. data/bricks/zena/zena/migrate/20131105160420_add_skin_id_to_sites.rb +9 -0
  47. data/bricks/zena/zena/migrate/20131105175822_add_profile_to_users.rb +11 -0
  48. data/bricks/zena/zena/migrate/20140213120038_fix_idx_scope.rb +13 -0
  49. data/bricks/zena/zena/migrate/20140628140247_add_site_readonly.rb +9 -0
  50. data/config/bricks.yml +8 -4
  51. data/config/gems.yml +5 -3
  52. data/db/init/base/skins/default/Node-+login.zafu +8 -1
  53. data/db/init/base/skins/default/Node-+search.zafu +1 -1
  54. data/lib/bricks/loader.rb +5 -5
  55. data/lib/gettext_strings.rb +3 -0
  56. data/lib/tasks/zena.rake +25 -22
  57. data/lib/zafu/process/context.rb +4 -0
  58. data/lib/zena/acts/secure_node.rb +3 -3
  59. data/lib/zena/app.rb +1 -0
  60. data/lib/zena/deploy.rb +1 -1
  61. data/lib/zena/deploy/template.rb +1 -1
  62. data/lib/zena/foxy_parser.rb +5 -2
  63. data/lib/zena/info.rb +1 -1
  64. data/lib/zena/site_worker.rb +2 -2
  65. data/lib/zena/test_controller.rb +5 -2
  66. data/lib/zena/use/action.rb +9 -2
  67. data/lib/zena/use/ajax.rb +20 -4
  68. data/lib/zena/use/ancestry.rb +89 -15
  69. data/lib/zena/use/authlogic.rb +8 -2
  70. data/lib/zena/use/context.rb +1 -0
  71. data/lib/zena/use/display.rb +1 -97
  72. data/lib/zena/use/forms.rb +28 -8
  73. data/lib/zena/use/html_tags.rb +16 -7
  74. data/lib/zena/use/i18n.rb +1 -1
  75. data/lib/zena/use/prop_eval.rb +6 -1
  76. data/lib/zena/use/query_node.rb +69 -4
  77. data/lib/zena/use/recursion.rb +1 -1
  78. data/lib/zena/use/refactor.rb +5 -2
  79. data/lib/zena/use/relations.rb +1 -0
  80. data/lib/zena/use/rendering.rb +7 -4
  81. data/lib/zena/use/test_helper.rb +8 -4
  82. data/lib/zena/use/upload.rb +14 -0
  83. data/lib/zena/use/urls.rb +39 -23
  84. data/lib/zena/use/version_hash.rb +5 -2
  85. data/lib/zena/use/workflow.rb +116 -70
  86. data/lib/zena/use/zafu_eval.rb +41 -0
  87. data/lib/zena/use/zafu_safe_definitions.rb +1 -0
  88. data/lib/zena/use/zafu_templates.rb +32 -26
  89. data/lib/zena/use/zazen.rb +8 -7
  90. data/locale/app.pot +5 -1
  91. data/locale/de/LC_MESSAGES/zena.mo +0 -0
  92. data/locale/de/zena.po +385 -281
  93. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  94. data/locale/en/zena.po +378 -271
  95. data/locale/fr/LC_MESSAGES/zena.mo +0 -0
  96. data/locale/fr/zena.po +387 -272
  97. data/locale/it/LC_MESSAGES/zena.mo +0 -0
  98. data/locale/it/zena.po +433 -404
  99. data/locale/zena.pot +362 -268
  100. data/public/javascripts/grid.js +280 -104
  101. data/public/javascripts/zena.js +43 -15
  102. data/public/stylesheets/admin.css +8 -2
  103. data/public/stylesheets/grid.css +5 -2
  104. data/public/stylesheets/popup.css +1 -1
  105. data/test/fixtures/files/TestNode.zafu +51 -0
  106. data/test/functional/nodes_controller_test.rb +20 -5
  107. data/test/functional/user_sessions_controller_test.rb +41 -6
  108. data/test/functional/users_controller_test.rb +1 -2
  109. data/test/integration/navigation_test.rb +22 -4
  110. data/test/integration/query_node/basic.yml +7 -0
  111. data/test/integration/query_node/complex.yml +1 -1
  112. data/test/integration/query_node/errors.yml +1 -1
  113. data/test/integration/query_node/filters.yml +34 -1
  114. data/test/integration/query_node/relations.yml +6 -13
  115. data/test/integration/query_node_test.rb +22 -3
  116. data/test/integration/zafu_compiler/action.yml +1 -1
  117. data/test/integration/zafu_compiler/alias_site.yml +52 -0
  118. data/test/integration/zafu_compiler/complex.yml +1 -1
  119. data/test/integration/zafu_compiler/complex_ok.yml +5 -5
  120. data/test/integration/zafu_compiler/context.yml +1 -1
  121. data/test/integration/zafu_compiler/display.yml +56 -5
  122. data/test/integration/zafu_compiler/forms.yml +35 -2
  123. data/test/integration/zafu_compiler/meta.yml +4 -0
  124. data/test/integration/zafu_compiler/rubyless.yml +1 -1
  125. data/test/integration/zafu_compiler/safe_definitions.yml +4 -0
  126. data/test/integration/zafu_compiler/security.yml +10 -0
  127. data/test/integration/zafu_compiler/site.yml +5 -1
  128. data/test/integration/zafu_compiler/urls.yml +8 -2
  129. data/test/integration/zafu_compiler/zafu_attributes.yml +2 -1
  130. data/test/integration/zafu_compiler/zazen.yml +4 -0
  131. data/test/integration/zafu_compiler_test.rb +47 -4
  132. data/test/selenium/Grid/grid1.rsel +8 -8
  133. data/test/sites/complex/sites.yml +2 -2
  134. data/test/sites/complex/users.yml +1 -0
  135. data/test/sites/zena/columns.yml +4 -0
  136. data/test/sites/zena/sites.yml +1 -0
  137. data/test/sites/zena/users.yml +1 -0
  138. data/test/unit/node_test.rb +53 -5
  139. data/test/unit/note_test.rb +1 -1
  140. data/test/unit/relation_proxy_test.rb +20 -0
  141. data/test/unit/role_test.rb +2 -0
  142. data/test/unit/site_test.rb +28 -6
  143. data/test/unit/user_test.rb +332 -1
  144. data/test/unit/virtual_class_test.rb +55 -0
  145. data/test/unit/workflow_test.rb +175 -0
  146. data/test/unit/zena/use/ancestry_test.rb +52 -10
  147. data/test/unit/zena/use/prop_eval_test.rb +44 -0
  148. data/test/unit/zena/use/rendering_test.rb +48 -2
  149. data/test/unit/zena/use/upload_test.rb +15 -13
  150. data/test/unit/zena/use/urls_test.rb +1 -0
  151. data/vendor/plugins/ar_mysql_full_text/lib/ar_mysql_full_text.rb +39 -25
  152. data/zena.gemspec +69 -307
  153. metadata +143 -368
  154. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/Run 2.tmCommand +0 -24
  155. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/Run Context.tmCommand +0 -58
  156. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/Run Focused Should.tmCommand +0 -88
  157. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/Run.tmCommand +0 -27
  158. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/YAML to Shoulda.tmCommand +0 -23
  159. data/vendor/TextMate/Ruby Shoulda.tmbundle/Preferences/Symbol List: Context.tmPreferences +0 -19
  160. data/vendor/TextMate/Ruby Shoulda.tmbundle/Preferences/Symbol List: Should.tmPreferences +0 -19
  161. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory attributes for.tmSnippet +0 -16
  162. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory build.tmSnippet +0 -16
  163. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory.tmSnippet +0 -16
  164. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory_define with class.tmSnippet +0 -18
  165. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory_define.tmSnippet +0 -18
  166. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory_next.tmSnippet +0 -16
  167. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory_sequence.tmSnippet +0 -18
  168. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_bad_value.tmSnippet +0 -16
  169. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_contains.tmSnippet +0 -16
  170. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_does_not_contain.tmSnippet +0 -16
  171. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_good_value.tmSnippet +0 -16
  172. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_same_elements.tmSnippet +0 -16
  173. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_save.tmSnippet +0 -16
  174. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_sent_email.tmSnippet +0 -18
  175. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_valid.tmSnippet +0 -16
  176. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/association.tmSnippet +0 -17
  177. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/attribute.tmSnippet +0 -17
  178. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/before_should block.tmSnippet +0 -18
  179. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/context block get.tmSnippet +0 -22
  180. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/context block post.tmSnippet +0 -23
  181. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/context block with setup.tmSnippet +0 -25
  182. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/setup.tmSnippet +0 -18
  183. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should block with before proc.tmSnippet +0 -18
  184. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should block.tmSnippet +0 -18
  185. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_allow_values_for.tmSnippet +0 -16
  186. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_assign_to.tmSnippet +0 -16
  187. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_be_restful denied.tmSnippet +0 -20
  188. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_be_restful.tmSnippet +0 -20
  189. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_belong_to.tmSnippet +0 -16
  190. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_change by.tmSnippet +0 -16
  191. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_change from to.tmSnippet +0 -16
  192. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_ensure_length_at_least.tmSnippet +0 -16
  193. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_ensure_length_in_range.tmSnippet +0 -16
  194. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_ensure_length_is.tmSnippet +0 -16
  195. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_ensure_value_in_range.tmSnippet +0 -16
  196. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_eventually.tmSnippet +0 -18
  197. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_filter_params.tmSnippet +0 -16
  198. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_and_belong_to_many.tmSnippet +0 -16
  199. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_class_methods.tmSnippet +0 -16
  200. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_db_column.tmSnippet +0 -16
  201. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_db_columns.tmSnippet +0 -16
  202. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_index.tmSnippet +0 -16
  203. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_indices.tmSnippet +0 -16
  204. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_instance_methods.tmSnippet +0 -16
  205. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_many.tmSnippet +0 -16
  206. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_named_scope.tmSnippet +0 -16
  207. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_one.tmSnippet +0 -16
  208. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_readonly_attributes.tmSnippet +0 -16
  209. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_allow_mass_assignment_of.tmSnippet +0 -16
  210. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_allow_values_for.tmSnippet +0 -16
  211. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_assign_to.tmSnippet +0 -16
  212. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_change.tmSnippet +0 -16
  213. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_set_the_flash.tmSnippet +0 -16
  214. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_redirect_to.tmSnippet +0 -16
  215. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_render_a_form.tmSnippet +0 -16
  216. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_render_template.tmSnippet +0 -16
  217. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_render_with_layout.tmSnippet +0 -16
  218. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_render_without_layout.tmSnippet +0 -16
  219. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_respond_with.tmSnippet +0 -16
  220. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_respond_with_content_type.tmSnippet +0 -16
  221. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_return_from_session.tmSnippet +0 -16
  222. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_route.tmSnippet +0 -16
  223. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_set_the_flash_to.tmSnippet +0 -16
  224. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_acceptance_of.tmSnippet +0 -16
  225. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_numericality_of.tmSnippet +0 -16
  226. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_presence_of.tmSnippet +0 -16
  227. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_uniqueness_of with scope.tmSnippet +0 -16
  228. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_uniqueness_of.tmSnippet +0 -16
  229. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/catch_exception.rb +0 -39
  230. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/run_script.rb +0 -104
  231. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/stdin_dialog.rb +0 -14
  232. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/test.rb +0 -17
  233. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/todo.txt +0 -13
  234. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/bin/yaml_to_shoulda.rb +0 -25
  235. data/vendor/TextMate/Ruby Shoulda.tmbundle/Syntaxes/Ruby on Rails (Shoulda).tmLanguage +0 -166
  236. data/vendor/TextMate/Ruby Shoulda.tmbundle/info.plist +0 -304
  237. data/vendor/TextMate/Zena.tmbundle/Commands/Run all yaml tests.tmCommand +0 -37
  238. data/vendor/TextMate/Zena.tmbundle/Commands/Run focused yaml test.tmCommand +0 -52
  239. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/catch_exception.rb +0 -39
  240. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/run_script.rb +0 -118
  241. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/stdin_dialog.rb +0 -14
  242. data/vendor/TextMate/Zena.tmbundle/info.plist +0 -17
  243. data/vendor/plugins/selenium-on-rails/CHANGELOG +0 -125
  244. data/vendor/plugins/selenium-on-rails/LICENSE-2.0.txt +0 -202
  245. data/vendor/plugins/selenium-on-rails/README.md +0 -202
  246. data/vendor/plugins/selenium-on-rails/Rakefile +0 -38
  247. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumController.html +0 -265
  248. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumHelper.html +0 -148
  249. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails.html +0 -126
  250. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/FixtureLoader.html +0 -231
  251. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/PartialsSupport.html +0 -195
  252. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/Paths.html +0 -295
  253. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/RSelenese.html +0 -219
  254. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/Renderer.html +0 -156
  255. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/Selenese.html +0 -179
  256. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/SuiteRenderer.html +0 -223
  257. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilder.html +0 -441
  258. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilderAccessors.html +0 -3098
  259. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilderActions.html +0 -2080
  260. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilderUserAccessors.html +0 -116
  261. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilderUserActions.html +0 -116
  262. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRailsConfig.html +0 -150
  263. data/vendor/plugins/selenium-on-rails/doc/files/CHANGELOG.html +0 -422
  264. data/vendor/plugins/selenium-on-rails/doc/files/README.html +0 -321
  265. data/vendor/plugins/selenium-on-rails/doc/files/lib/controllers/selenium_controller_rb.html +0 -108
  266. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_helper_rb.html +0 -101
  267. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/acceptance_test_runner_rb.html +0 -222
  268. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/fixture_loader_rb.html +0 -109
  269. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/partials_support_rb.html +0 -111
  270. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/paths_rb.html +0 -101
  271. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/renderer_rb.html +0 -101
  272. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/rselenese_rb.html +0 -118
  273. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/selenese_rb.html +0 -101
  274. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/suite_renderer_rb.html +0 -101
  275. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/test_builder_accessors_rb.html +0 -114
  276. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/test_builder_actions_rb.html +0 -113
  277. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/test_builder_rb.html +0 -120
  278. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails_config_rb.html +0 -108
  279. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails_rb.html +0 -115
  280. data/vendor/plugins/selenium-on-rails/doc/fr_class_index.html +0 -42
  281. data/vendor/plugins/selenium-on-rails/doc/fr_file_index.html +0 -43
  282. data/vendor/plugins/selenium-on-rails/doc/fr_method_index.html +0 -182
  283. data/vendor/plugins/selenium-on-rails/doc/index.html +0 -24
  284. data/vendor/plugins/selenium-on-rails/doc/rdoc-style.css +0 -208
  285. data/vendor/plugins/selenium-on-rails/generators/selenium/USAGE +0 -19
  286. data/vendor/plugins/selenium-on-rails/generators/selenium/selenium_generator.rb +0 -50
  287. data/vendor/plugins/selenium-on-rails/generators/selenium/templates/rhtml.rhtml +0 -16
  288. data/vendor/plugins/selenium-on-rails/generators/selenium/templates/rselenese.rhtml +0 -14
  289. data/vendor/plugins/selenium-on-rails/generators/selenium/templates/selenese.rhtml +0 -11
  290. data/vendor/plugins/selenium-on-rails/init.rb +0 -15
  291. data/vendor/plugins/selenium-on-rails/lib/controllers/selenium_controller.rb +0 -122
  292. data/vendor/plugins/selenium-on-rails/lib/controllers/switch_environment_controller.rb +0 -16
  293. data/vendor/plugins/selenium-on-rails/lib/selenium_helper.rb +0 -8
  294. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails.rb +0 -11
  295. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/acceptance_test_runner.rb +0 -215
  296. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/fixture_loader.rb +0 -57
  297. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/partials_support.rb +0 -36
  298. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/paths.rb +0 -61
  299. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/renderer.rb +0 -20
  300. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/rselenese.rb +0 -44
  301. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/selenese.rb +0 -87
  302. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/suite_renderer.rb +0 -56
  303. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder.rb +0 -116
  304. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder_accessors.rb +0 -1002
  305. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder_actions.rb +0 -514
  306. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder_user_accessors.rb.example +0 -91
  307. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder_user_actions.rb.example +0 -24
  308. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails_config.rb +0 -30
  309. data/vendor/plugins/selenium-on-rails/lib/views/layouts/layout.rhtml +0 -18
  310. data/vendor/plugins/selenium-on-rails/lib/views/record.rhtml +0 -5
  311. data/vendor/plugins/selenium-on-rails/lib/views/selenium_helper.rb +0 -9
  312. data/vendor/plugins/selenium-on-rails/lib/views/setup.rhtml +0 -67
  313. data/vendor/plugins/selenium-on-rails/lib/views/test_suite.rhtml +0 -26
  314. data/vendor/plugins/selenium-on-rails/routes.rb +0 -24
  315. data/vendor/plugins/selenium-on-rails/selenium-core/Blank.html +0 -7
  316. data/vendor/plugins/selenium-on-rails/selenium-core/InjectedRemoteRunner.html +0 -8
  317. data/vendor/plugins/selenium-on-rails/selenium-core/RemoteRunner.html +0 -110
  318. data/vendor/plugins/selenium-on-rails/selenium-core/SeleniumLog.html +0 -109
  319. data/vendor/plugins/selenium-on-rails/selenium-core/TestPrompt.html +0 -145
  320. data/vendor/plugins/selenium-on-rails/selenium-core/TestRunner-splash.html +0 -55
  321. data/vendor/plugins/selenium-on-rails/selenium-core/TestRunner.hta +0 -177
  322. data/vendor/plugins/selenium-on-rails/selenium-core/TestRunner.html +0 -177
  323. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/butmin.gif +0 -0
  324. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/butplus.gif +0 -0
  325. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/domviewer.css +0 -298
  326. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/domviewer.html +0 -16
  327. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/selenium-domviewer.js +0 -205
  328. data/vendor/plugins/selenium-on-rails/selenium-core/icons/all.png +0 -0
  329. data/vendor/plugins/selenium-on-rails/selenium-core/icons/continue.png +0 -0
  330. data/vendor/plugins/selenium-on-rails/selenium-core/icons/continue_disabled.png +0 -0
  331. data/vendor/plugins/selenium-on-rails/selenium-core/icons/pause.png +0 -0
  332. data/vendor/plugins/selenium-on-rails/selenium-core/icons/pause_disabled.png +0 -0
  333. data/vendor/plugins/selenium-on-rails/selenium-core/icons/selected.png +0 -0
  334. data/vendor/plugins/selenium-on-rails/selenium-core/icons/step.png +0 -0
  335. data/vendor/plugins/selenium-on-rails/selenium-core/icons/step_disabled.png +0 -0
  336. data/vendor/plugins/selenium-on-rails/selenium-core/iedoc-core.xml +0 -1759
  337. data/vendor/plugins/selenium-on-rails/selenium-core/iedoc.xml +0 -1800
  338. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/cssQuery-p.js +0 -6
  339. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/src/cssQuery-level2.js +0 -142
  340. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/src/cssQuery-level3.js +0 -150
  341. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/src/cssQuery-standard.js +0 -53
  342. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/src/cssQuery.js +0 -356
  343. data/vendor/plugins/selenium-on-rails/selenium-core/lib/prototype.js +0 -2006
  344. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/builder.js +0 -101
  345. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/controls.js +0 -815
  346. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/dragdrop.js +0 -915
  347. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/effects.js +0 -958
  348. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/scriptaculous.js +0 -47
  349. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/slider.js +0 -283
  350. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/unittest.js +0 -383
  351. data/vendor/plugins/selenium-on-rails/selenium-core/lib/snapsie.js +0 -91
  352. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/find_matching_child.js +0 -69
  353. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/htmlutils.js +0 -1616
  354. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/injection.html +0 -72
  355. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-api.js +0 -3184
  356. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-browserbot.js +0 -2300
  357. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-browserdetect.js +0 -153
  358. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-commandhandlers.js +0 -377
  359. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-executionloop.js +0 -175
  360. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-logging.js +0 -148
  361. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-remoterunner.js +0 -695
  362. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-testrunner.js +0 -1362
  363. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-version.js +0 -5
  364. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/ui-doc.html +0 -803
  365. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/ui-element.js +0 -1537
  366. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/ui-map-sample.js +0 -979
  367. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/user-extensions.js +0 -3
  368. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/user-extensions.js.sample +0 -75
  369. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/xmlextras.js +0 -153
  370. data/vendor/plugins/selenium-on-rails/selenium-core/selenium-logo.png +0 -0
  371. data/vendor/plugins/selenium-on-rails/selenium-core/selenium-test.css +0 -43
  372. data/vendor/plugins/selenium-on-rails/selenium-core/selenium.css +0 -316
  373. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/dom.js +0 -566
  374. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/javascript-xpath-0.1.11.js +0 -2816
  375. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/util.js +0 -549
  376. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/xmltoken.js +0 -149
  377. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/xpath.js +0 -2450
  378. data/vendor/plugins/selenium-on-rails/tasks/test_acceptance.rake +0 -8
  379. data/vendor/plugins/selenium-on-rails/test/fixtures/config.yml +0 -37
  380. data/vendor/plugins/selenium-on-rails/test/fixtures/selenium.yml +0 -27
  381. data/vendor/plugins/selenium-on-rails/test/paths_test.rb +0 -72
  382. data/vendor/plugins/selenium-on-rails/test/renderer_test.rb +0 -157
  383. data/vendor/plugins/selenium-on-rails/test/rselenese_test.rb +0 -708
  384. data/vendor/plugins/selenium-on-rails/test/selenese_test.rb +0 -242
  385. data/vendor/plugins/selenium-on-rails/test/selenium_controller_test.rb +0 -67
  386. data/vendor/plugins/selenium-on-rails/test/selenium_on_rails_config_test.rb +0 -43
  387. data/vendor/plugins/selenium-on-rails/test/selenium_support_test.rb +0 -35
  388. data/vendor/plugins/selenium-on-rails/test/setup_test.rb +0 -31
  389. data/vendor/plugins/selenium-on-rails/test/suite_renderer_test.rb +0 -109
  390. data/vendor/plugins/selenium-on-rails/test/switch_environment_controller_test.rb +0 -17
  391. data/vendor/plugins/selenium-on-rails/test/test_builder_functions_authortest.rb +0 -51
  392. data/vendor/plugins/selenium-on-rails/test/test_helper.rb +0 -101
  393. data/vendor/plugins/selenium-on-rails/test_data/_partial.rsel +0 -1
  394. data/vendor/plugins/selenium-on-rails/test_data/own_layout.html +0 -12
  395. data/vendor/plugins/selenium-on-rails/test_data/partials/_html.html +0 -6
  396. data/vendor/plugins/selenium-on-rails/test_data/partials/_nesting.rsel +0 -2
  397. data/vendor/plugins/selenium-on-rails/test_data/partials/_rhtml.rhtml +0 -6
  398. data/vendor/plugins/selenium-on-rails/test_data/partials/_rsel.rsel +0 -1
  399. data/vendor/plugins/selenium-on-rails/test_data/partials/_sel.sel +0 -5
  400. data/vendor/plugins/selenium-on-rails/test_data/partials/all_partials.rsel +0 -5
  401. data/vendor/plugins/selenium-on-rails/test_data/rhtml.rhtml +0 -7
  402. data/vendor/plugins/selenium-on-rails/test_data/rselenese.rsel +0 -8
  403. data/vendor/plugins/selenium-on-rails/test_data/selenese.sel +0 -7
  404. data/vendor/plugins/selenium-on-rails/test_data/suite_one/subsuite/suite_one_subsuite_testcase.sel +0 -1
  405. data/vendor/plugins/selenium-on-rails/test_data/suite_one/suite_one_testcase1.sel +0 -1
  406. data/vendor/plugins/selenium-on-rails/test_data/suite_one/suite_one_testcase2.sel +0 -1
  407. data/vendor/plugins/selenium-on-rails/test_data/suite_two/suite_two_testcase.sel +0 -1
@@ -1,91 +0,0 @@
1
- /**
2
- * This file wraps the Snapsie ActiveX object, exposing a single saveSnapshot()
3
- * method on a the object.
4
- *
5
- * See http://snapsie.sourceforge.net/
6
- */
7
-
8
- function Snapsie() {
9
- // private methods
10
-
11
- function isQuirksMode(inDocument) {
12
- return (inDocument.compatMode == 'BackCompat');
13
- }
14
-
15
- function getDrawableElement(inDocument) {
16
- if (isQuirksMode(inDocument)) {
17
- var body = inDocument.getElementsByTagName('body')[0];
18
- return body;
19
- }
20
- else {
21
- // standards mode
22
- return inDocument.documentElement;
23
- }
24
- }
25
-
26
- /**
27
- * Returns the canonical Windows path for a given path. This means
28
- * basically replacing any forwards slashes with backslashes.
29
- *
30
- * @param path the path whose canonical form to return
31
- */
32
- function getCanonicalPath(path) {
33
- path = path.replace(/\//g, '\\');
34
- path = path.replace(/\\\\/g, '\\');
35
- return path;
36
- }
37
-
38
- // public methods
39
-
40
- /**
41
- * Saves a screenshot of the current document to a file. If frameId is
42
- * specified, a screenshot of just the frame is captured instead.
43
- *
44
- * @param outputFile the file to which to save the screenshot
45
- * @param frameId the frame to capture; omit to capture entire document
46
- */
47
- this.saveSnapshot = function(outputFile, frameId) {
48
- var drawableElement = getDrawableElement(document);
49
- var drawableInfo = {
50
- overflow : drawableElement.style.overflow
51
- , scrollLeft: drawableElement.scrollLeft
52
- , scrollTop : drawableElement.scrollTop
53
- };
54
- drawableElement.style.overflow = 'hidden';
55
-
56
- var capturableDocument;
57
- var frameBCR = { left: 0, top: 0 };
58
- if (!frameId) {
59
- capturableDocument = document;
60
- }
61
- else {
62
- var frame = document.getElementById(frameId);
63
- capturableDocument = frame.document;
64
-
65
- // scroll as much of the frame into view as possible
66
- frameBCR = frame.getBoundingClientRect();
67
- window.scroll(frameBCR.left, frameBCR.top);
68
- frameBCR = frame.getBoundingClientRect();
69
- }
70
-
71
- var nativeObj = new ActiveXObject('Snapsie.CoSnapsie');
72
- nativeObj.saveSnapshot(
73
- getCanonicalPath(outputFile),
74
- frameId,
75
- drawableElement.scrollWidth,
76
- drawableElement.scrollHeight,
77
- drawableElement.clientWidth,
78
- drawableElement.clientHeight,
79
- drawableElement.clientLeft,
80
- drawableElement.clientTop,
81
- frameBCR.left,
82
- frameBCR.top
83
- );
84
-
85
- // revert
86
-
87
- drawableElement.style.overflow = drawableInfo.overflow;
88
- drawableElement.scrollLeft = drawableInfo.scrollLeft;
89
- drawableElement.scrollTop = drawableInfo.scrollTop;
90
- }
91
- };
@@ -1,69 +0,0 @@
1
- /*
2
- * Copyright 2004 ThoughtWorks, Inc
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- *
16
- */
17
-
18
- elementFindMatchingChildren = function(element, selector) {
19
- var matches = [];
20
-
21
- var childCount = element.childNodes.length;
22
- for (var i=0; i<childCount; i++) {
23
- var child = element.childNodes[i];
24
- if (selector(child)) {
25
- matches.push(child);
26
- } else {
27
- childMatches = elementFindMatchingChildren(child, selector);
28
- matches.push(childMatches);
29
- }
30
- }
31
-
32
- return matches.flatten();
33
- }
34
-
35
- ELEMENT_NODE_TYPE = 1;
36
-
37
- elementFindFirstMatchingChild = function(element, selector) {
38
-
39
- var childCount = element.childNodes.length;
40
- for (var i=0; i<childCount; i++) {
41
- var child = element.childNodes[i];
42
- if (child.nodeType == ELEMENT_NODE_TYPE) {
43
- if (selector(child)) {
44
- return child;
45
- }
46
- result = elementFindFirstMatchingChild(child, selector);
47
- if (result) {
48
- return result;
49
- }
50
- }
51
- }
52
- return null;
53
- }
54
-
55
- elementFindFirstMatchingParent = function(element, selector) {
56
- var current = element.parentNode;
57
- while (current != null) {
58
- if (selector(current)) {
59
- break;
60
- }
61
- current = current.parentNode;
62
- }
63
- return current;
64
- }
65
-
66
- elementFindMatchingChildById = function(element, id) {
67
- return elementFindFirstMatchingChild(element, function(element){return element.id==id} );
68
- }
69
-
@@ -1,1616 +0,0 @@
1
- /*
2
- * Copyright 2004 ThoughtWorks, Inc
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- *
16
- */
17
-
18
- // This script contains a badly-organised collection of miscellaneous
19
- // functions that really better homes.
20
-
21
- function classCreate() {
22
- return function() {
23
- this.initialize.apply(this, arguments);
24
- }
25
- }
26
-
27
- function objectExtend(destination, source) {
28
- for (var property in source) {
29
- destination[property] = source[property];
30
- }
31
- return destination;
32
- }
33
-
34
- function sel$() {
35
- var results = [], element;
36
- for (var i = 0; i < arguments.length; i++) {
37
- element = arguments[i];
38
- if (typeof element == 'string')
39
- element = document.getElementById(element);
40
- results[results.length] = element;
41
- }
42
- return results.length < 2 ? results[0] : results;
43
- }
44
-
45
- function sel$A(iterable) {
46
- if (!iterable) return [];
47
- if (iterable.toArray) {
48
- return iterable.toArray();
49
- } else {
50
- var results = [];
51
- for (var i = 0; i < iterable.length; i++)
52
- results.push(iterable[i]);
53
- return results;
54
- }
55
- }
56
-
57
- function fnBind() {
58
- var args = sel$A(arguments), __method = args.shift(), object = args.shift();
59
- var retval = function() {
60
- return __method.apply(object, args.concat(sel$A(arguments)));
61
- }
62
- retval.__method = __method;
63
- return retval;
64
- }
65
-
66
- function fnBindAsEventListener(fn, object) {
67
- var __method = fn;
68
- return function(event) {
69
- return __method.call(object, event || window.event);
70
- }
71
- }
72
-
73
- function removeClassName(element, name) {
74
- var re = new RegExp("\\b" + name + "\\b", "g");
75
- element.className = element.className.replace(re, "");
76
- }
77
-
78
- function addClassName(element, name) {
79
- element.className = element.className + ' ' + name;
80
- }
81
-
82
- function elementSetStyle(element, style) {
83
- for (var name in style) {
84
- var value = style[name];
85
- if (value == null) value = "";
86
- element.style[name] = value;
87
- }
88
- }
89
-
90
- function elementGetStyle(element, style) {
91
- var value = element.style[style];
92
- if (!value) {
93
- if (document.defaultView && document.defaultView.getComputedStyle) {
94
- var css = document.defaultView.getComputedStyle(element, null);
95
- value = css ? css.getPropertyValue(style) : null;
96
- } else if (element.currentStyle) {
97
- value = element.currentStyle[style];
98
- }
99
- }
100
-
101
- /** DGF necessary?
102
- if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
103
- if (Element.getStyle(element, 'position') == 'static') value = 'auto'; */
104
-
105
- return value == 'auto' ? null : value;
106
- }
107
-
108
- String.prototype.trim = function() {
109
- var result = this.replace(/^\s+/g, "");
110
- // strip leading
111
- return result.replace(/\s+$/g, "");
112
- // strip trailing
113
- };
114
- String.prototype.lcfirst = function() {
115
- return this.charAt(0).toLowerCase() + this.substr(1);
116
- };
117
- String.prototype.ucfirst = function() {
118
- return this.charAt(0).toUpperCase() + this.substr(1);
119
- };
120
- String.prototype.startsWith = function(str) {
121
- return this.indexOf(str) == 0;
122
- };
123
-
124
- /**
125
- * Given a string literal that would appear in an XPath, puts it in quotes and
126
- * returns it. Special consideration is given to literals who themselves
127
- * contain quotes. It's possible for a concat() expression to be returned.
128
- */
129
- String.prototype.quoteForXPath = function()
130
- {
131
- if (/\'/.test(this)) {
132
- if (/\"/.test(this)) {
133
- // concat scenario
134
- var pieces = [];
135
- var a = "'", b = '"', c;
136
- for (var i = 0, j = 0; i < this.length;) {
137
- if (this.charAt(i) == a) {
138
- // encountered a quote that cannot be contained in current
139
- // quote, so need to flip-flop quoting scheme
140
- if (j < i) {
141
- pieces.push(a + this.substring(j, i) + a);
142
- j = i;
143
- }
144
- c = a;
145
- a = b;
146
- b = c;
147
- }
148
- else {
149
- ++i;
150
- }
151
- }
152
- pieces.push(a + this.substring(j) + a);
153
- return 'concat(' + pieces.join(', ') + ')';
154
- }
155
- else {
156
- // quote with doubles
157
- return '"' + this + '"';
158
- }
159
- }
160
- // quote with singles
161
- return "'" + this + "'";
162
- };
163
-
164
- // Returns the text in this element
165
- function getText(element) {
166
- var text = "";
167
-
168
- var isRecentFirefox = (browserVersion.isFirefox && browserVersion.firefoxVersion >= "1.5");
169
- if (isRecentFirefox || browserVersion.isKonqueror || browserVersion.isSafari || browserVersion.isOpera) {
170
- text = getTextContent(element);
171
- } else if (element.textContent) {
172
- text = element.textContent;
173
- } else if (element.innerText) {
174
- text = element.innerText;
175
- }
176
-
177
- text = normalizeNewlines(text);
178
- text = normalizeSpaces(text);
179
-
180
- return text.trim();
181
- }
182
-
183
- function getTextContent(element, preformatted) {
184
- if (element.nodeType == 3 /*Node.TEXT_NODE*/) {
185
- var text = element.data;
186
- if (!preformatted) {
187
- text = text.replace(/\n|\r|\t/g, " ");
188
- }
189
- return text;
190
- }
191
- if (element.nodeType == 1 /*Node.ELEMENT_NODE*/) {
192
- var childrenPreformatted = preformatted || (element.tagName == "PRE");
193
- var text = "";
194
- for (var i = 0; i < element.childNodes.length; i++) {
195
- var child = element.childNodes.item(i);
196
- text += getTextContent(child, childrenPreformatted);
197
- }
198
- // Handle block elements that introduce newlines
199
- // -- From HTML spec:
200
- //<!ENTITY % block
201
- // "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT |
202
- // BLOCKQUOTE | F:wORM | HR | TABLE | FIELDSET | ADDRESS">
203
- //
204
- // TODO: should potentially introduce multiple newlines to separate blocks
205
- if (element.tagName == "P" || element.tagName == "BR" || element.tagName == "HR" || element.tagName == "DIV") {
206
- text += "\n";
207
- }
208
- return text;
209
- }
210
- return '';
211
- }
212
-
213
- /**
214
- * Convert all newlines to \n
215
- */
216
- function normalizeNewlines(text)
217
- {
218
- return text.replace(/\r\n|\r/g, "\n");
219
- }
220
-
221
- /**
222
- * Replace multiple sequential spaces with a single space, and then convert &nbsp; to space.
223
- */
224
- function normalizeSpaces(text)
225
- {
226
- // IE has already done this conversion, so doing it again will remove multiple nbsp
227
- if (browserVersion.isIE)
228
- {
229
- return text;
230
- }
231
-
232
- // Replace multiple spaces with a single space
233
- // TODO - this shouldn't occur inside PRE elements
234
- text = text.replace(/\ +/g, " ");
235
-
236
- // Replace &nbsp; with a space
237
- var nbspPattern = new RegExp(String.fromCharCode(160), "g");
238
- if (browserVersion.isSafari) {
239
- return replaceAll(text, String.fromCharCode(160), " ");
240
- } else {
241
- return text.replace(nbspPattern, " ");
242
- }
243
- }
244
-
245
- function replaceAll(text, oldText, newText) {
246
- while (text.indexOf(oldText) != -1) {
247
- text = text.replace(oldText, newText);
248
- }
249
- return text;
250
- }
251
-
252
-
253
- function xmlDecode(text) {
254
- text = text.replace(/&quot;/g, '"');
255
- text = text.replace(/&apos;/g, "'");
256
- text = text.replace(/&lt;/g, "<");
257
- text = text.replace(/&gt;/g, ">");
258
- text = text.replace(/&amp;/g, "&");
259
- return text;
260
- }
261
-
262
- // Sets the text in this element
263
- function setText(element, text) {
264
- if (element.textContent != null) {
265
- element.textContent = text;
266
- } else if (element.innerText != null) {
267
- element.innerText = text;
268
- }
269
- }
270
-
271
- // Get the value of an <input> element
272
- function getInputValue(inputElement) {
273
- if (inputElement.type) {
274
- if (inputElement.type.toUpperCase() == 'CHECKBOX' ||
275
- inputElement.type.toUpperCase() == 'RADIO')
276
- {
277
- return (inputElement.checked ? 'on' : 'off');
278
- }
279
- }
280
- if (inputElement.value == null) {
281
- throw new SeleniumError("This element has no value; is it really a form field?");
282
- }
283
- return inputElement.value;
284
- }
285
-
286
- /* Fire an event in a browser-compatible manner */
287
- function triggerEvent(element, eventType, canBubble, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) {
288
- canBubble = (typeof(canBubble) == undefined) ? true : canBubble;
289
- if (element.fireEvent && element.ownerDocument && element.ownerDocument.createEventObject) { // IE
290
- var evt = createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown);
291
- element.fireEvent('on' + eventType, evt);
292
- }
293
- else {
294
- var evt = document.createEvent('HTMLEvents');
295
-
296
- try {
297
- evt.shiftKey = shiftKeyDown;
298
- evt.metaKey = metaKeyDown;
299
- evt.altKey = altKeyDown;
300
- evt.ctrlKey = controlKeyDown;
301
- } catch (e) {
302
- // On Firefox 1.0, you can only set these during initMouseEvent or initKeyEvent
303
- // we'll have to ignore them here
304
- LOG.exception(e);
305
- }
306
-
307
- evt.initEvent(eventType, canBubble, true);
308
- element.dispatchEvent(evt);
309
- }
310
- }
311
-
312
- function getKeyCodeFromKeySequence(keySequence) {
313
- var match = /^\\(\d{1,3})$/.exec(keySequence);
314
- if (match != null) {
315
- return match[1];
316
- }
317
- match = /^.$/.exec(keySequence);
318
- if (match != null) {
319
- return match[0].charCodeAt(0);
320
- }
321
- // this is for backward compatibility with existing tests
322
- // 1 digit ascii codes will break however because they are used for the digit chars
323
- match = /^\d{2,3}$/.exec(keySequence);
324
- if (match != null) {
325
- return match[0];
326
- }
327
- throw new SeleniumError("invalid keySequence");
328
- }
329
-
330
- function createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) {
331
- var evt = element.ownerDocument.createEventObject();
332
- evt.shiftKey = shiftKeyDown;
333
- evt.metaKey = metaKeyDown;
334
- evt.altKey = altKeyDown;
335
- evt.ctrlKey = controlKeyDown;
336
- return evt;
337
- }
338
-
339
- function triggerKeyEvent(element, eventType, keySequence, canBubble, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) {
340
- var keycode = getKeyCodeFromKeySequence(keySequence);
341
- canBubble = (typeof(canBubble) == undefined) ? true : canBubble;
342
- if (element.fireEvent && element.ownerDocument && element.ownerDocument.createEventObject) { // IE
343
- var keyEvent = createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown);
344
- keyEvent.keyCode = keycode;
345
- element.fireEvent('on' + eventType, keyEvent);
346
- }
347
- else {
348
- var evt;
349
- if (window.KeyEvent) {
350
- evt = document.createEvent('KeyEvents');
351
- evt.initKeyEvent(eventType, true, true, window, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown, keycode, keycode);
352
- } else {
353
- evt = document.createEvent('UIEvents');
354
-
355
- evt.shiftKey = shiftKeyDown;
356
- evt.metaKey = metaKeyDown;
357
- evt.altKey = altKeyDown;
358
- evt.ctrlKey = controlKeyDown;
359
-
360
- evt.initUIEvent(eventType, true, true, window, 1);
361
- evt.keyCode = keycode;
362
- evt.which = keycode;
363
- }
364
-
365
- element.dispatchEvent(evt);
366
- }
367
- }
368
-
369
- function removeLoadListener(element, command) {
370
- LOG.debug('Removing loadListenter for ' + element + ', ' + command);
371
- if (window.removeEventListener)
372
- element.removeEventListener("load", command, true);
373
- else if (window.detachEvent)
374
- element.detachEvent("onload", command);
375
- }
376
-
377
- function addLoadListener(element, command) {
378
- LOG.debug('Adding loadListenter for ' + element + ', ' + command);
379
- var augmentedCommand = function() {
380
- command.call(this, element);
381
- }
382
- if (window.addEventListener && !browserVersion.isOpera)
383
- element.addEventListener("load", augmentedCommand, true);
384
- else if (window.attachEvent)
385
- element.attachEvent("onload", augmentedCommand);
386
- }
387
-
388
- /**
389
- * Override the broken getFunctionName() method from JsUnit
390
- * This file must be loaded _after_ the jsunitCore.js
391
- */
392
- function getFunctionName(aFunction) {
393
- var regexpResult = aFunction.toString().match(/function (\w*)/);
394
- if (regexpResult && regexpResult[1]) {
395
- return regexpResult[1];
396
- }
397
- return 'anonymous';
398
- }
399
-
400
- function getDocumentBase(doc) {
401
- var bases = document.getElementsByTagName("base");
402
- if (bases && bases.length && bases[0].href) {
403
- return bases[0].href;
404
- }
405
- return "";
406
- }
407
-
408
- function getTagName(element) {
409
- var tagName;
410
- if (element && element.tagName && element.tagName.toLowerCase) {
411
- tagName = element.tagName.toLowerCase();
412
- }
413
- return tagName;
414
- }
415
-
416
- function selArrayToString(a) {
417
- if (isArray(a)) {
418
- // DGF copying the array, because the array-like object may be a non-modifiable nodelist
419
- var retval = [];
420
- for (var i = 0; i < a.length; i++) {
421
- var item = a[i];
422
- var replaced = new String(item).replace(/([,\\])/g, '\\$1');
423
- retval[i] = replaced;
424
- }
425
- return retval;
426
- }
427
- return new String(a);
428
- }
429
-
430
-
431
- function isArray(x) {
432
- return ((typeof x) == "object") && (x["length"] != null);
433
- }
434
-
435
- function absolutify(url, baseUrl) {
436
- /** returns a relative url in its absolute form, given by baseUrl.
437
- *
438
- * This function is a little odd, because it can take baseUrls that
439
- * aren't necessarily directories. It uses the same rules as the HTML
440
- * &lt;base&gt; tag; if the baseUrl doesn't end with "/", we'll assume
441
- * that it points to a file, and strip the filename off to find its
442
- * base directory.
443
- *
444
- * So absolutify("foo", "http://x/bar") will return "http://x/foo" (stripping off bar),
445
- * whereas absolutify("foo", "http://x/bar/") will return "http://x/bar/foo" (preserving bar).
446
- * Naturally absolutify("foo", "http://x") will return "http://x/foo", appropriately.
447
- *
448
- * @param url the url to make absolute; if this url is already absolute, we'll just return that, unchanged
449
- * @param baseUrl the baseUrl from which we'll absolutify, following the rules above.
450
- * @return 'url' if it was already absolute, or the absolutized version of url if it was not absolute.
451
- */
452
-
453
- // DGF isn't there some library we could use for this?
454
-
455
- if (/^\w+:/.test(url)) {
456
- // it's already absolute
457
- return url;
458
- }
459
-
460
- var loc;
461
- try {
462
- loc = parseUrl(baseUrl);
463
- } catch (e) {
464
- // is it an absolute windows file path? let's play the hero in that case
465
- if (/^\w:\\/.test(baseUrl)) {
466
- baseUrl = "file:///" + baseUrl.replace(/\\/g, "/");
467
- loc = parseUrl(baseUrl);
468
- } else {
469
- throw new SeleniumError("baseUrl wasn't absolute: " + baseUrl);
470
- }
471
- }
472
- loc.search = null;
473
- loc.hash = null;
474
-
475
- // if url begins with /, then that's the whole pathname
476
- if (/^\//.test(url)) {
477
- loc.pathname = url;
478
- var result = reassembleLocation(loc);
479
- return result;
480
- }
481
-
482
- // if pathname is null, then we'll just append "/" + the url
483
- if (!loc.pathname) {
484
- loc.pathname = "/" + url;
485
- var result = reassembleLocation(loc);
486
- return result;
487
- }
488
-
489
- // if pathname ends with /, just append url
490
- if (/\/$/.test(loc.pathname)) {
491
- loc.pathname += url;
492
- var result = reassembleLocation(loc);
493
- return result;
494
- }
495
-
496
- // if we're here, then the baseUrl has a pathname, but it doesn't end with /
497
- // in that case, we replace everything after the final / with the relative url
498
- loc.pathname = loc.pathname.replace(/[^\/\\]+$/, url);
499
- var result = reassembleLocation(loc);
500
- return result;
501
-
502
- }
503
-
504
- var URL_REGEX = /^((\w+):\/\/)(([^:]+):?([^@]+)?@)?([^\/\?:]*):?(\d+)?(\/?[^\?#]+)?\??([^#]+)?#?(.+)?/;
505
-
506
- function parseUrl(url) {
507
- var fields = ['url', null, 'protocol', null, 'username', 'password', 'host', 'port', 'pathname', 'search', 'hash'];
508
- var result = URL_REGEX.exec(url);
509
- if (!result) {
510
- throw new SeleniumError("Invalid URL: " + url);
511
- }
512
- var loc = new Object();
513
- for (var i = 0; i < fields.length; i++) {
514
- var field = fields[i];
515
- if (field == null) {
516
- continue;
517
- }
518
- loc[field] = result[i];
519
- }
520
- return loc;
521
- }
522
-
523
- function reassembleLocation(loc) {
524
- if (!loc.protocol) {
525
- throw new Error("Not a valid location object: " + o2s(loc));
526
- }
527
- var protocol = loc.protocol;
528
- protocol = protocol.replace(/:$/, "");
529
- var url = protocol + "://";
530
- if (loc.username) {
531
- url += loc.username;
532
- if (loc.password) {
533
- url += ":" + loc.password;
534
- }
535
- url += "@";
536
- }
537
- if (loc.host) {
538
- url += loc.host;
539
- }
540
-
541
- if (loc.port) {
542
- url += ":" + loc.port;
543
- }
544
-
545
- if (loc.pathname) {
546
- url += loc.pathname;
547
- }
548
-
549
- if (loc.search) {
550
- url += "?" + loc.search;
551
- }
552
- if (loc.hash) {
553
- var hash = loc.hash;
554
- hash = loc.hash.replace(/^#/, "");
555
- url += "#" + hash;
556
- }
557
- return url;
558
- }
559
-
560
- function canonicalize(url) {
561
- if(url == "about:blank")
562
- {
563
- return url;
564
- }
565
- var tempLink = window.document.createElement("link");
566
- tempLink.href = url; // this will canonicalize the href on most browsers
567
- var loc = parseUrl(tempLink.href)
568
- if (!/\/\.\.\//.test(loc.pathname)) {
569
- return tempLink.href;
570
- }
571
- // didn't work... let's try it the hard way
572
- var originalParts = loc.pathname.split("/");
573
- var newParts = [];
574
- newParts.push(originalParts.shift());
575
- for (var i = 0; i < originalParts.length; i++) {
576
- var part = originalParts[i];
577
- if (".." == part) {
578
- newParts.pop();
579
- continue;
580
- }
581
- newParts.push(part);
582
- }
583
- loc.pathname = newParts.join("/");
584
- return reassembleLocation(loc);
585
- }
586
-
587
- function extractExceptionMessage(ex) {
588
- if (ex == null) return "null exception";
589
- if (ex.message != null) return ex.message;
590
- if (ex.toString && ex.toString() != null) return ex.toString();
591
- }
592
-
593
-
594
- function describe(object, delimiter) {
595
- var props = new Array();
596
- for (var prop in object) {
597
- try {
598
- props.push(prop + " -> " + object[prop]);
599
- } catch (e) {
600
- props.push(prop + " -> [htmlutils: ack! couldn't read this property! (Permission Denied?)]");
601
- }
602
- }
603
- return props.join(delimiter || '\n');
604
- }
605
-
606
- var PatternMatcher = function(pattern) {
607
- this.selectStrategy(pattern);
608
- };
609
- PatternMatcher.prototype = {
610
-
611
- selectStrategy: function(pattern) {
612
- this.pattern = pattern;
613
- var strategyName = 'glob';
614
- // by default
615
- if (/^([a-z-]+):(.*)/.test(pattern)) {
616
- var possibleNewStrategyName = RegExp.$1;
617
- var possibleNewPattern = RegExp.$2;
618
- if (PatternMatcher.strategies[possibleNewStrategyName]) {
619
- strategyName = possibleNewStrategyName;
620
- pattern = possibleNewPattern;
621
- }
622
- }
623
- var matchStrategy = PatternMatcher.strategies[strategyName];
624
- if (!matchStrategy) {
625
- throw new SeleniumError("cannot find PatternMatcher.strategies." + strategyName);
626
- }
627
- this.strategy = matchStrategy;
628
- this.matcher = new matchStrategy(pattern);
629
- },
630
-
631
- matches: function(actual) {
632
- return this.matcher.matches(actual + '');
633
- // Note: appending an empty string avoids a Konqueror bug
634
- }
635
-
636
- };
637
-
638
- /**
639
- * A "static" convenience method for easy matching
640
- */
641
- PatternMatcher.matches = function(pattern, actual) {
642
- return new PatternMatcher(pattern).matches(actual);
643
- };
644
-
645
- PatternMatcher.strategies = {
646
-
647
- /**
648
- * Exact matching, e.g. "exact:***"
649
- */
650
- exact: function(expected) {
651
- this.expected = expected;
652
- this.matches = function(actual) {
653
- return actual == this.expected;
654
- };
655
- },
656
-
657
- /**
658
- * Match by regular expression, e.g. "regexp:^[0-9]+$"
659
- */
660
- regexp: function(regexpString) {
661
- this.regexp = new RegExp(regexpString);
662
- this.matches = function(actual) {
663
- return this.regexp.test(actual);
664
- };
665
- },
666
-
667
- regex: function(regexpString) {
668
- this.regexp = new RegExp(regexpString);
669
- this.matches = function(actual) {
670
- return this.regexp.test(actual);
671
- };
672
- },
673
-
674
- regexpi: function(regexpString) {
675
- this.regexp = new RegExp(regexpString, "i");
676
- this.matches = function(actual) {
677
- return this.regexp.test(actual);
678
- };
679
- },
680
-
681
- regexi: function(regexpString) {
682
- this.regexp = new RegExp(regexpString, "i");
683
- this.matches = function(actual) {
684
- return this.regexp.test(actual);
685
- };
686
- },
687
-
688
- /**
689
- * "globContains" (aka "wildmat") patterns, e.g. "glob:one,two,*",
690
- * but don't require a perfect match; instead succeed if actual
691
- * contains something that matches globString.
692
- * Making this distinction is motivated by a bug in IE6 which
693
- * leads to the browser hanging if we implement *TextPresent tests
694
- * by just matching against a regular expression beginning and
695
- * ending with ".*". The globcontains strategy allows us to satisfy
696
- * the functional needs of the *TextPresent ops more efficiently
697
- * and so avoid running into this IE6 freeze.
698
- */
699
- globContains: function(globString) {
700
- this.regexp = new RegExp(PatternMatcher.regexpFromGlobContains(globString));
701
- this.matches = function(actual) {
702
- return this.regexp.test(actual);
703
- };
704
- },
705
-
706
-
707
- /**
708
- * "glob" (aka "wildmat") patterns, e.g. "glob:one,two,*"
709
- */
710
- glob: function(globString) {
711
- this.regexp = new RegExp(PatternMatcher.regexpFromGlob(globString));
712
- this.matches = function(actual) {
713
- return this.regexp.test(actual);
714
- };
715
- }
716
-
717
- };
718
-
719
- PatternMatcher.convertGlobMetaCharsToRegexpMetaChars = function(glob) {
720
- var re = glob;
721
- re = re.replace(/([.^$+(){}\[\]\\|])/g, "\\$1");
722
- re = re.replace(/\?/g, "(.|[\r\n])");
723
- re = re.replace(/\*/g, "(.|[\r\n])*");
724
- return re;
725
- };
726
-
727
- PatternMatcher.regexpFromGlobContains = function(globContains) {
728
- return PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(globContains);
729
- };
730
-
731
- PatternMatcher.regexpFromGlob = function(glob) {
732
- return "^" + PatternMatcher.convertGlobMetaCharsToRegexpMetaChars(glob) + "$";
733
- };
734
-
735
- if (!this["Assert"]) Assert = {};
736
-
737
-
738
- Assert.fail = function(message) {
739
- throw new AssertionFailedError(message);
740
- };
741
-
742
- /*
743
- * Assert.equals(comment?, expected, actual)
744
- */
745
- Assert.equals = function() {
746
- var args = new AssertionArguments(arguments);
747
- if (args.expected === args.actual) {
748
- return;
749
- }
750
- Assert.fail(args.comment +
751
- "Expected '" + args.expected +
752
- "' but was '" + args.actual + "'");
753
- };
754
-
755
- Assert.assertEquals = Assert.equals;
756
-
757
- /*
758
- * Assert.matches(comment?, pattern, actual)
759
- */
760
- Assert.matches = function() {
761
- var args = new AssertionArguments(arguments);
762
- if (PatternMatcher.matches(args.expected, args.actual)) {
763
- return;
764
- }
765
- Assert.fail(args.comment +
766
- "Actual value '" + args.actual +
767
- "' did not match '" + args.expected + "'");
768
- }
769
-
770
- /*
771
- * Assert.notMtches(comment?, pattern, actual)
772
- */
773
- Assert.notMatches = function() {
774
- var args = new AssertionArguments(arguments);
775
- if (!PatternMatcher.matches(args.expected, args.actual)) {
776
- return;
777
- }
778
- Assert.fail(args.comment +
779
- "Actual value '" + args.actual +
780
- "' did match '" + args.expected + "'");
781
- }
782
-
783
-
784
- // Preprocess the arguments to allow for an optional comment.
785
- function AssertionArguments(args) {
786
- if (args.length == 2) {
787
- this.comment = "";
788
- this.expected = args[0];
789
- this.actual = args[1];
790
- } else {
791
- this.comment = args[0] + "; ";
792
- this.expected = args[1];
793
- this.actual = args[2];
794
- }
795
- }
796
-
797
- function AssertionFailedError(message) {
798
- this.isAssertionFailedError = true;
799
- this.isSeleniumError = true;
800
- this.message = message;
801
- this.failureMessage = message;
802
- }
803
-
804
- function SeleniumError(message) {
805
- var error = new Error(message);
806
- if (typeof(arguments.caller) != 'undefined') { // IE, not ECMA
807
- var result = '';
808
- for (var a = arguments.caller; a != null; a = a.caller) {
809
- result += '> ' + a.callee.toString() + '\n';
810
- if (a.caller == a) {
811
- result += '*';
812
- break;
813
- }
814
- }
815
- error.stack = result;
816
- }
817
- error.isSeleniumError = true;
818
- return error;
819
- }
820
-
821
- function highlight(element) {
822
- var highLightColor = "yellow";
823
- if (element.originalColor == undefined) { // avoid picking up highlight
824
- element.originalColor = elementGetStyle(element, "background-color");
825
- }
826
- elementSetStyle(element, {"backgroundColor" : highLightColor});
827
- window.setTimeout(function() {
828
- try {
829
- //if element is orphan, probably page of it has already gone, so ignore
830
- if (!element.parentNode) {
831
- return;
832
- }
833
- elementSetStyle(element, {"backgroundColor" : element.originalColor});
834
- } catch (e) {} // DGF unhighlighting is very dangerous and low priority
835
- }, 200);
836
- }
837
-
838
-
839
-
840
- // for use from vs.2003 debugger
841
- function o2s(obj) {
842
- var s = "";
843
- for (key in obj) {
844
- var line = key + "->" + obj[key];
845
- line.replace("\n", " ");
846
- s += line + "\n";
847
- }
848
- return s;
849
- }
850
-
851
- var seenReadyStateWarning = false;
852
-
853
- function openSeparateApplicationWindow(url, suppressMozillaWarning) {
854
- // resize the Selenium window itself
855
- window.resizeTo(1200, 500);
856
- window.moveTo(window.screenX, 0);
857
-
858
- var appWindow = window.open(url + '?start=true', 'main');
859
- if (appWindow == null) {
860
- var errorMessage = "Couldn't open app window; is the pop-up blocker enabled?"
861
- LOG.error(errorMessage);
862
- throw new Error("Couldn't open app window; is the pop-up blocker enabled?");
863
- }
864
- try {
865
- var windowHeight = 500;
866
- if (window.outerHeight) {
867
- windowHeight = window.outerHeight;
868
- } else if (document.documentElement && document.documentElement.offsetHeight) {
869
- windowHeight = document.documentElement.offsetHeight;
870
- }
871
-
872
- if (window.screenLeft && !window.screenX) window.screenX = window.screenLeft;
873
- if (window.screenTop && !window.screenY) window.screenY = window.screenTop;
874
-
875
- appWindow.resizeTo(1200, screen.availHeight - windowHeight - 60);
876
- appWindow.moveTo(window.screenX, window.screenY + windowHeight + 25);
877
- } catch (e) {
878
- LOG.error("Couldn't resize app window");
879
- LOG.exception(e);
880
- }
881
-
882
-
883
- if (!suppressMozillaWarning && window.document.readyState == null && !seenReadyStateWarning) {
884
- alert("Beware! Mozilla bug 300992 means that we can't always reliably detect when a new page has loaded. Install the Selenium IDE extension or the readyState extension available from selenium.openqa.org to make page load detection more reliable.");
885
- seenReadyStateWarning = true;
886
- }
887
-
888
- return appWindow;
889
- }
890
-
891
- var URLConfiguration = classCreate();
892
- objectExtend(URLConfiguration.prototype, {
893
- initialize: function() {
894
- },
895
- _isQueryParameterTrue: function (name) {
896
- var parameterValue = this._getQueryParameter(name);
897
- if (parameterValue == null) return false;
898
- if (parameterValue.toLowerCase() == "true") return true;
899
- if (parameterValue.toLowerCase() == "on") return true;
900
- return false;
901
- },
902
-
903
- _getQueryParameter: function(searchKey) {
904
- var str = this.queryString
905
- if (str == null) return null;
906
- var clauses = str.split('&');
907
- for (var i = 0; i < clauses.length; i++) {
908
- var keyValuePair = clauses[i].split('=', 2);
909
- var key = unescape(keyValuePair[0]);
910
- if (key == searchKey) {
911
- return unescape(keyValuePair[1]);
912
- }
913
- }
914
- return null;
915
- },
916
-
917
- _extractArgs: function() {
918
- var str = SeleniumHTARunner.commandLine;
919
- if (str == null || str == "") return new Array();
920
- var matches = str.match(/(?:\"([^\"]+)\"|(?!\"([^\"]+)\")(\S+))/g);
921
- // We either want non quote stuff ([^"]+) surrounded by quotes
922
- // or we want to look-ahead, see that the next character isn't
923
- // a quoted argument, and then grab all the non-space stuff
924
- // this will return for the line: "foo" bar
925
- // the results "\"foo\"" and "bar"
926
-
927
- // So, let's unquote the quoted arguments:
928
- var args = new Array;
929
- for (var i = 0; i < matches.length; i++) {
930
- args[i] = matches[i];
931
- args[i] = args[i].replace(/^"(.*)"$/, "$1");
932
- }
933
- return args;
934
- },
935
-
936
- isMultiWindowMode:function() {
937
- return this._isQueryParameterTrue('multiWindow');
938
- },
939
-
940
- getBaseUrl:function() {
941
- return this._getQueryParameter('baseUrl');
942
-
943
- }
944
- });
945
-
946
-
947
- function safeScrollIntoView(element) {
948
- if (element.scrollIntoView) {
949
- element.scrollIntoView(false);
950
- return;
951
- }
952
- // TODO: work out how to scroll browsers that don't support
953
- // scrollIntoView (like Konqueror)
954
- }
955
-
956
- /**
957
- * Returns the absolute time represented as an offset of the current time.
958
- * Throws a SeleniumException if timeout is invalid.
959
- *
960
- * @param timeout the number of milliseconds from "now" whose absolute time
961
- * to return
962
- */
963
- function getTimeoutTime(timeout) {
964
- var now = new Date().getTime();
965
- var timeoutLength = parseInt(timeout);
966
-
967
- if (isNaN(timeoutLength)) {
968
- throw new SeleniumError("Timeout is not a number: '" + timeout + "'");
969
- }
970
-
971
- return now + timeoutLength;
972
- }
973
-
974
- /**
975
- * Returns true iff the current environment is the IDE.
976
- */
977
- function is_IDE()
978
- {
979
- return (typeof(SeleniumIDE) != 'undefined');
980
- }
981
-
982
- /**
983
- * Logs a message if the Logger exists, and does nothing if it doesn't exist.
984
- *
985
- * @param level the level to log at
986
- * @param msg the message to log
987
- */
988
- function safe_log(level, msg)
989
- {
990
- try {
991
- LOG[level](msg);
992
- }
993
- catch (e) {
994
- // couldn't log!
995
- }
996
- }
997
-
998
- /**
999
- * Displays a warning message to the user appropriate to the context under
1000
- * which the issue is encountered. This is primarily used to avoid popping up
1001
- * alert dialogs that might pause an automated test suite.
1002
- *
1003
- * @param msg the warning message to display
1004
- */
1005
- function safe_alert(msg)
1006
- {
1007
- if (is_IDE()) {
1008
- alert(msg);
1009
- }
1010
- }
1011
-
1012
- /**
1013
- * Returns true iff the given element represents a link with a javascript
1014
- * href attribute, and does not have an onclick attribute defined.
1015
- *
1016
- * @param element the element to test
1017
- */
1018
- function hasJavascriptHref(element) {
1019
- if (getTagName(element) != 'a') {
1020
- return false;
1021
- }
1022
- if (element.onclick) {
1023
- return false;
1024
- }
1025
- if (! element.href) {
1026
- return false;
1027
- }
1028
- if (! /\s*javascript:/i.test(element.href)) {
1029
- return false;
1030
- }
1031
- return true;
1032
- }
1033
-
1034
- /**
1035
- * Returns the given element, or its nearest ancestor, that satisfies
1036
- * hasJavascriptHref(). Returns null if none is found.
1037
- *
1038
- * @param element the element whose ancestors to test
1039
- */
1040
- function getAncestorOrSelfWithJavascriptHref(element) {
1041
- if (hasJavascriptHref(element)) {
1042
- return element;
1043
- }
1044
- if (element.parentNode == null) {
1045
- return null;
1046
- }
1047
- return getAncestorOrSelfWithJavascriptHref(element.parentNode);
1048
- }
1049
-
1050
- //******************************************************************************
1051
- // Locator evaluation support
1052
-
1053
- /**
1054
- * Parses a Selenium locator, returning its type and the unprefixed locator
1055
- * string as an object.
1056
- *
1057
- * @param locator the locator to parse
1058
- */
1059
- function parse_locator(locator)
1060
- {
1061
- var result = locator.match(/^([A-Za-z]+)=(.+)/);
1062
- if (result) {
1063
- return { type: result[1].toLowerCase(), string: result[2] };
1064
- }
1065
- return { type: 'implicit', string: locator };
1066
- }
1067
-
1068
- /**
1069
- * Evaluates an xpath on a document, and returns a list containing nodes in the
1070
- * resulting nodeset. The browserbot xpath methods are now backed by this
1071
- * function. A context node may optionally be provided, and the xpath will be
1072
- * evaluated from that context.
1073
- *
1074
- * @param xpath the xpath to evaluate
1075
- * @param inDocument the document in which to evaluate the xpath.
1076
- * @param opts (optional) An object containing various flags that can
1077
- * modify how the xpath is evaluated. Here's a listing of
1078
- * the meaningful keys:
1079
- *
1080
- * contextNode:
1081
- * the context node from which to evaluate the xpath. If
1082
- * unspecified, the context will be the root document
1083
- * element.
1084
- *
1085
- * namespaceResolver:
1086
- * the namespace resolver function. Defaults to null.
1087
- *
1088
- * xpathLibrary:
1089
- * the javascript library to use for XPath. "ajaxslt" is
1090
- * the default. "javascript-xpath" is newer and faster,
1091
- * but needs more testing.
1092
- *
1093
- * allowNativeXpath:
1094
- * whether to allow native evaluate(). Defaults to true.
1095
- *
1096
- * ignoreAttributesWithoutValue:
1097
- * whether it's ok to ignore attributes without value
1098
- * when evaluating the xpath. This can greatly improve
1099
- * performance in IE; however, if your xpaths depend on
1100
- * such attributes, you can't ignore them! Defaults to
1101
- * true.
1102
- *
1103
- * returnOnFirstMatch:
1104
- * whether to optimize the XPath evaluation to only
1105
- * return the first match. The match, if any, will still
1106
- * be returned in a list. Defaults to false.
1107
- */
1108
- function eval_xpath(xpath, inDocument, opts)
1109
- {
1110
- if (!opts) {
1111
- var opts = {};
1112
- }
1113
- var contextNode = opts.contextNode
1114
- ? opts.contextNode : inDocument;
1115
- var namespaceResolver = opts.namespaceResolver
1116
- ? opts.namespaceResolver : null;
1117
- var xpathLibrary = opts.xpathLibrary
1118
- ? opts.xpathLibrary : null;
1119
- var allowNativeXpath = (opts.allowNativeXpath != undefined)
1120
- ? opts.allowNativeXpath : true;
1121
- var ignoreAttributesWithoutValue = (opts.ignoreAttributesWithoutValue != undefined)
1122
- ? opts.ignoreAttributesWithoutValue : true;
1123
- var returnOnFirstMatch = (opts.returnOnFirstMatch != undefined)
1124
- ? opts.returnOnFirstMatch : false;
1125
-
1126
- // Trim any trailing "/": not valid xpath, and remains from attribute
1127
- // locator.
1128
- if (xpath.charAt(xpath.length - 1) == '/') {
1129
- xpath = xpath.slice(0, -1);
1130
- }
1131
- // HUGE hack - remove namespace from xpath for IE
1132
- if (browserVersion && browserVersion.isIE) {
1133
- xpath = xpath.replace(/x:/g, '')
1134
- }
1135
-
1136
- var nativeXpathAvailable = inDocument.evaluate;
1137
- var useNativeXpath = allowNativeXpath && nativeXpathAvailable;
1138
- var useDocumentEvaluate = useNativeXpath;
1139
-
1140
- // When using the new and faster javascript-xpath library,
1141
- // we'll use the TestRunner's document object, not the App-Under-Test's document.
1142
- // The new library only modifies the TestRunner document with the new
1143
- // functionality.
1144
- if (xpathLibrary == 'javascript-xpath' && !useNativeXpath) {
1145
- documentForXpath = document;
1146
- useDocumentEvaluate = true;
1147
- } else {
1148
- documentForXpath = inDocument;
1149
- }
1150
- var results = [];
1151
-
1152
- // this is either native xpath or javascript-xpath via TestRunner.evaluate
1153
- if (useDocumentEvaluate) {
1154
- try {
1155
- // Regarding use of the second argument to document.evaluate():
1156
- // http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/a59ce20639c74ba1/a9d9f53e88e5ebb5
1157
- var xpathResult = documentForXpath
1158
- .evaluate((contextNode == inDocument ? xpath : '.' + xpath),
1159
- contextNode, namespaceResolver, 0, null);
1160
- }
1161
- catch (e) {
1162
- throw new SeleniumError("Invalid xpath: " + extractExceptionMessage(e));
1163
- }
1164
- finally{
1165
- if (xpathResult == null) {
1166
- // If the result is null, we should still throw an Error.
1167
- throw new SeleniumError("Invalid xpath: " + xpath);
1168
- }
1169
- }
1170
- var result = xpathResult.iterateNext();
1171
- while (result) {
1172
- results.push(result);
1173
- result = xpathResult.iterateNext();
1174
- }
1175
- return results;
1176
- }
1177
-
1178
- // If not, fall back to slower JavaScript implementation
1179
- // DGF set xpathdebug = true (using getEval, if you like) to turn on JS XPath debugging
1180
- //xpathdebug = true;
1181
- var context;
1182
- if (contextNode == inDocument) {
1183
- context = new ExprContext(inDocument);
1184
- }
1185
- else {
1186
- // provide false values to get the default constructor values
1187
- context = new ExprContext(contextNode, false, false,
1188
- contextNode.parentNode);
1189
- }
1190
- context.setCaseInsensitive(true);
1191
- context.setIgnoreAttributesWithoutValue(ignoreAttributesWithoutValue);
1192
- context.setReturnOnFirstMatch(returnOnFirstMatch);
1193
- var xpathObj;
1194
- try {
1195
- xpathObj = xpathParse(xpath);
1196
- }
1197
- catch (e) {
1198
- throw new SeleniumError("Invalid xpath: " + extractExceptionMessage(e));
1199
- }
1200
- var xpathResult = xpathObj.evaluate(context);
1201
- if (xpathResult && xpathResult.value) {
1202
- for (var i = 0; i < xpathResult.value.length; ++i) {
1203
- results.push(xpathResult.value[i]);
1204
- }
1205
- }
1206
- return results;
1207
- }
1208
-
1209
- /**
1210
- * Returns the full resultset of a CSS selector evaluation.
1211
- */
1212
- function eval_css(locator, inDocument)
1213
- {
1214
- return cssQuery(locator, inDocument);
1215
- }
1216
-
1217
- /**
1218
- * This function duplicates part of BrowserBot.findElement() to open up locator
1219
- * evaluation on arbitrary documents. It returns a plain old array of located
1220
- * elements found by using a Selenium locator.
1221
- *
1222
- * Multiple results may be generated for xpath and CSS locators. Even though a
1223
- * list could potentially be generated for other locator types, such as link,
1224
- * we don't try for them, because they aren't very expressive location
1225
- * strategies; if you want a list, use xpath or CSS. Furthermore, strategies
1226
- * for these locators have been optimized to only return the first result. For
1227
- * these types of locators, performance is more important than ideal behavior.
1228
- *
1229
- * @param locator a locator string
1230
- * @param inDocument the document in which to apply the locator
1231
- * @param opt_contextNode the context within which to evaluate the locator
1232
- *
1233
- * @return a list of result elements
1234
- */
1235
- function eval_locator(locator, inDocument, opt_contextNode)
1236
- {
1237
- locator = parse_locator(locator);
1238
-
1239
- var pageBot;
1240
- if (typeof(selenium) != 'undefined' && selenium != undefined) {
1241
- if (typeof(editor) == 'undefined' || editor.state == 'playing') {
1242
- safe_log('info', 'Trying [' + locator.type + ']: '
1243
- + locator.string);
1244
- }
1245
- pageBot = selenium.browserbot;
1246
- }
1247
- else {
1248
- if (!UI_GLOBAL.mozillaBrowserBot) {
1249
- // create a browser bot to evaluate the locator. Hand it the IDE
1250
- // window as a dummy window, and cache it for future use.
1251
- UI_GLOBAL.mozillaBrowserBot = new MozillaBrowserBot(window)
1252
- }
1253
- pageBot = UI_GLOBAL.mozillaBrowserBot;
1254
- }
1255
-
1256
- var results = [];
1257
-
1258
- if (locator.type == 'xpath' || (locator.string.charAt(0) == '/' &&
1259
- locator.type == 'implicit')) {
1260
- results = eval_xpath(locator.string, inDocument,
1261
- { contextNode: opt_contextNode });
1262
- }
1263
- else if (locator.type == 'css') {
1264
- results = eval_css(locator.string, inDocument);
1265
- }
1266
- else {
1267
- var element = pageBot
1268
- .findElementBy(locator.type, locator.string, inDocument);
1269
- if (element != null) {
1270
- results.push(element);
1271
- }
1272
- }
1273
-
1274
- return results;
1275
- }
1276
-
1277
- //******************************************************************************
1278
- // UI-Element
1279
-
1280
- /**
1281
- * Escapes the special regular expression characters in a string intended to be
1282
- * used as a regular expression.
1283
- *
1284
- * Based on: http://simonwillison.net/2006/Jan/20/escape/
1285
- */
1286
- RegExp.escape = (function() {
1287
- var specials = [
1288
- '/', '.', '*', '+', '?', '|', '^', '$',
1289
- '(', ')', '[', ']', '{', '}', '\\'
1290
- ];
1291
-
1292
- var sRE = new RegExp(
1293
- '(\\' + specials.join('|\\') + ')', 'g'
1294
- );
1295
-
1296
- return function(text) {
1297
- return text.replace(sRE, '\\$1');
1298
- }
1299
- })();
1300
-
1301
- /**
1302
- * Returns true if two arrays are identical, and false otherwise.
1303
- *
1304
- * @param a1 the first array, may only contain simple values (strings or
1305
- * numbers)
1306
- * @param a2 the second array, same restricts on data as for a1
1307
- * @return true if the arrays are equivalent, false otherwise.
1308
- */
1309
- function are_equal(a1, a2)
1310
- {
1311
- if (typeof(a1) != typeof(a2))
1312
- return false;
1313
-
1314
- switch(typeof(a1)) {
1315
- case 'object':
1316
- // arrays
1317
- if (a1.length) {
1318
- if (a1.length != a2.length)
1319
- return false;
1320
- for (var i = 0; i < a1.length; ++i) {
1321
- if (!are_equal(a1[i], a2[i]))
1322
- return false
1323
- }
1324
- }
1325
- // associative arrays
1326
- else {
1327
- var keys = {};
1328
- for (var key in a1) {
1329
- keys[key] = true;
1330
- }
1331
- for (var key in a2) {
1332
- keys[key] = true;
1333
- }
1334
- for (var key in keys) {
1335
- if (!are_equal(a1[key], a2[key]))
1336
- return false;
1337
- }
1338
- }
1339
- return true;
1340
-
1341
- default:
1342
- return a1 == a2;
1343
- }
1344
- }
1345
-
1346
-
1347
- /**
1348
- * Create a clone of an object and return it. This is a deep copy of everything
1349
- * but functions, whose references are copied. You shouldn't expect a deep copy
1350
- * of functions anyway.
1351
- *
1352
- * @param orig the original object to copy
1353
- * @return a deep copy of the original object. Any functions attached,
1354
- * however, will have their references copied only.
1355
- */
1356
- function clone(orig) {
1357
- var copy;
1358
- switch(typeof(orig)) {
1359
- case 'object':
1360
- copy = (orig.length) ? [] : {};
1361
- for (var attr in orig) {
1362
- copy[attr] = clone(orig[attr]);
1363
- }
1364
- break;
1365
- default:
1366
- copy = orig;
1367
- break;
1368
- }
1369
- return copy;
1370
- }
1371
-
1372
- /**
1373
- * Emulates php's print_r() functionality. Returns a nicely formatted string
1374
- * representation of an object. Very useful for debugging.
1375
- *
1376
- * @param object the object to dump
1377
- * @param maxDepth the maximum depth to recurse into the object. Ellipses will
1378
- * be shown for objects whose depth exceeds the maximum.
1379
- * @param indent the string to use for indenting progressively deeper levels
1380
- * of the dump.
1381
- * @return a string representing a dump of the object
1382
- */
1383
- function print_r(object, maxDepth, indent)
1384
- {
1385
- var parentIndent, attr, str = "";
1386
- if (arguments.length == 1) {
1387
- var maxDepth = Number.MAX_VALUE;
1388
- } else {
1389
- maxDepth--;
1390
- }
1391
- if (arguments.length < 3) {
1392
- parentIndent = ''
1393
- var indent = ' ';
1394
- } else {
1395
- parentIndent = indent;
1396
- indent += ' ';
1397
- }
1398
-
1399
- switch(typeof(object)) {
1400
- case 'object':
1401
- if (object.length != undefined) {
1402
- if (object.length == 0) {
1403
- str += "Array ()\r\n";
1404
- }
1405
- else {
1406
- str += "Array (\r\n";
1407
- for (var i = 0; i < object.length; ++i) {
1408
- str += indent + '[' + i + '] => ';
1409
- if (maxDepth == 0)
1410
- str += "...\r\n";
1411
- else
1412
- str += print_r(object[i], maxDepth, indent);
1413
- }
1414
- str += parentIndent + ")\r\n";
1415
- }
1416
- }
1417
- else {
1418
- str += "Object (\r\n";
1419
- for (attr in object) {
1420
- str += indent + "[" + attr + "] => ";
1421
- if (maxDepth == 0)
1422
- str += "...\r\n";
1423
- else
1424
- str += print_r(object[attr], maxDepth, indent);
1425
- }
1426
- str += parentIndent + ")\r\n";
1427
- }
1428
- break;
1429
- case 'boolean':
1430
- str += (object ? 'true' : 'false') + "\r\n";
1431
- break;
1432
- case 'function':
1433
- str += "Function\r\n";
1434
- break;
1435
- default:
1436
- str += object + "\r\n";
1437
- break;
1438
-
1439
- }
1440
- return str;
1441
- }
1442
-
1443
- /**
1444
- * Return an array containing all properties of an object. Perl-style.
1445
- *
1446
- * @param object the object whose keys to return
1447
- * @return array of object keys, as strings
1448
- */
1449
- function keys(object)
1450
- {
1451
- var keys = [];
1452
- for (var k in object) {
1453
- keys.push(k);
1454
- }
1455
- return keys;
1456
- }
1457
-
1458
- /**
1459
- * Emulates python's range() built-in. Returns an array of integers, counting
1460
- * up (or down) from start to end. Note that the range returned is up to, but
1461
- * NOT INCLUDING, end.
1462
- *.
1463
- * @param start integer from which to start counting. If the end parameter is
1464
- * not provided, this value is considered the end and start will
1465
- * be zero.
1466
- * @param end integer to which to count. If omitted, the function will count
1467
- * up from zero to the value of the start parameter. Note that
1468
- * the array returned will count up to but will not include this
1469
- * value.
1470
- * @return an array of consecutive integers.
1471
- */
1472
- function range(start, end)
1473
- {
1474
- if (arguments.length == 1) {
1475
- var end = start;
1476
- start = 0;
1477
- }
1478
-
1479
- var r = [];
1480
- if (start < end) {
1481
- while (start != end)
1482
- r.push(start++);
1483
- }
1484
- else {
1485
- while (start != end)
1486
- r.push(start--);
1487
- }
1488
- return r;
1489
- }
1490
-
1491
- /**
1492
- * Parses a python-style keyword arguments string and returns the pairs in a
1493
- * new object.
1494
- *
1495
- * @param kwargs a string representing a set of keyword arguments. It should
1496
- * look like <tt>keyword1=value1, keyword2=value2, ...</tt>
1497
- * @return an object mapping strings to strings
1498
- */
1499
- function parse_kwargs(kwargs)
1500
- {
1501
- var args = new Object();
1502
- var pairs = kwargs.split(/,/);
1503
- for (var i = 0; i < pairs.length;) {
1504
- if (i > 0 && pairs[i].indexOf('=') == -1) {
1505
- // the value string contained a comma. Glue the parts back together.
1506
- pairs[i-1] += ',' + pairs.splice(i, 1)[0];
1507
- }
1508
- else {
1509
- ++i;
1510
- }
1511
- }
1512
- for (var i = 0; i < pairs.length; ++i) {
1513
- var splits = pairs[i].split(/=/);
1514
- if (splits.length == 1) {
1515
- continue;
1516
- }
1517
- var key = splits.shift();
1518
- var value = splits.join('=');
1519
- args[key.trim()] = value.trim();
1520
- }
1521
- return args;
1522
- }
1523
-
1524
- /**
1525
- * Creates a python-style keyword arguments string from an object.
1526
- *
1527
- * @param args an associative array mapping strings to strings
1528
- * @param sortedKeys (optional) a list of keys of the args parameter that
1529
- * specifies the order in which the arguments will appear in
1530
- * the returned kwargs string
1531
- *
1532
- * @return a kwarg string representation of args
1533
- */
1534
- function to_kwargs(args, sortedKeys)
1535
- {
1536
- var s = '';
1537
- if (!sortedKeys) {
1538
- var sortedKeys = keys(args).sort();
1539
- }
1540
- for (var i = 0; i < sortedKeys.length; ++i) {
1541
- var k = sortedKeys[i];
1542
- if (args[k] != undefined) {
1543
- if (s) {
1544
- s += ', ';
1545
- }
1546
- s += k + '=' + args[k];
1547
- }
1548
- }
1549
- return s;
1550
- }
1551
-
1552
- /**
1553
- * Returns true if a node is an ancestor node of a target node, and false
1554
- * otherwise.
1555
- *
1556
- * @param node the node being compared to the target node
1557
- * @param target the target node
1558
- * @return true if node is an ancestor node of target, false otherwise.
1559
- */
1560
- function is_ancestor(node, target)
1561
- {
1562
- while (target.parentNode) {
1563
- target = target.parentNode;
1564
- if (node == target)
1565
- return true;
1566
- }
1567
- return false;
1568
- }
1569
-
1570
- //******************************************************************************
1571
- // parseUri 1.2.1
1572
- // MIT License
1573
-
1574
- /*
1575
- Copyright (c) 2007 Steven Levithan <stevenlevithan.com>
1576
-
1577
- Permission is hereby granted, free of charge, to any person obtaining a copy
1578
- of this software and associated documentation files (the "Software"), to deal
1579
- in the Software without restriction, including without limitation the rights
1580
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1581
- copies of the Software, and to permit persons to whom the Software is
1582
- furnished to do so, subject to the following conditions:
1583
-
1584
- The above copyright notice and this permission notice shall be included in
1585
- all copies or substantial portions of the Software.
1586
- */
1587
-
1588
- function parseUri (str) {
1589
- var o = parseUri.options,
1590
- m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
1591
- uri = {},
1592
- i = 14;
1593
-
1594
- while (i--) uri[o.key[i]] = m[i] || "";
1595
-
1596
- uri[o.q.name] = {};
1597
- uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
1598
- if ($1) uri[o.q.name][$1] = $2;
1599
- });
1600
-
1601
- return uri;
1602
- };
1603
-
1604
- parseUri.options = {
1605
- strictMode: false,
1606
- key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
1607
- q: {
1608
- name: "queryKey",
1609
- parser: /(?:^|&)([^&=]*)=?([^&]*)/g
1610
- },
1611
- parser: {
1612
- strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
1613
- loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
1614
- }
1615
- };
1616
-