benmanns-atreides 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (449) hide show
  1. data/LICENSE +7 -0
  2. data/README.rdoc +1 -0
  3. data/app/assets/javascripts/atreides/admin.facebook.js +137 -0
  4. data/app/assets/javascripts/atreides/admin.js +23 -0
  5. data/app/assets/javascripts/atreides/admin_base.js.erb +273 -0
  6. data/app/assets/javascripts/atreides/admin_edit.js +9 -0
  7. data/app/assets/javascripts/atreides/application.js +15 -0
  8. data/app/assets/javascripts/atreides/public.js +24 -0
  9. data/app/assets/javascripts/atreides/public_base.js.erb +119 -0
  10. data/app/assets/javascripts/atreides/terryblr.js +57 -0
  11. data/app/assets/stylesheets/atreides/admin.css +21 -0
  12. data/app/assets/stylesheets/atreides/admin_base.css.erb +1693 -0
  13. data/app/assets/stylesheets/atreides/application.css +13 -0
  14. data/app/assets/stylesheets/atreides/formtastic_changes.css +10 -0
  15. data/app/assets/stylesheets/atreides/iphone-checkboxes.css.erb +97 -0
  16. data/app/assets/stylesheets/atreides/jBreadCrumb.css +109 -0
  17. data/app/assets/stylesheets/atreides/public.css +15 -0
  18. data/app/assets/stylesheets/atreides/public_base.css +101 -0
  19. data/app/assets/stylesheets/atreides/swfupload.css.erb +63 -0
  20. data/app/controllers/admin/atreides/content_parts_controller.rb +43 -0
  21. data/app/controllers/admin/atreides/dropbox_controller.rb +40 -0
  22. data/app/controllers/admin/atreides/facebook_controller.rb +38 -0
  23. data/app/controllers/admin/atreides/features_controller.rb +63 -0
  24. data/app/controllers/admin/atreides/github_controller.rb +35 -0
  25. data/app/controllers/admin/atreides/links_controller.rb +3 -0
  26. data/app/controllers/admin/atreides/messages_controller.rb +3 -0
  27. data/app/controllers/admin/atreides/orders_controller.rb +35 -0
  28. data/app/controllers/admin/atreides/pages_controller.rb +59 -0
  29. data/app/controllers/admin/atreides/photos_controller.rb +79 -0
  30. data/app/controllers/admin/atreides/posts_controller.rb +109 -0
  31. data/app/controllers/admin/atreides/products_controller.rb +39 -0
  32. data/app/controllers/admin/atreides/sessions_controller.rb +7 -0
  33. data/app/controllers/admin/atreides/sizes_controller.rb +4 -0
  34. data/app/controllers/admin/atreides/tags_controller.rb +20 -0
  35. data/app/controllers/admin/atreides/users_controller.rb +50 -0
  36. data/app/controllers/admin/atreides/videos_controller.rb +53 -0
  37. data/app/controllers/atreides/admin_controller.rb +96 -0
  38. data/app/controllers/atreides/admin_home_controller.rb +215 -0
  39. data/app/controllers/atreides/application_controller.rb +93 -0
  40. data/app/controllers/atreides/home_controller.rb +71 -0
  41. data/app/controllers/atreides/likes_controller.rb +44 -0
  42. data/app/controllers/atreides/pages_controller.rb +34 -0
  43. data/app/controllers/atreides/posts_controller.rb +119 -0
  44. data/app/controllers/atreides/public_controller.rb +43 -0
  45. data/app/helpers/admin/atreides/dropbox_helper.rb +42 -0
  46. data/app/helpers/admin/atreides/features_helper.rb +4 -0
  47. data/app/helpers/admin/atreides/github_helper.rb +43 -0
  48. data/app/helpers/admin/atreides/links_helper.rb +4 -0
  49. data/app/helpers/admin/atreides/messages_helper.rb +4 -0
  50. data/app/helpers/admin/atreides/orders_helper.rb +30 -0
  51. data/app/helpers/admin/atreides/pages_helper.rb +17 -0
  52. data/app/helpers/admin/atreides/photos_helper.rb +14 -0
  53. data/app/helpers/admin/atreides/posts_helper.rb +41 -0
  54. data/app/helpers/admin/atreides/products_helper.rb +37 -0
  55. data/app/helpers/admin/atreides/sizes_helper.rb +4 -0
  56. data/app/helpers/admin/atreides/user_sessions_helper.rb +4 -0
  57. data/app/helpers/admin/atreides/users_helper.rb +8 -0
  58. data/app/helpers/admin/atreides/videos_helper.rb +4 -0
  59. data/app/helpers/atreides/admin_helper.rb +243 -0
  60. data/app/helpers/atreides/admin_home_helper.rb +4 -0
  61. data/app/helpers/atreides/application_helper.rb +210 -0
  62. data/app/helpers/atreides/home_helper.rb +4 -0
  63. data/app/helpers/atreides/posts_helper.rb +119 -0
  64. data/app/inputs/files_input.rb +13 -0
  65. data/app/inputs/price_input.rb +18 -0
  66. data/app/inputs/underline_input.rb +16 -0
  67. data/app/models/atreides/ability.rb +24 -0
  68. data/app/models/atreides/content_part.rb +106 -0
  69. data/app/models/atreides/facebook_user.rb +103 -0
  70. data/app/models/atreides/feature.rb +90 -0
  71. data/app/models/atreides/github.rb +74 -0
  72. data/app/models/atreides/like.rb +35 -0
  73. data/app/models/atreides/line_item.rb +4 -0
  74. data/app/models/atreides/link.rb +32 -0
  75. data/app/models/atreides/message.rb +34 -0
  76. data/app/models/atreides/order.rb +209 -0
  77. data/app/models/atreides/page.rb +114 -0
  78. data/app/models/atreides/photo.rb +130 -0
  79. data/app/models/atreides/post.rb +271 -0
  80. data/app/models/atreides/preferences.rb +31 -0
  81. data/app/models/atreides/product.rb +75 -0
  82. data/app/models/atreides/site.rb +59 -0
  83. data/app/models/atreides/size.rb +44 -0
  84. data/app/models/atreides/tag.rb +31 -0
  85. data/app/models/atreides/tweet.rb +123 -0
  86. data/app/models/atreides/user.rb +129 -0
  87. data/app/models/atreides/video.rb +206 -0
  88. data/app/models/atreides/vote.rb +43 -0
  89. data/app/models/fb_post_publisher_job.rb +72 -0
  90. data/app/models/settings.rb +19 -0
  91. data/app/models/tumblr_post_publisher_job.rb +75 -0
  92. data/app/models/tw_post_publisher_job.rb +54 -0
  93. data/app/views/admin/_edit_head_content.html.haml +2 -0
  94. data/app/views/admin/atreides/content_parts/_form.html.haml +21 -0
  95. data/app/views/admin/atreides/content_parts/_photos.html.haml +18 -0
  96. data/app/views/admin/atreides/content_parts/_text.html.haml +1 -0
  97. data/app/views/admin/atreides/content_parts/_videos.html.haml +12 -0
  98. data/app/views/admin/atreides/content_parts/destroy.js.haml +3 -0
  99. data/app/views/admin/atreides/content_parts/edit.html.haml +0 -0
  100. data/app/views/admin/atreides/content_parts/new.html.haml +0 -0
  101. data/app/views/admin/atreides/content_parts/new.js.haml +11 -0
  102. data/app/views/admin/atreides/dropbox/_uploader.html.haml +134 -0
  103. data/app/views/admin/atreides/dropbox/list.html.haml +27 -0
  104. data/app/views/admin/atreides/dropbox/setup.html.haml +8 -0
  105. data/app/views/admin/atreides/facebook/index.html.haml +29 -0
  106. data/app/views/admin/atreides/features/_form.html.haml +60 -0
  107. data/app/views/admin/atreides/features/edit.html.haml +1 -0
  108. data/app/views/admin/atreides/features/index.html.haml +24 -0
  109. data/app/views/admin/atreides/features/new.html.haml +1 -0
  110. data/app/views/admin/atreides/github/index.html.haml +26 -0
  111. data/app/views/admin/atreides/github/show.html.haml +19 -0
  112. data/app/views/admin/atreides/likes/create.js.haml +2 -0
  113. data/app/views/admin/atreides/orders/_sidebar.html.haml +20 -0
  114. data/app/views/admin/atreides/orders/edit.html.haml +52 -0
  115. data/app/views/admin/atreides/orders/index.html.haml +8 -0
  116. data/app/views/admin/atreides/pages/_form.html.haml +31 -0
  117. data/app/views/admin/atreides/pages/edit.html.haml +3 -0
  118. data/app/views/admin/atreides/pages/index.html.haml +15 -0
  119. data/app/views/admin/atreides/pages/index.js.haml +4 -0
  120. data/app/views/admin/atreides/pages/new.html.haml +2 -0
  121. data/app/views/admin/atreides/photos/create.js.haml +18 -0
  122. data/app/views/admin/atreides/photos/destroy.js.haml +3 -0
  123. data/app/views/admin/atreides/posts/_archives.html.haml +19 -0
  124. data/app/views/admin/atreides/posts/_form.html.haml +66 -0
  125. data/app/views/admin/atreides/posts/_form_buttons.html.haml +9 -0
  126. data/app/views/admin/atreides/posts/_form_sidebar.html.haml +85 -0
  127. data/app/views/admin/atreides/posts/edit.html.haml +2 -0
  128. data/app/views/admin/atreides/posts/index.html.haml +24 -0
  129. data/app/views/admin/atreides/posts/index.js.haml +1 -0
  130. data/app/views/admin/atreides/posts/new.html.haml +2 -0
  131. data/app/views/admin/atreides/products/edit.html.haml +69 -0
  132. data/app/views/admin/atreides/products/index.html.haml +31 -0
  133. data/app/views/admin/atreides/sessions/new.html.haml +13 -0
  134. data/app/views/admin/atreides/user_sessions/new.html.haml +10 -0
  135. data/app/views/admin/atreides/users/_form.html.haml +19 -0
  136. data/app/views/admin/atreides/users/edit.html.haml +6 -0
  137. data/app/views/admin/atreides/users/index.html.haml +11 -0
  138. data/app/views/admin/atreides/users/new.html.haml +6 -0
  139. data/app/views/admin/atreides/users/show.html.haml +4 -0
  140. data/app/views/admin/atreides/videos/create.js.haml +9 -0
  141. data/app/views/admin/atreides/videos/destroy.js.haml +3 -0
  142. data/app/views/admin/common/_archive_sidebar.html.haml +28 -0
  143. data/app/views/admin/common/_list_table.html.erb +37 -0
  144. data/app/views/admin/common/_list_table_row.html.erb +18 -0
  145. data/app/views/admin/common/_pagination.html.erb +1 -0
  146. data/app/views/admin/common/_search_form.html.erb +6 -0
  147. data/app/views/admin/common/access_denied.html.haml +1 -0
  148. data/app/views/atreides/admin/_content_nav.html.haml +7 -0
  149. data/app/views/atreides/admin_home/_analytics.html.haml +93 -0
  150. data/app/views/atreides/admin_home/_fb_page_likes_analytics_tbody.haml +10 -0
  151. data/app/views/atreides/admin_home/_fb_page_views_analytics_tbody.haml +10 -0
  152. data/app/views/atreides/admin_home/_top_landing_pages_analytics_tbody.haml +14 -0
  153. data/app/views/atreides/admin_home/_top_referrers_analytics_tbody.haml +12 -0
  154. data/app/views/atreides/admin_home/_tweets_analytics_tbody.html.haml +8 -0
  155. data/app/views/atreides/admin_home/_visitors_analytics_tbody.html.haml +12 -0
  156. data/app/views/atreides/admin_home/index.html.haml +57 -0
  157. data/app/views/atreides/admin_home/search.html.haml +11 -0
  158. data/app/views/atreides/admin_home/setup.html.haml +15 -0
  159. data/app/views/atreides/common/_gallery_params.xml.erb +174 -0
  160. data/app/views/atreides/common/slideshow.xml.haml +6 -0
  161. data/app/views/atreides/errors/404.html.haml +10 -0
  162. data/app/views/atreides/errors/500.html.haml +4 -0
  163. data/app/views/atreides/home/index.html.haml +30 -0
  164. data/app/views/atreides/home/index.js.haml +1 -0
  165. data/app/views/atreides/home/robots.txt.erb +5 -0
  166. data/app/views/atreides/home/sitemap.xml.builder +35 -0
  167. data/app/views/atreides/pages/show.html.haml +3 -0
  168. data/app/views/atreides/posts/_archives.html.haml +19 -0
  169. data/app/views/atreides/posts/_featured_posts.html.haml +10 -0
  170. data/app/views/atreides/posts/_list.html.haml +9 -0
  171. data/app/views/atreides/posts/archives.html.haml +3 -0
  172. data/app/views/atreides/posts/archives.js.haml +1 -0
  173. data/app/views/atreides/posts/gallery_params.xml.haml +1 -0
  174. data/app/views/atreides/posts/index.atom.builder +22 -0
  175. data/app/views/atreides/posts/index.html.haml +13 -0
  176. data/app/views/atreides/posts/index.rss.builder +21 -0
  177. data/app/views/atreides/posts/show.html.haml +8 -0
  178. data/app/views/atreides/posts/tagged.html.haml +4 -0
  179. data/app/views/atreides/posts/tagged.js.haml +1 -0
  180. data/app/views/layouts/admin.html.haml +65 -0
  181. data/app/views/layouts/application.html.haml +37 -0
  182. data/app/views/layouts/atreides/application.html.erb +14 -0
  183. data/app/views/layouts/public.html.haml +39 -0
  184. data/config/cucumber.yml +11 -0
  185. data/config/locales/en.yml +207 -0
  186. data/config/locales/fr.yml +199 -0
  187. data/config/routes.rb +119 -0
  188. data/lib/assets/images/atreides/admin/add.png +0 -0
  189. data/lib/assets/images/atreides/admin/add_btn.png +0 -0
  190. data/lib/assets/images/atreides/admin/add_dashboard.png +0 -0
  191. data/lib/assets/images/atreides/admin/add_photo_button_sprite.png +0 -0
  192. data/lib/assets/images/atreides/admin/add_photos_btn.png +0 -0
  193. data/lib/assets/images/atreides/admin/background.png +0 -0
  194. data/lib/assets/images/atreides/admin/calendar.png +0 -0
  195. data/lib/assets/images/atreides/admin/chevron.gif +0 -0
  196. data/lib/assets/images/atreides/admin/chevron_overlay.png +0 -0
  197. data/lib/assets/images/atreides/admin/choose_photos_button_sprite.png +0 -0
  198. data/lib/assets/images/atreides/admin/content_bg.png +0 -0
  199. data/lib/assets/images/atreides/admin/content_bg_edit_form.png +0 -0
  200. data/lib/assets/images/atreides/admin/content_part_break.png +0 -0
  201. data/lib/assets/images/atreides/admin/content_part_drop_target.png +0 -0
  202. data/lib/assets/images/atreides/admin/content_part_icons.png +0 -0
  203. data/lib/assets/images/atreides/admin/content_part_photos.png +0 -0
  204. data/lib/assets/images/atreides/admin/content_part_text.png +0 -0
  205. data/lib/assets/images/atreides/admin/content_part_videos.png +0 -0
  206. data/lib/assets/images/atreides/admin/content_top_edit_form.png +0 -0
  207. data/lib/assets/images/atreides/admin/dashboard-indicator.gif +0 -0
  208. data/lib/assets/images/atreides/admin/dashboard_controls_activity.png +0 -0
  209. data/lib/assets/images/atreides/admin/dashboard_controls_customize.png +0 -0
  210. data/lib/assets/images/atreides/admin/dashboard_controls_drafts.png +0 -0
  211. data/lib/assets/images/atreides/admin/dashboard_controls_open.png +0 -0
  212. data/lib/assets/images/atreides/admin/dashboard_controls_posts.png +0 -0
  213. data/lib/assets/images/atreides/admin/dashboard_controls_queue.png +0 -0
  214. data/lib/assets/images/atreides/admin/dashboard_nav_border.png +0 -0
  215. data/lib/assets/images/atreides/admin/delete_bg.png +0 -0
  216. data/lib/assets/images/atreides/admin/down_arrow.png +0 -0
  217. data/lib/assets/images/atreides/admin/dropbox_big.jpg +0 -0
  218. data/lib/assets/images/atreides/admin/dropbox_btn.png +0 -0
  219. data/lib/assets/images/atreides/admin/dropbox_folder.png +0 -0
  220. data/lib/assets/images/atreides/admin/dropbox_icon.gif +0 -0
  221. data/lib/assets/images/atreides/admin/dropbox_icon.png +0 -0
  222. data/lib/assets/images/atreides/admin/expand_collapse.png +0 -0
  223. data/lib/assets/images/atreides/admin/form_sidebar_divider.png +0 -0
  224. data/lib/assets/images/atreides/admin/grey_hatch_bg.png +0 -0
  225. data/lib/assets/images/atreides/admin/header.png +0 -0
  226. data/lib/assets/images/atreides/admin/icon_dropbox.gif +0 -0
  227. data/lib/assets/images/atreides/admin/icon_home.gif +0 -0
  228. data/lib/assets/images/atreides/admin/input_bg.gif +0 -0
  229. data/lib/assets/images/atreides/admin/large_loading.gif +0 -0
  230. data/lib/assets/images/atreides/admin/new_content_icons.png +0 -0
  231. data/lib/assets/images/atreides/admin/off.png +0 -0
  232. data/lib/assets/images/atreides/admin/on.png +0 -0
  233. data/lib/assets/images/atreides/admin/page_icon.png +0 -0
  234. data/lib/assets/images/atreides/admin/permalink.png +0 -0
  235. data/lib/assets/images/atreides/admin/photos-display-type-gallery.png +0 -0
  236. data/lib/assets/images/atreides/admin/photos-display-type-photos.png +0 -0
  237. data/lib/assets/images/atreides/admin/product.png +0 -0
  238. data/lib/assets/images/atreides/admin/remove.png +0 -0
  239. data/lib/assets/images/atreides/admin/resize.png +0 -0
  240. data/lib/assets/images/atreides/admin/save_btn.png +0 -0
  241. data/lib/assets/images/atreides/admin/search_icon.png +0 -0
  242. data/lib/assets/images/atreides/admin/select_arrows.png +0 -0
  243. data/lib/assets/images/atreides/admin/slider.png +0 -0
  244. data/lib/assets/images/atreides/admin/slider_center.png +0 -0
  245. data/lib/assets/images/atreides/admin/slider_left.png +0 -0
  246. data/lib/assets/images/atreides/admin/slider_right.png +0 -0
  247. data/lib/assets/images/atreides/admin/sprite.png +0 -0
  248. data/lib/assets/images/atreides/admin/upload_btn.png +0 -0
  249. data/lib/assets/images/atreides/admin/video_bg.png +0 -0
  250. data/lib/assets/images/atreides/blank.gif +0 -0
  251. data/lib/assets/images/atreides/closelabel.png +0 -0
  252. data/lib/assets/images/atreides/loading.gif +0 -0
  253. data/lib/assets/images/atreides/sprite.png +0 -0
  254. data/lib/assets/images/atreides/tipsy.gif +0 -0
  255. data/lib/atreides.rb +81 -0
  256. data/lib/atreides/base/aasmstates.rb +117 -0
  257. data/lib/atreides/base/base.rb +40 -0
  258. data/lib/atreides/base/taggable.rb +43 -0
  259. data/lib/atreides/base/validation.rb +23 -0
  260. data/lib/atreides/configuration.rb +61 -0
  261. data/lib/atreides/engine.rb +41 -0
  262. data/lib/atreides/extendable.rb +12 -0
  263. data/lib/atreides/i18n_helpers.rb +65 -0
  264. data/lib/atreides/railties/tasks.rake +68 -0
  265. data/lib/atreides/time_formats.rb +19 -0
  266. data/lib/atreides/validators.rb +15 -0
  267. data/lib/atreides/version.rb +4 -0
  268. data/lib/generators/atreides/USAGE +0 -0
  269. data/lib/generators/atreides/atreides_generator.rb +57 -0
  270. data/lib/generators/templates/Procfile +2 -0
  271. data/lib/generators/templates/add_role_to_users.rb +16 -0
  272. data/lib/generators/templates/add_userid_to_resources.rb +15 -0
  273. data/lib/generators/templates/create_content_parts.rb +66 -0
  274. data/lib/generators/templates/create_features.rb +21 -0
  275. data/lib/generators/templates/create_likes.rb +16 -0
  276. data/lib/generators/templates/create_line_items.rb +21 -0
  277. data/lib/generators/templates/create_links.rb +16 -0
  278. data/lib/generators/templates/create_messages.rb +24 -0
  279. data/lib/generators/templates/create_orders.rb +31 -0
  280. data/lib/generators/templates/create_pages.rb +29 -0
  281. data/lib/generators/templates/create_photos.rb +22 -0
  282. data/lib/generators/templates/create_posts.rb +36 -0
  283. data/lib/generators/templates/create_preferences.rb +14 -0
  284. data/lib/generators/templates/create_products.rb +22 -0
  285. data/lib/generators/templates/create_sessions.rb +16 -0
  286. data/lib/generators/templates/create_sites.rb +35 -0
  287. data/lib/generators/templates/create_sizes.rb +16 -0
  288. data/lib/generators/templates/create_tweets.rb +25 -0
  289. data/lib/generators/templates/create_videos.rb +24 -0
  290. data/lib/generators/templates/create_votes.rb +20 -0
  291. data/lib/generators/templates/delayed_job.rb +5 -0
  292. data/lib/generators/templates/devise_create_users.rb +42 -0
  293. data/lib/generators/templates/em-net-http_override.rb +74 -0
  294. data/lib/generators/templates/initializer.rb +21 -0
  295. data/lib/generators/templates/new_relic.rb +6 -0
  296. data/lib/generators/templates/oembed.yml +63 -0
  297. data/lib/generators/templates/settings.yml +78 -0
  298. data/lib/generators/templates/string_extensions.rb +20 -0
  299. data/lib/generators/templates/unicorn.rb +2 -0
  300. data/lib/tasks/atreides_tasks.rake +4 -0
  301. data/lib/tasks/cucumber.rake +58 -0
  302. data/lib/tasks/tasks.rake +403 -0
  303. data/lib/tasks/yard.rake +18 -0
  304. data/vendor/assets/flash/atreides/player.swf +0 -0
  305. data/vendor/assets/flash/atreides/slideshowpro.swf +0 -0
  306. data/vendor/assets/flash/atreides/swfupload.swf +0 -0
  307. data/vendor/assets/images/atreides/share/aim_16.png +0 -0
  308. data/vendor/assets/images/atreides/share/apple_16.png +0 -0
  309. data/vendor/assets/images/atreides/share/bebo_16.png +0 -0
  310. data/vendor/assets/images/atreides/share/blogger_16.png +0 -0
  311. data/vendor/assets/images/atreides/share/brightkite_16.png +0 -0
  312. data/vendor/assets/images/atreides/share/cargo_16.png +0 -0
  313. data/vendor/assets/images/atreides/share/delicious_16.png +0 -0
  314. data/vendor/assets/images/atreides/share/designfloat_16.png +0 -0
  315. data/vendor/assets/images/atreides/share/designmoo_16.png +0 -0
  316. data/vendor/assets/images/atreides/share/deviantart_16.png +0 -0
  317. data/vendor/assets/images/atreides/share/digg_16.png +0 -0
  318. data/vendor/assets/images/atreides/share/digg_alt_16.png +0 -0
  319. data/vendor/assets/images/atreides/share/dopplr_16.png +0 -0
  320. data/vendor/assets/images/atreides/share/dribbble_16.png +0 -0
  321. data/vendor/assets/images/atreides/share/email_16.png +0 -0
  322. data/vendor/assets/images/atreides/share/ember_16.png +0 -0
  323. data/vendor/assets/images/atreides/share/evernote_16.png +0 -0
  324. data/vendor/assets/images/atreides/share/facebook_16.png +0 -0
  325. data/vendor/assets/images/atreides/share/flickr_16.png +0 -0
  326. data/vendor/assets/images/atreides/share/friendfeed_16.png +0 -0
  327. data/vendor/assets/images/atreides/share/gamespot_16.png +0 -0
  328. data/vendor/assets/images/atreides/share/google_16.png +0 -0
  329. data/vendor/assets/images/atreides/share/google_voice_16.png +0 -0
  330. data/vendor/assets/images/atreides/share/google_wave_16.png +0 -0
  331. data/vendor/assets/images/atreides/share/googletalk_16.png +0 -0
  332. data/vendor/assets/images/atreides/share/gowalla_16.png +0 -0
  333. data/vendor/assets/images/atreides/share/grooveshark_16.png +0 -0
  334. data/vendor/assets/images/atreides/share/ilike_16.png +0 -0
  335. data/vendor/assets/images/atreides/share/komodomedia_azure_16.png +0 -0
  336. data/vendor/assets/images/atreides/share/komodomedia_wood_16.png +0 -0
  337. data/vendor/assets/images/atreides/share/lastfm_16.png +0 -0
  338. data/vendor/assets/images/atreides/share/license.txt +9 -0
  339. data/vendor/assets/images/atreides/share/linkedin_16.png +0 -0
  340. data/vendor/assets/images/atreides/share/mixx_16.png +0 -0
  341. data/vendor/assets/images/atreides/share/mobileme_16.png +0 -0
  342. data/vendor/assets/images/atreides/share/mynameise_16.png +0 -0
  343. data/vendor/assets/images/atreides/share/myspace_16.png +0 -0
  344. data/vendor/assets/images/atreides/share/netvibes_16.png +0 -0
  345. data/vendor/assets/images/atreides/share/newsvine_16.png +0 -0
  346. data/vendor/assets/images/atreides/share/openid_16.png +0 -0
  347. data/vendor/assets/images/atreides/share/orkut_16.png +0 -0
  348. data/vendor/assets/images/atreides/share/pandora_16.png +0 -0
  349. data/vendor/assets/images/atreides/share/paypal_16.png +0 -0
  350. data/vendor/assets/images/atreides/share/picasa_16.png +0 -0
  351. data/vendor/assets/images/atreides/share/plurk_16.png +0 -0
  352. data/vendor/assets/images/atreides/share/posterous_16.png +0 -0
  353. data/vendor/assets/images/atreides/share/qik_16.png +0 -0
  354. data/vendor/assets/images/atreides/share/readernaut_16.png +0 -0
  355. data/vendor/assets/images/atreides/share/reddit_16.png +0 -0
  356. data/vendor/assets/images/atreides/share/roboto_16.png +0 -0
  357. data/vendor/assets/images/atreides/share/rss_16.png +0 -0
  358. data/vendor/assets/images/atreides/share/sharethis_16.png +0 -0
  359. data/vendor/assets/images/atreides/share/skype_16.png +0 -0
  360. data/vendor/assets/images/atreides/share/stumbleupon_16.png +0 -0
  361. data/vendor/assets/images/atreides/share/technorati_16.png +0 -0
  362. data/vendor/assets/images/atreides/share/tumblr_16.png +0 -0
  363. data/vendor/assets/images/atreides/share/twitter_16.png +0 -0
  364. data/vendor/assets/images/atreides/share/viddler_16.png +0 -0
  365. data/vendor/assets/images/atreides/share/vimeo_16.png +0 -0
  366. data/vendor/assets/images/atreides/share/virb_16.png +0 -0
  367. data/vendor/assets/images/atreides/share/windows_16.png +0 -0
  368. data/vendor/assets/images/atreides/share/wordpress_16.png +0 -0
  369. data/vendor/assets/images/atreides/share/xing_16.png +0 -0
  370. data/vendor/assets/images/atreides/share/yahoo_16.png +0 -0
  371. data/vendor/assets/images/atreides/share/yahoobuzz_16.png +0 -0
  372. data/vendor/assets/images/atreides/share/yelp_16.png +0 -0
  373. data/vendor/assets/images/atreides/share/youtube_16.png +0 -0
  374. data/vendor/assets/javascripts/atreides/backbone-0.3.3.js +1100 -0
  375. data/vendor/assets/javascripts/atreides/cufon-yui.js +7 -0
  376. data/vendor/assets/javascripts/atreides/facebox.js +309 -0
  377. data/vendor/assets/javascripts/atreides/fileuploader.js +1250 -0
  378. data/vendor/assets/javascripts/atreides/g.raphael-min.js +7 -0
  379. data/vendor/assets/javascripts/atreides/galleria.js +2 -0
  380. data/vendor/assets/javascripts/atreides/galleria/src/galleria.js +3816 -0
  381. data/vendor/assets/javascripts/atreides/galleria/src/plugins/galleria.flickr.js +221 -0
  382. data/vendor/assets/javascripts/atreides/galleria/src/plugins/galleria.history.js +602 -0
  383. data/vendor/assets/javascripts/atreides/galleria/src/themes/classic/classic-loader.gif +0 -0
  384. data/vendor/assets/javascripts/atreides/galleria/src/themes/classic/classic-map.png +0 -0
  385. data/vendor/assets/javascripts/atreides/galleria/src/themes/classic/galleria.classic.css +202 -0
  386. data/vendor/assets/javascripts/atreides/galleria/src/themes/classic/galleria.classic.js +92 -0
  387. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/b.png +0 -0
  388. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/down.gif +0 -0
  389. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/fix.gif +0 -0
  390. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/fullscreen-demo.html +34 -0
  391. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/galleria.fullscreen.css +46 -0
  392. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/galleria.fullscreen.js +193 -0
  393. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/i.png +0 -0
  394. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/l.gif +0 -0
  395. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/l2.png +0 -0
  396. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/loader.gif +0 -0
  397. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/n.gif +0 -0
  398. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/p.gif +0 -0
  399. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/r.gif +0 -0
  400. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/r2.png +0 -0
  401. data/vendor/assets/javascripts/atreides/galleria/src/themes/fullscreen/up.gif +0 -0
  402. data/vendor/assets/javascripts/atreides/jquery-1.7.js +4 -0
  403. data/vendor/assets/javascripts/atreides/jquery-ui.js +11603 -0
  404. data/vendor/assets/javascripts/atreides/jquery.autogrow.js +132 -0
  405. data/vendor/assets/javascripts/atreides/jquery.cookie.js +96 -0
  406. data/vendor/assets/javascripts/atreides/jquery.countdown.js +759 -0
  407. data/vendor/assets/javascripts/atreides/jquery.cycle.js +918 -0
  408. data/vendor/assets/javascripts/atreides/jquery.easing.1.3.js +205 -0
  409. data/vendor/assets/javascripts/atreides/jquery.flash.js +288 -0
  410. data/vendor/assets/javascripts/atreides/jquery.iphone-checkboxes.js +214 -0
  411. data/vendor/assets/javascripts/atreides/jquery.jBreadCrumb.1.1.js +240 -0
  412. data/vendor/assets/javascripts/atreides/jquery.multipleselectbox-min.js +15 -0
  413. data/vendor/assets/javascripts/atreides/jquery.multipleselectbox.js +446 -0
  414. data/vendor/assets/javascripts/atreides/jquery.swfupload.js +64 -0
  415. data/vendor/assets/javascripts/atreides/jquery.tipsy.js +104 -0
  416. data/vendor/assets/javascripts/atreides/jquery.uniform.js +461 -0
  417. data/vendor/assets/javascripts/atreides/jquery_ujs.js +316 -0
  418. data/vendor/assets/javascripts/atreides/jtags.js +125 -0
  419. data/vendor/assets/javascripts/atreides/raphael-min.js +7 -0
  420. data/vendor/assets/javascripts/atreides/raphael.analytics.js +205 -0
  421. data/vendor/assets/javascripts/atreides/raphael.path.methods.js +53 -0
  422. data/vendor/assets/javascripts/atreides/raphael.pie.js +44 -0
  423. data/vendor/assets/javascripts/atreides/sifr.js +18 -0
  424. data/vendor/assets/javascripts/atreides/swfobject.js +4 -0
  425. data/vendor/assets/javascripts/atreides/swfupload/handlers.js +290 -0
  426. data/vendor/assets/javascripts/atreides/swfupload/swfupload.cookies.js +53 -0
  427. data/vendor/assets/javascripts/atreides/swfupload/swfupload.js +980 -0
  428. data/vendor/assets/javascripts/atreides/swfupload/swfupload.queue.js +98 -0
  429. data/vendor/assets/javascripts/atreides/swfupload/swfupload.speed.js +342 -0
  430. data/vendor/assets/javascripts/atreides/swfupload/swfupload.swfobject.js +111 -0
  431. data/vendor/assets/javascripts/atreides/underscore-1.1.6.js +807 -0
  432. data/vendor/assets/stylesheets/atreides/admin_grid.css +258 -0
  433. data/vendor/assets/stylesheets/atreides/facebox.css +80 -0
  434. data/vendor/assets/stylesheets/atreides/formtastic.css +144 -0
  435. data/vendor/assets/stylesheets/atreides/galleria.css +24 -0
  436. data/vendor/assets/stylesheets/atreides/ie.css +35 -0
  437. data/vendor/assets/stylesheets/atreides/images/bg_fallback.png +0 -0
  438. data/vendor/assets/stylesheets/atreides/images/icon_sprite.png +0 -0
  439. data/vendor/assets/stylesheets/atreides/images/progress_bar.gif +0 -0
  440. data/vendor/assets/stylesheets/atreides/images/slider_handles.png +0 -0
  441. data/vendor/assets/stylesheets/atreides/images/ui-icons_222222_256x240.png +0 -0
  442. data/vendor/assets/stylesheets/atreides/images/ui-icons_454545_256x240.png +0 -0
  443. data/vendor/assets/stylesheets/atreides/jquery-ui.css +738 -0
  444. data/vendor/assets/stylesheets/atreides/multipleselectbox.css +33 -0
  445. data/vendor/assets/stylesheets/atreides/print.css +29 -0
  446. data/vendor/assets/stylesheets/atreides/public_grid.css +258 -0
  447. data/vendor/assets/stylesheets/atreides/tipsy.css +7 -0
  448. data/vendor/assets/stylesheets/atreides/uniform.default.css +476 -0
  449. metadata +1566 -0
@@ -0,0 +1,132 @@
1
+ /*
2
+ * Auto Expanding Text Area (1.2.2)
3
+ * by Chrys Bader (www.chrysbader.com)
4
+ * chrysb@gmail.com
5
+ *
6
+ * Special thanks to:
7
+ * Jake Chapa - jake@hybridstudio.com
8
+ * John Resig - jeresig@gmail.com
9
+ *
10
+ * Copyright (c) 2008 Chrys Bader (www.chrysbader.com)
11
+ * Licensed under the GPL (GPL-LICENSE.txt) license.
12
+ *
13
+ *
14
+ * NOTE: This script requires jQuery to work. Download jQuery at www.jquery.com
15
+ *
16
+ */
17
+
18
+ (function(jQuery) {
19
+
20
+ var self = null;
21
+
22
+ jQuery.fn.autogrow = function(o)
23
+ {
24
+ return this.each(function() {
25
+ new jQuery.autogrow(this, o);
26
+ });
27
+ };
28
+
29
+
30
+ /**
31
+ * The autogrow object.
32
+ *
33
+ * @constructor
34
+ * @name jQuery.autogrow
35
+ * @param Object e The textarea to create the autogrow for.
36
+ * @param Hash o A set of key/value pairs to set as configuration properties.
37
+ * @cat Plugins/autogrow
38
+ */
39
+
40
+ jQuery.autogrow = function (e, o)
41
+ {
42
+ this.options = o || {};
43
+ this.dummy = null;
44
+ this.interval = null;
45
+ this.line_height = this.options.lineHeight || parseInt(jQuery(e).css('line-height'));
46
+ this.min_height = this.options.minHeight || parseInt(jQuery(e).css('min-height'));
47
+ this.max_height = this.options.maxHeight || parseInt(jQuery(e).css('max-height'));;
48
+ this.textarea = jQuery(e);
49
+
50
+ if(this.line_height == NaN)
51
+ this.line_height = 0;
52
+
53
+ // Only one textarea activated at a time, the one being used
54
+ this.init();
55
+ };
56
+
57
+ jQuery.autogrow.fn = jQuery.autogrow.prototype = {
58
+ autogrow: '1.2.2'
59
+ };
60
+
61
+ jQuery.autogrow.fn.extend = jQuery.autogrow.extend = jQuery.extend;
62
+
63
+ jQuery.autogrow.fn.extend({
64
+
65
+ init: function() {
66
+ var self = this;
67
+ this.textarea.css({overflow: 'hidden', display: 'block'});
68
+ this.textarea.bind('focus', function() { self.startExpand() } ).bind('blur', function() { self.stopExpand() });
69
+ this.checkExpand();
70
+ },
71
+
72
+ startExpand: function() {
73
+ var self = this;
74
+ this.interval = window.setInterval(function() {self.checkExpand()}, 400);
75
+ },
76
+
77
+ stopExpand: function() {
78
+ clearInterval(this.interval);
79
+ },
80
+
81
+ checkExpand: function() {
82
+
83
+ if (this.dummy == null)
84
+ {
85
+ this.dummy = jQuery('<div></div>');
86
+ this.dummy.css({
87
+ 'font-size' : this.textarea.css('font-size'),
88
+ 'font-family': this.textarea.css('font-family'),
89
+ 'width' : this.textarea.css('width'),
90
+ 'padding' : this.textarea.css('padding'),
91
+ 'line-height': this.line_height + 'px',
92
+ 'overflow-x' : 'hidden',
93
+ 'position' : 'absolute',
94
+ 'top' : 0,
95
+ 'left' : -9999
96
+ }).appendTo('body');
97
+ }
98
+
99
+ // Strip HTML tags
100
+ var html = this.textarea.val().replace(/(<|>)/g, '');
101
+
102
+ // IE is different, as per usual
103
+ if ($.browser.msie)
104
+ {
105
+ html = html.replace(/\n/g, '<BR>new');
106
+ }
107
+ else
108
+ {
109
+ html = html.replace(/\n/g, '<br>new');
110
+ }
111
+
112
+ if (this.dummy.html() != html)
113
+ {
114
+ this.dummy.html(html);
115
+
116
+ if (this.max_height > 0 && (this.dummy.height() + this.line_height > this.max_height))
117
+ {
118
+ this.textarea.css('overflow-y', 'auto');
119
+ }
120
+ else
121
+ {
122
+ this.textarea.css('overflow-y', 'hidden');
123
+ if (this.textarea.height() < this.dummy.height() + this.line_height || (this.dummy.height() < this.textarea.height()))
124
+ {
125
+ this.textarea.animate({height: (this.dummy.height() + this.line_height) + 'px'}, 100);
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ });
132
+ })(jQuery);
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Cookie plugin
3
+ *
4
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
5
+ * Dual licensed under the MIT and GPL licenses:
6
+ * http://www.opensource.org/licenses/mit-license.php
7
+ * http://www.gnu.org/licenses/gpl.html
8
+ *
9
+ */
10
+
11
+ /**
12
+ * Create a cookie with the given name and value and other optional parameters.
13
+ *
14
+ * @example $.cookie('the_cookie', 'the_value');
15
+ * @desc Set the value of a cookie.
16
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
17
+ * @desc Create a cookie with all available options.
18
+ * @example $.cookie('the_cookie', 'the_value');
19
+ * @desc Create a session cookie.
20
+ * @example $.cookie('the_cookie', null);
21
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
22
+ * used when the cookie was set.
23
+ *
24
+ * @param String name The name of the cookie.
25
+ * @param String value The value of the cookie.
26
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
27
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
28
+ * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
29
+ * If set to null or omitted, the cookie will be a session cookie and will not be retained
30
+ * when the the browser exits.
31
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
32
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
33
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
34
+ * require a secure protocol (like HTTPS).
35
+ * @type undefined
36
+ *
37
+ * @name $.cookie
38
+ * @cat Plugins/Cookie
39
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
40
+ */
41
+
42
+ /**
43
+ * Get the value of a cookie with the given name.
44
+ *
45
+ * @example $.cookie('the_cookie');
46
+ * @desc Get the value of a cookie.
47
+ *
48
+ * @param String name The name of the cookie.
49
+ * @return The value of the cookie.
50
+ * @type String
51
+ *
52
+ * @name $.cookie
53
+ * @cat Plugins/Cookie
54
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
55
+ */
56
+ jQuery.cookie = function(name, value, options) {
57
+ if (typeof value != 'undefined') { // name and value given, set cookie
58
+ options = options || {};
59
+ if (value === null) {
60
+ value = '';
61
+ options.expires = -1;
62
+ }
63
+ var expires = '';
64
+ if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
65
+ var date;
66
+ if (typeof options.expires == 'number') {
67
+ date = new Date();
68
+ date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
69
+ } else {
70
+ date = options.expires;
71
+ }
72
+ expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
73
+ }
74
+ // CAUTION: Needed to parenthesize options.path and options.domain
75
+ // in the following expressions, otherwise they evaluate to undefined
76
+ // in the packed version for some reason...
77
+ var path = options.path ? '; path=' + (options.path) : '';
78
+ var domain = options.domain ? '; domain=' + (options.domain) : '';
79
+ var secure = options.secure ? '; secure' : '';
80
+ document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
81
+ } else { // only name given, get cookie
82
+ var cookieValue = null;
83
+ if (document.cookie && document.cookie != '') {
84
+ var cookies = document.cookie.split(';');
85
+ for (var i = 0; i < cookies.length; i++) {
86
+ var cookie = jQuery.trim(cookies[i]);
87
+ // Does this cookie string begin with the name we want?
88
+ if (cookie.substring(0, name.length + 1) == (name + '=')) {
89
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
90
+ break;
91
+ }
92
+ }
93
+ }
94
+ return cookieValue;
95
+ }
96
+ };
@@ -0,0 +1,759 @@
1
+ /* http://keith-wood.name/countdown.html
2
+ Countdown for jQuery v1.5.8.
3
+ Written by Keith Wood (kbwood{at}iinet.com.au) January 2008.
4
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
5
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
6
+ Please attribute the author if you use it. */
7
+
8
+ /* Display a countdown timer.
9
+ Attach it with options like:
10
+ $('div selector').countdown(
11
+ {until: new Date(2009, 1 - 1, 1, 0, 0, 0), onExpiry: happyNewYear}); */
12
+
13
+ (function($) { // Hide scope, no $ conflict
14
+
15
+ /* Countdown manager. */
16
+ function Countdown() {
17
+ this.regional = []; // Available regional settings, indexed by language code
18
+ this.regional[''] = { // Default regional settings
19
+ // The display texts for the counters
20
+ labels: ['Years', 'Months', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds'],
21
+ // The display texts for the counters if only one
22
+ labels1: ['Year', 'Month', 'Week', 'Day', 'Hour', 'Minute', 'Second'],
23
+ compactLabels: ['y', 'm', 'w', 'd'], // The compact texts for the counters
24
+ whichLabels: null, // Function to determine which labels to use
25
+ timeSeparator: ':', // Separator for time periods
26
+ isRTL: false // True for right-to-left languages, false for left-to-right
27
+ };
28
+ this._defaults = {
29
+ until: null, // new Date(year, mth - 1, day, hr, min, sec) - date/time to count down to
30
+ // or numeric for seconds offset, or string for unit offset(s):
31
+ // 'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds
32
+ since: null, // new Date(year, mth - 1, day, hr, min, sec) - date/time to count up from
33
+ // or numeric for seconds offset, or string for unit offset(s):
34
+ // 'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds
35
+ timezone: null, // The timezone (hours or minutes from GMT) for the target times,
36
+ // or null for client local
37
+ serverSync: null, // A function to retrieve the current server time for synchronisation
38
+ format: 'dHMS', // Format for display - upper case for always, lower case only if non-zero,
39
+ // 'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds
40
+ layout: '', // Build your own layout for the countdown
41
+ compact: false, // True to display in a compact format, false for an expanded one
42
+ significant: 0, // The number of periods with values to show, zero for all
43
+ description: '', // The description displayed for the countdown
44
+ expiryUrl: '', // A URL to load upon expiry, replacing the current page
45
+ expiryText: '', // Text to display upon expiry, replacing the countdown
46
+ alwaysExpire: false, // True to trigger onExpiry even if never counted down
47
+ onExpiry: null, // Callback when the countdown expires -
48
+ // receives no parameters and 'this' is the containing division
49
+ onTick: null, // Callback when the countdown is updated -
50
+ // receives int[7] being the breakdown by period (based on format)
51
+ // and 'this' is the containing division
52
+ tickInterval: 1 // Interval (seconds) between onTick callbacks
53
+ };
54
+ $.extend(this._defaults, this.regional['']);
55
+ this._serverSyncs = [];
56
+ }
57
+
58
+ var PROP_NAME = 'countdown';
59
+
60
+ var Y = 0; // Years
61
+ var O = 1; // Months
62
+ var W = 2; // Weeks
63
+ var D = 3; // Days
64
+ var H = 4; // Hours
65
+ var M = 5; // Minutes
66
+ var S = 6; // Seconds
67
+
68
+ $.extend(Countdown.prototype, {
69
+ /* Class name added to elements to indicate already configured with countdown. */
70
+ markerClassName: 'hasCountdown',
71
+
72
+ /* Shared timer for all countdowns. */
73
+ _timer: setInterval(function() { $.countdown._updateTargets(); }, 980),
74
+ /* List of currently active countdown targets. */
75
+ _timerTargets: [],
76
+
77
+ /* Override the default settings for all instances of the countdown widget.
78
+ @param options (object) the new settings to use as defaults */
79
+ setDefaults: function(options) {
80
+ this._resetExtraLabels(this._defaults, options);
81
+ extendRemove(this._defaults, options || {});
82
+ },
83
+
84
+ /* Convert a date/time to UTC.
85
+ @param tz (number) the hour or minute offset from GMT, e.g. +9, -360
86
+ @param year (Date) the date/time in that timezone or
87
+ (number) the year in that timezone
88
+ @param month (number, optional) the month (0 - 11) (omit if year is a Date)
89
+ @param day (number, optional) the day (omit if year is a Date)
90
+ @param hours (number, optional) the hour (omit if year is a Date)
91
+ @param mins (number, optional) the minute (omit if year is a Date)
92
+ @param secs (number, optional) the second (omit if year is a Date)
93
+ @param ms (number, optional) the millisecond (omit if year is a Date)
94
+ @return (Date) the equivalent UTC date/time */
95
+ UTCDate: function(tz, year, month, day, hours, mins, secs, ms) {
96
+ if (typeof year == 'object' && year.constructor == Date) {
97
+ ms = year.getMilliseconds();
98
+ secs = year.getSeconds();
99
+ mins = year.getMinutes();
100
+ hours = year.getHours();
101
+ day = year.getDate();
102
+ month = year.getMonth();
103
+ year = year.getFullYear();
104
+ }
105
+ var d = new Date();
106
+ d.setUTCFullYear(year);
107
+ d.setUTCDate(1);
108
+ d.setUTCMonth(month || 0);
109
+ d.setUTCDate(day || 1);
110
+ d.setUTCHours(hours || 0);
111
+ d.setUTCMinutes((mins || 0) - (Math.abs(tz) < 30 ? tz * 60 : tz));
112
+ d.setUTCSeconds(secs || 0);
113
+ d.setUTCMilliseconds(ms || 0);
114
+ return d;
115
+ },
116
+
117
+ /* Convert a set of periods into seconds.
118
+ Averaged for months and years.
119
+ @param periods (number[7]) the periods per year/month/week/day/hour/minute/second
120
+ @return (number) the corresponding number of seconds */
121
+ periodsToSeconds: function(periods) {
122
+ return periods[0] * 31557600 + periods[1] * 2629800 + periods[2] * 604800 +
123
+ periods[3] * 86400 + periods[4] * 3600 + periods[5] * 60 + periods[6];
124
+ },
125
+
126
+ /* Retrieve one or more settings values.
127
+ @param name (string, optional) the name of the setting to retrieve
128
+ or 'all' for all instance settings or omit for all default settings
129
+ @return (any) the requested setting(s) */
130
+ _settingsCountdown: function(target, name) {
131
+ if (!name) {
132
+ return $.countdown._defaults;
133
+ }
134
+ var inst = $.data(target, PROP_NAME);
135
+ return (name == 'all' ? inst.options : inst.options[name]);
136
+ },
137
+
138
+ /* Attach the countdown widget to a div.
139
+ @param target (element) the containing division
140
+ @param options (object) the initial settings for the countdown */
141
+ _attachCountdown: function(target, options) {
142
+ var $target = $(target);
143
+ if ($target.hasClass(this.markerClassName)) {
144
+ return;
145
+ }
146
+ $target.addClass(this.markerClassName);
147
+ var inst = {options: $.extend({}, options),
148
+ _periods: [0, 0, 0, 0, 0, 0, 0]};
149
+ $.data(target, PROP_NAME, inst);
150
+ this._changeCountdown(target);
151
+ },
152
+
153
+ /* Add a target to the list of active ones.
154
+ @param target (element) the countdown target */
155
+ _addTarget: function(target) {
156
+ if (!this._hasTarget(target)) {
157
+ this._timerTargets.push(target);
158
+ }
159
+ },
160
+
161
+ /* See if a target is in the list of active ones.
162
+ @param target (element) the countdown target
163
+ @return (boolean) true if present, false if not */
164
+ _hasTarget: function(target) {
165
+ return ($.inArray(target, this._timerTargets) > -1);
166
+ },
167
+
168
+ /* Remove a target from the list of active ones.
169
+ @param target (element) the countdown target */
170
+ _removeTarget: function(target) {
171
+ this._timerTargets = $.map(this._timerTargets,
172
+ function(value) { return (value == target ? null : value); }); // delete entry
173
+ },
174
+
175
+ /* Update each active timer target. */
176
+ _updateTargets: function() {
177
+ for (var i = this._timerTargets.length - 1; i >= 0; i--) {
178
+ this._updateCountdown(this._timerTargets[i]);
179
+ }
180
+ },
181
+
182
+ /* Redisplay the countdown with an updated display.
183
+ @param target (jQuery) the containing division
184
+ @param inst (object) the current settings for this instance */
185
+ _updateCountdown: function(target, inst) {
186
+ var $target = $(target);
187
+ inst = inst || $.data(target, PROP_NAME);
188
+ if (!inst) {
189
+ return;
190
+ }
191
+ $target.html(this._generateHTML(inst));
192
+ $target[(this._get(inst, 'isRTL') ? 'add' : 'remove') + 'Class']('countdown_rtl');
193
+ var onTick = this._get(inst, 'onTick');
194
+ if (onTick) {
195
+ var periods = inst._hold != 'lap' ? inst._periods :
196
+ this._calculatePeriods(inst, inst._show, this._get(inst, 'significant'), new Date());
197
+ var tickInterval = this._get(inst, 'tickInterval');
198
+ if (tickInterval == 1 || this.periodsToSeconds(periods) % tickInterval == 0) {
199
+ onTick.apply(target, [periods]);
200
+ }
201
+ }
202
+ var expired = inst._hold != 'pause' &&
203
+ (inst._since ? inst._now.getTime() < inst._since.getTime() :
204
+ inst._now.getTime() >= inst._until.getTime());
205
+ if (expired && !inst._expiring) {
206
+ inst._expiring = true;
207
+ if (this._hasTarget(target) || this._get(inst, 'alwaysExpire')) {
208
+ this._removeTarget(target);
209
+ var onExpiry = this._get(inst, 'onExpiry');
210
+ if (onExpiry) {
211
+ onExpiry.apply(target, []);
212
+ }
213
+ var expiryText = this._get(inst, 'expiryText');
214
+ if (expiryText) {
215
+ var layout = this._get(inst, 'layout');
216
+ inst.options.layout = expiryText;
217
+ this._updateCountdown(target, inst);
218
+ inst.options.layout = layout;
219
+ }
220
+ var expiryUrl = this._get(inst, 'expiryUrl');
221
+ if (expiryUrl) {
222
+ window.location = expiryUrl;
223
+ }
224
+ }
225
+ inst._expiring = false;
226
+ }
227
+ else if (inst._hold == 'pause') {
228
+ this._removeTarget(target);
229
+ }
230
+ $.data(target, PROP_NAME, inst);
231
+ },
232
+
233
+ /* Reconfigure the settings for a countdown div.
234
+ @param target (element) the containing division
235
+ @param options (object) the new settings for the countdown or
236
+ (string) an individual property name
237
+ @param value (any) the individual property value
238
+ (omit if options is an object) */
239
+ _changeCountdown: function(target, options, value) {
240
+ options = options || {};
241
+ if (typeof options == 'string') {
242
+ var name = options;
243
+ options = {};
244
+ options[name] = value;
245
+ }
246
+ var inst = $.data(target, PROP_NAME);
247
+ if (inst) {
248
+ this._resetExtraLabels(inst.options, options);
249
+ extendRemove(inst.options, options);
250
+ this._adjustSettings(target, inst);
251
+ $.data(target, PROP_NAME, inst);
252
+ var now = new Date();
253
+ if ((inst._since && inst._since < now) ||
254
+ (inst._until && inst._until > now)) {
255
+ this._addTarget(target);
256
+ }
257
+ this._updateCountdown(target, inst);
258
+ }
259
+ },
260
+
261
+ /* Reset any extra labelsn and compactLabelsn entries if changing labels.
262
+ @param base (object) the options to be updated
263
+ @param options (object) the new option values */
264
+ _resetExtraLabels: function(base, options) {
265
+ var changingLabels = false;
266
+ for (var n in options) {
267
+ if (n != 'whichLabels' && n.match(/[Ll]abels/)) {
268
+ changingLabels = true;
269
+ break;
270
+ }
271
+ }
272
+ if (changingLabels) {
273
+ for (var n in base) { // Remove custom numbered labels
274
+ if (n.match(/[Ll]abels[0-9]/)) {
275
+ base[n] = null;
276
+ }
277
+ }
278
+ }
279
+ },
280
+
281
+ /* Calculate interal settings for an instance.
282
+ @param target (element) the containing division
283
+ @param inst (object) the current settings for this instance */
284
+ _adjustSettings: function(target, inst) {
285
+ var now;
286
+ var serverSync = this._get(inst, 'serverSync');
287
+ var serverOffset = 0;
288
+ var serverEntry = null;
289
+ for (var i = 0; i < this._serverSyncs.length; i++) {
290
+ if (this._serverSyncs[i][0] == serverSync) {
291
+ serverEntry = this._serverSyncs[i][1];
292
+ break;
293
+ }
294
+ }
295
+ if (serverEntry != null) {
296
+ serverOffset = (serverSync ? serverEntry : 0);
297
+ now = new Date();
298
+ }
299
+ else {
300
+ var serverResult = (serverSync ? serverSync.apply(target, []) : null);
301
+ now = new Date();
302
+ serverOffset = (serverResult ? now.getTime() - serverResult.getTime() : 0);
303
+ this._serverSyncs.push([serverSync, serverOffset]);
304
+ }
305
+ var timezone = this._get(inst, 'timezone');
306
+ timezone = (timezone == null ? -now.getTimezoneOffset() : timezone);
307
+ inst._since = this._get(inst, 'since');
308
+ if (inst._since != null) {
309
+ inst._since = this.UTCDate(timezone, this._determineTime(inst._since, null));
310
+ if (inst._since && serverOffset) {
311
+ inst._since.setMilliseconds(inst._since.getMilliseconds() + serverOffset);
312
+ }
313
+ }
314
+ inst._until = this.UTCDate(timezone, this._determineTime(this._get(inst, 'until'), now));
315
+ if (serverOffset) {
316
+ inst._until.setMilliseconds(inst._until.getMilliseconds() + serverOffset);
317
+ }
318
+ inst._show = this._determineShow(inst);
319
+ },
320
+
321
+ /* Remove the countdown widget from a div.
322
+ @param target (element) the containing division */
323
+ _destroyCountdown: function(target) {
324
+ var $target = $(target);
325
+ if (!$target.hasClass(this.markerClassName)) {
326
+ return;
327
+ }
328
+ this._removeTarget(target);
329
+ $target.removeClass(this.markerClassName).empty();
330
+ $.removeData(target, PROP_NAME);
331
+ },
332
+
333
+ /* Pause a countdown widget at the current time.
334
+ Stop it running but remember and display the current time.
335
+ @param target (element) the containing division */
336
+ _pauseCountdown: function(target) {
337
+ this._hold(target, 'pause');
338
+ },
339
+
340
+ /* Pause a countdown widget at the current time.
341
+ Stop the display but keep the countdown running.
342
+ @param target (element) the containing division */
343
+ _lapCountdown: function(target) {
344
+ this._hold(target, 'lap');
345
+ },
346
+
347
+ /* Resume a paused countdown widget.
348
+ @param target (element) the containing division */
349
+ _resumeCountdown: function(target) {
350
+ this._hold(target, null);
351
+ },
352
+
353
+ /* Pause or resume a countdown widget.
354
+ @param target (element) the containing division
355
+ @param hold (string) the new hold setting */
356
+ _hold: function(target, hold) {
357
+ var inst = $.data(target, PROP_NAME);
358
+ if (inst) {
359
+ if (inst._hold == 'pause' && !hold) {
360
+ inst._periods = inst._savePeriods;
361
+ var sign = (inst._since ? '-' : '+');
362
+ inst[inst._since ? '_since' : '_until'] =
363
+ this._determineTime(sign + inst._periods[0] + 'y' +
364
+ sign + inst._periods[1] + 'o' + sign + inst._periods[2] + 'w' +
365
+ sign + inst._periods[3] + 'd' + sign + inst._periods[4] + 'h' +
366
+ sign + inst._periods[5] + 'm' + sign + inst._periods[6] + 's');
367
+ this._addTarget(target);
368
+ }
369
+ inst._hold = hold;
370
+ inst._savePeriods = (hold == 'pause' ? inst._periods : null);
371
+ $.data(target, PROP_NAME, inst);
372
+ this._updateCountdown(target, inst);
373
+ }
374
+ },
375
+
376
+ /* Return the current time periods.
377
+ @param target (element) the containing division
378
+ @return (number[7]) the current periods for the countdown */
379
+ _getTimesCountdown: function(target) {
380
+ var inst = $.data(target, PROP_NAME);
381
+ return (!inst ? null : (!inst._hold ? inst._periods :
382
+ this._calculatePeriods(inst, inst._show, this._get(inst, 'significant'), new Date())));
383
+ },
384
+
385
+ /* Get a setting value, defaulting if necessary.
386
+ @param inst (object) the current settings for this instance
387
+ @param name (string) the name of the required setting
388
+ @return (any) the setting's value or a default if not overridden */
389
+ _get: function(inst, name) {
390
+ return (inst.options[name] != null ?
391
+ inst.options[name] : $.countdown._defaults[name]);
392
+ },
393
+
394
+ /* A time may be specified as an exact value or a relative one.
395
+ @param setting (string or number or Date) - the date/time value
396
+ as a relative or absolute value
397
+ @param defaultTime (Date) the date/time to use if no other is supplied
398
+ @return (Date) the corresponding date/time */
399
+ _determineTime: function(setting, defaultTime) {
400
+ var offsetNumeric = function(offset) { // e.g. +300, -2
401
+ var time = new Date();
402
+ time.setTime(time.getTime() + offset * 1000);
403
+ return time;
404
+ };
405
+ var offsetString = function(offset) { // e.g. '+2d', '-4w', '+3h +30m'
406
+ offset = offset.toLowerCase();
407
+ var time = new Date();
408
+ var year = time.getFullYear();
409
+ var month = time.getMonth();
410
+ var day = time.getDate();
411
+ var hour = time.getHours();
412
+ var minute = time.getMinutes();
413
+ var second = time.getSeconds();
414
+ var pattern = /([+-]?[0-9]+)\s*(s|m|h|d|w|o|y)?/g;
415
+ var matches = pattern.exec(offset);
416
+ while (matches) {
417
+ switch (matches[2] || 's') {
418
+ case 's': second += parseInt(matches[1], 10); break;
419
+ case 'm': minute += parseInt(matches[1], 10); break;
420
+ case 'h': hour += parseInt(matches[1], 10); break;
421
+ case 'd': day += parseInt(matches[1], 10); break;
422
+ case 'w': day += parseInt(matches[1], 10) * 7; break;
423
+ case 'o':
424
+ month += parseInt(matches[1], 10);
425
+ day = Math.min(day, $.countdown._getDaysInMonth(year, month));
426
+ break;
427
+ case 'y':
428
+ year += parseInt(matches[1], 10);
429
+ day = Math.min(day, $.countdown._getDaysInMonth(year, month));
430
+ break;
431
+ }
432
+ matches = pattern.exec(offset);
433
+ }
434
+ return new Date(year, month, day, hour, minute, second, 0);
435
+ };
436
+ var time = (setting == null ? defaultTime :
437
+ (typeof setting == 'string' ? offsetString(setting) :
438
+ (typeof setting == 'number' ? offsetNumeric(setting) : setting)));
439
+ if (time) time.setMilliseconds(0);
440
+ return time;
441
+ },
442
+
443
+ /* Determine the number of days in a month.
444
+ @param year (number) the year
445
+ @param month (number) the month
446
+ @return (number) the days in that month */
447
+ _getDaysInMonth: function(year, month) {
448
+ return 32 - new Date(year, month, 32).getDate();
449
+ },
450
+
451
+ /* Determine which set of labels should be used for an amount.
452
+ @param num (number) the amount to be displayed
453
+ @return (number) the set of labels to be used for this amount */
454
+ _normalLabels: function(num) {
455
+ return num;
456
+ },
457
+
458
+ /* Generate the HTML to display the countdown widget.
459
+ @param inst (object) the current settings for this instance
460
+ @return (string) the new HTML for the countdown display */
461
+ _generateHTML: function(inst) {
462
+ // Determine what to show
463
+ var significant = this._get(inst, 'significant');
464
+ inst._periods = (inst._hold ? inst._periods :
465
+ this._calculatePeriods(inst, inst._show, significant, new Date()));
466
+ // Show all 'asNeeded' after first non-zero value
467
+ var shownNonZero = false;
468
+ var showCount = 0;
469
+ var sigCount = significant;
470
+ var show = $.extend({}, inst._show);
471
+ for (var period = Y; period <= S; period++) {
472
+ shownNonZero |= (inst._show[period] == '?' && inst._periods[period] > 0);
473
+ show[period] = (inst._show[period] == '?' && !shownNonZero ? null : inst._show[period]);
474
+ showCount += (show[period] ? 1 : 0);
475
+ sigCount -= (inst._periods[period] > 0 ? 1 : 0);
476
+ }
477
+ var showSignificant = [false, false, false, false, false, false, false];
478
+ for (var period = S; period >= Y; period--) { // Determine significant periods
479
+ if (inst._show[period]) {
480
+ if (inst._periods[period]) {
481
+ showSignificant[period] = true;
482
+ }
483
+ else {
484
+ showSignificant[period] = sigCount > 0;
485
+ sigCount--;
486
+ }
487
+ }
488
+ }
489
+ var compact = this._get(inst, 'compact');
490
+ var layout = this._get(inst, 'layout');
491
+ var labels = (compact ? this._get(inst, 'compactLabels') : this._get(inst, 'labels'));
492
+ var whichLabels = this._get(inst, 'whichLabels') || this._normalLabels;
493
+ var timeSeparator = this._get(inst, 'timeSeparator');
494
+ var description = this._get(inst, 'description') || '';
495
+ var showCompact = function(period) {
496
+ var labelsNum = $.countdown._get(inst,
497
+ 'compactLabels' + whichLabels(inst._periods[period]));
498
+ return (show[period] ? inst._periods[period] +
499
+ (labelsNum ? labelsNum[period] : labels[period]) + ' ' : '');
500
+ };
501
+ var showFull = function(period) {
502
+ var labelsNum = $.countdown._get(inst, 'labels' + whichLabels(inst._periods[period]));
503
+ return ((!significant && show[period]) || (significant && showSignificant[period]) ?
504
+ '<span class="countdown_section"><span class="countdown_amount">' +
505
+ inst._periods[period] + '</span><br/>' +
506
+ (labelsNum ? labelsNum[period] : labels[period]) + '</span>' : '');
507
+ };
508
+ return (layout ? this._buildLayout(inst, show, layout, compact, significant, showSignificant) :
509
+ ((compact ? // Compact version
510
+ '<span class="countdown_row countdown_amount' +
511
+ (inst._hold ? ' countdown_holding' : '') + '">' +
512
+ showCompact(Y) + showCompact(O) + showCompact(W) + showCompact(D) +
513
+ (show[H] ? this._minDigits(inst._periods[H], 2) : '') +
514
+ (show[M] ? (show[H] ? timeSeparator : '') +
515
+ this._minDigits(inst._periods[M], 2) : '') +
516
+ (show[S] ? (show[H] || show[M] ? timeSeparator : '') +
517
+ this._minDigits(inst._periods[S], 2) : '') :
518
+ // Full version
519
+ '<span class="countdown_row countdown_show' + (significant || showCount) +
520
+ (inst._hold ? ' countdown_holding' : '') + '">' +
521
+ showFull(Y) + showFull(O) + showFull(W) + showFull(D) +
522
+ showFull(H) + showFull(M) + showFull(S)) + '</span>' +
523
+ (description ? '<span class="countdown_row countdown_descr">' + description + '</span>' : '')));
524
+ },
525
+
526
+ /* Construct a custom layout.
527
+ @param inst (object) the current settings for this instance
528
+ @param show (string[7]) flags indicating which periods are requested
529
+ @param layout (string) the customised layout
530
+ @param compact (boolean) true if using compact labels
531
+ @param significant (number) the number of periods with values to show, zero for all
532
+ @param showSignificant (boolean[7]) other periods to show for significance
533
+ @return (string) the custom HTML */
534
+ _buildLayout: function(inst, show, layout, compact, significant, showSignificant) {
535
+ var labels = this._get(inst, (compact ? 'compactLabels' : 'labels'));
536
+ var whichLabels = this._get(inst, 'whichLabels') || this._normalLabels;
537
+ var labelFor = function(index) {
538
+ return ($.countdown._get(inst,
539
+ (compact ? 'compactLabels' : 'labels') + whichLabels(inst._periods[index])) ||
540
+ labels)[index];
541
+ };
542
+ var digit = function(value, position) {
543
+ return Math.floor(value / position) % 10;
544
+ };
545
+ var subs = {desc: this._get(inst, 'description'), sep: this._get(inst, 'timeSeparator'),
546
+ yl: labelFor(Y), yn: inst._periods[Y], ynn: this._minDigits(inst._periods[Y], 2),
547
+ ynnn: this._minDigits(inst._periods[Y], 3), y1: digit(inst._periods[Y], 1),
548
+ y10: digit(inst._periods[Y], 10), y100: digit(inst._periods[Y], 100),
549
+ y1000: digit(inst._periods[Y], 1000),
550
+ ol: labelFor(O), on: inst._periods[O], onn: this._minDigits(inst._periods[O], 2),
551
+ onnn: this._minDigits(inst._periods[O], 3), o1: digit(inst._periods[O], 1),
552
+ o10: digit(inst._periods[O], 10), o100: digit(inst._periods[O], 100),
553
+ o1000: digit(inst._periods[O], 1000),
554
+ wl: labelFor(W), wn: inst._periods[W], wnn: this._minDigits(inst._periods[W], 2),
555
+ wnnn: this._minDigits(inst._periods[W], 3), w1: digit(inst._periods[W], 1),
556
+ w10: digit(inst._periods[W], 10), w100: digit(inst._periods[W], 100),
557
+ w1000: digit(inst._periods[W], 1000),
558
+ dl: labelFor(D), dn: inst._periods[D], dnn: this._minDigits(inst._periods[D], 2),
559
+ dnnn: this._minDigits(inst._periods[D], 3), d1: digit(inst._periods[D], 1),
560
+ d10: digit(inst._periods[D], 10), d100: digit(inst._periods[D], 100),
561
+ d1000: digit(inst._periods[D], 1000),
562
+ hl: labelFor(H), hn: inst._periods[H], hnn: this._minDigits(inst._periods[H], 2),
563
+ hnnn: this._minDigits(inst._periods[H], 3), h1: digit(inst._periods[H], 1),
564
+ h10: digit(inst._periods[H], 10), h100: digit(inst._periods[H], 100),
565
+ h1000: digit(inst._periods[H], 1000),
566
+ ml: labelFor(M), mn: inst._periods[M], mnn: this._minDigits(inst._periods[M], 2),
567
+ mnnn: this._minDigits(inst._periods[M], 3), m1: digit(inst._periods[M], 1),
568
+ m10: digit(inst._periods[M], 10), m100: digit(inst._periods[M], 100),
569
+ m1000: digit(inst._periods[M], 1000),
570
+ sl: labelFor(S), sn: inst._periods[S], snn: this._minDigits(inst._periods[S], 2),
571
+ snnn: this._minDigits(inst._periods[S], 3), s1: digit(inst._periods[S], 1),
572
+ s10: digit(inst._periods[S], 10), s100: digit(inst._periods[S], 100),
573
+ s1000: digit(inst._periods[S], 1000)};
574
+ var html = layout;
575
+ // Replace period containers: {p<}...{p>}
576
+ for (var i = Y; i <= S; i++) {
577
+ var period = 'yowdhms'.charAt(i);
578
+ var re = new RegExp('\\{' + period + '<\\}(.*)\\{' + period + '>\\}', 'g');
579
+ html = html.replace(re, ((!significant && show[i]) ||
580
+ (significant && showSignificant[i]) ? '$1' : ''));
581
+ }
582
+ // Replace period values: {pn}
583
+ $.each(subs, function(n, v) {
584
+ var re = new RegExp('\\{' + n + '\\}', 'g');
585
+ html = html.replace(re, v);
586
+ });
587
+ return html;
588
+ },
589
+
590
+ /* Ensure a numeric value has at least n digits for display.
591
+ @param value (number) the value to display
592
+ @param len (number) the minimum length
593
+ @return (string) the display text */
594
+ _minDigits: function(value, len) {
595
+ value = '' + value;
596
+ if (value.length >= len) {
597
+ return value;
598
+ }
599
+ value = '0000000000' + value;
600
+ return value.substr(value.length - len);
601
+ },
602
+
603
+ /* Translate the format into flags for each period.
604
+ @param inst (object) the current settings for this instance
605
+ @return (string[7]) flags indicating which periods are requested (?) or
606
+ required (!) by year, month, week, day, hour, minute, second */
607
+ _determineShow: function(inst) {
608
+ var format = this._get(inst, 'format');
609
+ var show = [];
610
+ show[Y] = (format.match('y') ? '?' : (format.match('Y') ? '!' : null));
611
+ show[O] = (format.match('o') ? '?' : (format.match('O') ? '!' : null));
612
+ show[W] = (format.match('w') ? '?' : (format.match('W') ? '!' : null));
613
+ show[D] = (format.match('d') ? '?' : (format.match('D') ? '!' : null));
614
+ show[H] = (format.match('h') ? '?' : (format.match('H') ? '!' : null));
615
+ show[M] = (format.match('m') ? '?' : (format.match('M') ? '!' : null));
616
+ show[S] = (format.match('s') ? '?' : (format.match('S') ? '!' : null));
617
+ return show;
618
+ },
619
+
620
+ /* Calculate the requested periods between now and the target time.
621
+ @param inst (object) the current settings for this instance
622
+ @param show (string[7]) flags indicating which periods are requested/required
623
+ @param significant (number) the number of periods with values to show, zero for all
624
+ @param now (Date) the current date and time
625
+ @return (number[7]) the current time periods (always positive)
626
+ by year, month, week, day, hour, minute, second */
627
+ _calculatePeriods: function(inst, show, significant, now) {
628
+ // Find endpoints
629
+ inst._now = now;
630
+ inst._now.setMilliseconds(0);
631
+ var until = new Date(inst._now.getTime());
632
+ if (inst._since) {
633
+ if (now.getTime() < inst._since.getTime()) {
634
+ inst._now = now = until;
635
+ }
636
+ else {
637
+ now = inst._since;
638
+ }
639
+ }
640
+ else {
641
+ until.setTime(inst._until.getTime());
642
+ if (now.getTime() > inst._until.getTime()) {
643
+ inst._now = now = until;
644
+ }
645
+ }
646
+ // Calculate differences by period
647
+ var periods = [0, 0, 0, 0, 0, 0, 0];
648
+ if (show[Y] || show[O]) {
649
+ // Treat end of months as the same
650
+ var lastNow = $.countdown._getDaysInMonth(now.getFullYear(), now.getMonth());
651
+ var lastUntil = $.countdown._getDaysInMonth(until.getFullYear(), until.getMonth());
652
+ var sameDay = (until.getDate() == now.getDate() ||
653
+ (until.getDate() >= Math.min(lastNow, lastUntil) &&
654
+ now.getDate() >= Math.min(lastNow, lastUntil)));
655
+ var getSecs = function(date) {
656
+ return (date.getHours() * 60 + date.getMinutes()) * 60 + date.getSeconds();
657
+ };
658
+ var months = Math.max(0,
659
+ (until.getFullYear() - now.getFullYear()) * 12 + until.getMonth() - now.getMonth() +
660
+ ((until.getDate() < now.getDate() && !sameDay) ||
661
+ (sameDay && getSecs(until) < getSecs(now)) ? -1 : 0));
662
+ periods[Y] = (show[Y] ? Math.floor(months / 12) : 0);
663
+ periods[O] = (show[O] ? months - periods[Y] * 12 : 0);
664
+ // Adjust for months difference and end of month if necessary
665
+ now = new Date(now.getTime());
666
+ var wasLastDay = (now.getDate() == lastNow);
667
+ var lastDay = $.countdown._getDaysInMonth(now.getFullYear() + periods[Y],
668
+ now.getMonth() + periods[O]);
669
+ if (now.getDate() > lastDay) {
670
+ now.setDate(lastDay);
671
+ }
672
+ now.setFullYear(now.getFullYear() + periods[Y]);
673
+ now.setMonth(now.getMonth() + periods[O]);
674
+ if (wasLastDay) {
675
+ now.setDate(lastDay);
676
+ }
677
+ }
678
+ var diff = Math.floor((until.getTime() - now.getTime()) / 1000);
679
+ var extractPeriod = function(period, numSecs) {
680
+ periods[period] = (show[period] ? Math.floor(diff / numSecs) : 0);
681
+ diff -= periods[period] * numSecs;
682
+ };
683
+ extractPeriod(W, 604800);
684
+ extractPeriod(D, 86400);
685
+ extractPeriod(H, 3600);
686
+ extractPeriod(M, 60);
687
+ extractPeriod(S, 1);
688
+ if (diff > 0 && !inst._since) { // Round up if left overs
689
+ var multiplier = [1, 12, 4.3482, 7, 24, 60, 60];
690
+ var lastShown = S;
691
+ var max = 1;
692
+ for (var period = S; period >= Y; period--) {
693
+ if (show[period]) {
694
+ if (periods[lastShown] >= max) {
695
+ periods[lastShown] = 0;
696
+ diff = 1;
697
+ }
698
+ if (diff > 0) {
699
+ periods[period]++;
700
+ diff = 0;
701
+ lastShown = period;
702
+ max = 1;
703
+ }
704
+ }
705
+ max *= multiplier[period];
706
+ }
707
+ }
708
+ if (significant) { // Zero out insignificant periods
709
+ for (var period = Y; period <= S; period++) {
710
+ if (significant && periods[period]) {
711
+ significant--;
712
+ }
713
+ else if (!significant) {
714
+ periods[period] = 0;
715
+ }
716
+ }
717
+ }
718
+ return periods;
719
+ }
720
+ });
721
+
722
+ /* jQuery extend now ignores nulls!
723
+ @param target (object) the object to update
724
+ @param props (object) the new settings
725
+ @return (object) the updated object */
726
+ function extendRemove(target, props) {
727
+ $.extend(target, props);
728
+ for (var name in props) {
729
+ if (props[name] == null) {
730
+ target[name] = null;
731
+ }
732
+ }
733
+ return target;
734
+ }
735
+
736
+ /* Process the countdown functionality for a jQuery selection.
737
+ @param command (string) the command to run (optional, default 'attach')
738
+ @param options (object) the new settings to use for these countdown instances
739
+ @return (jQuery) for chaining further calls */
740
+ $.fn.countdown = function(options) {
741
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
742
+ if (options == 'getTimes' || options == 'settings') {
743
+ return $.countdown['_' + options + 'Countdown'].
744
+ apply($.countdown, [this[0]].concat(otherArgs));
745
+ }
746
+ return this.each(function() {
747
+ if (typeof options == 'string') {
748
+ $.countdown['_' + options + 'Countdown'].apply($.countdown, [this].concat(otherArgs));
749
+ }
750
+ else {
751
+ $.countdown._attachCountdown(this, options);
752
+ }
753
+ });
754
+ };
755
+
756
+ /* Initialise the countdown functionality. */
757
+ $.countdown = new Countdown(); // singleton instance
758
+
759
+ })(jQuery);