adva_cms 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (551) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/NOTES +132 -0
  6. data/README.md +29 -0
  7. data/Rakefile +2 -0
  8. data/adva_cms.gemspec +22 -0
  9. data/app/assets/images/adva_cms/admin/header_bg.png +0 -0
  10. data/app/assets/images/adva_cms/admin/section_menu_bg.png +0 -0
  11. data/app/assets/images/adva_cms/admin/tab_action_active.png +0 -0
  12. data/app/assets/images/adva_cms/admin/tab_main_active.png +0 -0
  13. data/app/assets/images/adva_cms/admin/tab_sidebar_active.png +0 -0
  14. data/app/assets/images/adva_cms/admin/tab_top_active.png +0 -0
  15. data/app/assets/images/adva_cms/asset_selected.png +0 -0
  16. data/app/assets/images/adva_cms/avatar.gif +0 -0
  17. data/app/assets/images/adva_cms/filter-bg.png +0 -0
  18. data/app/assets/images/adva_cms/icons/accept.png +0 -0
  19. data/app/assets/images/adva_cms/icons/add.png +0 -0
  20. data/app/assets/images/adva_cms/icons/arrow_cross.png +0 -0
  21. data/app/assets/images/adva_cms/icons/arrow_cross_2.png +0 -0
  22. data/app/assets/images/adva_cms/icons/arrow_cross_3.png +0 -0
  23. data/app/assets/images/adva_cms/icons/arrow_up_down.png +0 -0
  24. data/app/assets/images/adva_cms/icons/assets/audio.png +0 -0
  25. data/app/assets/images/adva_cms/icons/assets/doc.png +0 -0
  26. data/app/assets/images/adva_cms/icons/assets/pdf.png +0 -0
  27. data/app/assets/images/adva_cms/icons/assets/video.png +0 -0
  28. data/app/assets/images/adva_cms/icons/attach.png +0 -0
  29. data/app/assets/images/adva_cms/icons/bin.png +0 -0
  30. data/app/assets/images/adva_cms/icons/bin_closed.png +0 -0
  31. data/app/assets/images/adva_cms/icons/bin_empty.png +0 -0
  32. data/app/assets/images/adva_cms/icons/bullet_black.png +0 -0
  33. data/app/assets/images/adva_cms/icons/bullet_delete.png +0 -0
  34. data/app/assets/images/adva_cms/icons/bullet_error.png +0 -0
  35. data/app/assets/images/adva_cms/icons/bullet_go.png +0 -0
  36. data/app/assets/images/adva_cms/icons/bullet_red.png +0 -0
  37. data/app/assets/images/adva_cms/icons/bullet_white.png +0 -0
  38. data/app/assets/images/adva_cms/icons/bullet_yellow.png +0 -0
  39. data/app/assets/images/adva_cms/icons/cancel.png +0 -0
  40. data/app/assets/images/adva_cms/icons/comment.gif +0 -0
  41. data/app/assets/images/adva_cms/icons/comment.png +0 -0
  42. data/app/assets/images/adva_cms/icons/comment_add.png +0 -0
  43. data/app/assets/images/adva_cms/icons/comment_blue.gif +0 -0
  44. data/app/assets/images/adva_cms/icons/comment_delete.png +0 -0
  45. data/app/assets/images/adva_cms/icons/comment_edit.png +0 -0
  46. data/app/assets/images/adva_cms/icons/comment_yellow.gif +0 -0
  47. data/app/assets/images/adva_cms/icons/cross.png +0 -0
  48. data/app/assets/images/adva_cms/icons/delete.png +0 -0
  49. data/app/assets/images/adva_cms/icons/eye.png +0 -0
  50. data/app/assets/images/adva_cms/icons/favorites.png +0 -0
  51. data/app/assets/images/adva_cms/icons/help.png +0 -0
  52. data/app/assets/images/adva_cms/icons/hourglass.png +0 -0
  53. data/app/assets/images/adva_cms/icons/icon_attachment.gif +0 -0
  54. data/app/assets/images/adva_cms/icons/icon_padlock.gif +0 -0
  55. data/app/assets/images/adva_cms/icons/link.png +0 -0
  56. data/app/assets/images/adva_cms/icons/lock.png +0 -0
  57. data/app/assets/images/adva_cms/icons/magnifier.png +0 -0
  58. data/app/assets/images/adva_cms/icons/minus.gif +0 -0
  59. data/app/assets/images/adva_cms/icons/page_add.png +0 -0
  60. data/app/assets/images/adva_cms/icons/page_delete.png +0 -0
  61. data/app/assets/images/adva_cms/icons/page_edit.png +0 -0
  62. data/app/assets/images/adva_cms/icons/page_favorites.png +0 -0
  63. data/app/assets/images/adva_cms/icons/page_go.png +0 -0
  64. data/app/assets/images/adva_cms/icons/page_green.png +0 -0
  65. data/app/assets/images/adva_cms/icons/page_red.png +0 -0
  66. data/app/assets/images/adva_cms/icons/page_white_add.png +0 -0
  67. data/app/assets/images/adva_cms/icons/page_white_delete.png +0 -0
  68. data/app/assets/images/adva_cms/icons/page_white_edit.png +0 -0
  69. data/app/assets/images/adva_cms/icons/page_white_go.png +0 -0
  70. data/app/assets/images/adva_cms/icons/page_white_link.png +0 -0
  71. data/app/assets/images/adva_cms/icons/page_white_magnify.png +0 -0
  72. data/app/assets/images/adva_cms/icons/pencil.png +0 -0
  73. data/app/assets/images/adva_cms/icons/star.png +0 -0
  74. data/app/assets/images/adva_cms/icons/stop.png +0 -0
  75. data/app/assets/images/adva_cms/icons/tag_green.png +0 -0
  76. data/app/assets/images/adva_cms/icons/tick.png +0 -0
  77. data/app/assets/images/adva_cms/icons/zoom.png +0 -0
  78. data/app/assets/images/adva_cms/indicator.gif +0 -0
  79. data/app/assets/images/adva_cms/preview.png +0 -0
  80. data/app/assets/images/adva_cms/rails.png +0 -0
  81. data/app/assets/images/adva_cms/sortable_tree/drag.png +0 -0
  82. data/app/assets/images/adva_cms/theme_selected.png +0 -0
  83. data/app/assets/javascripts/admin.js +1 -0
  84. data/app/assets/javascripts/adva_cms/admin/jquery.admin.js +23 -0
  85. data/app/assets/javascripts/adva_cms/admin/jquery.article.js +22 -0
  86. data/app/assets/javascripts/adva_cms/admin/jquery.cached_pages.js +14 -0
  87. data/app/assets/javascripts/adva_cms/admin/jquery.table_tree.js +7 -0
  88. data/app/assets/javascripts/adva_cms/application.js +14 -0
  89. data/app/assets/javascripts/adva_cms/base.js +4 -0
  90. data/app/assets/javascripts/adva_cms/cookie.js +49 -0
  91. data/app/assets/javascripts/adva_cms/jquery.common.js +41 -0
  92. data/app/assets/javascripts/adva_cms/jquery.dates.js +51 -0
  93. data/app/assets/javascripts/adva_cms/jquery.flash.js +57 -0
  94. data/app/assets/javascripts/adva_cms/jquery.roles.js +25 -0
  95. data/app/assets/javascripts/adva_cms/jquery/jquery-lowpro.js +224 -0
  96. data/app/assets/javascripts/adva_cms/jquery/jquery.qtip.js +2085 -0
  97. data/app/assets/javascripts/adva_cms/jquery/jquery.table_tree.js +307 -0
  98. data/app/assets/javascripts/adva_cms/jquery/jquery.tablednd_0_5.js +386 -0
  99. data/app/assets/javascripts/adva_cms/json.js +139 -0
  100. data/app/assets/stylesheets/admin.css +1 -0
  101. data/app/assets/stylesheets/adva_cms/admin.css +16 -0
  102. data/app/assets/stylesheets/adva_cms/admin/alternate/common.css +76 -0
  103. data/app/assets/stylesheets/adva_cms/admin/alternate/forms.css +121 -0
  104. data/app/assets/stylesheets/adva_cms/admin/alternate/header.css +125 -0
  105. data/app/assets/stylesheets/adva_cms/admin/alternate/layout.css +103 -0
  106. data/app/assets/stylesheets/adva_cms/admin/alternate/lists.css +153 -0
  107. data/app/assets/stylesheets/adva_cms/admin/alternate/sidebar.css +65 -0
  108. data/app/assets/stylesheets/adva_cms/admin/alternate/top.css +123 -0
  109. data/app/assets/stylesheets/adva_cms/admin/common.css +76 -0
  110. data/app/assets/stylesheets/adva_cms/admin/content.css +11 -0
  111. data/app/assets/stylesheets/adva_cms/admin/forms.css +116 -0
  112. data/app/assets/stylesheets/adva_cms/admin/header.css +114 -0
  113. data/app/assets/stylesheets/adva_cms/admin/helptip.css +35 -0
  114. data/app/assets/stylesheets/adva_cms/admin/layout.css +56 -0
  115. data/app/assets/stylesheets/adva_cms/admin/lists.css +152 -0
  116. data/app/assets/stylesheets/adva_cms/admin/projection.css +118 -0
  117. data/app/assets/stylesheets/adva_cms/admin/reset.css +25 -0
  118. data/app/assets/stylesheets/adva_cms/admin/screen/top.css +8 -0
  119. data/app/assets/stylesheets/adva_cms/admin/sidebar.css +67 -0
  120. data/app/assets/stylesheets/adva_cms/admin/themes.css +49 -0
  121. data/app/assets/stylesheets/adva_cms/admin/top.css +83 -0
  122. data/app/assets/stylesheets/adva_cms/admin/users.css +40 -0
  123. data/app/assets/stylesheets/adva_cms/common.css +49 -0
  124. data/app/assets/stylesheets/adva_cms/default.css +201 -0
  125. data/app/assets/stylesheets/adva_cms/forms.css +60 -0
  126. data/app/assets/stylesheets/adva_cms/jquery/alternate/jquery.tooltip.css +13 -0
  127. data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  128. data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  129. data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  130. data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  131. data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  132. data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  133. data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  134. data/app/assets/stylesheets/adva_cms/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  135. data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_222222_256x240.png +0 -0
  136. data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_2e83ff_256x240.png +0 -0
  137. data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_454545_256x240.png +0 -0
  138. data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_888888_256x240.png +0 -0
  139. data/app/assets/stylesheets/adva_cms/jquery/images/ui-icons_cd0a0a_256x240.png +0 -0
  140. data/app/assets/stylesheets/adva_cms/jquery/jquery-ui.css +406 -0
  141. data/app/assets/stylesheets/adva_cms/jquery/jquery.tooltip.css +10 -0
  142. data/app/assets/stylesheets/adva_cms/layout/login.css +8 -0
  143. data/app/assets/stylesheets/adva_cms/layout/simple.css +8 -0
  144. data/app/assets/stylesheets/adva_cms/menu.css +129 -0
  145. data/app/assets/stylesheets/adva_cms/reset.css +25 -0
  146. data/app/controllers/admin/base_controller.rb +101 -0
  147. data/app/controllers/admin/categories_controller.rb +3 -0
  148. data/app/controllers/admin/install_controller.rb +61 -0
  149. data/app/controllers/admin/page/articles_controller.rb +150 -0
  150. data/app/controllers/admin/page/categories_controller.rb +62 -0
  151. data/app/controllers/admin/page/contents_controller.rb +52 -0
  152. data/app/controllers/admin/page/links_controller.rb +69 -0
  153. data/app/controllers/admin/pages_controller.rb +2 -0
  154. data/app/controllers/admin/plugins_controller.rb +40 -0
  155. data/app/controllers/admin/sections_controller.rb +91 -0
  156. data/app/controllers/admin/sites_controller.rb +99 -0
  157. data/app/controllers/articles_controller.rb +81 -0
  158. data/app/controllers/base_controller.rb +82 -0
  159. data/app/helpers/admin/base_helper.rb +106 -0
  160. data/app/helpers/base_helper.rb +56 -0
  161. data/app/helpers/content_helper.rb +90 -0
  162. data/app/helpers/resource_helper.rb +127 -0
  163. data/app/models/article.rb +40 -0
  164. data/app/models/categorization.rb +4 -0
  165. data/app/models/category.rb +60 -0
  166. data/app/models/content.rb +155 -0
  167. data/app/models/event.rb +34 -0
  168. data/app/models/link.rb +4 -0
  169. data/app/models/page.rb +36 -0
  170. data/app/models/section.rb +126 -0
  171. data/app/models/site.rb +104 -0
  172. data/app/views/admin/cached_pages/_filter.html.erb +8 -0
  173. data/app/views/admin/cached_pages/destroy.js.erb +18 -0
  174. data/app/views/admin/cached_pages/index.html.erb +26 -0
  175. data/app/views/admin/install/confirmation.html.erb +10 -0
  176. data/app/views/admin/install/index.html.erb +38 -0
  177. data/app/views/admin/page/articles/_form.html.erb +40 -0
  178. data/app/views/admin/page/articles/_options.html.erb +20 -0
  179. data/app/views/admin/page/articles/edit.html.erb +15 -0
  180. data/app/views/admin/page/articles/new.html.erb +12 -0
  181. data/app/views/admin/page/categories/edit.html.erb +22 -0
  182. data/app/views/admin/page/categories/index.html.erb +23 -0
  183. data/app/views/admin/page/categories/new.html.erb +19 -0
  184. data/app/views/admin/page/contents/index.html.erb +40 -0
  185. data/app/views/admin/page/links/_form.html.erb +26 -0
  186. data/app/views/admin/page/links/_options.html.erb +23 -0
  187. data/app/views/admin/page/links/edit.html.erb +12 -0
  188. data/app/views/admin/page/links/new.html.erb +12 -0
  189. data/app/views/admin/plugins/_form.html.erb +11 -0
  190. data/app/views/admin/plugins/index.html.erb +16 -0
  191. data/app/views/admin/plugins/show.html.erb +43 -0
  192. data/app/views/admin/sections/_form.html.haml +20 -0
  193. data/app/views/admin/sections/edit.html.haml +6 -0
  194. data/app/views/admin/sections/index.html.erb +27 -0
  195. data/app/views/admin/sections/new.html.erb +29 -0
  196. data/app/views/admin/sections/settings/_page.html.haml +10 -0
  197. data/app/views/admin/shared/_header.html.erb +18 -0
  198. data/app/views/admin/shared/_language_select.html.erb +6 -0
  199. data/app/views/admin/shared/_section.html.erb +8 -0
  200. data/app/views/admin/shared/_section_summary.html.erb +23 -0
  201. data/app/views/admin/shared/_section_tree.html.erb +23 -0
  202. data/app/views/admin/sites/_email_notifications.html.erb +9 -0
  203. data/app/views/admin/sites/_form.html.erb +15 -0
  204. data/app/views/admin/sites/_recent_users.html.erb +11 -0
  205. data/app/views/admin/sites/_sections.html.erb +10 -0
  206. data/app/views/admin/sites/_unapproved_comments.html.erb +10 -0
  207. data/app/views/admin/sites/edit.html.erb +4 -0
  208. data/app/views/admin/sites/index.html.erb +21 -0
  209. data/app/views/admin/sites/multi_sites_disabled.html.erb +11 -0
  210. data/app/views/admin/sites/new.html.erb +21 -0
  211. data/app/views/admin/sites/show.html.erb +16 -0
  212. data/app/views/categories/_checkboxes.html.erb +12 -0
  213. data/app/views/layouts/admin.html.haml +50 -0
  214. data/app/views/layouts/default.html.erb +38 -0
  215. data/app/views/layouts/simple.html.erb +22 -0
  216. data/app/views/pages/articles/index.html.erb +10 -0
  217. data/app/views/pages/articles/show.html.erb +17 -0
  218. data/app/views/shared/_flash.html.erb +3 -0
  219. data/app/views/shared/_footer.html.erb +4 -0
  220. data/app/views/shared/_menu.html.erb +10 -0
  221. data/app/views/shared/_sidebar.html.erb +19 -0
  222. data/app/views/shared/messages/insufficient_permissions.html.erb +4 -0
  223. data/config/environment.rb +21 -0
  224. data/config/initializers/has_options.rb +2 -0
  225. data/config/initializers/has_permalink.rb +27 -0
  226. data/config/initializers/mailer.rb +12 -0
  227. data/config/initializers/menus.rb +184 -0
  228. data/config/initializers/roles.rb +91 -0
  229. data/config/initializers/settings.rb +26 -0
  230. data/config/initializers/site.rb +5 -0
  231. data/config/initializers/translations_are_a_pain.rb +9 -0
  232. data/config/locales/en.yml +1295 -0
  233. data/config/routes.rb +47 -0
  234. data/db/migrate/20080401000001_create_sites_table.rb +28 -0
  235. data/db/migrate/20080401000002_create_sections_table.rb +25 -0
  236. data/db/migrate/20080401000003_create_contents_table.rb +35 -0
  237. data/db/migrate/20080401000004_create_categories_table.rb +17 -0
  238. data/db/migrate/20080401000005_create_category_assignments.rb +12 -0
  239. data/db/migrate/20080401000006_create_taggable_tables.rb +26 -0
  240. data/db/migrate/20080710000000_create_plugin_configs.rb +13 -0
  241. data/db/migrate/20080715131051_plugin_owner_column.rb +13 -0
  242. data/db/migrate/20081208161500_add_content_type_to_join_tables.rb +10 -0
  243. data/db/migrate/20090216114034_rename_category_assignment_to_categorization.rb +13 -0
  244. data/db/migrate/20090305123429_move_sections_to_pages.rb +9 -0
  245. data/db/migrate/20090519132700_add_published_at_to_sections.rb +10 -0
  246. data/db/migrate/20090702085459_create_section_translations.rb +9 -0
  247. data/db/migrate/20090702200226_create_category_translations.rb +9 -0
  248. data/db/migrate/20090707171100_upgrade_paperclip_paths.rb +31 -0
  249. data/db/migrate/20090709111934_add_email_notification_to_site.rb +12 -0
  250. data/db/migrate/20091026000906_add_nesting_to_articles.rb +26 -0
  251. data/db/migrate/20140721000000_add_title_to_contents.rb +7 -0
  252. data/lib/adva_cms.rb +50 -0
  253. data/lib/adva_cms/version.rb +3 -0
  254. data/lib/core_ext.rb +7 -0
  255. data/lib/extensible_forms.rb +283 -0
  256. data/lib/has_options.rb +46 -0
  257. data/lib/html_diff.rb +48 -0
  258. data/lib/rails_ext.rb +15 -0
  259. data/lib/rails_ext/action_controller/cacheable_flash.rb +30 -0
  260. data/lib/rails_ext/action_controller/content_for_assignments.rb +105 -0
  261. data/lib/rails_ext/action_controller/default_params.rb +19 -0
  262. data/lib/rails_ext/action_controller/event_helper.rb +18 -0
  263. data/lib/rails_ext/action_controller/page_caching.rb +23 -0
  264. data/lib/rails_ext/action_controller/render_with_error_proc.rb +46 -0
  265. data/lib/rails_ext/action_controller/responds_to_parent.rb +46 -0
  266. data/lib/rails_ext/action_controller/url_for_returning.rb +12 -0
  267. data/lib/rails_ext/active_record/exists.rb +5 -0
  268. data/lib/rails_ext/active_record/sti_instantiation.rb +35 -0
  269. data/lib/rails_ext/active_record/sticky_changes.rb +30 -0
  270. data/lib/rails_ext/railties/plugin.rb +58 -0
  271. data/lib/rails_ext/railties/plugin_configuration.rb +72 -0
  272. data/lib/rails_ext/railties/plugin_initializers.rb +25 -0
  273. data/lib/registry.rb +49 -0
  274. data/lib/tasks/adva_cms.rake +178 -0
  275. data/lib/tasks/translation.rake +69 -0
  276. data/lib/time_hacks.rb +57 -0
  277. data/lib/webrat_patch.rb +11 -0
  278. data/locale/rails/fr.yml +123 -0
  279. data/test/NOTES +56 -0
  280. data/test/contexts.rb +365 -0
  281. data/test/fixtures.rb +190 -0
  282. data/test/fixtures/templates/alternative_templates/index.html.erb +1 -0
  283. data/test/fixtures/templates/context_templates_test/index.html.erb +1 -0
  284. data/test/fixtures/templates/context_templates_test/show.html.erb +0 -0
  285. data/test/fixtures/templates/layouts/alternative.html.erb +0 -0
  286. data/test/fixtures/templates/layouts/default.html.erb +0 -0
  287. data/test/fixtures/templates/menu/shared/_menu.html.erb +8 -0
  288. data/test/functional/admin/articles_controller_test.rb +329 -0
  289. data/test/functional/admin/base_controller_test.rb +68 -0
  290. data/test/functional/admin/cached_pages_controller_test.rb +66 -0
  291. data/test/functional/admin/categories_controller_test.rb +164 -0
  292. data/test/functional/admin/cells_controller_spec.rb +32 -0
  293. data/test/functional/admin/install_controller_test.rb +89 -0
  294. data/test/functional/admin/plugins_controller_test.rb +93 -0
  295. data/test/functional/admin/sections_controller_test.rb +201 -0
  296. data/test/functional/admin/sites_controller_test.rb +240 -0
  297. data/test/functional/asset_tag_expansions_test.rb +82 -0
  298. data/test/functional/base_controller_test.rb +73 -0
  299. data/test/functional/page_articles_controller_test.rb +168 -0
  300. data/test/functional/page_articles_routes_test.rb +73 -0
  301. data/test/integration/admin/cached_pages_test.rb +43 -0
  302. data/test/integration/admin/categories_test.rb +66 -0
  303. data/test/integration/admin/custom_templates_test.rb +42 -0
  304. data/test/integration/admin/filtering_articles_test.rb +32 -0
  305. data/test/integration/admin/plugins.rb +32 -0
  306. data/test/integration/admin/section_article_test.rb +150 -0
  307. data/test/integration/admin/section_test.rb +88 -0
  308. data/test/integration/admin/sites_test.rb +48 -0
  309. data/test/integration/installation_test.rb +109 -0
  310. data/test/integration/page_article_comment_test.rb +51 -0
  311. data/test/integration/page_article_test.rb +87 -0
  312. data/test/integration/section_index_test.rb +37 -0
  313. data/test/javascript/assets/jquery-lowpro.js +224 -0
  314. data/test/javascript/assets/jquery-ui.js +298 -0
  315. data/test/javascript/assets/jquery.js +4376 -0
  316. data/test/javascript/assets/testrunner.js +815 -0
  317. data/test/javascript/assets/testsuite.css +120 -0
  318. data/test/javascript/lib/jstest.rb +588 -0
  319. data/test/javascript/templates/test_case.erb +33 -0
  320. data/test/plugins/adva_context_templates/context_templates_test.rb +138 -0
  321. data/test/plugins/adva_post_ping/controller/integration_test.rb +78 -0
  322. data/test/plugins/adva_post_ping/post_ping_test.rb +94 -0
  323. data/test/plugins/adva_url_history/article_test.rb +94 -0
  324. data/test/plugins/adva_url_history/init_url_history.rb +18 -0
  325. data/test/plugins/adva_url_history/section_test.rb +49 -0
  326. data/test/test_helper.rb +75 -0
  327. data/test/test_helper/clear_directories.rb +16 -0
  328. data/test/test_helper/ensure_single_site_mode.rb +10 -0
  329. data/test/test_helper/extensions/cacheable_flash.rb +14 -0
  330. data/test/test_helper/extensions/cronjob.rb +11 -0
  331. data/test/test_helper/extensions/even_test_log.rb +21 -0
  332. data/test/test_helper/extensions/integration_test.rb +78 -0
  333. data/test/test_helper/extensions/matchy.rb +365 -0
  334. data/test/test_helper/extensions/matchy_adva_cms.rb +441 -0
  335. data/test/test_helper/extensions/rails_patch.rb +40 -0
  336. data/test/test_helper/extensions/rr.rb +7 -0
  337. data/test/test_helper/extensions/test_unit.rb +35 -0
  338. data/test/test_helper/extensions/with_sugar.rb +166 -0
  339. data/test/test_helper/parse_options.rb +18 -0
  340. data/test/test_helper/setup_db_transaction.rb +15 -0
  341. data/test/test_helper/setup_webrat.rb +9 -0
  342. data/test/test_helper/test_server/init.rb +15 -0
  343. data/test/unit/helpers/admin/base_helper_test.rb +139 -0
  344. data/test/unit/helpers/base_helper_spec.rb +54 -0
  345. data/test/unit/helpers/base_helper_test.rb +165 -0
  346. data/test/unit/helpers/content_helper_test.rb +127 -0
  347. data/test/unit/helpers/resource_helper_test.rb +180 -0
  348. data/test/unit/i18n_test.rb +22 -0
  349. data/test/unit/lib/cells_ext_spec.rb +96 -0
  350. data/test/unit/lib/extensible_forms_test.rb +362 -0
  351. data/test/unit/lib/menu_test.rb +119 -0
  352. data/test/unit/lib/rails_ext/content_for_assignments_test.rb +75 -0
  353. data/test/unit/lib/rails_ext/plugin_configuration_test.rb +40 -0
  354. data/test/unit/lib/rails_ext/sticky_changes_test.rb +33 -0
  355. data/test/unit/lib/registry_test.rb +91 -0
  356. data/test/unit/lib/routing_filter/routing_filter_categories_spec.rb +63 -0
  357. data/test/unit/lib/routing_filter/routing_filter_categories_test.rb +159 -0
  358. data/test/unit/lib/routing_filter/routing_filter_locale_spec.rb +73 -0
  359. data/test/unit/lib/routing_filter/routing_filter_root_blog_archive_spec.rb +40 -0
  360. data/test/unit/lib/routing_filter/routing_filter_root_section_articles_spec.rb +48 -0
  361. data/test/unit/lib/routing_filter/routing_filter_root_wikipages_spec.rb +40 -0
  362. data/test/unit/lib/routing_filter/routing_filter_sections_spec.rb +143 -0
  363. data/test/unit/lib/routing_filter/routing_filter_sections_test.rb +32 -0
  364. data/test/unit/lib/routing_filter/routing_filter_sets_test.rb +86 -0
  365. data/test/unit/models/article_test.rb +191 -0
  366. data/test/unit/models/category_test.rb +68 -0
  367. data/test/unit/models/content_test.rb +409 -0
  368. data/test/unit/models/counter_test.rb +43 -0
  369. data/test/unit/models/event_test.rb +41 -0
  370. data/test/unit/models/nested_categories_test.rb +34 -0
  371. data/test/unit/models/page_test.rb +63 -0
  372. data/test/unit/models/section_test.rb +315 -0
  373. data/test/unit/models/site_test.rb +199 -0
  374. data/test/unit/observers/activities_article_observer_test.rb +42 -0
  375. data/vendor/gems/belongs_to_cacheable/.gitignore +17 -0
  376. data/vendor/gems/belongs_to_cacheable/Gemfile +4 -0
  377. data/vendor/gems/belongs_to_cacheable/LICENSE +22 -0
  378. data/vendor/gems/belongs_to_cacheable/README.md +29 -0
  379. data/vendor/gems/belongs_to_cacheable/Rakefile +2 -0
  380. data/vendor/gems/belongs_to_cacheable/belongs_to_cacheable.gemspec +22 -0
  381. data/vendor/gems/belongs_to_cacheable/init.rb +1 -0
  382. data/vendor/gems/belongs_to_cacheable/lib/active_record/belongs_to_cacheable.rb +77 -0
  383. data/vendor/gems/belongs_to_cacheable/lib/belongs_to_cacheable.rb +3 -0
  384. data/vendor/gems/belongs_to_cacheable/lib/belongs_to_cacheable/version.rb +3 -0
  385. data/vendor/gems/belongs_to_cacheable/spec/belongs_to_cacheable_spec.rb +52 -0
  386. data/vendor/gems/belongs_to_cacheable/spec/spec_helper.rb +50 -0
  387. data/vendor/gems/filtered_column/.gitignore +17 -0
  388. data/vendor/gems/filtered_column/Gemfile +4 -0
  389. data/vendor/gems/filtered_column/LICENSE +22 -0
  390. data/vendor/gems/filtered_column/README +4 -0
  391. data/vendor/gems/filtered_column/README.md +29 -0
  392. data/vendor/gems/filtered_column/Rakefile +23 -0
  393. data/vendor/gems/filtered_column/filtered_column.gemspec +17 -0
  394. data/vendor/gems/filtered_column/lib/filtered_column.rb +17 -0
  395. data/vendor/gems/filtered_column/lib/filtered_column/filters/base.rb +28 -0
  396. data/vendor/gems/filtered_column/lib/filtered_column/filters/smartypants_filter.rb +14 -0
  397. data/vendor/gems/filtered_column/lib/filtered_column/filters/textile_filter.rb +13 -0
  398. data/vendor/gems/filtered_column/lib/filtered_column/macros/base.rb +25 -0
  399. data/vendor/gems/filtered_column/lib/filtered_column/mixin.rb +46 -0
  400. data/vendor/gems/filtered_column/lib/filtered_column/processor.rb +52 -0
  401. data/vendor/gems/filtered_column/lib/filtered_column/version.rb +3 -0
  402. data/vendor/gems/filtered_column/tasks/filtered_column_tasks.rake +4 -0
  403. data/vendor/gems/filtered_column/test/abstract_unit.rb +73 -0
  404. data/vendor/gems/filtered_column/test/filtered_column_test.rb +53 -0
  405. data/vendor/gems/filtered_column/test/macro_filter_test.rb +23 -0
  406. data/vendor/gems/has_counter/.gitignore +17 -0
  407. data/vendor/gems/has_counter/Gemfile +4 -0
  408. data/vendor/gems/has_counter/LICENSE +22 -0
  409. data/vendor/gems/has_counter/MIT-LICENSE +20 -0
  410. data/vendor/gems/has_counter/README.markdown +64 -0
  411. data/vendor/gems/has_counter/README.md +29 -0
  412. data/vendor/gems/has_counter/Rakefile +2 -0
  413. data/vendor/gems/has_counter/db/migrate/20080601194338_create_counters_table.rb.rb +13 -0
  414. data/vendor/gems/has_counter/has_counter.gemspec +17 -0
  415. data/vendor/gems/has_counter/lib/active_record/has_counter.rb +64 -0
  416. data/vendor/gems/has_counter/lib/counter.rb +23 -0
  417. data/vendor/gems/has_counter/lib/has_counter.rb +4 -0
  418. data/vendor/gems/has_counter/lib/has_counter/version.rb +3 -0
  419. data/vendor/gems/has_counter/spec/has_counter.spec.log +0 -0
  420. data/vendor/gems/has_counter/spec/has_counter.sqlite3.db +0 -0
  421. data/vendor/gems/has_counter/spec/has_counter_spec.rb +55 -0
  422. data/vendor/gems/has_counter/spec/spec_helper.rb +117 -0
  423. data/vendor/gems/has_filter/.gitignore +17 -0
  424. data/vendor/gems/has_filter/Gemfile +4 -0
  425. data/vendor/gems/has_filter/LICENSE +22 -0
  426. data/vendor/gems/has_filter/README.md +29 -0
  427. data/vendor/gems/has_filter/Rakefile +2 -0
  428. data/vendor/gems/has_filter/app/assets/images/has_filter/filter_add.png +0 -0
  429. data/vendor/gems/has_filter/app/assets/images/has_filter/filter_button_left.png +0 -0
  430. data/vendor/gems/has_filter/app/assets/images/has_filter/filter_button_right.png +0 -0
  431. data/vendor/gems/has_filter/app/assets/images/has_filter/filter_remove.png +0 -0
  432. data/vendor/gems/has_filter/app/assets/javascripts/has_filter/filter.js +35 -0
  433. data/vendor/gems/has_filter/app/assets/javascripts/has_filter/jquery.filter.js +23 -0
  434. data/vendor/gems/has_filter/app/assets/stylesheets/has_filter/alternate/filter.css +102 -0
  435. data/vendor/gems/has_filter/app/assets/stylesheets/has_filter/filter.css +100 -0
  436. data/vendor/gems/has_filter/app/helpers/filter_helper.rb +3 -0
  437. data/vendor/gems/has_filter/has_filter.gemspec +17 -0
  438. data/vendor/gems/has_filter/init.rb +3 -0
  439. data/vendor/gems/has_filter/lib/has_filter.rb +22 -0
  440. data/vendor/gems/has_filter/lib/has_filter/active_record/act_macro.rb +102 -0
  441. data/vendor/gems/has_filter/lib/has_filter/filter.rb +17 -0
  442. data/vendor/gems/has_filter/lib/has_filter/filter/base.rb +67 -0
  443. data/vendor/gems/has_filter/lib/has_filter/filter/categorized.rb +24 -0
  444. data/vendor/gems/has_filter/lib/has_filter/filter/chain.rb +45 -0
  445. data/vendor/gems/has_filter/lib/has_filter/filter/set.rb +80 -0
  446. data/vendor/gems/has_filter/lib/has_filter/filter/state.rb +25 -0
  447. data/vendor/gems/has_filter/lib/has_filter/filter/tagged.rb +22 -0
  448. data/vendor/gems/has_filter/lib/has_filter/filter/text.rb +55 -0
  449. data/vendor/gems/has_filter/lib/has_filter/version.rb +3 -0
  450. data/vendor/gems/has_filter/test/db/setup.rb +45 -0
  451. data/vendor/gems/has_filter/test/db/test.sqlite3.db +0 -0
  452. data/vendor/gems/has_filter/test/fixtures.rb +15 -0
  453. data/vendor/gems/has_filter/test/has_filter/filter_chain_test.rb +41 -0
  454. data/vendor/gems/has_filter/test/has_filter/filter_scopes_test.rb +102 -0
  455. data/vendor/gems/has_filter/test/has_filter/filter_tags_test.rb +113 -0
  456. data/vendor/gems/has_filter/test/has_filter/integration.rb +15 -0
  457. data/vendor/gems/has_filter/test/has_filter/scopes_test.rb +48 -0
  458. data/vendor/gems/has_filter/test/log/test.log +34346 -0
  459. data/vendor/gems/has_filter/test/models.rb +23 -0
  460. data/vendor/gems/has_filter/test/templates/has_filter/test/index.html.erb +5 -0
  461. data/vendor/gems/has_filter/test/test_helper.rb +66 -0
  462. data/vendor/gems/simple_taggable/.gitignore +17 -0
  463. data/vendor/gems/simple_taggable/Gemfile +4 -0
  464. data/vendor/gems/simple_taggable/LICENSE +22 -0
  465. data/vendor/gems/simple_taggable/README +24 -0
  466. data/vendor/gems/simple_taggable/README.md +29 -0
  467. data/vendor/gems/simple_taggable/Rakefile +2 -0
  468. data/vendor/gems/simple_taggable/lib/simple_taggable.rb +153 -0
  469. data/vendor/gems/simple_taggable/lib/simple_taggable/version.rb +3 -0
  470. data/vendor/gems/simple_taggable/lib/tag.rb +31 -0
  471. data/vendor/gems/simple_taggable/lib/tag_list.rb +90 -0
  472. data/vendor/gems/simple_taggable/lib/tagging.rb +8 -0
  473. data/vendor/gems/simple_taggable/simple_taggable.gemspec +17 -0
  474. data/vendor/gems/simple_taggable/test/db/schema.rb +41 -0
  475. data/vendor/gems/simple_taggable/test/db/simple_taggable.sqlite3.db +0 -0
  476. data/vendor/gems/simple_taggable/test/fixtures/magazine.rb +3 -0
  477. data/vendor/gems/simple_taggable/test/fixtures/magazines.yml +2 -0
  478. data/vendor/gems/simple_taggable/test/fixtures/photo.rb +8 -0
  479. data/vendor/gems/simple_taggable/test/fixtures/photos.yml +19 -0
  480. data/vendor/gems/simple_taggable/test/fixtures/post.rb +5 -0
  481. data/vendor/gems/simple_taggable/test/fixtures/posts.yml +27 -0
  482. data/vendor/gems/simple_taggable/test/fixtures/subscription.rb +4 -0
  483. data/vendor/gems/simple_taggable/test/fixtures/subscriptions.yml +3 -0
  484. data/vendor/gems/simple_taggable/test/fixtures/taggings.yml +112 -0
  485. data/vendor/gems/simple_taggable/test/fixtures/tags.yml +14 -0
  486. data/vendor/gems/simple_taggable/test/fixtures/user.rb +6 -0
  487. data/vendor/gems/simple_taggable/test/fixtures/users.yml +5 -0
  488. data/vendor/gems/simple_taggable/test/log/simple_taggable.log +1614 -0
  489. data/vendor/gems/simple_taggable/test/simple_taggable_test.rb +226 -0
  490. data/vendor/gems/simple_taggable/test/tag_list_test.rb +105 -0
  491. data/vendor/gems/simple_taggable/test/test_helper.rb +80 -0
  492. data/vendor/gems/table_builder/.gitignore +17 -0
  493. data/vendor/gems/table_builder/Gemfile +4 -0
  494. data/vendor/gems/table_builder/LICENSE +22 -0
  495. data/vendor/gems/table_builder/README.md +29 -0
  496. data/vendor/gems/table_builder/Rakefile +2 -0
  497. data/vendor/gems/table_builder/lib/table_builder.rb +27 -0
  498. data/vendor/gems/table_builder/lib/table_builder/body.rb +28 -0
  499. data/vendor/gems/table_builder/lib/table_builder/cell.rb +21 -0
  500. data/vendor/gems/table_builder/lib/table_builder/column.rb +26 -0
  501. data/vendor/gems/table_builder/lib/table_builder/foot.rb +6 -0
  502. data/vendor/gems/table_builder/lib/table_builder/head.rb +16 -0
  503. data/vendor/gems/table_builder/lib/table_builder/row.rb +40 -0
  504. data/vendor/gems/table_builder/lib/table_builder/rows.rb +26 -0
  505. data/vendor/gems/table_builder/lib/table_builder/table.rb +75 -0
  506. data/vendor/gems/table_builder/lib/table_builder/tag.rb +58 -0
  507. data/vendor/gems/table_builder/lib/table_builder/version.rb +3 -0
  508. data/vendor/gems/table_builder/table_builder.gemspec +17 -0
  509. data/vendor/gems/table_builder/test/fixtures/templates/table_all.html.erb +20 -0
  510. data/vendor/gems/table_builder/test/fixtures/templates/table_auto_body.html.erb +3 -0
  511. data/vendor/gems/table_builder/test/fixtures/templates/table_auto_columns.html.erb +1 -0
  512. data/vendor/gems/table_builder/test/fixtures/templates/table_simple.html.erb +7 -0
  513. data/vendor/gems/table_builder/test/table_builder/table_test.rb +230 -0
  514. data/vendor/gems/table_builder/test/test_helper.rb +49 -0
  515. data/vendor/gems/tags/.gitignore +17 -0
  516. data/vendor/gems/tags/Gemfile +4 -0
  517. data/vendor/gems/tags/LICENSE +22 -0
  518. data/vendor/gems/tags/README.md +29 -0
  519. data/vendor/gems/tags/Rakefile +2 -0
  520. data/vendor/gems/tags/lib/breadcrumbs.rb +13 -0
  521. data/vendor/gems/tags/lib/menu.rb +179 -0
  522. data/vendor/gems/tags/lib/menu/builder.rb +74 -0
  523. data/vendor/gems/tags/lib/tags.rb +7 -0
  524. data/vendor/gems/tags/lib/tags/tag.rb +125 -0
  525. data/vendor/gems/tags/lib/tags/version.rb +3 -0
  526. data/vendor/gems/tags/tags.gemspec +17 -0
  527. data/vendor/gems/tags/test/tags/menu_test.rb +173 -0
  528. data/vendor/gems/tags/test/tags/tag_test.rb +13 -0
  529. data/vendor/gems/tags/test/test_helper.rb +18 -0
  530. data/vendor/gems/xss_terminate/.gitignore +17 -0
  531. data/vendor/gems/xss_terminate/Gemfile +4 -0
  532. data/vendor/gems/xss_terminate/LICENSE +22 -0
  533. data/vendor/gems/xss_terminate/MIT-LICENSE +20 -0
  534. data/vendor/gems/xss_terminate/README +94 -0
  535. data/vendor/gems/xss_terminate/README.md +29 -0
  536. data/vendor/gems/xss_terminate/Rakefile +23 -0
  537. data/vendor/gems/xss_terminate/lib/html5lib_sanitize.rb +2453 -0
  538. data/vendor/gems/xss_terminate/lib/rails_sanitize.rb +8 -0
  539. data/vendor/gems/xss_terminate/lib/xss_terminate.rb +141 -0
  540. data/vendor/gems/xss_terminate/lib/xss_terminate/version.rb +3 -0
  541. data/vendor/gems/xss_terminate/tasks/xss_terminate_tasks.rake +7 -0
  542. data/vendor/gems/xss_terminate/test/models/comment.rb +5 -0
  543. data/vendor/gems/xss_terminate/test/models/entry.rb +7 -0
  544. data/vendor/gems/xss_terminate/test/models/message.rb +3 -0
  545. data/vendor/gems/xss_terminate/test/models/person.rb +5 -0
  546. data/vendor/gems/xss_terminate/test/models/review.rb +5 -0
  547. data/vendor/gems/xss_terminate/test/schema.rb +34 -0
  548. data/vendor/gems/xss_terminate/test/setup_test.rb +16 -0
  549. data/vendor/gems/xss_terminate/test/xss_terminate_test.rb +50 -0
  550. data/vendor/gems/xss_terminate/xss_terminate.gemspec +17 -0
  551. metadata +744 -0
@@ -0,0 +1,2085 @@
1
+ /*!
2
+ * jquery.qtip. The jQuery tooltip plugin
3
+ *
4
+ * Copyright (c) 2009 Craig Thompson
5
+ * http://craigsworks.com
6
+ *
7
+ * Licensed under MIT
8
+ * http://www.opensource.org/licenses/mit-license.php
9
+ *
10
+ * Launch : February 2009
11
+ * Version : 1.0.0-rc3
12
+ * Released: Tuesday 12th May, 2009 - 00:00
13
+ * Debug: jquery.qtip.debug.js
14
+ */
15
+ (function($)
16
+ {
17
+ // Implementation
18
+ $.fn.qtip = function(options, blanket)
19
+ {
20
+ var i, id, interfaces, opts, obj, command, config, api;
21
+
22
+ // Return API / Interfaces if requested
23
+ if(typeof options == 'string')
24
+ {
25
+ // Make sure API data exists if requested
26
+ if(typeof $(this).data('qtip') !== 'object')
27
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.NO_TOOLTIP_PRESENT, false);
28
+
29
+ // Return requested object
30
+ if(options == 'api')
31
+ return $(this).data('qtip').interfaces[ $(this).data('qtip').current ];
32
+ else if(options == 'interfaces')
33
+ return $(this).data('qtip').interfaces;
34
+ }
35
+
36
+ // Validate provided options
37
+ else
38
+ {
39
+ // Set null options object if no options are provided
40
+ if(!options) options = {};
41
+
42
+ // Sanitize option data
43
+ if(typeof options.content !== 'object' || (options.content.jquery && options.content.length > 0)) options.content = { text: options.content };
44
+ if(typeof options.content.title !== 'object') options.content.title = { text: options.content.title };
45
+ if(typeof options.position !== 'object') options.position = { corner: options.position };
46
+ if(typeof options.position.corner !== 'object') options.position.corner = { target: options.position.corner, tooltip: options.position.corner };
47
+ if(typeof options.show !== 'object') options.show = { when: options.show };
48
+ if(typeof options.show.when !== 'object') options.show.when = { event: options.show.when };
49
+ if(typeof options.show.effect !== 'object') options.show.effect = { type: options.show.effect };
50
+ if(typeof options.hide !== 'object') options.hide = { when: options.hide };
51
+ if(typeof options.hide.when !== 'object') options.hide.when = { event: options.hide.when };
52
+ if(typeof options.hide.effect !== 'object') options.hide.effect = { type: options.hide.effect };
53
+ if(typeof options.style !== 'object') options.style = { name: options.style };
54
+ options.style = sanitizeStyle(options.style);
55
+
56
+ // Build main options object
57
+ opts = $.extend(true, {}, $.fn.qtip.defaults, options);
58
+
59
+ // Inherit all style properties into one syle object and include original options
60
+ opts.style = buildStyle.call({ options: opts }, opts.style);
61
+ opts.user = $.extend(true, {}, options);
62
+ };
63
+
64
+ // Iterate each matched element
65
+ return $(this).each(function() // Return original elements as per jQuery guidelines
66
+ {
67
+ // Check for API commands
68
+ if(typeof options == 'string')
69
+ {
70
+ command = options.toLowerCase();
71
+ interfaces = $(this).qtip('interfaces');
72
+
73
+ // Make sure API data exists$('.qtip').qtip('destroy')
74
+ if(typeof interfaces == 'object')
75
+ {
76
+ // Check if API call is a BLANKET DESTROY command
77
+ if(blanket === true && command == 'destroy')
78
+ while(interfaces.length > 0) interfaces[interfaces.length-1].destroy();
79
+
80
+ // API call is not a BLANKET DESTROY command
81
+ else
82
+ {
83
+ // Check if supplied command effects this tooltip only (NOT BLANKET)
84
+ if(blanket !== true) interfaces = [ $(this).qtip('api') ];
85
+
86
+ // Execute command on chosen qTips
87
+ for(i = 0; i < interfaces.length; i++)
88
+ {
89
+ // Destroy command doesn't require tooltip to be rendered
90
+ if(command == 'destroy') interfaces[i].destroy();
91
+
92
+ // Only call API if tooltip is rendered and it wasn't a destroy call
93
+ else if(interfaces[i].status.rendered === true)
94
+ {
95
+ if(command == 'show') interfaces[i].show();
96
+ else if(command == 'hide') interfaces[i].hide();
97
+ else if(command == 'focus') interfaces[i].focus();
98
+ else if(command == 'disable') interfaces[i].disable(true);
99
+ else if(command == 'enable') interfaces[i].disable(false);
100
+ };
101
+ };
102
+ };
103
+ };
104
+ }
105
+
106
+ // No API commands, continue with qTip creation
107
+ else
108
+ {
109
+ // Create unique configuration object
110
+ config = $.extend(true, {}, opts);
111
+ config.hide.effect.length = opts.hide.effect.length;
112
+ config.show.effect.length = opts.show.effect.length;
113
+
114
+ // Sanitize target options
115
+ if(config.position.container === false) config.position.container = $(document.body);
116
+ if(config.position.target === false) config.position.target = $(this);
117
+ if(config.show.when.target === false) config.show.when.target = $(this);
118
+ if(config.hide.when.target === false) config.hide.when.target = $(this);
119
+
120
+ // Determine tooltip ID (Reuse array slots if possible)
121
+ id = $.fn.qtip.interfaces.length;
122
+ for(i = 0; i < id; i++)
123
+ {
124
+ if(typeof $.fn.qtip.interfaces[i] == 'undefined'){ id = i; break; };
125
+ };
126
+
127
+ // Instantiate the tooltip
128
+ obj = new qTip($(this), config, id);
129
+
130
+ // Add API references
131
+ $.fn.qtip.interfaces[id] = obj;
132
+
133
+ // Check if element already has qTip data assigned
134
+ if(typeof $(this).data('qtip') == 'object')
135
+ {
136
+ // Set new current interface id
137
+ if(typeof $(this).attr('qtip') === 'undefined')
138
+ $(this).data('qtip').current = $(this).data('qtip').interfaces.length;
139
+
140
+ // Push new API interface onto interfaces array
141
+ $(this).data('qtip').interfaces.push(obj);
142
+ }
143
+
144
+ // No qTip data is present, create now
145
+ else $(this).data('qtip', { current: 0, interfaces: [obj] });
146
+
147
+ // If prerendering is disabled, create tooltip on showEvent
148
+ if(config.content.prerender === false && config.show.when.event !== false && config.show.ready !== true)
149
+ {
150
+ config.show.when.target.bind(config.show.when.event+'.qtip-'+id+'-create', { qtip: id }, function(event)
151
+ {
152
+ // Retrieve API interface via passed qTip Id
153
+ api = $.fn.qtip.interfaces[ event.data.qtip ];
154
+
155
+ // Unbind show event and cache mouse coords
156
+ api.options.show.when.target.unbind(api.options.show.when.event+'.qtip-'+event.data.qtip+'-create');
157
+ api.cache.mouse = { x: event.pageX, y: event.pageY };
158
+
159
+ // Render tooltip and start the event sequence
160
+ construct.call( api );
161
+ api.options.show.when.target.trigger(api.options.show.when.event);
162
+ });
163
+ }
164
+
165
+ // Prerendering is enabled, create tooltip now
166
+ else
167
+ {
168
+ // Set mouse position cache to top left of the element
169
+ obj.cache.mouse = {
170
+ x: config.show.when.target.offset().left,
171
+ y: config.show.when.target.offset().top
172
+ };
173
+
174
+ // Construct the tooltip
175
+ construct.call(obj);
176
+ }
177
+ };
178
+ });
179
+ };
180
+
181
+ // Instantiator
182
+ function qTip(target, options, id)
183
+ {
184
+ // Declare this reference
185
+ var self = this;
186
+
187
+ // Setup class attributes
188
+ self.id = id;
189
+ self.options = options;
190
+ self.status = {
191
+ animated: false,
192
+ rendered: false,
193
+ disabled: false,
194
+ focused: false
195
+ };
196
+ self.elements = {
197
+ target: target.addClass(self.options.style.classes.target),
198
+ tooltip: null,
199
+ wrapper: null,
200
+ content: null,
201
+ contentWrapper: null,
202
+ title: null,
203
+ button: null,
204
+ tip: null,
205
+ bgiframe: null
206
+ };
207
+ self.cache = {
208
+ mouse: {},
209
+ position: {},
210
+ toggle: 0
211
+ };
212
+ self.timers = {};
213
+
214
+ // Define exposed API methods
215
+ $.extend(self, self.options.api,
216
+ {
217
+ show: function(event)
218
+ {
219
+ var returned, solo;
220
+
221
+ // Make sure tooltip is rendered and if not, return
222
+ if(!self.status.rendered)
223
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'show');
224
+
225
+ // Only continue if element is visible
226
+ if(self.elements.tooltip.css('display') !== 'none') return self;
227
+
228
+ // Clear animation queue
229
+ self.elements.tooltip.stop(true, false);
230
+
231
+ // Call API method and if return value is false, halt
232
+ returned = self.beforeShow.call(self, event);
233
+ if(returned === false) return self;
234
+
235
+ // Define afterShow callback method
236
+ function afterShow()
237
+ {
238
+ // Call API method and focus if it isn't static
239
+ if(self.options.position.type !== 'static') self.focus();
240
+ self.onShow.call(self, event);
241
+
242
+ // Prevent antialias from disappearing in IE7 by removing filter attribute
243
+ self.elements.tooltip.get(0).style.removeAttribute('filter');
244
+ };
245
+
246
+ // Maintain toggle functionality if enabled
247
+ self.cache.toggle = 1;
248
+
249
+ // Update tooltip position if it isn't static
250
+ if(self.options.position.type !== 'static')
251
+ self.updatePosition(event, (self.options.show.effect.length > 0));
252
+
253
+ // Hide other tooltips if tooltip is solo
254
+ if(typeof self.options.show.solo == 'object') solo = $(self.options.show.solo);
255
+ else if(self.options.show.solo === true) solo = $('div.qtip').not(self.elements.tooltip);
256
+ if(solo) solo.each(function(){ if($(this).qtip('api').status.rendered === true) $(this).qtip('api').hide(); });
257
+
258
+ // Show tooltip
259
+ if(typeof self.options.show.effect.type == 'function')
260
+ {
261
+ self.options.show.effect.type.call(self.elements.tooltip, self.options.show.effect.length);
262
+ self.elements.tooltip.queue(function(){ afterShow(); $(this).dequeue(); });
263
+ }
264
+ else
265
+ {
266
+ switch(self.options.show.effect.type.toLowerCase())
267
+ {
268
+ case 'fade':
269
+ self.elements.tooltip.fadeIn(self.options.show.effect.length, afterShow);
270
+ break;
271
+ case 'slide':
272
+ self.elements.tooltip.slideDown(self.options.show.effect.length, function()
273
+ {
274
+ afterShow();
275
+ if(self.options.position.type !== 'static') self.updatePosition(event, true);
276
+ });
277
+ break;
278
+ case 'grow':
279
+ self.elements.tooltip.show(self.options.show.effect.length, afterShow);
280
+ break;
281
+ default:
282
+ self.elements.tooltip.show(null, afterShow);
283
+ break;
284
+ };
285
+
286
+ // Add active class to tooltip
287
+ self.elements.tooltip.addClass(self.options.style.classes.active);
288
+ };
289
+
290
+ // Log event and return
291
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_SHOWN, 'show');
292
+ },
293
+
294
+ hide: function(event)
295
+ {
296
+ var returned;
297
+
298
+ // Make sure tooltip is rendered and if not, return
299
+ if(!self.status.rendered)
300
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'hide');
301
+
302
+ // Only continue if element is visible
303
+ else if(self.elements.tooltip.css('display') === 'none') return self;
304
+
305
+ // Stop show timer and animation queue
306
+ clearTimeout(self.timers.show);
307
+ self.elements.tooltip.stop(true, false);
308
+
309
+ // Call API method and if return value is false, halt
310
+ returned = self.beforeHide.call(self, event);
311
+ if(returned === false) return self;
312
+
313
+ // Define afterHide callback method
314
+ function afterHide(){ self.onHide.call(self, event); };
315
+
316
+ // Maintain toggle functionality if enabled
317
+ self.cache.toggle = 0;
318
+
319
+ // Hide tooltip
320
+ if(typeof self.options.hide.effect.type == 'function')
321
+ {
322
+ self.options.hide.effect.type.call(self.elements.tooltip, self.options.hide.effect.length);
323
+ self.elements.tooltip.queue(function(){ afterHide(); $(this).dequeue(); });
324
+ }
325
+ else
326
+ {
327
+ switch(self.options.hide.effect.type.toLowerCase())
328
+ {
329
+ case 'fade':
330
+ self.elements.tooltip.fadeOut(self.options.hide.effect.length, afterHide);
331
+ break;
332
+ case 'slide':
333
+ self.elements.tooltip.slideUp(self.options.hide.effect.length, afterHide);
334
+ break;
335
+ case 'grow':
336
+ self.elements.tooltip.hide(self.options.hide.effect.length, afterHide);
337
+ break;
338
+ default:
339
+ self.elements.tooltip.hide(null, afterHide);
340
+ break;
341
+ };
342
+
343
+ // Remove active class to tooltip
344
+ self.elements.tooltip.removeClass(self.options.style.classes.active);
345
+ };
346
+
347
+ // Log event and return
348
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_HIDDEN, 'hide');
349
+ },
350
+
351
+ updatePosition: function(event, animate)
352
+ {
353
+ var i, target, tooltip, coords, mapName, imagePos, newPosition, borderAdjust, mouseAdjust, offset, curPosition, returned
354
+
355
+ // Make sure tooltip is rendered and if not, return
356
+ if(!self.status.rendered)
357
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updatePosition');
358
+
359
+ // If tooltip is static, return
360
+ else if(self.options.position.type == 'static')
361
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.CANNOT_POSITION_STATIC, 'updatePosition');
362
+
363
+ // Define property objects
364
+ target = {
365
+ position: { left: 0, top: 0 },
366
+ dimensions: { height: 0, width: 0 },
367
+ corner: self.options.position.corner.target
368
+ };
369
+ tooltip = {
370
+ position: self.getPosition(),
371
+ dimensions: self.getDimensions(),
372
+ corner: self.options.position.corner.tooltip
373
+ };
374
+
375
+ // Target is an HTML element
376
+ if(self.options.position.target !== 'mouse')
377
+ {
378
+ // If the HTML element is AREA, calculate position manually
379
+ if(self.options.position.target.get(0).nodeName.toLowerCase() == 'area')
380
+ {
381
+ // Retrieve coordinates from coords attribute and parse into integers
382
+ coords = self.options.position.target.attr('coords').split(',');
383
+ for(i = 0; i < coords.length; i++) coords[i] = parseInt(coords[i]);
384
+
385
+ // Setup target position object
386
+ mapName = self.options.position.target.parent('map').attr('name');
387
+ imagePos = $('img[usemap="#'+mapName+'"]:first').offset();
388
+ target.position = {
389
+ left: Math.floor(imagePos.left + coords[0]),
390
+ top: Math.floor(imagePos.top + coords[1])
391
+ };
392
+
393
+ // Determine width and height of the area
394
+ switch(self.options.position.target.attr('shape').toLowerCase())
395
+ {
396
+ case 'rect':
397
+ target.dimensions = {
398
+ width: Math.ceil(Math.abs(coords[2] - coords[0])),
399
+ height: Math.ceil(Math.abs(coords[3] - coords[1]))
400
+ };
401
+ break;
402
+
403
+ case 'circle':
404
+ target.dimensions = {
405
+ width: coords[2] + 1,
406
+ height: coords[2] + 1
407
+ };
408
+ break;
409
+
410
+ case 'poly':
411
+ target.dimensions = {
412
+ width: coords[0],
413
+ height: coords[1]
414
+ };
415
+
416
+ for(i = 0; i < coords.length; i++)
417
+ {
418
+ if(i % 2 == 0)
419
+ {
420
+ if(coords[i] > target.dimensions.width)
421
+ target.dimensions.width = coords[i];
422
+ if(coords[i] < coords[0])
423
+ target.position.left = Math.floor(imagePos.left + coords[i]);
424
+ }
425
+ else
426
+ {
427
+ if(coords[i] > target.dimensions.height)
428
+ target.dimensions.height = coords[i];
429
+ if(coords[i] < coords[1])
430
+ target.position.top = Math.floor(imagePos.top + coords[i]);
431
+ };
432
+ };
433
+
434
+ target.dimensions.width = target.dimensions.width - (target.position.left - imagePos.left);
435
+ target.dimensions.height = target.dimensions.height - (target.position.top - imagePos.top);
436
+ break;
437
+
438
+ default:
439
+ return $.fn.qtip.log.error.call(self, 4, $.fn.qtip.constants.INVALID_AREA_SHAPE, 'updatePosition');
440
+ break;
441
+ };
442
+
443
+ // Adjust position by 2 pixels (Positioning bug?)
444
+ target.dimensions.width -= 2; target.dimensions.height -= 2;
445
+ }
446
+
447
+ // Target is the document
448
+ else if(self.options.position.target.add(document.body).length === 1)
449
+ {
450
+ target.position = { left: $(document).scrollLeft(), top: $(document).scrollTop() };
451
+ target.dimensions = { height: $(window).height(), width: $(window).width() };
452
+ }
453
+
454
+ // Target is a regular HTML element, find position normally
455
+ else
456
+ {
457
+ // Check if the target is another tooltip. If its animated, retrieve position from newPosition data
458
+ if(typeof self.options.position.target.attr('qtip') !== 'undefined')
459
+ target.position = self.options.position.target.qtip('api').cache.position;
460
+ else
461
+ target.position = self.options.position.target.offset();
462
+
463
+ // Setup dimensions objects
464
+ target.dimensions = {
465
+ height: self.options.position.target.outerHeight(),
466
+ width: self.options.position.target.outerWidth()
467
+ };
468
+ };
469
+
470
+ // Calculate correct target corner position
471
+ newPosition = $.extend({}, target.position);
472
+ if(target.corner.search(/right/i) !== -1)
473
+ newPosition.left += target.dimensions.width;
474
+
475
+ if(target.corner.search(/bottom/i) !== -1)
476
+ newPosition.top += target.dimensions.height;
477
+
478
+ if(target.corner.search(/((top|bottom)Middle)|center/) !== -1)
479
+ newPosition.left += (target.dimensions.width / 2);
480
+
481
+ if(target.corner.search(/((left|right)Middle)|center/) !== -1)
482
+ newPosition.top += (target.dimensions.height / 2);
483
+ }
484
+
485
+ // Mouse is the target, set position to current mouse coordinates
486
+ else
487
+ {
488
+ // Setup target position and dimensions objects
489
+ target.position = newPosition = { left: self.cache.mouse.x, top: self.cache.mouse.y };
490
+ target.dimensions = { height: 1, width: 1 };
491
+ };
492
+
493
+ // Calculate correct target corner position
494
+ if(tooltip.corner.search(/right/i) !== -1)
495
+ newPosition.left -= tooltip.dimensions.width;
496
+
497
+ if(tooltip.corner.search(/bottom/i) !== -1)
498
+ newPosition.top -= tooltip.dimensions.height;
499
+
500
+ if(tooltip.corner.search(/((top|bottom)Middle)|center/) !== -1)
501
+ newPosition.left -= (tooltip.dimensions.width / 2);
502
+
503
+ if(tooltip.corner.search(/((left|right)Middle)|center/) !== -1)
504
+ newPosition.top -= (tooltip.dimensions.height / 2);
505
+
506
+ // Adjust for border radius
507
+ if(self.options.style.border.radius > 0)
508
+ {
509
+ if(tooltip.corner.search(/Left/) !== -1)
510
+ newPosition.left -= self.options.style.border.radius;
511
+ else if(tooltip.corner.search(/Right/) !== -1)
512
+ newPosition.left += self.options.style.border.radius;
513
+
514
+ if(tooltip.corner.search(/Top/) !== -1)
515
+ newPosition.top -= self.options.style.border.radius;
516
+ else if(tooltip.corner.search(/Bottom/) !== -1)
517
+ newPosition.top += self.options.style.border.radius;
518
+ };
519
+
520
+ // If screen adjustment is enabled, apply adjustments
521
+ if(self.options.position.adjust.screen === true)
522
+ newPosition = screenAdjust.call(self, newPosition, target, tooltip);
523
+
524
+ // If mouse is the target, prevent tooltip appearing directly under the mouse
525
+ if(self.options.position.target === 'mouse' && self.options.position.adjust.mouse === true)
526
+ {
527
+ if(self.options.position.adjust.screen === true && self.elements.tip)
528
+ mouseAdjust = self.elements.tip.attr('rel');
529
+ else
530
+ mouseAdjust = self.options.position.corner.tooltip;
531
+
532
+ newPosition.left += (mouseAdjust.search(/right/i) !== -1) ? -6 : 6;
533
+ newPosition.top += (mouseAdjust.search(/bottom/i) !== -1) ? -6 : 6;
534
+ }
535
+
536
+ // Add user xy adjustments
537
+ newPosition.left += self.options.position.adjust.x;
538
+ newPosition.top += self.options.position.adjust.y;
539
+
540
+ // Set new tooltip position if its moved, animate if enabled
541
+ curPosition = self.getPosition();
542
+ if(newPosition.left != curPosition.left || newPosition.top != curPosition.top)
543
+ {
544
+ // Call API method and if return value is false, halt
545
+ returned = self.beforePositionUpdate.call(self, event);
546
+ if(returned === false) return self;
547
+
548
+ // Cache new position
549
+ self.cache.position = newPosition;
550
+
551
+ // Check if animation is enabled
552
+ if(animate === true)
553
+ {
554
+ // Set animated status
555
+ self.status.animated = true;
556
+
557
+ // Animate and reset animated status on animation end
558
+ self.elements.tooltip.animate(newPosition, 200, 'swing', function(){ self.status.animated = false });
559
+ }
560
+
561
+ // Set new position via CSS
562
+ else self.elements.tooltip.css(newPosition);
563
+
564
+ // Call API method and log event if its not a mouse move
565
+ self.onPositionUpdate.call(self, event);
566
+ if(typeof event !== 'undefined' && event.type && event.type !== 'mousemove')
567
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_POSITION_UPDATED, 'updatePosition');
568
+ };
569
+
570
+ return self;
571
+ },
572
+
573
+ updateWidth: function(newWidth)
574
+ {
575
+ var hidden;
576
+
577
+ // Make sure tooltip is rendered and if not, return
578
+ if(!self.status.rendered)
579
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateWidth');
580
+
581
+ // Make sure supplied width is a number and if not, return
582
+ else if(newWidth && typeof newWidth !== 'number')
583
+ return $.fn.qtip.log.error.call(self, 2, 'newWidth must be of type number', 'updateWidth');
584
+
585
+ // Setup elements which must be hidden during width update
586
+ hidden = self.elements.contentWrapper.siblings().add(self.elements.tip).add(self.elements.button);
587
+
588
+ // Calculate the new width if one is not supplied
589
+ if(!newWidth)
590
+ {
591
+ // Explicit width is set
592
+ if(typeof self.options.style.width.value == 'number')
593
+ newWidth = self.options.style.width.value;
594
+
595
+ // No width is set, proceed with auto detection
596
+ else
597
+ {
598
+ // Set width to auto initally to determine new width and hide other elements
599
+ self.elements.tooltip.css({ width: 'auto' });
600
+ hidden.hide();
601
+
602
+ // Set position and zoom to defaults to prevent IE hasLayout bug
603
+ self.elements.wrapper.add(self.elements.contentWrapper.children()).css({ zoom: 'normal' });
604
+
605
+ // Set the new width
606
+ newWidth = self.getDimensions().width + 1;
607
+
608
+ // Make sure its within the maximum and minimum width boundries
609
+ if(!self.options.style.width.value)
610
+ {
611
+ if(newWidth > self.options.style.width.max) newWidth = self.options.style.width.max
612
+ if(newWidth < self.options.style.width.min) newWidth = self.options.style.width.min
613
+ };
614
+ };
615
+ };
616
+
617
+ // Adjust newWidth by 1px if width is odd (IE6 rounding bug fix)
618
+ if(newWidth % 2 !== 0) newWidth -= 1;
619
+
620
+ // Set the new calculated width and unhide other elements
621
+ self.elements.tooltip.width(newWidth);
622
+ hidden.show();
623
+
624
+ // Set the border width, if enabled
625
+ if(self.options.style.border.radius)
626
+ {
627
+ self.elements.tooltip.find('.qtip-betweenCorners').each(function(i)
628
+ {
629
+ $(this).width(newWidth - (self.options.style.border.radius * 2));
630
+ })
631
+ };
632
+
633
+ // IE only adjustments
634
+ if(true) // if($.browser.msie)
635
+ {
636
+ // Reset position and zoom to give the wrapper layout (IE hasLayout bug)
637
+ self.elements.wrapper.add(self.elements.contentWrapper.children()).css({ zoom: '1' });
638
+
639
+ // Set the new width
640
+ self.elements.wrapper.width(newWidth);
641
+
642
+ // Adjust BGIframe height and width if enabled
643
+ if(self.elements.bgiframe) self.elements.bgiframe.width(newWidth).height(self.getDimensions.height);
644
+ };
645
+
646
+ // Log event and return
647
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_WIDTH_UPDATED, 'updateWidth');
648
+ },
649
+
650
+ updateStyle: function(name)
651
+ {
652
+ var tip, borders, context, corner, coordinates;
653
+
654
+ // Make sure tooltip is rendered and if not, return
655
+ if(!self.status.rendered)
656
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateStyle');
657
+
658
+ // Return if style is not defined or name is not a string
659
+ else if(typeof name !== 'string' || !$.fn.qtip.styles[name])
660
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.STYLE_NOT_DEFINED, 'updateStyle');
661
+
662
+ // Set the new style object
663
+ self.options.style = buildStyle.call(self, $.fn.qtip.styles[name], self.options.user.style);
664
+
665
+ // Update initial styles of content and title elements
666
+ self.elements.content.css( jQueryStyle(self.options.style) );
667
+ if(self.options.content.title.text !== false)
668
+ self.elements.title.css( jQueryStyle(self.options.style.title, true) );
669
+
670
+ // Update CSS border colour
671
+ self.elements.contentWrapper.css({ borderColor: self.options.style.border.color });
672
+
673
+ // Update tip color if enabled
674
+ if(self.options.style.tip.corner !== false)
675
+ {
676
+ if($('<canvas>').get(0).getContext)
677
+ {
678
+ // Retrieve canvas context and clear
679
+ tip = self.elements.tooltip.find('.qtip-tip canvas:first');
680
+ context = tip.get(0).getContext('2d');
681
+ context.clearRect(0,0,300,300);
682
+
683
+ // Draw new tip
684
+ corner = tip.parent('div[rel]:first').attr('rel');
685
+ coordinates = calculateTip(corner, self.options.style.tip.size.width, self.options.style.tip.size.height);
686
+ drawTip.call(self, tip, coordinates, self.options.style.tip.color || self.options.style.border.color);
687
+ }
688
+ else
689
+ {
690
+ // Set new fillcolor attribute
691
+ tip = self.elements.tooltip.find('.qtip-tip [nodeName="shape"]');
692
+ tip.attr('fillcolor', self.options.style.tip.color || self.options.style.border.color);
693
+ };
694
+ };
695
+
696
+ // Update border colors if enabled
697
+ if(self.options.style.border.radius > 0)
698
+ {
699
+ self.elements.tooltip.find('.qtip-betweenCorners').css({ backgroundColor: self.options.style.border.color });
700
+
701
+ if($('<canvas>').get(0).getContext)
702
+ {
703
+ borders = calculateBorders(self.options.style.border.radius)
704
+ self.elements.tooltip.find('.qtip-wrapper canvas').each(function()
705
+ {
706
+ // Retrieve canvas context and clear
707
+ context = $(this).get(0).getContext('2d');
708
+ context.clearRect(0,0,300,300);
709
+
710
+ // Draw new border
711
+ corner = $(this).parent('div[rel]:first').attr('rel')
712
+ drawBorder.call(self, $(this), borders[corner],
713
+ self.options.style.border.radius, self.options.style.border.color);
714
+ });
715
+ }
716
+ else
717
+ {
718
+ // Set new fillcolor attribute on each border corner
719
+ self.elements.tooltip.find('.qtip-wrapper [nodeName="arc"]').each(function()
720
+ {
721
+ $(this).attr('fillcolor', self.options.style.border.color)
722
+ });
723
+ };
724
+ };
725
+
726
+ // Log event and return
727
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_STYLE_UPDATED, 'updateStyle');
728
+ },
729
+
730
+ updateContent: function(content, reposition)
731
+ {
732
+ var parsedContent, images, loadedImages;
733
+
734
+ // Make sure tooltip is rendered and if not, return
735
+ if(!self.status.rendered)
736
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateContent');
737
+
738
+ // Make sure content is defined before update
739
+ else if(!content)
740
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.NO_CONTENT_PROVIDED, 'updateContent');
741
+
742
+ // Call API method and set new content if a string is returned
743
+ parsedContent = self.beforeContentUpdate.call(self, content);
744
+ if(typeof parsedContent == 'string') content = parsedContent;
745
+ else if(parsedContent === false) return;
746
+
747
+ // Set position and zoom to defaults to prevent IE hasLayout bug
748
+ self.elements.contentWrapper.children().css({ zoom: 'normal' });
749
+
750
+ // Append new content if its a DOM array and show it if hidden
751
+ if(content.jquery && content.length > 0)
752
+ content.clone(true).appendTo(self.elements.content).show();
753
+
754
+ // Content is a regular string, insert the new content
755
+ else self.elements.content.html(content);
756
+
757
+ // Check if images need to be loaded before position is updated to prevent mis-positioning
758
+ images = self.elements.content.find('img[complete=false]');
759
+ if(images.length > 0)
760
+ {
761
+ loadedImages = 0;
762
+ images.each(function(i)
763
+ {
764
+ $('<img src="'+ $(this).attr('src') +'" />')
765
+ .load(function(){ if(++loadedImages == images.length) afterLoad(); });
766
+ });
767
+ }
768
+ else afterLoad();
769
+
770
+ function afterLoad()
771
+ {
772
+ // Update the tooltip width
773
+ self.updateWidth();
774
+
775
+ // If repositioning is enabled, update positions
776
+ if(reposition !== false)
777
+ {
778
+ // Update position if tooltip isn't static
779
+ if(self.options.position.type !== 'static')
780
+ self.updatePosition(self.elements.tooltip.is(':visible'), true);
781
+
782
+ // Reposition the tip if enabled
783
+ if(self.options.style.tip.corner !== false)
784
+ positionTip.call(self);
785
+ };
786
+ };
787
+
788
+ // Call API method and log event
789
+ self.onContentUpdate.call(self);
790
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_CONTENT_UPDATED, 'loadContent');
791
+ },
792
+
793
+ loadContent: function(url, data, method)
794
+ {
795
+ var returned;
796
+
797
+ // Make sure tooltip is rendered and if not, return
798
+ if(!self.status.rendered)
799
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'loadContent');
800
+
801
+ // Call API method and if return value is false, halt
802
+ returned = self.beforeContentLoad.call(self);
803
+ if(returned === false) return self;
804
+
805
+ // Load content using specified request type
806
+ if(method == 'post')
807
+ $.post(url, data, setupContent);
808
+ else
809
+ $.get(url, data, setupContent);
810
+
811
+ function setupContent(content)
812
+ {
813
+ // Call API method and log event
814
+ self.onContentLoad.call(self);
815
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_CONTENT_LOADED, 'loadContent');
816
+
817
+ // Update the content
818
+ self.updateContent(content);
819
+ };
820
+
821
+ return self;
822
+ },
823
+
824
+ updateTitle: function(content)
825
+ {
826
+ // Make sure tooltip is rendered and if not, return
827
+ if(!self.status.rendered)
828
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'updateTitle');
829
+
830
+ // Make sure content is defined before update
831
+ else if(!content)
832
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.NO_CONTENT_PROVIDED, 'updateTitle');
833
+
834
+ // Call API method and if return value is false, halt
835
+ returned = self.beforeTitleUpdate.call(self);
836
+ if(returned === false) return self;
837
+
838
+ // Set the new content and reappend the button if enabled
839
+ if(self.elements.button) self.elements.button = self.elements.button.clone(true);
840
+ self.elements.title.html(content)
841
+ if(self.elements.button) self.elements.title.prepend(self.elements.button);
842
+
843
+ // Call API method and log event
844
+ self.onTitleUpdate.call(self);
845
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_TITLE_UPDATED, 'updateTitle');
846
+ },
847
+
848
+ focus: function(event)
849
+ {
850
+ var curIndex, newIndex, elemIndex, returned;
851
+
852
+ // Make sure tooltip is rendered and if not, return
853
+ if(!self.status.rendered)
854
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'focus');
855
+
856
+ else if(self.options.position.type == 'static')
857
+ return $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.CANNOT_FOCUS_STATIC, 'focus');
858
+
859
+ // Set z-index variables
860
+ curIndex = parseInt( self.elements.tooltip.css('z-index') );
861
+ newIndex = 6000 + $('div.qtip[qtip]').length - 1;
862
+
863
+ // Only update the z-index if it has changed and tooltip is not already focused
864
+ if(!self.status.focused && curIndex !== newIndex)
865
+ {
866
+ // Call API method and if return value is false, halt
867
+ returned = self.beforeFocus.call(self, event);
868
+ if(returned === false) return self;
869
+
870
+ // Loop through all other tooltips
871
+ $('div.qtip[qtip]').not(self.elements.tooltip).each(function()
872
+ {
873
+ if($(this).qtip('api').status.rendered === true)
874
+ {
875
+ elemIndex = parseInt($(this).css('z-index'));
876
+
877
+ // Reduce all other tooltip z-index by 1
878
+ if(typeof elemIndex == 'number' && elemIndex > -1)
879
+ $(this).css({ zIndex: parseInt( $(this).css('z-index') ) - 1 });
880
+
881
+ // Set focused status to false
882
+ $(this).qtip('api').status.focused = false;
883
+ }
884
+ })
885
+
886
+ // Set the new z-index and set focus status to true
887
+ self.elements.tooltip.css({ zIndex: newIndex });
888
+ self.status.focused = true;
889
+
890
+ // Call API method and log event
891
+ self.onFocus.call(self, event);
892
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_FOCUSED, 'focus');
893
+ };
894
+
895
+ return self;
896
+ },
897
+
898
+ disable: function(state)
899
+ {
900
+ // Make sure tooltip is rendered and if not, return
901
+ if(!self.status.rendered)
902
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'disable');
903
+
904
+ if(state)
905
+ {
906
+ // Tooltip is not already disabled, proceed
907
+ if(!self.status.disabled)
908
+ {
909
+ // Set the disabled flag and log event
910
+ self.status.disabled = true;
911
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_DISABLED, 'disable');
912
+ }
913
+
914
+ // Tooltip is already disabled, inform user via log
915
+ else $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.TOOLTIP_ALREADY_DISABLED, 'disable');
916
+ }
917
+ else
918
+ {
919
+ // Tooltip is not already enabled, proceed
920
+ if(self.status.disabled)
921
+ {
922
+ // Reassign events, set disable status and log
923
+ self.status.disabled = false;
924
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_ENABLED, 'disable');
925
+ }
926
+
927
+ // Tooltip is already enabled, inform the user via log
928
+ else $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.TOOLTIP_ALREADY_ENABLED, 'disable');
929
+ };
930
+
931
+ return self;
932
+ },
933
+
934
+ destroy: function()
935
+ {
936
+ var i, returned, interfaces;
937
+
938
+ // Call API method and if return value is false, halt
939
+ returned = self.beforeDestroy.call(self);
940
+ if(returned === false) return self;
941
+
942
+ // Check if tooltip is rendered
943
+ if(self.status.rendered)
944
+ {
945
+ // Remove event handlers and remove element
946
+ self.options.show.when.target.unbind('mousemove.qtip', self.updatePosition);
947
+ self.options.show.when.target.unbind('mouseout.qtip', self.hide);
948
+ self.options.show.when.target.unbind(self.options.show.when.event + '.qtip');
949
+ self.options.hide.when.target.unbind(self.options.hide.when.event + '.qtip');
950
+ self.elements.tooltip.unbind(self.options.hide.when.event + '.qtip');
951
+ self.elements.tooltip.unbind('mouseover.qtip', self.focus);
952
+ self.elements.tooltip.remove();
953
+ }
954
+
955
+ // Tooltip isn't yet rendered, remove render event
956
+ else self.options.show.when.target.unbind(self.options.show.when.event+'.qtip-create');
957
+
958
+ // Check to make sure qTip data is present on target element
959
+ if(typeof self.elements.target.data('qtip') == 'object')
960
+ {
961
+ // Remove API references from interfaces object
962
+ interfaces = self.elements.target.data('qtip').interfaces;
963
+ if(typeof interfaces == 'object' && interfaces.length > 0)
964
+ {
965
+ // Remove API from interfaces array
966
+ for(i = 0; i < interfaces.length - 1; i++)
967
+ if(interfaces[i].id == self.id) interfaces.splice(i, 1)
968
+ }
969
+ }
970
+ delete $.fn.qtip.interfaces[self.id];
971
+
972
+ // Set qTip current id to previous tooltips API if available
973
+ if(typeof interfaces == 'object' && interfaces.length > 0)
974
+ self.elements.target.data('qtip').current = interfaces.length -1;
975
+ else
976
+ self.elements.target.removeData('qtip');
977
+
978
+ // Call API method and log destroy
979
+ self.onDestroy.call(self);
980
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_DESTROYED, 'destroy');
981
+
982
+ return self.elements.target
983
+ },
984
+
985
+ getPosition: function()
986
+ {
987
+ var show, offset;
988
+
989
+ // Make sure tooltip is rendered and if not, return
990
+ if(!self.status.rendered)
991
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'getPosition');
992
+
993
+ show = (self.elements.tooltip.css('display') !== 'none') ? false : true;
994
+
995
+ // Show and hide tooltip to make sure coordinates are returned
996
+ if(show) self.elements.tooltip.css({ visiblity: 'hidden' }).show();
997
+ offset = self.elements.tooltip.offset();
998
+ if(show) self.elements.tooltip.css({ visiblity: 'visible' }).hide();
999
+
1000
+ return offset;
1001
+ },
1002
+
1003
+ getDimensions: function()
1004
+ {
1005
+ var show, dimensions;
1006
+
1007
+ // Make sure tooltip is rendered and if not, return
1008
+ if(!self.status.rendered)
1009
+ return $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.TOOLTIP_NOT_RENDERED, 'getDimensions');
1010
+
1011
+ show = (!self.elements.tooltip.is(':visible')) ? true : false;
1012
+
1013
+ // Show and hide tooltip to make sure dimensions are returned
1014
+ if(show) self.elements.tooltip.css({ visiblity: 'hidden' }).show();
1015
+ dimensions = {
1016
+ height: self.elements.tooltip.outerHeight(),
1017
+ width: self.elements.tooltip.outerWidth()
1018
+ };
1019
+ if(show) self.elements.tooltip.css({ visiblity: 'visible' }).hide();
1020
+
1021
+ return dimensions;
1022
+ }
1023
+ });
1024
+ };
1025
+
1026
+ // Define priamry construct function
1027
+ function construct()
1028
+ {
1029
+ var self, adjust, content, url, data, method, tempLength;
1030
+ self = this;
1031
+
1032
+ // Call API method
1033
+ self.beforeRender.call(self);
1034
+
1035
+ // Set rendered status to true
1036
+ self.status.rendered = true;
1037
+
1038
+ // Create initial tooltip elements
1039
+ self.elements.tooltip = '<div qtip="'+self.id+'" ' +
1040
+ 'class="qtip '+(self.options.style.classes.tooltip || self.options.style)+'"' +
1041
+ 'style="display:none; -moz-border-radius:0; -webkit-border-radius:0; border-radius:0;' +
1042
+ 'position:'+self.options.position.type+';">' +
1043
+ ' <div class="qtip-wrapper" style="position:relative; overflow:hidden; text-align:left;">' +
1044
+ ' <div class="qtip-contentWrapper" style="overflow:hidden;">' +
1045
+ ' <div class="qtip-content '+self.options.style.classes.content+'"></div>' +
1046
+ '</div></div></div>';
1047
+
1048
+ // Append to container element
1049
+ self.elements.tooltip = $(self.elements.tooltip);
1050
+ self.elements.tooltip.appendTo(self.options.position.container)
1051
+
1052
+ // Setup tooltip qTip data
1053
+ self.elements.tooltip.data('qtip', { current: 0, interfaces: [self] });
1054
+
1055
+ // Setup element references
1056
+ self.elements.wrapper = self.elements.tooltip.children('div:first');
1057
+ self.elements.contentWrapper = self.elements.wrapper.children('div:first').css({ background: self.options.style.background });
1058
+ self.elements.content = self.elements.contentWrapper.children('div:first').css( jQueryStyle(self.options.style) );
1059
+
1060
+ // Apply IE hasLayout fix to wrapper and content elements
1061
+ self.elements.wrapper.add(self.elements.content).css({ zoom: 1 });
1062
+
1063
+ // Setup tooltip attributes
1064
+ if(self.options.hide.when.event == 'unfocus') self.elements.tooltip.attr('unfocus', true);
1065
+
1066
+ // If an explicit width is set, updateWidth prior to setting content to prevent dirty rendering
1067
+ if(typeof self.options.style.width.value == 'number') self.updateWidth();
1068
+
1069
+ // Create borders and tips if supported by the browser
1070
+ if($('<canvas>').get(0).getContext)
1071
+ {
1072
+ // Create border
1073
+ if(self.options.style.border.radius > 0)
1074
+ createBorder.call(self);
1075
+ else
1076
+ self.elements.contentWrapper.css({ border: self.options.style.border.width+'px solid '+self.options.style.border.color });
1077
+
1078
+ // Create tip if enabled
1079
+ if(self.options.style.tip.corner !== false)
1080
+ createTip.call(self);
1081
+ }
1082
+
1083
+ // Neither canvas or VML is supported, tips and borders cannot be drawn!
1084
+ else
1085
+ {
1086
+ // Set defined border width
1087
+ self.elements.contentWrapper.css({ border: self.options.style.border.width+'px solid '+self.options.style.border.color });
1088
+
1089
+ // Reset border radius and tip
1090
+ self.options.style.border.radius = 0;
1091
+ self.options.style.tip.corner = false;
1092
+
1093
+ // Inform via log
1094
+ $.fn.qtip.log.error.call(self, 2, $.fn.qtip.constants.CANVAS_VML_NOT_SUPPORTED, 'render');
1095
+ };
1096
+
1097
+ // Use the provided content string or DOM array
1098
+ if((typeof self.options.content.text == 'string' && self.options.content.text.length > 0)
1099
+ || (self.options.content.text.jquery && self.options.content.text.length > 0))
1100
+ content = self.options.content.text;
1101
+
1102
+ // Use title string for content if present
1103
+ else if(typeof self.elements.target.attr('title') == 'string' && self.elements.target.attr('title').length > 0)
1104
+ {
1105
+ content = self.elements.target.attr('title').replace("\\n", '<br />');
1106
+ self.elements.target.attr('title', ''); // Remove title attribute to prevent default tooltip showing
1107
+ }
1108
+
1109
+ // No title is present, use alt attribute instead
1110
+ else if(typeof self.elements.target.attr('alt') == 'string' && self.elements.target.attr('alt').length > 0)
1111
+ {
1112
+ content = self.elements.target.attr('alt').replace("\\n", '<br />');
1113
+ self.elements.target.attr('alt', ''); // Remove alt attribute to prevent default tooltip showing
1114
+ }
1115
+
1116
+ // No valid content was provided, inform via log
1117
+ else
1118
+ {
1119
+ content = ' ';
1120
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.NO_VALID_CONTENT, 'render');
1121
+ };
1122
+
1123
+ // Set the tooltips content and create title if enabled
1124
+ if(self.options.content.title.text !== false) createTitle.call(self);
1125
+ self.updateContent(content);
1126
+
1127
+ // Assign events and toggle tooltip with focus
1128
+ assignEvents.call(self);
1129
+ if(self.options.show.ready === true) self.show();
1130
+
1131
+ // Retrieve ajax content if provided
1132
+ if(self.options.content.url !== false)
1133
+ {
1134
+ url = self.options.content.url;
1135
+ data = self.options.content.data;
1136
+ method = self.options.content.method || 'get';
1137
+ self.loadContent(url, data, method);
1138
+ };
1139
+
1140
+ // Call API method and log event
1141
+ self.onRender.call(self);
1142
+ $.fn.qtip.log.error.call(self, 1, $.fn.qtip.constants.EVENT_RENDERED, 'render');
1143
+ };
1144
+
1145
+ // Create borders using canvas and VML
1146
+ function createBorder()
1147
+ {
1148
+ var self, i, width, radius, color, coordinates, containers, size, betweenWidth, betweenCorners, borderTop, borderBottom, borderCoord, sideWidth, vertWidth;
1149
+ self = this;
1150
+
1151
+ // Destroy previous border elements, if present
1152
+ self.elements.wrapper.find('.qtip-borderBottom, .qtip-borderTop').remove();
1153
+
1154
+ // Setup local variables
1155
+ width = self.options.style.border.width;
1156
+ radius = self.options.style.border.radius;
1157
+ color = self.options.style.border.color || self.options.style.tip.color;
1158
+
1159
+ // Calculate border coordinates
1160
+ coordinates = calculateBorders(radius);
1161
+
1162
+ // Create containers for the border shapes
1163
+ containers = {};
1164
+ for(i in coordinates)
1165
+ {
1166
+ // Create shape container
1167
+ containers[i] = '<div rel="'+i+'" style="'+((i.search(/Left/) !== -1) ? 'left' : 'right') + ':0; ' +
1168
+ 'position:absolute; height:'+radius+'px; width:'+radius+'px; overflow:hidden; line-height:0.1px; font-size:1px">';
1169
+
1170
+ // Canvas is supported
1171
+ if($('<canvas>').get(0).getContext)
1172
+ containers[i] += '<canvas height="'+radius+'" width="'+radius+'" style="vertical-align: top"></canvas>';
1173
+
1174
+ // No canvas, but if it's IE use VML
1175
+ else
1176
+ {
1177
+ size = radius * 2 + 3;
1178
+ containers[i] += '<v:arc stroked="false" fillcolor="'+color+'" startangle="'+coordinates[i][0]+'" endangle="'+coordinates[i][1]+'" ' +
1179
+ 'style="width:'+size+'px; height:'+size+'px; margin-top:'+((i.search(/bottom/) !== -1) ? -2 : -1)+'px; ' +
1180
+ 'margin-left:'+((i.search(/Right/) !== -1) ? coordinates[i][2] - 3.5 : -1)+'px; ' +
1181
+ 'vertical-align:top; display:inline-block; behavior:url(#default#VML)"></v:arc>';
1182
+
1183
+ };
1184
+
1185
+ containers[i] += '</div>';
1186
+ };
1187
+
1188
+ // Create between corners elements
1189
+ betweenWidth = self.getDimensions().width - (Math.max(width, radius) * 2);
1190
+ betweenCorners = '<div class="qtip-betweenCorners" style="height:'+radius+'px; width:'+betweenWidth+'px; ' +
1191
+ 'overflow:hidden; background-color:'+color+'; line-height:0.1px; font-size:1px;">';
1192
+
1193
+ // Create top border container
1194
+ borderTop = '<div class="qtip-borderTop" dir="ltr" style="height:'+radius+'px; ' +
1195
+ 'margin-left:'+radius+'px; line-height:0.1px; font-size:1px; padding:0;">' +
1196
+ containers['topLeft'] + containers['topRight'] + betweenCorners;
1197
+ self.elements.wrapper.prepend(borderTop);
1198
+
1199
+ // Create bottom border container
1200
+ borderBottom = '<div class="qtip-borderBottom" dir="ltr" style="height:'+radius+'px; ' +
1201
+ 'margin-left:'+radius+'px; line-height:0.1px; font-size:1px; padding:0;">' +
1202
+ containers['bottomLeft'] + containers['bottomRight'] + betweenCorners;
1203
+ self.elements.wrapper.append(borderBottom);
1204
+
1205
+ // Draw the borders if canvas were used (Delayed til after DOM creation)
1206
+ if($('<canvas>').get(0).getContext)
1207
+ {
1208
+ self.elements.wrapper.find('canvas').each(function()
1209
+ {
1210
+ borderCoord = coordinates[ $(this).parent('[rel]:first').attr('rel') ];
1211
+ drawBorder.call(self, $(this), borderCoord, radius, color);
1212
+ })
1213
+ }
1214
+
1215
+ // Create a phantom VML element (IE won't show the last created VML element otherwise)
1216
+ else self.elements.tooltip.append('<v:image style="behavior:url(#default#VML);"></v:image>');
1217
+
1218
+ // Setup contentWrapper border
1219
+ sideWidth = Math.max(radius, (radius + (width - radius)) )
1220
+ vertWidth = Math.max(width - radius, 0);
1221
+ self.elements.contentWrapper.css({
1222
+ border: '0px solid ' + color,
1223
+ borderWidth: vertWidth + 'px ' + sideWidth + 'px'
1224
+ })
1225
+ };
1226
+
1227
+ // Border canvas draw method
1228
+ function drawBorder(canvas, coordinates, radius, color)
1229
+ {
1230
+ // Create corner
1231
+ var context = canvas.get(0).getContext('2d');
1232
+ context.fillStyle = color;
1233
+ context.beginPath();
1234
+ context.arc(coordinates[0], coordinates[1], radius, 0, Math.PI * 2, false);
1235
+ context.fill();
1236
+ };
1237
+
1238
+ // Create tip using canvas and VML
1239
+ function createTip(corner)
1240
+ {
1241
+ var self, color, coordinates, coordsize, path;
1242
+ self = this;
1243
+
1244
+ // Destroy previous tip, if there is one
1245
+ if(self.elements.tip !== null) self.elements.tip.remove();
1246
+
1247
+ // Setup color and corner values
1248
+ color = self.options.style.tip.color || self.options.style.border.color;
1249
+ if(self.options.style.tip.corner === false) return;
1250
+ else if(!corner) corner = self.options.style.tip.corner;
1251
+
1252
+ // Calculate tip coordinates
1253
+ coordinates = calculateTip(corner, self.options.style.tip.size.width, self.options.style.tip.size.height);
1254
+
1255
+ // Create tip element
1256
+ self.elements.tip = '<div class="'+self.options.style.classes.tip+'" dir="ltr" rel="'+corner+'" style="position:absolute; ' +
1257
+ 'height:'+self.options.style.tip.size.height+'px; width:'+self.options.style.tip.size.width+'px; ' +
1258
+ 'margin:0 auto; line-height:0.1px; font-size:1px;">';
1259
+
1260
+ // Use canvas element if supported
1261
+ if($('<canvas>').get(0).getContext)
1262
+ self.elements.tip += '<canvas height="'+self.options.style.tip.size.height+'" width="'+self.options.style.tip.size.width+'"></canvas>';
1263
+
1264
+ // Canvas not supported - Use VML (IE)
1265
+ else
1266
+ {
1267
+ // Create coordize and tip path using tip coordinates
1268
+ coordsize = self.options.style.tip.size.width + ',' + self.options.style.tip.size.height;
1269
+ path = 'm' + coordinates[0][0] + ',' + coordinates[0][1];
1270
+ path += ' l' + coordinates[1][0] + ',' + coordinates[1][1];
1271
+ path += ' ' + coordinates[2][0] + ',' + coordinates[2][1];
1272
+ path += ' xe';
1273
+
1274
+ // Create VML element
1275
+ self.elements.tip += '<v:shape fillcolor="'+color+'" stroked="false" filled="true" path="'+path+'" coordsize="'+coordsize+'" ' +
1276
+ 'style="width:'+self.options.style.tip.size.width+'px; height:'+self.options.style.tip.size.height+'px; ' +
1277
+ 'line-height:0.1px; display:inline-block; behavior:url(#default#VML); ' +
1278
+ 'vertical-align:'+((corner.search(/top/) !== -1) ? 'bottom' : 'top')+'"></v:shape>';
1279
+
1280
+ // Create a phantom VML element (IE won't show the last created VML element otherwise)
1281
+ self.elements.tip += '<v:image style="behavior:url(#default#VML);"></v:image>';
1282
+
1283
+ // Prevent tooltip appearing above the content (IE z-index bug)
1284
+ self.elements.contentWrapper.css('position', 'relative');
1285
+ };
1286
+
1287
+ // Attach new tip to tooltip element
1288
+ self.elements.tooltip.prepend(self.elements.tip + '</div>');
1289
+
1290
+ // Create element reference and draw the canvas tip (Delayed til after DOM creation)
1291
+ self.elements.tip = self.elements.tooltip.find('.'+self.options.style.classes.tip).eq(0);
1292
+ if($('<canvas>').get(0).getContext)
1293
+ drawTip.call(self, self.elements.tip.find('canvas:first'), coordinates, color);
1294
+
1295
+ // Set the tip position
1296
+ positionTip.call(self, corner);
1297
+ };
1298
+
1299
+ // Canvas tip drawing method
1300
+ function drawTip(canvas, coordinates, color)
1301
+ {
1302
+ // Setup properties
1303
+ var context = canvas.get(0).getContext('2d');
1304
+ context.fillStyle = color;
1305
+
1306
+ // Create tip
1307
+ context.beginPath();
1308
+ context.moveTo(coordinates[0][0], coordinates[0][1]);
1309
+ context.lineTo(coordinates[1][0], coordinates[1][1]);
1310
+ context.lineTo(coordinates[2][0], coordinates[2][1]);
1311
+ context.fill();
1312
+ };
1313
+
1314
+ function positionTip(corner)
1315
+ {
1316
+ var self, paddingCorner, paddingSize, newMargin;
1317
+ self = this;
1318
+
1319
+ // Return if tips are disabled or tip is not yet rendered
1320
+ if(self.options.style.tip.corner === false || !self.elements.tip) return;
1321
+ if(!corner) corner = self.elements.tip.attr('rel');
1322
+
1323
+ // Set initial position
1324
+ self.elements.tip.css(corner.match(/left|right|top|bottom/)[0], 0);
1325
+
1326
+ // Set position of tip to correct side
1327
+ if(corner.search(/top|bottom/) !== -1)
1328
+ {
1329
+ if(corner.search(/Middle/) !== -1)
1330
+ self.elements.tip.css({ left: '50%', marginLeft: -(self.options.style.tip.size.width / 2) });
1331
+
1332
+ else if(corner.search(/Left/) !== -1)
1333
+ self.elements.tip.css({ left: self.options.style.border.radius });
1334
+
1335
+ else if(corner.search(/Right/) !== -1)
1336
+ self.elements.tip.css({ right: self.options.style.border.radius });
1337
+
1338
+ if(corner.search(/top/) !== -1)
1339
+ self.elements.tip.css({ top: -positionAdjust });
1340
+ else
1341
+ self.elements.tip.css({ bottom: positionAdjust });
1342
+
1343
+ }
1344
+ else if(corner.search(/left|right/) !== -1)
1345
+ {
1346
+ if(corner.search(/Middle/) !== -1)
1347
+ self.elements.tip.css({ top: '50%', marginTop: -(self.options.style.tip.size.height / 2) });
1348
+
1349
+ else if(corner.search(/Top/) !== -1)
1350
+ self.elements.tip.css({ top: self.options.style.border.radius });
1351
+
1352
+ else if(corner.search(/Bottom/) !== -1)
1353
+ self.elements.tip.css({ bottom: self.options.style.border.radius });
1354
+
1355
+ if(corner.search(/left/) !== -1)
1356
+ self.elements.tip.css({ left: -positionAdjust });
1357
+ else
1358
+ self.elements.tip.css({ right: positionAdjust });
1359
+ };
1360
+
1361
+ // Adjust tooltip padding to compensate for tip
1362
+ paddingCorner = 'padding-' + corner.match(/left|right|top|bottom/)[0];
1363
+ paddingSize = self.options.style.tip.size[ (paddingCorner.search(/left|right/) !== -1) ? 'width' : 'height' ];
1364
+ self.elements.tooltip.css('padding', 0);
1365
+ self.elements.tooltip.css(paddingCorner, paddingSize);
1366
+
1367
+ };
1368
+
1369
+ // Create title bar for content
1370
+ function createTitle()
1371
+ {
1372
+ var self = this;
1373
+
1374
+ // Destroy previous title element, if present
1375
+ if(self.elements.title !== null) self.elements.title.remove();
1376
+
1377
+ // Create title element
1378
+ self.elements.title = $('<div class="'+self.options.style.classes.title+'">')
1379
+ .css( jQueryStyle(self.options.style.title, true) )
1380
+ .css({ zoom: 1 })
1381
+ .prependTo(self.elements.contentWrapper);
1382
+
1383
+ // Update title with contents if enabled
1384
+ if(self.options.content.title.text) self.updateTitle.call(self, self.options.content.title.text);
1385
+
1386
+ // Create title close buttons if enabled
1387
+ if(self.options.content.title.button !== false
1388
+ && typeof self.options.content.title.button == 'string')
1389
+ {
1390
+ self.elements.button = $('<a class="'+self.options.style.classes.button+'" style="float:right; position: relative"></a>')
1391
+ .css( jQueryStyle(self.options.style.button, true) )
1392
+ .html(self.options.content.title.button)
1393
+ .prependTo(self.elements.title)
1394
+ .click(function(event){ if(!self.status.disabled) self.hide(event) });
1395
+ };
1396
+ };
1397
+
1398
+ // Assign hide and show events
1399
+ function assignEvents()
1400
+ {
1401
+ var self, showTarget, hideTarget, inactiveEvents;
1402
+ self = this;
1403
+
1404
+ // Setup event target variables
1405
+ showTarget = self.options.show.when.target;
1406
+ hideTarget = self.options.hide.when.target;
1407
+
1408
+ // Add tooltip as a hideTarget is its fixed
1409
+ if(self.options.hide.fixed) hideTarget = hideTarget.add(self.elements.tooltip);
1410
+
1411
+ // Check if the hide event is special 'inactive' type
1412
+ if(self.options.hide.when.event == 'inactive')
1413
+ {
1414
+ // Define events which reset the 'inactive' event handler
1415
+ inactiveEvents = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove',
1416
+ 'mouseout', 'mouseenter', 'mouseleave', 'mouseover' ];
1417
+
1418
+ // Define 'inactive' event timer method
1419
+ function inactiveMethod(event)
1420
+ {
1421
+ if(self.status.disabled === true) return;
1422
+
1423
+ //Clear and reset the timer
1424
+ clearTimeout(self.timers.inactive);
1425
+ self.timers.inactive = setTimeout(function()
1426
+ {
1427
+ // Unassign 'inactive' events
1428
+ $(inactiveEvents).each(function()
1429
+ {
1430
+ hideTarget.unbind(this+'.qtip-inactive');
1431
+ self.elements.content.unbind(this+'.qtip-inactive');
1432
+ });
1433
+
1434
+ // Hide the tooltip
1435
+ self.hide(event);
1436
+ }
1437
+ , self.options.hide.delay);
1438
+ };
1439
+ }
1440
+
1441
+ // Check if the tooltip is 'fixed'
1442
+ else if(self.options.hide.fixed === true)
1443
+ {
1444
+ self.elements.tooltip.bind('mouseover.qtip', function()
1445
+ {
1446
+ if(self.status.disabled === true) return;
1447
+
1448
+ // Reset the hide timer
1449
+ clearTimeout(self.timers.hide);
1450
+ });
1451
+ };
1452
+
1453
+ // Define show event method
1454
+ function showMethod(event)
1455
+ {
1456
+ if(self.status.disabled === true) return;
1457
+
1458
+ // If set, hide tooltip when inactive for delay period
1459
+ if(self.options.hide.when.event == 'inactive')
1460
+ {
1461
+ // Assign each reset event
1462
+ $(inactiveEvents).each(function()
1463
+ {
1464
+ hideTarget.bind(this+'.qtip-inactive', inactiveMethod);
1465
+ self.elements.content.bind(this+'.qtip-inactive', inactiveMethod);
1466
+ });
1467
+
1468
+ // Start the inactive timer
1469
+ inactiveMethod();
1470
+ };
1471
+
1472
+ // Clear hide timers
1473
+ clearTimeout(self.timers.show);
1474
+ clearTimeout(self.timers.hide);
1475
+
1476
+ // Start show timer
1477
+ self.timers.show = setTimeout(function(){ self.show(event); }, self.options.show.delay);
1478
+ };
1479
+
1480
+ // Define hide event method
1481
+ function hideMethod(event)
1482
+ {
1483
+ if(self.status.disabled === true) return;
1484
+
1485
+ // Prevent hiding if tooltip is fixed and event target is the tooltip
1486
+ if(self.options.hide.fixed === true
1487
+ && self.options.hide.when.event.search(/mouse(out|leave)/i) !== -1
1488
+ && $(event.relatedTarget).parents('div.qtip[qtip]').length > 0)
1489
+ {
1490
+ // Prevent default and popagation
1491
+ event.stopPropagation();
1492
+ event.preventDefault();
1493
+
1494
+ // Reset the hide timer
1495
+ clearTimeout(self.timers.hide);
1496
+ return false;
1497
+ };
1498
+
1499
+ // Clear timers and stop animation queue
1500
+ clearTimeout(self.timers.show);
1501
+ clearTimeout(self.timers.hide);
1502
+ self.elements.tooltip.stop(true, true);
1503
+
1504
+ // If tooltip has displayed, start hide timer
1505
+ self.timers.hide = setTimeout(function(){ self.hide(event); }, self.options.hide.delay);
1506
+ };
1507
+
1508
+ // Both events and targets are identical, apply events using a toggle
1509
+ if((self.options.show.when.target.add(self.options.hide.when.target).length === 1
1510
+ && self.options.show.when.event == self.options.hide.when.event
1511
+ && self.options.hide.when.event !== 'inactive')
1512
+ || self.options.hide.when.event == 'unfocus')
1513
+ {
1514
+ self.cache.toggle = 0;
1515
+ // Use a toggle to prevent hide/show conflicts
1516
+ showTarget.bind(self.options.show.when.event + '.qtip', function(event)
1517
+ {
1518
+ if(self.cache.toggle == 0) showMethod(event);
1519
+ else hideMethod(event);
1520
+ });
1521
+ }
1522
+
1523
+ // Events are not identical, bind normally
1524
+ else
1525
+ {
1526
+ showTarget.bind(self.options.show.when.event + '.qtip', showMethod);
1527
+
1528
+ // If the hide event is not 'inactive', bind the hide method
1529
+ if(self.options.hide.when.event !== 'inactive')
1530
+ hideTarget.bind(self.options.hide.when.event + '.qtip', hideMethod);
1531
+ };
1532
+
1533
+ // Focus the tooltip on mouseover
1534
+ if(self.options.position.type.search(/(fixed|absolute)/) !== -1)
1535
+ self.elements.tooltip.bind('mouseover.qtip', self.focus);
1536
+
1537
+ // If mouse is the target, update tooltip position on mousemove
1538
+ if(self.options.position.target === 'mouse' && self.options.position.type !== 'static')
1539
+ {
1540
+ showTarget.bind('mousemove.qtip', function(event)
1541
+ {
1542
+ // Set the new mouse positions if adjustment is enabled
1543
+ self.cache.mouse = { x: event.pageX, y: event.pageY };
1544
+
1545
+ // Update the tooltip position only if the tooltip is visible and adjustment is enabled
1546
+ if(self.status.disabled === false
1547
+ && self.options.position.adjust.mouse === true
1548
+ && self.options.position.type !== 'static'
1549
+ && self.elements.tooltip.css('display') !== 'none')
1550
+ self.updatePosition(event);
1551
+ });
1552
+ };
1553
+ };
1554
+
1555
+ // Screen position adjustment
1556
+ function screenAdjust(position, target, tooltip)
1557
+ {
1558
+ var self, adjustedPosition, adjust, newCorner, overflow, corner;
1559
+ self = this;
1560
+
1561
+ // Setup corner and adjustment variable
1562
+ if(tooltip.corner == 'center') return target.position // TODO: 'center' corner adjustment
1563
+ adjustedPosition = $.extend({}, position);
1564
+ newCorner = { x: false, y: false };
1565
+
1566
+ // Define overflow properties
1567
+ overflow = {
1568
+ left: (adjustedPosition.left < $.fn.qtip.cache.screen.scroll.left),
1569
+ right: (adjustedPosition.left + tooltip.dimensions.width + 2 >= $.fn.qtip.cache.screen.width + $.fn.qtip.cache.screen.scroll.left),
1570
+ top: (adjustedPosition.top < $.fn.qtip.cache.screen.scroll.top),
1571
+ bottom: (adjustedPosition.top + tooltip.dimensions.height + 2 >= $.fn.qtip.cache.screen.height + $.fn.qtip.cache.screen.scroll.top)
1572
+ };
1573
+
1574
+ // Determine new positioning properties
1575
+ adjust = {
1576
+ left: (overflow.left && (tooltip.corner.search(/right/i) != -1 || (tooltip.corner.search(/right/i) == -1 && !overflow.right))),
1577
+ right: (overflow.right && (tooltip.corner.search(/left/i) != -1 || (tooltip.corner.search(/left/i) == -1 && !overflow.left))),
1578
+ top: (overflow.top && tooltip.corner.search(/top/i) == -1),
1579
+ bottom: (overflow.bottom && tooltip.corner.search(/bottom/i) == -1)
1580
+ };
1581
+
1582
+ // Tooltip overflows off the left side of the screen
1583
+ if(adjust.left)
1584
+ {
1585
+ if(self.options.position.target !== 'mouse')
1586
+ adjustedPosition.left = target.position.left + target.dimensions.width;
1587
+ else
1588
+ adjustedPosition.left = self.cache.mouse.x
1589
+
1590
+ newCorner.x = 'Left';
1591
+ }
1592
+
1593
+ // Tooltip overflows off the right side of the screen
1594
+ else if(adjust.right)
1595
+ {
1596
+ if(self.options.position.target !== 'mouse')
1597
+ adjustedPosition.left = target.position.left - tooltip.dimensions.width;
1598
+ else
1599
+ adjustedPosition.left = self.cache.mouse.x - tooltip.dimensions.width;
1600
+
1601
+ newCorner.x = 'Right';
1602
+ };
1603
+
1604
+ // Tooltip overflows off the top of the screen
1605
+ if(adjust.top)
1606
+ {
1607
+ if(self.options.position.target !== 'mouse')
1608
+ adjustedPosition.top = target.position.top + target.dimensions.height;
1609
+ else
1610
+ adjustedPosition.top = self.cache.mouse.y
1611
+
1612
+ newCorner.y = 'top';
1613
+ }
1614
+
1615
+ // Tooltip overflows off the bottom of the screen
1616
+ else if(adjust.bottom)
1617
+ {
1618
+ if(self.options.position.target !== 'mouse')
1619
+ adjustedPosition.top = target.position.top - tooltip.dimensions.height;
1620
+ else
1621
+ adjustedPosition.top = self.cache.mouse.y - tooltip.dimensions.height;
1622
+
1623
+ newCorner.y = 'bottom';
1624
+ };
1625
+
1626
+ // Don't adjust if resulting position is negative
1627
+ if(adjustedPosition.left < 0)
1628
+ {
1629
+ adjustedPosition.left = position.left;
1630
+ newCorner.x = false;
1631
+ };
1632
+ if(adjustedPosition.top < 0)
1633
+ {
1634
+ adjustedPosition.top = position.top;
1635
+ newCorner.y = false;
1636
+ };
1637
+
1638
+ // Change tip corner if positioning has changed and tips are enabled
1639
+ if(self.options.style.tip.corner !== false)
1640
+ {
1641
+ // Determine new corner properties
1642
+ adjustedPosition.corner = new String(tooltip.corner);
1643
+ if(newCorner.x !== false) adjustedPosition.corner = adjustedPosition.corner.replace(/Left|Right|Middle/, newCorner.x);
1644
+ if(newCorner.y !== false) adjustedPosition.corner = adjustedPosition.corner.replace(/top|bottom/, newCorner.y);
1645
+
1646
+ // Adjust tip if position has changed and tips are enabled
1647
+ if(adjustedPosition.corner !== self.elements.tip.attr('rel'))
1648
+ createTip.call(self, adjustedPosition.corner);
1649
+ };
1650
+
1651
+ return adjustedPosition;
1652
+ };
1653
+
1654
+ // Build a jQuery style object from supplied style object
1655
+ function jQueryStyle(style, sub)
1656
+ {
1657
+ var styleObj, i;
1658
+
1659
+ styleObj = $.extend(true, {}, style);
1660
+ for(i in styleObj)
1661
+ {
1662
+ if(sub === true && i.search(/(tip|classes)/i) !== -1)
1663
+ delete styleObj[i];
1664
+ else if(!sub && i.search(/(width|border|tip|title|classes|user)/i) !== -1)
1665
+ delete styleObj[i];
1666
+ };
1667
+
1668
+ return styleObj;
1669
+ };
1670
+
1671
+ // Sanitize styles
1672
+ function sanitizeStyle(style)
1673
+ {
1674
+ if(typeof style.tip !== 'object') style.tip = { corner: style.tip };
1675
+ if(typeof style.tip.size !== 'object') style.tip.size = { width: style.tip.size, height: style.tip.size };
1676
+ if(typeof style.border !== 'object') style.border = { width: style.border };
1677
+ if(typeof style.width !== 'object') style.width = { value: style.width };
1678
+ if(typeof style.width.max == 'string') style.width.max = parseInt(style.width.max.replace(/([0-9]+)/i, "$1"));
1679
+ if(typeof style.width.min == 'string') style.width.min = parseInt(style.width.min.replace(/([0-9]+)/i, "$1"));
1680
+
1681
+ // Convert deprecated x and y tip values to width/height
1682
+ if(typeof style.tip.size.x == 'number')
1683
+ {
1684
+ style.tip.size.width = style.tip.size.x;
1685
+ delete style.tip.size.x;
1686
+ };
1687
+ if(typeof style.tip.size.y == 'number')
1688
+ {
1689
+ style.tip.size.height = style.tip.size.y;
1690
+ delete style.tip.size.y;
1691
+ };
1692
+
1693
+ return style;
1694
+ };
1695
+
1696
+ // Build styles recursively with inheritance
1697
+ function buildStyle()
1698
+ {
1699
+ var self, i, styleArray, styleExtend, finalStyle;
1700
+ self = this;
1701
+
1702
+ // Build style options from supplied arguments
1703
+ styleArray = [true, {}];
1704
+ for(i = 0; i < arguments.length; i++)
1705
+ styleArray.push(arguments[i]);
1706
+ styleExtend = [ $.extend.apply($, styleArray) ];
1707
+
1708
+ // Loop through each named style inheritance
1709
+ while(typeof styleExtend[0].name == 'string')
1710
+ {
1711
+ // Sanitize style data and append to extend array
1712
+ styleExtend.unshift( sanitizeStyle($.fn.qtip.styles[ styleExtend[0].name ]) );
1713
+ };
1714
+
1715
+ // Make sure resulting tooltip className represents final style
1716
+ styleExtend.unshift(true, {classes:{ tooltip: 'qtip-' + (arguments[0].name || 'defaults') }}, $.fn.qtip.styles.defaults);
1717
+
1718
+ // Extend into a single style object
1719
+ finalStyle = $.extend.apply($, styleExtend);
1720
+
1721
+ // Force even numbers for pixel precision
1722
+ if(finalStyle.tip.size.width % 2 > 0) finalStyle.tip.size.width += 1;
1723
+ if(finalStyle.tip.size.height % 2 > 0) finalStyle.tip.size.height += 1;
1724
+
1725
+ // Sanitize final styles tip corner value
1726
+ if(finalStyle.tip.corner === true)
1727
+ finalStyle.tip.corner = (self.options.position.corner.tooltip === 'center') ? false : self.options.position.corner.tooltip;
1728
+
1729
+ return finalStyle;
1730
+ };
1731
+
1732
+ // Tip coordinates calculator
1733
+ function calculateTip(corner, width, height)
1734
+ {
1735
+ // Define tip coordinates in terms of height and width values
1736
+ var tips = {
1737
+ bottomRight: [[0,0], [width,height], [width,0]],
1738
+ bottomLeft: [[0,0], [width,0], [0,height]],
1739
+ topRight: [[0,height], [width,0], [width,height]],
1740
+ topLeft: [[0,0], [0,height], [width,height]],
1741
+ topMiddle: [[0,height], [width / 2,0], [width,height]],
1742
+ bottomMiddle: [[0,0], [width,0], [width / 2,height]],
1743
+ rightMiddle: [[0,0], [width,height / 2], [0,height]],
1744
+ leftMiddle: [[width,0], [width,height], [0,height / 2]]
1745
+ };
1746
+ tips.leftTop = tips.bottomRight;
1747
+ tips.rightTop = tips.bottomLeft;
1748
+ tips.leftBottom = tips.topRight;
1749
+ tips.rightBottom = tips.topLeft;
1750
+
1751
+ return tips[corner];
1752
+ };
1753
+
1754
+ // Border coordinates calculator
1755
+ function calculateBorders(radius)
1756
+ {
1757
+ var borders;
1758
+
1759
+ // Use canvas element if supported
1760
+ if($('<canvas>').get(0).getContext)
1761
+ {
1762
+ borders = {
1763
+ topLeft: [radius,radius], topRight: [0,radius],
1764
+ bottomLeft: [radius,0], bottomRight: [0,0]
1765
+ };
1766
+ }
1767
+
1768
+ // Canvas not supported - Use VML (IE)
1769
+ else
1770
+ {
1771
+ borders = {
1772
+ topLeft: [-90,90,0], topRight: [-90,90,-radius],
1773
+ bottomLeft: [90,270,0], bottomRight: [90, 270,-radius]
1774
+ };
1775
+ };
1776
+
1777
+ return borders;
1778
+ };
1779
+
1780
+ // BGIFRAME JQUERY PLUGIN ADAPTION
1781
+ // Special thanks to Brandon Aaron for this plugin
1782
+ // http://plugins.jquery.com/project/bgiframe
1783
+ function bgiframe()
1784
+ {
1785
+ var self, html, dimensions;
1786
+ self = this;
1787
+ dimensions = self.getDimensions();
1788
+
1789
+ // Setup iframe HTML string
1790
+ html = '<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:false" '+
1791
+ 'style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=\'0\'); border: 1px solid red; ' +
1792
+ 'height:'+dimensions.height+'px; width:'+dimensions.width+'px" />';
1793
+
1794
+ // Append the new HTML and setup element reference
1795
+ self.elements.bgiframe = self.elements.wrapper.prepend(html).children('.qtip-bgiframe:first');
1796
+ };
1797
+
1798
+ // Assign cache and event initialisation on document load
1799
+ $(document).ready(function()
1800
+ {
1801
+ // Setup library cache with window scroll and dimensions of document
1802
+ $.fn.qtip.cache = {
1803
+ screen: {
1804
+ scroll: { left: $(window).scrollLeft(), top: $(window).scrollTop() },
1805
+ width: $(window).width(),
1806
+ height: $(window).height()
1807
+ }
1808
+ };
1809
+
1810
+ // Adjust positions of the tooltips on window resize or scroll if enabled
1811
+ var adjustTimer;
1812
+ $(window).bind('resize scroll', function(event)
1813
+ {
1814
+ clearTimeout(adjustTimer);
1815
+ adjustTimer = setTimeout(function()
1816
+ {
1817
+ // Readjust cached screen values
1818
+ if(event.type === 'scroll')
1819
+ $.fn.qtip.cache.screen.scroll = { left: $(window).scrollLeft(), top: $(window).scrollTop() };
1820
+ else
1821
+ {
1822
+ $.fn.qtip.cache.screen.width = $(window).width();
1823
+ $.fn.qtip.cache.screen.height = $(window).height();
1824
+ };
1825
+
1826
+ for(i = 0; i < $.fn.qtip.interfaces.length; i++)
1827
+ {
1828
+ // Access current elements API
1829
+ var api = $.fn.qtip.interfaces[i];
1830
+
1831
+ // Update position if resize or scroll adjustments are enabled
1832
+ if(api.status.rendered === true
1833
+ && (api.options.position.type !== 'static'
1834
+ || api.options.position.adjust.scroll && event.type === 'scroll'
1835
+ || api.options.position.adjust.resize && event.type === 'resize'))
1836
+ {
1837
+ // Queue the animation so positions are updated correctly
1838
+ api.updatePosition(event, true);
1839
+ }
1840
+ };
1841
+ }
1842
+ , 100);
1843
+ })
1844
+
1845
+ // Hide unfocus toolipts on document mousedown
1846
+ $(document).bind('mousedown.qtip', function(event)
1847
+ {
1848
+ if($(event.target).parents('div.qtip').length === 0)
1849
+ {
1850
+ $('.qtip[unfocus]').each(function()
1851
+ {
1852
+ var api = $(this).qtip("api");
1853
+
1854
+ // Only hide if its visible and not the tooltips target
1855
+ if($(this).is(':visible') && !api.status.disabled
1856
+ && $(event.target).add(api.elements.target).length > 1)
1857
+ api.hide(event);
1858
+ })
1859
+ };
1860
+ })
1861
+ });
1862
+
1863
+ // Define qTip API interfaces array
1864
+ $.fn.qtip.interfaces = []
1865
+
1866
+ // Define log and constant place holders
1867
+ $.fn.qtip.log = { error: function(){ return this; } };
1868
+ $.fn.qtip.constants = {};
1869
+
1870
+ // Define configuration defaults
1871
+ $.fn.qtip.defaults = {
1872
+ // Content
1873
+ content: {
1874
+ prerender: false,
1875
+ text: false,
1876
+ url: false,
1877
+ data: null,
1878
+ title: {
1879
+ text: false,
1880
+ button: false
1881
+ }
1882
+ },
1883
+ // Position
1884
+ position: {
1885
+ target: false,
1886
+ corner: {
1887
+ target: 'bottomRight',
1888
+ tooltip: 'topLeft'
1889
+ },
1890
+ adjust: {
1891
+ x: 0, y: 0,
1892
+ mouse: true,
1893
+ screen: false,
1894
+ scroll: true,
1895
+ resize: true
1896
+ },
1897
+ type: 'absolute',
1898
+ container: false
1899
+ },
1900
+ // Effects
1901
+ show: {
1902
+ when: {
1903
+ target: false,
1904
+ event: 'mouseover'
1905
+ },
1906
+ effect: {
1907
+ type: 'fade',
1908
+ length: 100
1909
+ },
1910
+ delay: 140,
1911
+ solo: false,
1912
+ ready: false
1913
+ },
1914
+ hide: {
1915
+ when: {
1916
+ target: false,
1917
+ event: 'mouseout'
1918
+ },
1919
+ effect: {
1920
+ type: 'fade',
1921
+ length: 100
1922
+ },
1923
+ delay: 0,
1924
+ fixed: false
1925
+ },
1926
+ // Callbacks
1927
+ api: {
1928
+ beforeRender: function(){},
1929
+ onRender: function(){},
1930
+ beforePositionUpdate: function(){},
1931
+ onPositionUpdate: function(){},
1932
+ beforeShow: function(){},
1933
+ onShow: function(){},
1934
+ beforeHide: function(){},
1935
+ onHide: function(){},
1936
+ beforeContentUpdate: function(){},
1937
+ onContentUpdate: function(){},
1938
+ beforeContentLoad: function(){},
1939
+ onContentLoad: function(){},
1940
+ beforeTitleUpdate: function(){},
1941
+ onTitleUpdate: function(){},
1942
+ beforeDestroy: function(){},
1943
+ onDestroy: function(){},
1944
+ beforeFocus: function(){},
1945
+ onFocus: function(){}
1946
+ }
1947
+ };
1948
+
1949
+ $.fn.qtip.styles = {
1950
+ defaults: {
1951
+ background: 'white',
1952
+ color: '#111',
1953
+ overflow: 'hidden',
1954
+ textAlign: 'left',
1955
+ width: {
1956
+ min: 0,
1957
+ max: 250
1958
+ },
1959
+ padding: '5px 9px',
1960
+ border: {
1961
+ width: 1,
1962
+ radius: 0,
1963
+ color: '#d3d3d3'
1964
+ },
1965
+ tip: {
1966
+ corner: false,
1967
+ color: false,
1968
+ size: { width: 13, height: 13 },
1969
+ opacity: 1
1970
+ },
1971
+ title: {
1972
+ background: '#e1e1e1',
1973
+ fontWeight: 'bold',
1974
+ padding: '7px 12px'
1975
+ },
1976
+ button: {
1977
+ cursor: 'pointer'
1978
+ },
1979
+ classes: {
1980
+ target: '',
1981
+ tip: 'qtip-tip',
1982
+ title: 'qtip-title',
1983
+ button: 'qtip-button',
1984
+ content: 'qtip-content',
1985
+ active: 'qtip-active'
1986
+ }
1987
+ },
1988
+ cream: {
1989
+ border: {
1990
+ width: 3,
1991
+ radius: 0,
1992
+ color: '#F9E98E'
1993
+ },
1994
+ title: {
1995
+ background: '#F0DE7D',
1996
+ color: '#A27D35'
1997
+ },
1998
+ background: '#FBF7AA',
1999
+ color: '#A27D35',
2000
+
2001
+ classes: { tooltip: 'qtip-cream' }
2002
+ },
2003
+ light: {
2004
+ border: {
2005
+ width: 3,
2006
+ radius: 0,
2007
+ color: '#E2E2E2'
2008
+ },
2009
+ title: {
2010
+ background: '#f1f1f1',
2011
+ color: '#454545'
2012
+ },
2013
+ background: 'white',
2014
+ color: '#454545',
2015
+
2016
+ classes: { tooltip: 'qtip-light' }
2017
+ },
2018
+ dark: {
2019
+ border: {
2020
+ width: 3,
2021
+ radius: 0,
2022
+ color: '#303030'
2023
+ },
2024
+ title: {
2025
+ background: '#404040',
2026
+ color: '#f3f3f3'
2027
+ },
2028
+ background: '#505050',
2029
+ color: '#f3f3f3',
2030
+
2031
+ classes: { tooltip: 'qtip-dark' }
2032
+ },
2033
+ red: {
2034
+ border: {
2035
+ width: 3,
2036
+ radius: 0,
2037
+ color: '#CE6F6F'
2038
+ },
2039
+ title: {
2040
+ background: '#f28279',
2041
+ color: '#9C2F2F'
2042
+ },
2043
+ background: '#F79992',
2044
+ color: '#9C2F2F',
2045
+
2046
+ classes: { tooltip: 'qtip-red' }
2047
+ },
2048
+ green: {
2049
+ border: {
2050
+ width: 3,
2051
+ radius: 0,
2052
+ color: '#A9DB66'
2053
+ },
2054
+ title: {
2055
+ background: '#b9db8c',
2056
+ color: '#58792E'
2057
+ },
2058
+ background: '#CDE6AC',
2059
+ color: '#58792E',
2060
+
2061
+ classes: { tooltip: 'qtip-green' }
2062
+ },
2063
+ blue: {
2064
+ border: {
2065
+ width: 3,
2066
+ radius: 0,
2067
+ color: '#ADD9ED'
2068
+ },
2069
+ title: {
2070
+ background: '#D0E9F5',
2071
+ color: '#5E99BD'
2072
+ },
2073
+ background: '#E5F6FE',
2074
+ color: '#4D9FBF',
2075
+
2076
+ classes: { tooltip: 'qtip-blue' }
2077
+ }
2078
+ };
2079
+ })(jQuery);
2080
+
2081
+
2082
+
2083
+
2084
+
2085
+