adva_cms 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+