refinerycms-core 0.9.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (305) hide show
  1. data/app/controllers/admin/base_controller.rb +10 -0
  2. data/app/controllers/admin/dialogs_controller.rb +26 -0
  3. data/app/controllers/admin/refinery_core_controller.rb +12 -0
  4. data/app/controllers/application_controller.rb +6 -0
  5. data/app/controllers/refinery/fast_controller.rb +9 -0
  6. data/app/controllers/sitemap_controller.rb +14 -0
  7. data/app/helpers/application_helper.rb +5 -0
  8. data/app/views/admin/_head.html.erb +43 -0
  9. data/app/views/admin/_javascripts.html.erb +32 -0
  10. data/app/views/admin/_menu.html.erb +17 -0
  11. data/app/views/admin/dialogs/show.html.erb +19 -0
  12. data/app/views/layouts/admin.html.erb +24 -0
  13. data/app/views/layouts/admin_dialog.html.erb +14 -0
  14. data/app/views/layouts/application.html.erb +21 -0
  15. data/app/views/shared/_content_page.html.erb +63 -0
  16. data/app/views/shared/_draft_page_message.html.erb +3 -0
  17. data/app/views/shared/_footer.html.erb +4 -0
  18. data/app/views/shared/_google_analytics.html.erb +8 -0
  19. data/app/views/shared/_head.html.erb +42 -0
  20. data/app/views/shared/_header.html.erb +8 -0
  21. data/app/views/shared/_html_tag.html.erb +6 -0
  22. data/app/views/shared/_ie6check.html.erb +63 -0
  23. data/app/views/shared/_javascripts.html.erb +10 -0
  24. data/app/views/shared/_menu.html.erb +30 -0
  25. data/app/views/shared/_menu_branch.html.erb +26 -0
  26. data/app/views/shared/_message.html.erb +10 -0
  27. data/app/views/shared/_no_script.html.erb +9 -0
  28. data/app/views/shared/_site_bar.html.erb +25 -0
  29. data/app/views/shared/admin/_continue_editing.html.erb +3 -0
  30. data/app/views/shared/admin/_error_messages.html.erb +16 -0
  31. data/app/views/shared/admin/_form_actions.html.erb +75 -0
  32. data/app/views/shared/admin/_image_picker.html.erb +60 -0
  33. data/app/views/shared/admin/_make_sortable.html.erb +13 -0
  34. data/app/views/shared/admin/_resource_picker.html.erb +66 -0
  35. data/app/views/shared/admin/_search.html.erb +6 -0
  36. data/app/views/shared/admin/_sortable_list.html.erb +7 -0
  37. data/app/views/shared/admin/_tabbed_fields.html.erb +42 -0
  38. data/app/views/welcome.html.erb +17 -0
  39. data/app/views/wymiframe.html.erb +15 -0
  40. data/config/locales/cs.yml +77 -0
  41. data/config/locales/da.yml +75 -0
  42. data/config/locales/de.yml +75 -0
  43. data/config/locales/el.yml +75 -0
  44. data/config/locales/en.yml +75 -0
  45. data/config/locales/es.yml +68 -0
  46. data/config/locales/fr.yml +72 -0
  47. data/config/locales/it.yml +96 -0
  48. data/config/locales/lolcat.yml +68 -0
  49. data/config/locales/lt.yml +75 -0
  50. data/config/locales/lv.yml +72 -0
  51. data/config/locales/nb.yml +75 -0
  52. data/config/locales/nl.yml +75 -0
  53. data/config/locales/pl.yml +75 -0
  54. data/config/locales/pt-BR.yml +72 -0
  55. data/config/locales/rs.yml +76 -0
  56. data/config/locales/ru.yml +71 -0
  57. data/config/locales/sl.yml +72 -0
  58. data/config/locales/sv.yml +75 -0
  59. data/config/locales/vi.yml +75 -0
  60. data/config/locales/zh-CN.yml +75 -0
  61. data/config/locales/zh-TW.yml +75 -0
  62. data/config/routes.rb +19 -0
  63. data/crud.md +197 -0
  64. data/doc/included-jquery-ui-packages.jpg +0 -0
  65. data/engines.md +179 -0
  66. data/features/search.feature +55 -0
  67. data/features/site_bar.feature +24 -0
  68. data/features/step_definitions/core_steps.rb +61 -0
  69. data/features/support/paths.rb +14 -0
  70. data/features/uploads/beach.jpeg +0 -0
  71. data/features/uploads/refinery_is_awesome.txt +1 -0
  72. data/lib/gemspec.rb +43 -0
  73. data/lib/generators/refinerycms_generator.rb +110 -0
  74. data/lib/generators/templates/.gitignore +83 -0
  75. data/lib/generators/templates/app/views/sitemap/index.xml.builder +22 -0
  76. data/lib/generators/templates/autotest/autotest.rb +17 -0
  77. data/lib/generators/templates/autotest/discover.rb +2 -0
  78. data/lib/generators/templates/config/database.yml.mysql +20 -0
  79. data/lib/generators/templates/config/database.yml.postgresql +57 -0
  80. data/lib/generators/templates/config/database.yml.sqlite3 +26 -0
  81. data/lib/generators/templates/config/i18n-js.yml +6 -0
  82. data/lib/generators/templates/config/initializers/devise.rb +142 -0
  83. data/lib/generators/templates/config/settings.rb +2 -0
  84. data/lib/generators/templates/db/seeds.rb +5 -0
  85. data/lib/refinery/activity.rb +45 -0
  86. data/lib/refinery/admin/base_controller.rb +111 -0
  87. data/lib/refinery/admin_base_controller.rb +5 -0
  88. data/lib/refinery/application.rb +48 -0
  89. data/lib/refinery/application_controller.rb +120 -0
  90. data/lib/refinery/application_helper.rb +19 -0
  91. data/lib/refinery/base_presenter.rb +27 -0
  92. data/lib/refinery/catch_all_routes.rb +11 -0
  93. data/lib/refinery/crud.rb +295 -0
  94. data/lib/refinery/helpers/form_helper.rb +66 -0
  95. data/lib/refinery/helpers/head_helper.rb +17 -0
  96. data/lib/refinery/helpers/html_truncation_helper.rb +25 -0
  97. data/lib/refinery/helpers/image_helper.rb +49 -0
  98. data/lib/refinery/helpers/menu_helper.rb +68 -0
  99. data/lib/refinery/helpers/meta_helper.rb +67 -0
  100. data/lib/refinery/helpers/pagination_helper.rb +16 -0
  101. data/lib/refinery/helpers/script_helper.rb +36 -0
  102. data/lib/refinery/helpers/site_bar_helper.rb +24 -0
  103. data/lib/refinery/helpers/tag_helper.rb +21 -0
  104. data/lib/refinery/helpers/translation_helper.rb +17 -0
  105. data/lib/refinery/link_renderer.rb +55 -0
  106. data/lib/refinery/plugin.rb +106 -0
  107. data/lib/refinery/plugins.rb +75 -0
  108. data/lib/refinerycms-core.rb +156 -0
  109. data/lib/tasks/doc.rake +29 -0
  110. data/lib/tasks/refinery.rake +231 -0
  111. data/lib/tasks/yard.rake +30 -0
  112. data/license.md +21 -0
  113. data/public/404.html +26 -0
  114. data/public/422.html +26 -0
  115. data/public/500.html +26 -0
  116. data/public/favicon.ico +0 -0
  117. data/public/images/refinery/add.png +0 -0
  118. data/public/images/refinery/admin_bg.png +0 -0
  119. data/public/images/refinery/ajax-loader.gif +0 -0
  120. data/public/images/refinery/branch-end.gif +0 -0
  121. data/public/images/refinery/branch-start.gif +0 -0
  122. data/public/images/refinery/branch.gif +0 -0
  123. data/public/images/refinery/carousel-left.png +0 -0
  124. data/public/images/refinery/carousel-right.png +0 -0
  125. data/public/images/refinery/cross.png +0 -0
  126. data/public/images/refinery/dialogLoadingAnimation.gif +0 -0
  127. data/public/images/refinery/header_background.png +0 -0
  128. data/public/images/refinery/hover-gradient.jpg +0 -0
  129. data/public/images/refinery/icons/accept.png +0 -0
  130. data/public/images/refinery/icons/add.png +0 -0
  131. data/public/images/refinery/icons/ajax-loader.gif +0 -0
  132. data/public/images/refinery/icons/application_edit.png +0 -0
  133. data/public/images/refinery/icons/application_go.png +0 -0
  134. data/public/images/refinery/icons/arrow_left.png +0 -0
  135. data/public/images/refinery/icons/arrow_switch.png +0 -0
  136. data/public/images/refinery/icons/arrow_up.png +0 -0
  137. data/public/images/refinery/icons/bin.png +0 -0
  138. data/public/images/refinery/icons/bin_closed.png +0 -0
  139. data/public/images/refinery/icons/cancel.png +0 -0
  140. data/public/images/refinery/icons/cog_add.png +0 -0
  141. data/public/images/refinery/icons/cog_edit.png +0 -0
  142. data/public/images/refinery/icons/cross.png +0 -0
  143. data/public/images/refinery/icons/delete.png +0 -0
  144. data/public/images/refinery/icons/doc.png +0 -0
  145. data/public/images/refinery/icons/down.gif +0 -0
  146. data/public/images/refinery/icons/edit.png +0 -0
  147. data/public/images/refinery/icons/email.png +0 -0
  148. data/public/images/refinery/icons/email_edit.png +0 -0
  149. data/public/images/refinery/icons/email_go.png +0 -0
  150. data/public/images/refinery/icons/email_open.png +0 -0
  151. data/public/images/refinery/icons/eye.png +0 -0
  152. data/public/images/refinery/icons/folder_page_white.png +0 -0
  153. data/public/images/refinery/icons/image_add.png +0 -0
  154. data/public/images/refinery/icons/image_edit.png +0 -0
  155. data/public/images/refinery/icons/img.png +0 -0
  156. data/public/images/refinery/icons/information.png +0 -0
  157. data/public/images/refinery/icons/layout_add.png +0 -0
  158. data/public/images/refinery/icons/layout_edit.png +0 -0
  159. data/public/images/refinery/icons/music.png +0 -0
  160. data/public/images/refinery/icons/page_add.png +0 -0
  161. data/public/images/refinery/icons/page_edit.png +0 -0
  162. data/public/images/refinery/icons/page_white_edit.png +0 -0
  163. data/public/images/refinery/icons/page_white_gear.png +0 -0
  164. data/public/images/refinery/icons/page_white_put.png +0 -0
  165. data/public/images/refinery/icons/pdf.png +0 -0
  166. data/public/images/refinery/icons/ppt.png +0 -0
  167. data/public/images/refinery/icons/star.png +0 -0
  168. data/public/images/refinery/icons/tick.png +0 -0
  169. data/public/images/refinery/icons/up.gif +0 -0
  170. data/public/images/refinery/icons/user_add.png +0 -0
  171. data/public/images/refinery/icons/user_comment.png +0 -0
  172. data/public/images/refinery/icons/user_edit.png +0 -0
  173. data/public/images/refinery/icons/xls.png +0 -0
  174. data/public/images/refinery/icons/zip.png +0 -0
  175. data/public/images/refinery/icons/zoom.png +0 -0
  176. data/public/images/refinery/logo-large.png +0 -0
  177. data/public/images/refinery/logo-medium.png +0 -0
  178. data/public/images/refinery/logo-site-bar.png +0 -0
  179. data/public/images/refinery/logo-small-medium.png +0 -0
  180. data/public/images/refinery/logo-small.png +0 -0
  181. data/public/images/refinery/logo-tiny.png +0 -0
  182. data/public/images/refinery/logo.png +0 -0
  183. data/public/images/refinery/nav-3-background.gif +0 -0
  184. data/public/images/refinery/nav_inactive_background.png +0 -0
  185. data/public/images/refinery/orange_button.png +0 -0
  186. data/public/images/refinery/page_bg.png +0 -0
  187. data/public/images/refinery/resolve_digital_footer_logo.png +0 -0
  188. data/public/images/refinery/text_field_background.png +0 -0
  189. data/public/images/refinery/tooltip-nib.gif +0 -0
  190. data/public/images/refinery/tooltip-nib.png +0 -0
  191. data/public/images/wymeditor/skins/refinery/arrow_redo.png +0 -0
  192. data/public/images/wymeditor/skins/refinery/arrow_undo.png +0 -0
  193. data/public/images/wymeditor/skins/refinery/eye.png +0 -0
  194. data/public/images/wymeditor/skins/refinery/iframe/lbl-blockquote.png +0 -0
  195. data/public/images/wymeditor/skins/refinery/iframe/lbl-h1.png +0 -0
  196. data/public/images/wymeditor/skins/refinery/iframe/lbl-h2.png +0 -0
  197. data/public/images/wymeditor/skins/refinery/iframe/lbl-h3.png +0 -0
  198. data/public/images/wymeditor/skins/refinery/iframe/lbl-h4.png +0 -0
  199. data/public/images/wymeditor/skins/refinery/iframe/lbl-h5.png +0 -0
  200. data/public/images/wymeditor/skins/refinery/iframe/lbl-h6.png +0 -0
  201. data/public/images/wymeditor/skins/refinery/iframe/lbl-p.png +0 -0
  202. data/public/images/wymeditor/skins/refinery/iframe/lbl-pre.png +0 -0
  203. data/public/images/wymeditor/skins/refinery/link_add.png +0 -0
  204. data/public/images/wymeditor/skins/refinery/link_break.png +0 -0
  205. data/public/images/wymeditor/skins/refinery/page_code.png +0 -0
  206. data/public/images/wymeditor/skins/refinery/page_paste.png +0 -0
  207. data/public/images/wymeditor/skins/refinery/photo_add.png +0 -0
  208. data/public/images/wymeditor/skins/refinery/right.png +0 -0
  209. data/public/images/wymeditor/skins/refinery/style.png +0 -0
  210. data/public/images/wymeditor/skins/refinery/table_add.png +0 -0
  211. data/public/images/wymeditor/skins/refinery/text_align_center.png +0 -0
  212. data/public/images/wymeditor/skins/refinery/text_align_justify.png +0 -0
  213. data/public/images/wymeditor/skins/refinery/text_align_left.png +0 -0
  214. data/public/images/wymeditor/skins/refinery/text_align_right.png +0 -0
  215. data/public/images/wymeditor/skins/refinery/text_bold.png +0 -0
  216. data/public/images/wymeditor/skins/refinery/text_heading_1.png +0 -0
  217. data/public/images/wymeditor/skins/refinery/text_heading_2.png +0 -0
  218. data/public/images/wymeditor/skins/refinery/text_heading_3.png +0 -0
  219. data/public/images/wymeditor/skins/refinery/text_heading_4.png +0 -0
  220. data/public/images/wymeditor/skins/refinery/text_heading_5.png +0 -0
  221. data/public/images/wymeditor/skins/refinery/text_heading_6.png +0 -0
  222. data/public/images/wymeditor/skins/refinery/text_indent.png +0 -0
  223. data/public/images/wymeditor/skins/refinery/text_indent_remove.png +0 -0
  224. data/public/images/wymeditor/skins/refinery/text_italic.png +0 -0
  225. data/public/images/wymeditor/skins/refinery/text_list_bullets.png +0 -0
  226. data/public/images/wymeditor/skins/refinery/text_list_numbers.png +0 -0
  227. data/public/images/wymeditor/skins/refinery/text_paragraph.png +0 -0
  228. data/public/images/wymeditor/skins/refinery/text_strikethrough.png +0 -0
  229. data/public/images/wymeditor/skins/refinery/text_subscript.png +0 -0
  230. data/public/images/wymeditor/skins/refinery/text_superscript.png +0 -0
  231. data/public/images/wymeditor/skins/refinery/text_underline.png +0 -0
  232. data/public/images/wymeditor/skins/wymeditor_icon.png +0 -0
  233. data/public/javascripts/admin.js +7 -0
  234. data/public/javascripts/application.js +1 -0
  235. data/public/javascripts/dd_belatedpng.js +13 -0
  236. data/public/javascripts/i18n-messages.js +2 -0
  237. data/public/javascripts/jquery-min.js +16 -0
  238. data/public/javascripts/jquery-ui-custom-min.js +251 -0
  239. data/public/javascripts/jquery.js +8176 -0
  240. data/public/javascripts/jquery/GPL-LICENSE.txt +278 -0
  241. data/public/javascripts/jquery/MIT-LICENSE.txt +20 -0
  242. data/public/javascripts/jquery/jquery.corner.js +345 -0
  243. data/public/javascripts/jquery/jquery.html5-placeholder-shim.js +88 -0
  244. data/public/javascripts/jquery/jquery.jcarousel.js +900 -0
  245. data/public/javascripts/jquery/jquery.textTruncate.js +174 -0
  246. data/public/javascripts/jquery/jquery.timers.js +138 -0
  247. data/public/javascripts/modernizr-min.js +30 -0
  248. data/public/javascripts/rails.js +175 -0
  249. data/public/javascripts/refinery/admin.js +1114 -0
  250. data/public/javascripts/refinery/boot_wym.js +285 -0
  251. data/public/javascripts/refinery/core.js +18 -0
  252. data/public/javascripts/refinery/i18n.js +340 -0
  253. data/public/javascripts/refinery/nestedsortables.js +164 -0
  254. data/public/javascripts/refinery/serializelist.js +66 -0
  255. data/public/javascripts/refinery/site_bar.js +16 -0
  256. data/public/javascripts/refinery/submenu.js +49 -0
  257. data/public/javascripts/wymeditor/jquery.refinery.wymeditor.js +5156 -0
  258. data/public/javascripts/wymeditor/lang/ca.js +45 -0
  259. data/public/javascripts/wymeditor/lang/cs.js +45 -0
  260. data/public/javascripts/wymeditor/lang/da.js +48 -0
  261. data/public/javascripts/wymeditor/lang/de.js +45 -0
  262. data/public/javascripts/wymeditor/lang/en.js +47 -0
  263. data/public/javascripts/wymeditor/lang/es.js +48 -0
  264. data/public/javascripts/wymeditor/lang/fa.js +46 -0
  265. data/public/javascripts/wymeditor/lang/fr.js +45 -0
  266. data/public/javascripts/wymeditor/lang/he.js +45 -0
  267. data/public/javascripts/wymeditor/lang/hu.js +45 -0
  268. data/public/javascripts/wymeditor/lang/it.js +48 -0
  269. data/public/javascripts/wymeditor/lang/lv.js +47 -0
  270. data/public/javascripts/wymeditor/lang/nb.js +48 -0
  271. data/public/javascripts/wymeditor/lang/nl.js +47 -0
  272. data/public/javascripts/wymeditor/lang/nn.js +45 -0
  273. data/public/javascripts/wymeditor/lang/pl.js +45 -0
  274. data/public/javascripts/wymeditor/lang/pt-BR.js +47 -0
  275. data/public/javascripts/wymeditor/lang/pt.js +45 -0
  276. data/public/javascripts/wymeditor/lang/rs.js +47 -0
  277. data/public/javascripts/wymeditor/lang/ru.js +45 -0
  278. data/public/javascripts/wymeditor/lang/sl.js +47 -0
  279. data/public/javascripts/wymeditor/lang/sv.js +45 -0
  280. data/public/javascripts/wymeditor/lang/tr.js +45 -0
  281. data/public/javascripts/wymeditor/lang/vi.js +47 -0
  282. data/public/javascripts/wymeditor/lang/zh_cn.js +47 -0
  283. data/public/javascripts/wymeditor/skins/refinery/skin.js +48 -0
  284. data/public/robots.txt +3 -0
  285. data/public/stylesheets/application.css +4 -0
  286. data/public/stylesheets/formatting.css +4 -0
  287. data/public/stylesheets/home.css +4 -0
  288. data/public/stylesheets/refinery/application.css +72 -0
  289. data/public/stylesheets/refinery/formatting.css +57 -0
  290. data/public/stylesheets/refinery/home.css +0 -0
  291. data/public/stylesheets/refinery/refinery.css +1579 -0
  292. data/public/stylesheets/refinery/site_bar.css +87 -0
  293. data/public/stylesheets/refinery/submenu.css +22 -0
  294. data/public/stylesheets/refinery/theme.css +36 -0
  295. data/public/stylesheets/refinery/tooltips.css +34 -0
  296. data/public/stylesheets/refinery/ui.css +107 -0
  297. data/public/stylesheets/theme.css +4 -0
  298. data/public/stylesheets/wymeditor/skins/refinery/skin.css +528 -0
  299. data/public/stylesheets/wymeditor/skins/refinery/wymiframe.css +96 -0
  300. data/public/wymeditor/GPL-license.txt +278 -0
  301. data/public/wymeditor/MIT-license.txt +20 -0
  302. data/public/wymeditor/README +35 -0
  303. data/refinerycms-core.gemspec +391 -0
  304. data/spec/lib/refinery/plugins_spec.rb +90 -0
  305. metadata +482 -0
@@ -0,0 +1,88 @@
1
+ (function($) {
2
+ $.extend($,{ placeholder: {
3
+ browser_supported: function() {
4
+ return this._supported !== undefined ?
5
+ this._supported :
6
+ ( this._supported = !!('placeholder' in $('<input type="text">')[0]) );
7
+ },
8
+ shim: function(opts) {
9
+ var config = {
10
+ color: '#888',
11
+ cls: '',
12
+ lr_padding:4,
13
+ selector: 'input[placeholder], textarea[placeholder]'
14
+ };
15
+ $.extend(config,opts);
16
+ !this.browser_supported() && $(config.selector)._placeholder_shim(config);
17
+ }
18
+ }});
19
+
20
+ $.extend($.fn,{
21
+ _placeholder_shim: function(config) {
22
+ function calcPositionCss(target)
23
+ {
24
+ var op = $(target).offsetParent().offset();
25
+ var ot = $(target).offset();
26
+
27
+ return {
28
+ top: ot.top - op.top + ($(target).outerHeight() - $(target).height()) /2,
29
+ left: ot.left - op.left + config.lr_padding,
30
+ width: $(target).width() - config.lr_padding
31
+ };
32
+ }
33
+ return this.each(function() {
34
+ if( $(this).data('placeholder') ) {
35
+ var $ol = $(this).data('placeholder');
36
+ $ol.css(calcPositionCss($(this)));
37
+ return true;
38
+ }
39
+
40
+ var possible_line_height = {};
41
+ if( $(this).css('height') != 'auto') {
42
+ possible_line_height = { lineHeight: $(this).css('height') };
43
+ }
44
+
45
+ var ol = $('<label />')
46
+ .text($(this).attr('placeholder'))
47
+ .addClass(config.cls)
48
+ .css($.extend({
49
+ position:'absolute',
50
+ display: 'inline',
51
+ float:'none',
52
+ overflow:'hidden',
53
+ whiteSpace:'nowrap',
54
+ textAlign: 'left',
55
+ color: config.color,
56
+ cursor: 'text',
57
+ fontSize: $(this).css('font-size')
58
+ }, possible_line_height))
59
+ .css(calcPositionCss(this))
60
+ .attr('for', this.id)
61
+ .data('target',$(this))
62
+ .click(function(){
63
+ $(this).data('target').focus()
64
+ })
65
+ .insertBefore(this);
66
+ $(this)
67
+ .data('placeholder',ol)
68
+ .focus(function(){
69
+ ol.hide();
70
+ }).blur(function() {
71
+ ol[$(this).val().length ? 'hide' : 'show']();
72
+ }).triggerHandler('blur');
73
+ $(window)
74
+ .resize(function() {
75
+ var $target = ol.data('target')
76
+ ol.css(calcPositionCss($target))
77
+ });
78
+ });
79
+ }
80
+ });
81
+
82
+ })(jQuery);
83
+
84
+ $(document).ready(function() {
85
+ if ($.placeholder) {
86
+ $.placeholder.shim();
87
+ }
88
+ });
@@ -0,0 +1,900 @@
1
+ /*!
2
+ * jCarousel - Riding carousels with jQuery
3
+ * http://sorgalla.com/jcarousel/
4
+ *
5
+ * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com)
6
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
7
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
8
+ *
9
+ * Built on top of the jQuery library
10
+ * http://jquery.com
11
+ *
12
+ * Inspired by the "Carousel Component" by Bill Scott
13
+ * http://billwscott.com/carousel/
14
+ */
15
+
16
+ (function($) {
17
+ /**
18
+ * Creates a carousel for all matched elements.
19
+ *
20
+ * @example $("#mycarousel").jcarousel();
21
+ * @before <ul id="mycarousel" class="jcarousel-skin-name"><li>First item</li><li>Second item</li></ul>
22
+ * @result
23
+ *
24
+ * <div class="jcarousel-skin-name">
25
+ * <div class="jcarousel-container">
26
+ * <div disabled="disabled" class="jcarousel-prev jcarousel-prev-disabled"></div>
27
+ * <div class="jcarousel-clip">
28
+ * <ul class="jcarousel-list">
29
+ * <li class="jcarousel-item-1">First item</li>
30
+ * <li class="jcarousel-item-2">Second item</li>
31
+ * </ul>
32
+ * </div>
33
+ * <div class="jcarousel-next"></div>
34
+ * </div>
35
+ * </div>
36
+ *
37
+ * @method jcarousel
38
+ * @return jQuery
39
+ * @param o {Hash|String} A set of key/value pairs to set as configuration properties or a method name to call on a formerly created instance.
40
+ */
41
+ $.fn.jcarousel = function(o) {
42
+ if (typeof o == 'string') {
43
+ var instance = $(this).data('jcarousel'), args = Array.prototype.slice.call(arguments, 1);
44
+ return instance[o].apply(instance, args);
45
+ } else
46
+ return this.each(function() {
47
+ $(this).data('jcarousel', new $jc(this, o));
48
+ });
49
+ };
50
+
51
+ // Default configuration properties.
52
+ var defaults = {
53
+ vertical: false,
54
+ listTag: 'ul',
55
+ itemTag: 'li',
56
+ start: 1,
57
+ offset: 1,
58
+ size: null,
59
+ scroll: 3,
60
+ visible: null,
61
+ animation: 'normal',
62
+ easing: 'swing',
63
+ auto: 0,
64
+ wrap: null,
65
+ initCallback: null,
66
+ reloadCallback: null,
67
+ itemLoadCallback: null,
68
+ itemFirstInCallback: null,
69
+ itemFirstOutCallback: null,
70
+ itemLastInCallback: null,
71
+ itemLastOutCallback: null,
72
+ itemVisibleInCallback: null,
73
+ itemVisibleOutCallback: null,
74
+ buttonNextHTML: '<div></div>',
75
+ buttonPrevHTML: '<div></div>',
76
+ buttonNextEvent: 'click',
77
+ buttonPrevEvent: 'click',
78
+ buttonNextCallback: null,
79
+ buttonPrevCallback: null
80
+ };
81
+
82
+ /**
83
+ * The jCarousel object.
84
+ *
85
+ * @constructor
86
+ * @class jcarousel
87
+ * @param e {HTMLElement} The element to create the carousel for.
88
+ * @param o {Object} A set of key/value pairs to set as configuration properties.
89
+ * @cat Plugins/jCarousel
90
+ */
91
+ $.jcarousel = function(e, o) {
92
+ this.options = $.extend({}, defaults, o || {});
93
+
94
+ this.locked = false;
95
+
96
+ this.container = null;
97
+ this.clip = null;
98
+ this.list = null;
99
+ this.buttonNext = null;
100
+ this.buttonPrev = null;
101
+
102
+ this.wh = !this.options.vertical ? 'width' : 'height';
103
+ this.lt = !this.options.vertical ? 'left' : 'top';
104
+
105
+ // Extract skin class
106
+ var skin = '', split = e.className.split(' ');
107
+
108
+ for (var i = 0; i < split.length; i++) {
109
+ if (split[i].indexOf('jcarousel-skin') != -1) {
110
+ $(e).removeClass(split[i]);
111
+ skin = split[i];
112
+ break;
113
+ }
114
+ }
115
+
116
+ if (e.nodeName.toUpperCase() == this.options.listTag.toUpperCase()) {
117
+ this.list = $(e);
118
+ this.container = this.list.parent();
119
+
120
+ if (this.container.hasClass('jcarousel-clip')) {
121
+ if (!this.container.parent().hasClass('jcarousel-container'))
122
+ this.container = this.container.wrap('<div></div>');
123
+
124
+ this.container = this.container.parent();
125
+ } else if (!this.container.hasClass('jcarousel-container'))
126
+ this.container = this.list.wrap('<div></div>').parent();
127
+ } else {
128
+ this.container = $(e);
129
+ this.list = this.container.find(this.options.listTag).eq(0);
130
+ }
131
+
132
+ if (skin != '' && this.container.parent()[0].className.indexOf('jcarousel-skin') == -1)
133
+ this.container.wrap('<div class=" '+ skin + '"></div>');
134
+
135
+ this.clip = this.list.parent();
136
+
137
+ if (!this.clip.length || !this.clip.hasClass('jcarousel-clip'))
138
+ this.clip = this.list.wrap('<div></div>').parent();
139
+
140
+ this.buttonNext = $('.jcarousel-next', this.container);
141
+
142
+ if (this.buttonNext.size() == 0 && this.options.buttonNextHTML != null)
143
+ this.buttonNext = this.clip.after(this.options.buttonNextHTML).next();
144
+
145
+ this.buttonNext.addClass(this.className('jcarousel-next'));
146
+
147
+ this.buttonPrev = $('.jcarousel-prev', this.container);
148
+
149
+ if (this.buttonPrev.size() == 0 && this.options.buttonPrevHTML != null)
150
+ this.buttonPrev = this.clip.before(this.options.buttonPrevHTML).prev();
151
+
152
+ this.buttonPrev.addClass(this.className('jcarousel-prev'));
153
+
154
+ this.clip.addClass(this.className('jcarousel-clip')).css({
155
+ overflow: 'hidden',
156
+ position: 'relative'
157
+ });
158
+ this.list.addClass(this.className('jcarousel-list')).css({
159
+ overflow: 'hidden',
160
+ position: 'relative',
161
+ top: 0,
162
+ left: 0,
163
+ margin: 0,
164
+ padding: 0
165
+ });
166
+ this.container.addClass(this.className('jcarousel-container')).css({
167
+ position: 'relative'
168
+ });
169
+
170
+ var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
171
+ var li = this.list.children(this.options.itemTag);
172
+
173
+ var self = this;
174
+
175
+ if (li.size() > 0) {
176
+ var wh = 0, i = this.options.offset;
177
+ li.each(function() {
178
+ self.format(this, i++);
179
+ wh += self.dimension(this, di);
180
+ });
181
+
182
+ this.list.css(this.wh, wh + 'px');
183
+
184
+ // Only set if not explicitly passed as option
185
+ if (!o || o.size === undefined)
186
+ this.options.size = li.size();
187
+ }
188
+
189
+ // For whatever reason, .show() does not work in Safari...
190
+ this.container.css('display', 'block');
191
+ this.buttonNext.css('display', 'block');
192
+ this.buttonPrev.css('display', 'block');
193
+
194
+ this.funcNext = function() { self.next(); };
195
+ this.funcPrev = function() { self.prev(); };
196
+ this.funcResize = function() { self.reload(); };
197
+
198
+ if (this.options.initCallback != null)
199
+ this.options.initCallback(this, 'init');
200
+
201
+ if ($.browser.safari) {
202
+ this.buttons(false, false);
203
+ $(window).bind('load.jcarousel', function() { self.setup(); });
204
+ } else
205
+ this.setup();
206
+ };
207
+
208
+ // Create shortcut for internal use
209
+ var $jc = $.jcarousel;
210
+
211
+ $jc.fn = $jc.prototype = {
212
+ jcarousel: '0.2.4'
213
+ };
214
+
215
+ $jc.fn.extend = $jc.extend = $.extend;
216
+
217
+ $jc.fn.extend({
218
+ /**
219
+ * Setups the carousel.
220
+ *
221
+ * @method setup
222
+ * @return undefined
223
+ */
224
+ setup: function() {
225
+ this.first = null;
226
+ this.last = null;
227
+ this.prevFirst = null;
228
+ this.prevLast = null;
229
+ this.animating = false;
230
+ this.timer = null;
231
+ this.tail = null;
232
+ this.inTail = false;
233
+
234
+ if (this.locked)
235
+ return;
236
+
237
+ this.list.css(this.lt, this.pos(this.options.offset) + 'px');
238
+ var p = this.pos(this.options.start);
239
+ this.prevFirst = this.prevLast = null;
240
+ this.animate(p, false);
241
+
242
+ $(window).unbind('resize.jcarousel', this.funcResize).bind('resize.jcarousel', this.funcResize);
243
+ },
244
+
245
+ /**
246
+ * Clears the list and resets the carousel.
247
+ *
248
+ * @method reset
249
+ * @return undefined
250
+ */
251
+ reset: function() {
252
+ this.list.empty();
253
+
254
+ this.list.css(this.lt, '0px');
255
+ this.list.css(this.wh, '10px');
256
+
257
+ if (this.options.initCallback != null)
258
+ this.options.initCallback(this, 'reset');
259
+
260
+ this.setup();
261
+ },
262
+
263
+ /**
264
+ * Reloads the carousel and adjusts positions.
265
+ *
266
+ * @method reload
267
+ * @return undefined
268
+ */
269
+ reload: function() {
270
+ if (this.tail != null && this.inTail)
271
+ this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + this.tail);
272
+
273
+ this.tail = null;
274
+ this.inTail = false;
275
+
276
+ if (this.options.reloadCallback != null)
277
+ this.options.reloadCallback(this);
278
+
279
+ if (this.options.visible != null) {
280
+ var self = this;
281
+ var di = Math.ceil(this.clipping() / this.options.visible), wh = 0, lt = 0;
282
+ $(this.options.itemTag, this.list).each(function(i) {
283
+ wh += self.dimension(this, di);
284
+ if (i + 1 < self.first)
285
+ lt = wh;
286
+ });
287
+
288
+ this.list.css(this.wh, wh + 'px');
289
+ this.list.css(this.lt, -lt + 'px');
290
+ }
291
+
292
+ this.scroll(this.first, false);
293
+ },
294
+
295
+ /**
296
+ * Locks the carousel.
297
+ *
298
+ * @method lock
299
+ * @return undefined
300
+ */
301
+ lock: function() {
302
+ this.locked = true;
303
+ this.buttons();
304
+ },
305
+
306
+ /**
307
+ * Unlocks the carousel.
308
+ *
309
+ * @method unlock
310
+ * @return undefined
311
+ */
312
+ unlock: function() {
313
+ this.locked = false;
314
+ this.buttons();
315
+ },
316
+
317
+ /**
318
+ * Sets the size of the carousel.
319
+ *
320
+ * @method size
321
+ * @return undefined
322
+ * @param s {Number} The size of the carousel.
323
+ */
324
+ size: function(s) {
325
+ if (s != undefined) {
326
+ this.options.size = s;
327
+ if (!this.locked)
328
+ this.buttons();
329
+ }
330
+
331
+ return this.options.size;
332
+ },
333
+
334
+ /**
335
+ * Checks whether a list element exists for the given index (or index range).
336
+ *
337
+ * @method get
338
+ * @return bool
339
+ * @param i {Number} The index of the (first) element.
340
+ * @param i2 {Number} The index of the last element.
341
+ */
342
+ has: function(i, i2) {
343
+ if (i2 == undefined || !i2)
344
+ i2 = i;
345
+
346
+ if (this.options.size !== null && i2 > this.options.size)
347
+ i2 = this.options.size;
348
+
349
+ for (var j = i; j <= i2; j++) {
350
+ var e = this.get(j);
351
+ if (!e.length || e.hasClass('jcarousel-item-placeholder'))
352
+ return false;
353
+ }
354
+
355
+ return true;
356
+ },
357
+
358
+ /**
359
+ * Returns a jQuery object with list element for the given index.
360
+ *
361
+ * @method get
362
+ * @return jQuery
363
+ * @param i {Number} The index of the element.
364
+ */
365
+ get: function(i) {
366
+ return $('.jcarousel-item-' + i, this.list);
367
+ },
368
+
369
+ /**
370
+ * Adds an element for the given index to the list.
371
+ * If the element already exists, it updates the inner html.
372
+ * Returns the created element as jQuery object.
373
+ *
374
+ * @method add
375
+ * @return jQuery
376
+ * @param i {Number} The index of the element.
377
+ * @param s {String} The innerHTML of the element.
378
+ */
379
+ add: function(i, s) {
380
+ var e = this.get(i), old = 0, add = 0;
381
+
382
+ if (e.length == 0) {
383
+ var c, e = this.create(i), j = $jc.intval(i);
384
+ while (c = this.get(--j)) {
385
+ if (j <= 0 || c.length) {
386
+ j <= 0 ? this.list.prepend(e) : c.after(e);
387
+ break;
388
+ }
389
+ }
390
+ } else
391
+ old = this.dimension(e);
392
+
393
+ e.removeClass(this.className('jcarousel-item-placeholder'));
394
+ typeof s == 'string' ? e.html(s) : e.empty().append(s);
395
+
396
+ var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null;
397
+ var wh = this.dimension(e, di) - old;
398
+
399
+ if (i > 0 && i < this.first)
400
+ this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - wh + 'px');
401
+
402
+ this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) + wh + 'px');
403
+
404
+ return e;
405
+ },
406
+
407
+ /**
408
+ * Removes an element for the given index from the list.
409
+ *
410
+ * @method remove
411
+ * @return undefined
412
+ * @param i {Number} The index of the element.
413
+ */
414
+ remove: function(i) {
415
+ var e = this.get(i);
416
+
417
+ // Check if item exists and is not currently visible
418
+ if (!e.length || (i >= this.first && i <= this.last))
419
+ return;
420
+
421
+ var d = this.dimension(e);
422
+
423
+ if (i < this.first)
424
+ this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + d + 'px');
425
+
426
+ e.remove();
427
+
428
+ this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) - d + 'px');
429
+ },
430
+
431
+ /**
432
+ * Moves the carousel forwards.
433
+ *
434
+ * @method next
435
+ * @return undefined
436
+ */
437
+ next: function() {
438
+ this.stopAuto();
439
+
440
+ if (this.tail != null && !this.inTail)
441
+ this.scrollTail(false);
442
+ else
443
+ this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'last') && this.options.size != null && this.last == this.options.size) ? 1 : this.first + this.options.scroll);
444
+ },
445
+
446
+ /**
447
+ * Moves the carousel backwards.
448
+ *
449
+ * @method prev
450
+ * @return undefined
451
+ */
452
+ prev: function() {
453
+ this.stopAuto();
454
+
455
+ if (this.tail != null && this.inTail)
456
+ this.scrollTail(true);
457
+ else
458
+ this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'first') && this.options.size != null && this.first == 1) ? this.options.size : this.first - this.options.scroll);
459
+ },
460
+
461
+ /**
462
+ * Scrolls the tail of the carousel.
463
+ *
464
+ * @method scrollTail
465
+ * @return undefined
466
+ * @param b {Boolean} Whether scroll the tail back or forward.
467
+ */
468
+ scrollTail: function(b) {
469
+ if (this.locked || this.animating || !this.tail)
470
+ return;
471
+
472
+ var pos = $jc.intval(this.list.css(this.lt));
473
+
474
+ !b ? pos -= this.tail : pos += this.tail;
475
+ this.inTail = !b;
476
+
477
+ // Save for callbacks
478
+ this.prevFirst = this.first;
479
+ this.prevLast = this.last;
480
+
481
+ this.animate(pos);
482
+ },
483
+
484
+ /**
485
+ * Scrolls the carousel to a certain position.
486
+ *
487
+ * @method scroll
488
+ * @return undefined
489
+ * @param i {Number} The index of the element to scoll to.
490
+ * @param a {Boolean} Flag indicating whether to perform animation.
491
+ */
492
+ scroll: function(i, a) {
493
+ if (this.locked || this.animating)
494
+ return;
495
+
496
+ this.animate(this.pos(i), a);
497
+ },
498
+
499
+ /**
500
+ * Prepares the carousel and return the position for a certian index.
501
+ *
502
+ * @method pos
503
+ * @return {Number}
504
+ * @param i {Number} The index of the element to scoll to.
505
+ */
506
+ pos: function(i) {
507
+ var pos = $jc.intval(this.list.css(this.lt));
508
+
509
+ if (this.locked || this.animating)
510
+ return pos;
511
+
512
+ if (this.options.wrap != 'circular')
513
+ i = i < 1 ? 1 : (this.options.size && i > this.options.size ? this.options.size : i);
514
+
515
+ var back = this.first > i;
516
+
517
+ // Create placeholders, new list width/height
518
+ // and new list position
519
+ var f = this.options.wrap != 'circular' && this.first <= 1 ? 1 : this.first;
520
+ var c = back ? this.get(f) : this.get(this.last);
521
+ var j = back ? f : f - 1;
522
+ var e = null, l = 0, p = false, d = 0, g;
523
+
524
+ while (back ? --j >= i : ++j < i) {
525
+ e = this.get(j);
526
+ p = !e.length;
527
+ if (e.length == 0) {
528
+ e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
529
+ c[back ? 'before' : 'after' ](e);
530
+
531
+ if (this.first != null && this.options.wrap == 'circular' && this.options.size !== null && (j <= 0 || j > this.options.size)) {
532
+ g = this.get(this.index(j));
533
+ if (g.length)
534
+ this.add(j, g.children().clone(true));
535
+ }
536
+ }
537
+
538
+ c = e;
539
+ d = this.dimension(e);
540
+
541
+ if (p)
542
+ l += d;
543
+
544
+ if (this.first != null && (this.options.wrap == 'circular' || (j >= 1 && (this.options.size == null || j <= this.options.size))))
545
+ pos = back ? pos + d : pos - d;
546
+ }
547
+
548
+ // Calculate visible items
549
+ var clipping = this.clipping();
550
+ var cache = [];
551
+ var visible = 0, j = i, v = 0;
552
+ var c = this.get(i - 1);
553
+
554
+ while (++visible) {
555
+ e = this.get(j);
556
+ p = !e.length;
557
+ if (e.length == 0) {
558
+ e = this.create(j).addClass(this.className('jcarousel-item-placeholder'));
559
+ // This should only happen on a next scroll
560
+ c.length == 0 ? this.list.prepend(e) : c[back ? 'before' : 'after' ](e);
561
+
562
+ if (this.first != null && this.options.wrap == 'circular' && this.options.size !== null && (j <= 0 || j > this.options.size)) {
563
+ g = this.get(this.index(j));
564
+ if (g.length)
565
+ this.add(j, g.find('>*').clone(true));
566
+ }
567
+ }
568
+
569
+ c = e;
570
+ var d = this.dimension(e);
571
+ if (d == 0) {
572
+ if (console && $.isFunction(console.log)) {
573
+ console.log('jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...');
574
+ }
575
+ return 0;
576
+ }
577
+
578
+ if (this.options.wrap != 'circular' && this.options.size !== null && j > this.options.size)
579
+ cache.push(e);
580
+ else if (p)
581
+ l += d;
582
+
583
+ v += d;
584
+
585
+ if (v >= clipping)
586
+ break;
587
+
588
+ j++;
589
+ }
590
+
591
+ // Remove out-of-range placeholders
592
+ for (var x = 0; x < cache.length; x++)
593
+ cache[x].remove();
594
+
595
+ // Resize list
596
+ if (l > 0) {
597
+ this.list.css(this.wh, this.dimension(this.list) + l + 'px');
598
+
599
+ if (back) {
600
+ pos -= l;
601
+ this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - l + 'px');
602
+ }
603
+ }
604
+
605
+ // Calculate first and last item
606
+ var last = i + visible - 1;
607
+ if (this.options.wrap != 'circular' && this.options.size && last > this.options.size)
608
+ last = this.options.size;
609
+
610
+ if (j > last) {
611
+ visible = 0, j = last, v = 0;
612
+ while (++visible) {
613
+ var e = this.get(j--);
614
+ if (!e.length)
615
+ break;
616
+ v += this.dimension(e);
617
+ if (v >= clipping)
618
+ break;
619
+ }
620
+ }
621
+
622
+ var first = last - visible + 1;
623
+ if (this.options.wrap != 'circular' && first < 1)
624
+ first = 1;
625
+
626
+ if (this.inTail && back) {
627
+ pos += this.tail;
628
+ this.inTail = false;
629
+ }
630
+
631
+ this.tail = null;
632
+ if (this.options.wrap != 'circular' && last == this.options.size && (last - visible + 1) >= 1) {
633
+ var m = $jc.margin(this.get(last), !this.options.vertical ? 'marginRight' : 'marginBottom');
634
+ if ((v - m) > clipping)
635
+ this.tail = v - clipping - m;
636
+ }
637
+
638
+ // Adjust position
639
+ while (i-- > first)
640
+ pos += this.dimension(this.get(i));
641
+
642
+ // Save visible item range
643
+ this.prevFirst = this.first;
644
+ this.prevLast = this.last;
645
+ this.first = first;
646
+ this.last = last;
647
+
648
+ return pos;
649
+ },
650
+
651
+ /**
652
+ * Animates the carousel to a certain position.
653
+ *
654
+ * @method animate
655
+ * @return undefined
656
+ * @param p {Number} Position to scroll to.
657
+ * @param a {Boolean} Flag indicating whether to perform animation.
658
+ */
659
+ animate: function(p, a) {
660
+ if (this.locked || this.animating)
661
+ return;
662
+
663
+ this.animating = true;
664
+
665
+ var self = this;
666
+ var scrolled = function() {
667
+ self.animating = false;
668
+
669
+ if (p == 0)
670
+ self.list.css(self.lt, 0);
671
+
672
+ if (self.options.wrap == 'circular' || self.options.wrap == 'both' || self.options.wrap == 'last' || self.options.size == null || self.last < self.options.size)
673
+ self.startAuto();
674
+
675
+ self.buttons();
676
+ self.notify('onAfterAnimation');
677
+ };
678
+
679
+ this.notify('onBeforeAnimation');
680
+
681
+ // Animate
682
+ if (!this.options.animation || a == false) {
683
+ this.list.css(this.lt, p + 'px');
684
+ scrolled();
685
+ } else {
686
+ var o = !this.options.vertical ? {'left': p} : {'top': p};
687
+ this.list.animate(o, this.options.animation, this.options.easing, scrolled);
688
+ }
689
+ },
690
+
691
+ /**
692
+ * Starts autoscrolling.
693
+ *
694
+ * @method auto
695
+ * @return undefined
696
+ * @param s {Number} Seconds to periodically autoscroll the content.
697
+ */
698
+ startAuto: function(s) {
699
+ if (s != undefined)
700
+ this.options.auto = s;
701
+
702
+ if (this.options.auto == 0)
703
+ return this.stopAuto();
704
+
705
+ if (this.timer != null)
706
+ return;
707
+
708
+ var self = this;
709
+ this.timer = setTimeout(function() { self.next(); }, this.options.auto * 1000);
710
+ },
711
+
712
+ /**
713
+ * Stops autoscrolling.
714
+ *
715
+ * @method stopAuto
716
+ * @return undefined
717
+ */
718
+ stopAuto: function() {
719
+ if (this.timer == null)
720
+ return;
721
+
722
+ clearTimeout(this.timer);
723
+ this.timer = null;
724
+ },
725
+
726
+ /**
727
+ * Sets the states of the prev/next buttons.
728
+ *
729
+ * @method buttons
730
+ * @return undefined
731
+ */
732
+ buttons: function(n, p) {
733
+ if (n == undefined || n == null) {
734
+ var n = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'first') || this.options.size == null || this.last < this.options.size);
735
+ if (!this.locked && (!this.options.wrap || this.options.wrap == 'first') && this.options.size != null && this.last >= this.options.size)
736
+ n = this.tail != null && !this.inTail;
737
+ }
738
+
739
+ if (p == undefined || p == null) {
740
+ var p = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'last') || this.first > 1);
741
+ if (!this.locked && (!this.options.wrap || this.options.wrap == 'last') && this.options.size != null && this.first == 1)
742
+ p = this.tail != null && this.inTail;
743
+ }
744
+
745
+ var self = this;
746
+
747
+ this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent + '.jcarousel', this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);
748
+ this.buttonPrev[p ? 'bind' : 'unbind'](this.options.buttonPrevEvent + '.jcarousel', this.funcPrev)[p ? 'removeClass' : 'addClass'](this.className('jcarousel-prev-disabled')).attr('disabled', p ? false : true);
749
+
750
+ if (this.buttonNext.length > 0 && (this.buttonNext[0].jcarouselstate == undefined || this.buttonNext[0].jcarouselstate != n) && this.options.buttonNextCallback != null) {
751
+ this.buttonNext.each(function() { self.options.buttonNextCallback(self, this, n); });
752
+ this.buttonNext[0].jcarouselstate = n;
753
+ }
754
+
755
+ if (this.buttonPrev.length > 0 && (this.buttonPrev[0].jcarouselstate == undefined || this.buttonPrev[0].jcarouselstate != p) && this.options.buttonPrevCallback != null) {
756
+ this.buttonPrev.each(function() { self.options.buttonPrevCallback(self, this, p); });
757
+ this.buttonPrev[0].jcarouselstate = p;
758
+ }
759
+ },
760
+
761
+ /**
762
+ * Notify callback of a specified event.
763
+ *
764
+ * @method notify
765
+ * @return undefined
766
+ * @param evt {String} The event name
767
+ */
768
+ notify: function(evt) {
769
+ var state = this.prevFirst == null ? 'init' : (this.prevFirst < this.first ? 'next' : 'prev');
770
+
771
+ // Load items
772
+ this.callback('itemLoadCallback', evt, state);
773
+
774
+ if (this.prevFirst !== this.first) {
775
+ this.callback('itemFirstInCallback', evt, state, this.first);
776
+ this.callback('itemFirstOutCallback', evt, state, this.prevFirst);
777
+ }
778
+
779
+ if (this.prevLast !== this.last) {
780
+ this.callback('itemLastInCallback', evt, state, this.last);
781
+ this.callback('itemLastOutCallback', evt, state, this.prevLast);
782
+ }
783
+
784
+ this.callback('itemVisibleInCallback', evt, state, this.first, this.last, this.prevFirst, this.prevLast);
785
+ this.callback('itemVisibleOutCallback', evt, state, this.prevFirst, this.prevLast, this.first, this.last);
786
+ },
787
+
788
+ callback: function(cb, evt, state, i1, i2, i3, i4) {
789
+ if (this.options[cb] == undefined || (typeof this.options[cb] != 'object' && evt != 'onAfterAnimation'))
790
+ return;
791
+
792
+ var callback = typeof this.options[cb] == 'object' ? this.options[cb][evt] : this.options[cb];
793
+
794
+ if (!$.isFunction(callback))
795
+ return;
796
+
797
+ var self = this;
798
+
799
+ if (i1 === undefined)
800
+ callback(self, state, evt);
801
+ else if (i2 === undefined)
802
+ this.get(i1).each(function() { callback(self, this, i1, state, evt); });
803
+ else {
804
+ for (var i = i1; i <= i2; i++)
805
+ if (i !== null && !(i >= i3 && i <= i4))
806
+ this.get(i).each(function() { callback(self, this, i, state, evt); });
807
+ }
808
+ },
809
+
810
+ create: function(i) {
811
+ return this.format('<' + this.options.itemTag + '></' + this.options.itemTag + '>', i);
812
+ },
813
+
814
+ format: function(e, i) {
815
+ var $e = $(e).addClass(this.className('jcarousel-item')).addClass(this.className('jcarousel-item-' + i)).css({
816
+ 'float': 'left',
817
+ 'list-style': 'none'
818
+ });
819
+ $e.attr('jcarouselindex', i);
820
+ return $e;
821
+ },
822
+
823
+ className: function(c) {
824
+ return c + ' ' + c + (!this.options.vertical ? '-horizontal' : '-vertical');
825
+ },
826
+
827
+ dimension: function(e, d) {
828
+ var el = e.jquery != undefined ? e[0] : e;
829
+
830
+ var old = !this.options.vertical ?
831
+ el.offsetWidth + $jc.margin(el, 'marginLeft') + $jc.margin(el, 'marginRight') :
832
+ el.offsetHeight + $jc.margin(el, 'marginTop') + $jc.margin(el, 'marginBottom');
833
+
834
+ if (d == undefined || old == d)
835
+ return old;
836
+
837
+ var w = !this.options.vertical ?
838
+ d - $jc.margin(el, 'marginLeft') - $jc.margin(el, 'marginRight') :
839
+ d - $jc.margin(el, 'marginTop') - $jc.margin(el, 'marginBottom');
840
+
841
+ $(el).css(this.wh, w + 'px');
842
+
843
+ return this.dimension(el);
844
+ },
845
+
846
+ clipping: function() {
847
+ if (this.clip[0] != null) {
848
+ return !this.options.vertical ?
849
+ this.clip[0].offsetWidth - $jc.intval(this.clip.css('borderLeftWidth')) - $jc.intval(this.clip.css('borderRightWidth')) :
850
+ this.clip[0].offsetHeight - $jc.intval(this.clip.css('borderTopWidth')) - $jc.intval(this.clip.css('borderBottomWidth'));
851
+ }
852
+ },
853
+
854
+ index: function(i, s) {
855
+ if (s == undefined)
856
+ s = this.options.size;
857
+
858
+ return Math.round((((i-1) / s) - Math.floor((i-1) / s)) * s) + 1;
859
+ }
860
+ });
861
+
862
+ $jc.extend({
863
+ /**
864
+ * Gets/Sets the global default configuration properties.
865
+ *
866
+ * @method defaults
867
+ * @return {Object}
868
+ * @param d {Object} A set of key/value pairs to set as configuration properties.
869
+ */
870
+ defaults: function(d) {
871
+ return $.extend(defaults, d || {});
872
+ },
873
+
874
+ margin: function(e, p) {
875
+ if (!e)
876
+ return 0;
877
+
878
+ var el = e.jquery != undefined ? e[0] : e;
879
+
880
+ if (p == 'marginRight' && $.browser.safari) {
881
+ var old = {'display': 'block', 'float': 'none', 'width': 'auto'}, oWidth, oWidth2;
882
+
883
+ $.swap(el, old, function() { oWidth = el.offsetWidth; });
884
+
885
+ old['marginRight'] = 0;
886
+ $.swap(el, old, function() { oWidth2 = el.offsetWidth; });
887
+
888
+ return oWidth2 - oWidth;
889
+ }
890
+
891
+ return $jc.intval($.css(el, p));
892
+ },
893
+
894
+ intval: function(v) {
895
+ v = parseInt(v);
896
+ return isNaN(v) ? 0 : v;
897
+ }
898
+ });
899
+
900
+ })(jQuery);