spree_showcase 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +11 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +9 -0
  4. data/Gemfile.lock +179 -0
  5. data/LICENSE +26 -0
  6. data/README.md +33 -0
  7. data/Rakefile +29 -0
  8. data/Versionfile +11 -0
  9. data/app/assets/images/store/bg_control_nav.png +0 -0
  10. data/app/assets/images/store/bg_direction_nav.png +0 -0
  11. data/app/assets/javascripts/admin/spree_showcase.js +1 -0
  12. data/app/assets/javascripts/store/spree_showcase.js +3 -0
  13. data/app/assets/stylesheets/admin/spree_showcase.css +3 -0
  14. data/app/assets/stylesheets/store/spree_showcase.css +4 -0
  15. data/app/controllers/spree/admin/showcase_settings_controller.rb +22 -0
  16. data/app/controllers/spree/admin/slides_controller.rb +25 -0
  17. data/app/models/spree/slide.rb +10 -0
  18. data/app/overrides/add_showcase_to_admin_configuration_menu.rb +9 -0
  19. data/app/overrides/add_showcase_to_admin_configurations_side_menu.rb +7 -0
  20. data/app/overrides/add_showcase_to_home_layout.rb +8 -0
  21. data/app/overrides/insert_slider_into_spree_application.rb +10 -0
  22. data/app/views/spree/admin/shared/_showcase_settings.html.erb +4 -0
  23. data/app/views/spree/admin/shared/_showcase_submenu.html.erb +6 -0
  24. data/app/views/spree/admin/showcase_settings/edit.html.erb +19 -0
  25. data/app/views/spree/admin/showcase_settings/show.html.erb +16 -0
  26. data/app/views/spree/admin/slides/_form.html.erb +28 -0
  27. data/app/views/spree/admin/slides/edit.html.erb +10 -0
  28. data/app/views/spree/admin/slides/index.html.erb +34 -0
  29. data/app/views/spree/admin/slides/new.html.erb +9 -0
  30. data/app/views/spree/admin/slides/show.html.erb +41 -0
  31. data/app/views/spree/slides/_content_insert.html.erb +5 -0
  32. data/app/views/spree/slides/_showcase.html.erb +28 -0
  33. data/config/locales/en.yml +5 -0
  34. data/config/routes.rb +14 -0
  35. data/db/migrate/20120506161852_create_slides.rb +17 -0
  36. data/db/migrate/20120507074922_add_position_to_slide.rb +9 -0
  37. data/lib/generators/spree_showcase/install/assets/javascripts/store/jquery.flexslider.js +563 -0
  38. data/lib/generators/spree_showcase/install/assets/javascripts/store/showcase.js +32 -0
  39. data/lib/generators/spree_showcase/install/assets/partials/_showcase.html.erb +28 -0
  40. data/lib/generators/spree_showcase/install/assets/stylesheets/store/flexslider.css +64 -0
  41. data/lib/generators/spree_showcase/install/assets/stylesheets/store/showcase.css.scss +26 -0
  42. data/lib/generators/spree_showcase/install/install_generator.rb +65 -0
  43. data/lib/spree/showcase_configuration.rb +8 -0
  44. data/lib/spree_showcase.rb +3 -0
  45. data/lib/spree_showcase/engine.rb +30 -0
  46. data/script/rails +7 -0
  47. data/spec/spec_helper.rb +43 -0
  48. data/spree_showcase-0.5.0.gem +0 -0
  49. data/spree_showcase-0.5.1.gem +0 -0
  50. data/spree_showcase.gemspec +26 -0
  51. metadata +118 -4
@@ -0,0 +1,19 @@
1
+ <%= render :partial => 'spree/admin/shared/configuration_menu' %>
2
+ <%= render :partial=>'spree/admin/shared/showcase_submenu'%>
3
+ <h1><%= t(:edit_showcase_settings) %></h1>
4
+
5
+ <%= form_tag admin_showcase_settings_path, :method => :put do %>
6
+ <fieldset id="preferences" data-hook>
7
+ <% @preferences.each do |key|
8
+ type = SpreeShowcase::Config.preference_type(key) %>
9
+ <%= label_tag(key, t(key) + ': ') + tag(:br) if type != :boolean %>
10
+ <%= preference_field_tag(key, SpreeShowcase::Config[key], :type => type) %>
11
+ <%= label_tag(key, t(key)) + tag(:br) if type == :boolean %>
12
+ <% end %>
13
+ </fieldset>
14
+ <p class="form-buttons" data-hook="buttons">
15
+ <%= button t(:update) %>
16
+ <%= t(:or) %> <%= link_to t(:cancel), admin_showcase_settings_url %>
17
+ </p>
18
+ <% end %>
19
+ <%= render :partial =>"spree/admin/shared/showcase_settings" %>
@@ -0,0 +1,16 @@
1
+ <%= render :partial => 'spree/admin/shared/configuration_menu' %>
2
+ <%= render :partial=>'spree/admin/shared/showcase_submenu'%>
3
+ <h1><%= t(:showcase_settings) %></h1>
4
+
5
+ <table data-hook="preferences">
6
+ <% @preferences.each do |key| %>
7
+ <tr>
8
+ <th scope="row"><%= t(key) %>:</th>
9
+ <td><%= SpreeShowcase::Config[key] %></td>
10
+ </tr>
11
+ <% end %>
12
+ </table>
13
+
14
+ <p><%= link_to_with_icon 'edit', t(:edit), edit_admin_showcase_settings_path, :id => 'admin_showcase_settings_link' %></p>
15
+
16
+ <%= render :partial =>"spree/admin/shared/showcase_settings" %>
@@ -0,0 +1,28 @@
1
+ <%= f.field_container :name do %>
2
+ <%= f.label :name, t(:name) %><br />
3
+ <%= f.text_field :name %>
4
+ <% end %>
5
+ <%= f.field_container :body do %>
6
+ <%= f.label :body, t(:body) %><br />
7
+ <%= f.text_area :body, {:cols => 60, :rows => 4, :class => 'fullwidth', :id=>:page_body} %>
8
+ <% end %>
9
+
10
+ <%= f.field_container :target_url do %>
11
+ <%= f.label :target_url, t(:target_url) %><br />
12
+ <%= f.text_field :target_url %>
13
+ <% end %>
14
+
15
+ <%= f.field_container :image do %>
16
+ <%= f.label :image, t(:image) %><br />
17
+ <%= f.file_field :image %>
18
+ <% end %>
19
+
20
+ <%= f.field_container :thumbnail_message do %>
21
+ <%= f.label "Thumb Message" %>
22
+ <%= f.text_field :thumbnail_message %>
23
+ <% end %>
24
+ <%= f.field_container :published do %>
25
+ <%= f.label :is_published, t(:published) %><br />
26
+ <%= f.check_box :published %>
27
+ <% end %>
28
+
@@ -0,0 +1,10 @@
1
+ <%= render :partial => 'spree/admin/shared/configuration_menu' %>
2
+ <%= render :partial=>'spree/admin/shared/showcase_submenu'%>
3
+ <h1>Editing Slide</h1>
4
+
5
+ <%= render 'spree/shared/error_messages', :target => @slide %>
6
+
7
+ <%= form_for [:admin, @slide], :html => { :multipart => true } do |f| %>
8
+ <%= render :partial => 'form', :locals => { :f => f } %>
9
+ <%= render :partial => 'spree/admin/shared/edit_resource_links' %>
10
+ <% end %>
@@ -0,0 +1,34 @@
1
+ <%= render :partial => 'spree/admin/shared/configuration_menu' %>
2
+ <%= render :partial=>'spree/admin/shared/showcase_submenu'%>
3
+ <div class="toolbar" data-hook="toolbar">
4
+ <ul class="actions">
5
+ <li>
6
+ <p><%= button_link_to 'New Slide', new_object_url, :icon => 'add', :id => 'admin_new_slide_link' %></p>
7
+ </li>
8
+ </ul>
9
+ <br class="clear" />
10
+ </div>
11
+
12
+ <h1>Showcase </h1>
13
+
14
+ <table class="index sortable" id="listing_slides" data-hook data-sortable-link="<%= update_positions_admin_slides_url %>">
15
+ <thead>
16
+ <tr data-hook="admin_slides_index_headers">
17
+ <th>Name</th>
18
+ <th data-hook="admin_slides_index_header_actions"></th>
19
+ </tr>
20
+ </thead>
21
+ <tbody>
22
+ <% @slides.each do |slide|%>
23
+ <tr id="<%= spree_dom_id slide %>" data-hook="admin_slides_index_rows">
24
+ <td width="350px" ><span class="handle" style="margin-right:5px"> </span> <%=link_to slide.name, object_url(slide) %></td>
25
+ <td data-hook="admin_slides_index_row_actions">
26
+ <%= link_to_edit slide, :class => 'edit' %> &nbsp;
27
+ <%= link_to_delete slide %>
28
+ </td>
29
+ </tr>
30
+ <% end %>
31
+ </tbody>
32
+ </table>
33
+
34
+ <p>Showcase is done by Damon Aw - @daemonsy</p>
@@ -0,0 +1,9 @@
1
+ <%= render :partial => 'spree/admin/shared/configuration_menu' %>
2
+ <%= render :partial=>'spree/admin/shared/showcase_submenu'%>
3
+ <h1>New Showcase Slide</h1>
4
+ <%= render 'spree/shared/error_messages', :target => @slide %>
5
+
6
+ <%= form_for [:admin, @slide] , :html => { :multipart => true } do |f| %>
7
+ <%= render :partial => 'form', :locals => { :f => f } %>
8
+ <p class="form-buttons" data-hook="buttons"><%= button t(:create) %></p>
9
+ <% end %>
@@ -0,0 +1,41 @@
1
+ <%= render :partial => 'spree/admin/shared/configuration_menu' %>
2
+ <%= render :partial=>'spree/admin/shared/showcase_submenu'%>
3
+ <h1><%= t(:slide) %></h1>
4
+
5
+ <table>
6
+ <tr data-hook="name">
7
+ <th><%= t(:name) %></th>
8
+ <td>
9
+ <%= @slide.name %>
10
+ </td>
11
+ </tr>
12
+ <tr data-hook="body">
13
+ <th><%= t(:body) %></th>
14
+ <td>
15
+ <%= @slide.body %>
16
+ </td>
17
+ </tr>
18
+ <tr data-hook="link_url">
19
+ <th><%= t(:target_url) %></th>
20
+ <td>
21
+ <%= @slide.target_url %>
22
+ </td>
23
+ </tr>
24
+ <tr data-hook="published">
25
+ <th><%= t(:published) %></th>
26
+ <td>
27
+ <%= @slide.published %>
28
+ </td>
29
+ </tr>
30
+ <tr data-hook="image_file_name">
31
+ <th><%= t(:image_file_name) %></th>
32
+ <td>
33
+ <%= @slide.image_file_name %>
34
+ </td>
35
+ </tr>
36
+ </table>
37
+
38
+ <p>
39
+ <%= link_to_edit @slide, :class => 'edit_slide' %> <%= t(:or) %>
40
+ <%= link_to t(:back), collection_url %>
41
+ </p>
@@ -0,0 +1,5 @@
1
+ <% if SpreeShowcase::Config.enabled %>
2
+ <% content_for :spree_showcase do %>
3
+ <%= render :partial => 'spree/slides/showcase' %>
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,28 @@
1
+ <div class="flex-container">
2
+ <div class="row">
3
+ <div class="flexslider alpha omega sixteen columns">
4
+ <ul class="slides">
5
+ <% Spree::Slide.published.no_slides(SpreeShowcase::Config.number_of_slides_to_show).each do |slide| %>
6
+ <li>
7
+ <%= link_to(slide.target_url.present? ? slide.target_url : "#") do %>
8
+ <%= slide.image.present? ? image_tag(slide.image) : image_tag("http://www.placehold.it/#{SpreeShowcase::Config.preferences[:showcase_style].match(/\d{2,}x\d{2,}/)}&text=Spree%20Showcase%20by%20@daemonsy") %>
9
+ <% end %>
10
+ </li>
11
+ <% end %>
12
+ </ul>
13
+ </div>
14
+ </div>
15
+ <div class="row">
16
+ <div class="sixteen columns alpha omega">
17
+ <ul class="custom-controls">
18
+ <% Spree::Slide.published.no_slides(SpreeShowcase::Config.number_of_slides_to_show).each do |slide| %>
19
+ <li>
20
+ <%= link_to "#" do %>
21
+ <%=slide.image.present? ? image_tag(slide.image.url(:thumb),:class=>"alpha four columns") : image_tag("http://www.placehold.it/#{SpreeShowcase::Config.preferences[:thumbnail_style].match(/\d{2,}x\d{2,}/)}",:class=>"alpha four columns") %>
22
+ <% end %>
23
+ </li>
24
+ <% end %>
25
+ </ul>
26
+ </div>
27
+ </div>
28
+ </div>
@@ -0,0 +1,5 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ hello: "Hello world"
@@ -0,0 +1,14 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ # Add your extension routes here
3
+ namespace :admin do
4
+ resources :slides do
5
+ collection do
6
+ post :update_positions
7
+ end
8
+ end
9
+ end
10
+ namespace :admin do
11
+ resource :showcase_settings
12
+ end
13
+ end
14
+
@@ -0,0 +1,17 @@
1
+ class CreateSlides < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_slides do |t|
4
+ t.string :name
5
+ t.text :body
6
+ t.string :thumbnail_message
7
+ t.string :target_url
8
+ t.boolean :published
9
+ t.string :image_file_name
10
+ t.string :image_content_type
11
+ t.integer :image_file_size
12
+ t.datetime :image_updated_at
13
+
14
+ t.timestamps
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ class AddPositionToSlide < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :spree_slides, :position, :integer
4
+ end
5
+
6
+ def self.down
7
+ remove_column :spree_slides, :position
8
+ end
9
+ end
@@ -0,0 +1,563 @@
1
+ /*
2
+ * jQuery FlexSlider v1.8
3
+ * http://www.woothemes.com/flexslider/
4
+ *
5
+ * Copyright 2012 WooThemes
6
+ * Free to use under the MIT license.
7
+ * http://www.opensource.org/licenses/mit-license.php
8
+ *
9
+ * Contributing Author: Tyler Smith
10
+ */
11
+
12
+ ;(function ($) {
13
+
14
+ //FlexSlider: Object Instance
15
+ $.flexslider = function(el, options) {
16
+ var slider = $(el);
17
+
18
+ // slider DOM reference for use outside of the plugin
19
+ $.data(el, "flexslider", slider);
20
+
21
+ slider.init = function() {
22
+ slider.vars = $.extend({}, $.flexslider.defaults, options);
23
+ $.data(el, 'flexsliderInit', true);
24
+ slider.container = $('.slides', slider).first();
25
+ slider.slides = $('.slides:first > li', slider);
26
+ slider.count = slider.slides.length;
27
+ slider.animating = false;
28
+ slider.currentSlide = slider.vars.slideToStart;
29
+ slider.animatingTo = slider.currentSlide;
30
+ slider.atEnd = (slider.currentSlide == 0) ? true : false;
31
+ slider.eventType = ('ontouchstart' in document.documentElement) ? 'touchstart' : 'click';
32
+ slider.cloneCount = 0;
33
+ slider.cloneOffset = 0;
34
+ slider.manualPause = false;
35
+ slider.vertical = (slider.vars.slideDirection == "vertical");
36
+ slider.prop = (slider.vertical) ? "top" : "marginLeft";
37
+ slider.args = {};
38
+
39
+ //Test for webbkit CSS3 Animations
40
+ slider.transitions = "webkitTransition" in document.body.style;
41
+ if (slider.transitions) slider.prop = "-webkit-transform";
42
+
43
+ //Test for controlsContainer
44
+ if (slider.vars.controlsContainer != "") {
45
+ slider.controlsContainer = $(slider.vars.controlsContainer).eq($('.slides').index(slider.container));
46
+ slider.containerExists = slider.controlsContainer.length > 0;
47
+ }
48
+ //Test for manualControls
49
+ if (slider.vars.manualControls != "") {
50
+ slider.manualControls = $(slider.vars.manualControls, ((slider.containerExists) ? slider.controlsContainer : slider));
51
+ slider.manualExists = slider.manualControls.length > 0;
52
+ }
53
+
54
+ ///////////////////////////////////////////////////////////////////
55
+ // FlexSlider: Randomize Slides
56
+ if (slider.vars.randomize) {
57
+ slider.slides.sort(function() { return (Math.round(Math.random())-0.5); });
58
+ slider.container.empty().append(slider.slides);
59
+ }
60
+ ///////////////////////////////////////////////////////////////////
61
+
62
+ ///////////////////////////////////////////////////////////////////
63
+ // FlexSlider: Slider Animation Initialize
64
+ if (slider.vars.animation.toLowerCase() == "slide") {
65
+ if (slider.transitions) {
66
+ slider.setTransition(0);
67
+ }
68
+ slider.css({"overflow": "hidden"});
69
+ if (slider.vars.animationLoop) {
70
+ slider.cloneCount = 2;
71
+ slider.cloneOffset = 1;
72
+ slider.container.append(slider.slides.filter(':first').clone().addClass('clone')).prepend(slider.slides.filter(':last').clone().addClass('clone'));
73
+ }
74
+ //create newSlides to capture possible clones
75
+ slider.newSlides = $('.slides:first > li', slider);
76
+ var sliderOffset = (-1 * (slider.currentSlide + slider.cloneOffset));
77
+ if (slider.vertical) {
78
+ slider.newSlides.css({"display": "block", "width": "100%", "float": "left"});
79
+ slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%");
80
+ //Timeout function to give browser enough time to get proper height initially
81
+ setTimeout(function() {
82
+ slider.css({"position": "relative"}).height(slider.slides.filter(':first').height());
83
+ slider.args[slider.prop] = (slider.transitions) ? "translate3d(0," + sliderOffset * slider.height() + "px,0)" : sliderOffset * slider.height() + "px";
84
+ slider.container.css(slider.args);
85
+ }, 100);
86
+
87
+ } else {
88
+ slider.args[slider.prop] = (slider.transitions) ? "translate3d(" + sliderOffset * slider.width() + "px,0,0)" : sliderOffset * slider.width() + "px";
89
+ slider.container.width((slider.count + slider.cloneCount) * 200 + "%").css(slider.args);
90
+ //Timeout function to give browser enough time to get proper width initially
91
+ setTimeout(function() {
92
+ slider.newSlides.width(slider.width()).css({"float": "left", "display": "block"});
93
+ }, 100);
94
+ }
95
+
96
+ } else { //Default to fade
97
+ //Not supporting fade CSS3 transitions right now
98
+ slider.transitions = false;
99
+ slider.slides.css({"width": "100%", "float": "left", "marginRight": "-100%"}).eq(slider.currentSlide).fadeIn(slider.vars.animationDuration);
100
+ }
101
+ ///////////////////////////////////////////////////////////////////
102
+
103
+ ///////////////////////////////////////////////////////////////////
104
+ // FlexSlider: Control Nav
105
+ if (slider.vars.controlNav) {
106
+ if (slider.manualExists) {
107
+ slider.controlNav = slider.manualControls;
108
+ } else {
109
+ var controlNavScaffold = $('<ol class="flex-control-nav"></ol>');
110
+ var j = 1;
111
+ for (var i = 0; i < slider.count; i++) {
112
+ controlNavScaffold.append('<li><a>' + j + '</a></li>');
113
+ j++;
114
+ }
115
+
116
+ if (slider.containerExists) {
117
+ $(slider.controlsContainer).append(controlNavScaffold);
118
+ slider.controlNav = $('.flex-control-nav li a', slider.controlsContainer);
119
+ } else {
120
+ slider.append(controlNavScaffold);
121
+ slider.controlNav = $('.flex-control-nav li a', slider);
122
+ }
123
+ }
124
+
125
+ slider.controlNav.eq(slider.currentSlide).addClass('active');
126
+
127
+ slider.controlNav.bind(slider.eventType, function(event) {
128
+ event.preventDefault();
129
+ if (!$(this).hasClass('active')) {
130
+ (slider.controlNav.index($(this)) > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev";
131
+ slider.flexAnimate(slider.controlNav.index($(this)), slider.vars.pauseOnAction);
132
+ }
133
+ });
134
+ }
135
+ ///////////////////////////////////////////////////////////////////
136
+
137
+ //////////////////////////////////////////////////////////////////
138
+ //FlexSlider: Direction Nav
139
+ if (slider.vars.directionNav) {
140
+ var directionNavScaffold = $('<ul class="flex-direction-nav"><li><a class="prev" href="#">' + slider.vars.prevText + '</a></li><li><a class="next" href="#">' + slider.vars.nextText + '</a></li></ul>');
141
+
142
+ if (slider.containerExists) {
143
+ $(slider.controlsContainer).append(directionNavScaffold);
144
+ slider.directionNav = $('.flex-direction-nav li a', slider.controlsContainer);
145
+ } else {
146
+ slider.append(directionNavScaffold);
147
+ slider.directionNav = $('.flex-direction-nav li a', slider);
148
+ }
149
+
150
+ //Set initial disable styles if necessary
151
+ if (!slider.vars.animationLoop) {
152
+ if (slider.currentSlide == 0) {
153
+ slider.directionNav.filter('.prev').addClass('disabled');
154
+ } else if (slider.currentSlide == slider.count - 1) {
155
+ slider.directionNav.filter('.next').addClass('disabled');
156
+ }
157
+ }
158
+
159
+ slider.directionNav.bind(slider.eventType, function(event) {
160
+ event.preventDefault();
161
+ var target = ($(this).hasClass('next')) ? slider.getTarget('next') : slider.getTarget('prev');
162
+
163
+ if (slider.canAdvance(target)) {
164
+ slider.flexAnimate(target, slider.vars.pauseOnAction);
165
+ }
166
+ });
167
+ }
168
+ //////////////////////////////////////////////////////////////////
169
+
170
+ //////////////////////////////////////////////////////////////////
171
+ //FlexSlider: Keyboard Nav
172
+ if (slider.vars.keyboardNav && $('ul.slides').length == 1) {
173
+ function keyboardMove(event) {
174
+ if (slider.animating) {
175
+ return;
176
+ } else if (event.keyCode != 39 && event.keyCode != 37){
177
+ return;
178
+ } else {
179
+ if (event.keyCode == 39) {
180
+ var target = slider.getTarget('next');
181
+ } else if (event.keyCode == 37){
182
+ var target = slider.getTarget('prev');
183
+ }
184
+
185
+ if (slider.canAdvance(target)) {
186
+ slider.flexAnimate(target, slider.vars.pauseOnAction);
187
+ }
188
+ }
189
+ }
190
+ $(document).bind('keyup', keyboardMove);
191
+ }
192
+ //////////////////////////////////////////////////////////////////
193
+
194
+ ///////////////////////////////////////////////////////////////////
195
+ // FlexSlider: Mousewheel interaction
196
+ if (slider.vars.mousewheel) {
197
+ slider.mousewheelEvent = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
198
+ slider.bind(slider.mousewheelEvent, function(e) {
199
+ e.preventDefault();
200
+ e = e ? e : window.event;
201
+ var wheelData = e.detail ? e.detail * -1 : e.originalEvent.wheelDelta / 40,
202
+ target = (wheelData < 0) ? slider.getTarget('next') : slider.getTarget('prev');
203
+
204
+ if (slider.canAdvance(target)) {
205
+ slider.flexAnimate(target, slider.vars.pauseOnAction);
206
+ }
207
+ });
208
+ }
209
+ ///////////////////////////////////////////////////////////////////
210
+
211
+ //////////////////////////////////////////////////////////////////
212
+ //FlexSlider: Slideshow Setup
213
+ if (slider.vars.slideshow) {
214
+ //pauseOnHover
215
+ if (slider.vars.pauseOnHover && slider.vars.slideshow) {
216
+ slider.hover(function() {
217
+ slider.pause();
218
+ }, function() {
219
+ if (!slider.manualPause) {
220
+ slider.resume();
221
+ }
222
+ });
223
+ }
224
+
225
+ //Initialize animation
226
+ slider.animatedSlides = setInterval(slider.animateSlides, slider.vars.slideshowSpeed);
227
+ }
228
+ //////////////////////////////////////////////////////////////////
229
+
230
+ //////////////////////////////////////////////////////////////////
231
+ //FlexSlider: Pause/Play
232
+ if (slider.vars.pausePlay) {
233
+ var pausePlayScaffold = $('<div class="flex-pauseplay"><span></span></div>');
234
+
235
+ if (slider.containerExists) {
236
+ slider.controlsContainer.append(pausePlayScaffold);
237
+ slider.pausePlay = $('.flex-pauseplay span', slider.controlsContainer);
238
+ } else {
239
+ slider.append(pausePlayScaffold);
240
+ slider.pausePlay = $('.flex-pauseplay span', slider);
241
+ }
242
+
243
+ var pausePlayState = (slider.vars.slideshow) ? 'pause' : 'play';
244
+ slider.pausePlay.addClass(pausePlayState).text((pausePlayState == 'pause') ? slider.vars.pauseText : slider.vars.playText);
245
+
246
+ slider.pausePlay.bind(slider.eventType, function(event) {
247
+ event.preventDefault();
248
+ if ($(this).hasClass('pause')) {
249
+ slider.pause();
250
+ slider.manualPause = true;
251
+ } else {
252
+ slider.resume();
253
+ slider.manualPause = false;
254
+ }
255
+ });
256
+ }
257
+ //////////////////////////////////////////////////////////////////
258
+
259
+ //////////////////////////////////////////////////////////////////
260
+ //FlexSlider:Touch Swip Gestures
261
+ //Some brilliant concepts adapted from the following sources
262
+ //Source: TouchSwipe - http://www.netcu.de/jquery-touchwipe-iphone-ipad-library
263
+ //Source: SwipeJS - http://swipejs.com
264
+ if ('ontouchstart' in document.documentElement) {
265
+ //For brevity, variables are named for x-axis scrolling
266
+ //The variables are then swapped if vertical sliding is applied
267
+ //This reduces redundant code...I think :)
268
+ //If debugging, recognize variables are named for horizontal scrolling
269
+ var startX,
270
+ startY,
271
+ offset,
272
+ cwidth,
273
+ dx,
274
+ startT,
275
+ scrolling = false;
276
+
277
+ slider.each(function() {
278
+ if ('ontouchstart' in document.documentElement) {
279
+ this.addEventListener('touchstart', onTouchStart, false);
280
+ }
281
+ });
282
+
283
+ function onTouchStart(e) {
284
+ if (slider.animating) {
285
+ e.preventDefault();
286
+ } else if (e.touches.length == 1) {
287
+ slider.pause();
288
+ cwidth = (slider.vertical) ? slider.height() : slider.width();
289
+ startT = Number(new Date());
290
+ offset = (slider.vertical) ? (slider.currentSlide + slider.cloneOffset) * slider.height() : (slider.currentSlide + slider.cloneOffset) * slider.width();
291
+ startX = (slider.vertical) ? e.touches[0].pageY : e.touches[0].pageX;
292
+ startY = (slider.vertical) ? e.touches[0].pageX : e.touches[0].pageY;
293
+ slider.setTransition(0);
294
+
295
+ this.addEventListener('touchmove', onTouchMove, false);
296
+ this.addEventListener('touchend', onTouchEnd, false);
297
+ }
298
+ }
299
+
300
+ function onTouchMove(e) {
301
+ dx = (slider.vertical) ? startX - e.touches[0].pageY : startX - e.touches[0].pageX;
302
+ scrolling = (slider.vertical) ? (Math.abs(dx) < Math.abs(e.touches[0].pageX - startY)) : (Math.abs(dx) < Math.abs(e.touches[0].pageY - startY));
303
+
304
+ if (!scrolling) {
305
+ e.preventDefault();
306
+ if (slider.vars.animation == "slide" && slider.transitions) {
307
+ if (!slider.vars.animationLoop) {
308
+ dx = dx/((slider.currentSlide == 0 && dx < 0 || slider.currentSlide == slider.count - 1 && dx > 0) ? (Math.abs(dx)/cwidth+2) : 1);
309
+ }
310
+ slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + (-offset - dx) + "px,0)": "translate3d(" + (-offset - dx) + "px,0,0)";
311
+ slider.container.css(slider.args);
312
+ }
313
+ }
314
+ }
315
+
316
+ function onTouchEnd(e) {
317
+ slider.animating = false;
318
+ if (slider.animatingTo == slider.currentSlide && !scrolling && !(dx == null)) {
319
+ var target = (dx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
320
+ if (slider.canAdvance(target) && Number(new Date()) - startT < 550 && Math.abs(dx) > 20 || Math.abs(dx) > cwidth/2) {
321
+ slider.flexAnimate(target, slider.vars.pauseOnAction);
322
+ } else {
323
+ slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction);
324
+ }
325
+ }
326
+
327
+ //Finish the touch by undoing the touch session
328
+ this.removeEventListener('touchmove', onTouchMove, false);
329
+ this.removeEventListener('touchend', onTouchEnd, false);
330
+ startX = null;
331
+ startY = null;
332
+ dx = null;
333
+ offset = null;
334
+ }
335
+ }
336
+ //////////////////////////////////////////////////////////////////
337
+
338
+ //////////////////////////////////////////////////////////////////
339
+ //FlexSlider: Resize Functions (If necessary)
340
+ if (slider.vars.animation.toLowerCase() == "slide") {
341
+ $(window).resize(function(){
342
+ if (!slider.animating && slider.is(":visible")) {
343
+ if (slider.vertical) {
344
+ slider.height(slider.slides.filter(':first').height());
345
+ slider.args[slider.prop] = (-1 * (slider.currentSlide + slider.cloneOffset))* slider.slides.filter(':first').height() + "px";
346
+ if (slider.transitions) {
347
+ slider.setTransition(0);
348
+ slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.args[slider.prop] + ",0)" : "translate3d(" + slider.args[slider.prop] + ",0,0)";
349
+ }
350
+ slider.container.css(slider.args);
351
+ } else {
352
+ slider.newSlides.width(slider.width());
353
+ slider.args[slider.prop] = (-1 * (slider.currentSlide + slider.cloneOffset))* slider.width() + "px";
354
+ if (slider.transitions) {
355
+ slider.setTransition(0);
356
+ slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.args[slider.prop] + ",0)" : "translate3d(" + slider.args[slider.prop] + ",0,0)";
357
+ }
358
+ slider.container.css(slider.args);
359
+ }
360
+ }
361
+ });
362
+ }
363
+ //////////////////////////////////////////////////////////////////
364
+
365
+ //FlexSlider: start() Callback
366
+ slider.vars.start(slider);
367
+ }
368
+
369
+ //FlexSlider: Animation Actions
370
+ slider.flexAnimate = function(target, pause) {
371
+ if (!slider.animating && slider.is(":visible")) {
372
+ //Animating flag
373
+ slider.animating = true;
374
+
375
+ //FlexSlider: before() animation Callback
376
+ slider.animatingTo = target;
377
+ slider.vars.before(slider);
378
+
379
+ //Optional paramter to pause slider when making an anmiation call
380
+ if (pause) {
381
+ slider.pause();
382
+ }
383
+
384
+ //Update controlNav
385
+ if (slider.vars.controlNav) {
386
+ slider.controlNav.removeClass('active').eq(target).addClass('active');
387
+ }
388
+
389
+ //Is the slider at either end
390
+ slider.atEnd = (target == 0 || target == slider.count - 1) ? true : false;
391
+ if (!slider.vars.animationLoop && slider.vars.directionNav) {
392
+ if (target == 0) {
393
+ slider.directionNav.removeClass('disabled').filter('.prev').addClass('disabled');
394
+ } else if (target == slider.count - 1) {
395
+ slider.directionNav.removeClass('disabled').filter('.next').addClass('disabled');
396
+ } else {
397
+ slider.directionNav.removeClass('disabled');
398
+ }
399
+ }
400
+
401
+ if (!slider.vars.animationLoop && target == slider.count - 1) {
402
+ slider.pause();
403
+ //FlexSlider: end() of cycle Callback
404
+ slider.vars.end(slider);
405
+ }
406
+
407
+ if (slider.vars.animation.toLowerCase() == "slide") {
408
+ var dimension = (slider.vertical) ? slider.slides.filter(':first').height() : slider.slides.filter(':first').width();
409
+
410
+ if (slider.currentSlide == 0 && target == slider.count - 1 && slider.vars.animationLoop && slider.direction != "next") {
411
+ slider.slideString = "0px";
412
+ } else if (slider.currentSlide == slider.count - 1 && target == 0 && slider.vars.animationLoop && slider.direction != "prev") {
413
+ slider.slideString = (-1 * (slider.count + 1)) * dimension + "px";
414
+ } else {
415
+ slider.slideString = (-1 * (target + slider.cloneOffset)) * dimension + "px";
416
+ }
417
+ slider.args[slider.prop] = slider.slideString;
418
+
419
+ if (slider.transitions) {
420
+ slider.setTransition(slider.vars.animationDuration);
421
+ slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.slideString + ",0)" : "translate3d(" + slider.slideString + ",0,0)";
422
+ slider.container.css(slider.args).one("webkitTransitionEnd transitionend", function(){
423
+ slider.wrapup(dimension);
424
+ });
425
+ } else {
426
+ slider.container.animate(slider.args, slider.vars.animationDuration, function(){
427
+ slider.wrapup(dimension);
428
+ });
429
+ }
430
+ } else { //Default to Fade
431
+ slider.slides.eq(slider.currentSlide).fadeOut(slider.vars.animationDuration);
432
+ slider.slides.eq(target).fadeIn(slider.vars.animationDuration, function() {
433
+ slider.wrapup();
434
+ });
435
+ }
436
+ }
437
+ }
438
+
439
+ //FlexSlider: Function to minify redundant animation actions
440
+ slider.wrapup = function(dimension) {
441
+ if (slider.vars.animation == "slide") {
442
+ //Jump the slider if necessary
443
+ if (slider.currentSlide == 0 && slider.animatingTo == slider.count - 1 && slider.vars.animationLoop) {
444
+ slider.args[slider.prop] = (-1 * slider.count) * dimension + "px";
445
+ if (slider.transitions) {
446
+ slider.setTransition(0);
447
+ slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.args[slider.prop] + ",0)" : "translate3d(" + slider.args[slider.prop] + ",0,0)";
448
+ }
449
+ slider.container.css(slider.args);
450
+ } else if (slider.currentSlide == slider.count - 1 && slider.animatingTo == 0 && slider.vars.animationLoop) {
451
+ slider.args[slider.prop] = -1 * dimension + "px";
452
+ if (slider.transitions) {
453
+ slider.setTransition(0);
454
+ slider.args[slider.prop] = (slider.vertical) ? "translate3d(0," + slider.args[slider.prop] + ",0)" : "translate3d(" + slider.args[slider.prop] + ",0,0)";
455
+ }
456
+ slider.container.css(slider.args);
457
+ }
458
+ }
459
+ slider.animating = false;
460
+ slider.currentSlide = slider.animatingTo;
461
+ //FlexSlider: after() animation Callback
462
+ slider.vars.after(slider);
463
+ }
464
+
465
+ //FlexSlider: Automatic Slideshow
466
+ slider.animateSlides = function() {
467
+ if (!slider.animating) {
468
+ slider.flexAnimate(slider.getTarget("next"));
469
+ }
470
+ }
471
+
472
+ //FlexSlider: Automatic Slideshow Pause
473
+ slider.pause = function() {
474
+ clearInterval(slider.animatedSlides);
475
+ if (slider.vars.pausePlay) {
476
+ slider.pausePlay.removeClass('pause').addClass('play').text(slider.vars.playText);
477
+ }
478
+ }
479
+
480
+ //FlexSlider: Automatic Slideshow Start/Resume
481
+ slider.resume = function() {
482
+ slider.animatedSlides = setInterval(slider.animateSlides, slider.vars.slideshowSpeed);
483
+ if (slider.vars.pausePlay) {
484
+ slider.pausePlay.removeClass('play').addClass('pause').text(slider.vars.pauseText);
485
+ }
486
+ }
487
+
488
+ //FlexSlider: Helper function for non-looping sliders
489
+ slider.canAdvance = function(target) {
490
+ if (!slider.vars.animationLoop && slider.atEnd) {
491
+ if (slider.currentSlide == 0 && target == slider.count - 1 && slider.direction != "next") {
492
+ return false;
493
+ } else if (slider.currentSlide == slider.count - 1 && target == 0 && slider.direction == "next") {
494
+ return false;
495
+ } else {
496
+ return true;
497
+ }
498
+ } else {
499
+ return true;
500
+ }
501
+ }
502
+
503
+ //FlexSlider: Helper function to determine animation target
504
+ slider.getTarget = function(dir) {
505
+ slider.direction = dir;
506
+ if (dir == "next") {
507
+ return (slider.currentSlide == slider.count - 1) ? 0 : slider.currentSlide + 1;
508
+ } else {
509
+ return (slider.currentSlide == 0) ? slider.count - 1 : slider.currentSlide - 1;
510
+ }
511
+ }
512
+
513
+ //FlexSlider: Helper function to set CSS3 transitions
514
+ slider.setTransition = function(dur) {
515
+ slider.container.css({'-webkit-transition-duration': (dur/1000) + "s"});
516
+ }
517
+
518
+ //FlexSlider: Initialize
519
+ slider.init();
520
+ }
521
+
522
+ //FlexSlider: Default Settings
523
+ $.flexslider.defaults = {
524
+ animation: "fade", //String: Select your animation type, "fade" or "slide"
525
+ slideDirection: "horizontal", //String: Select the sliding direction, "horizontal" or "vertical"
526
+ slideshow: true, //Boolean: Animate slider automatically
527
+ slideshowSpeed: 7000, //Integer: Set the speed of the slideshow cycling, in milliseconds
528
+ animationDuration: 600, //Integer: Set the speed of animations, in milliseconds
529
+ directionNav: true, //Boolean: Create navigation for previous/next navigation? (true/false)
530
+ controlNav: true, //Boolean: Create navigation for paging control of each clide? Note: Leave true for manualControls usage
531
+ keyboardNav: true, //Boolean: Allow slider navigating via keyboard left/right keys
532
+ mousewheel: false, //Boolean: Allow slider navigating via mousewheel
533
+ prevText: "Previous", //String: Set the text for the "previous" directionNav item
534
+ nextText: "Next", //String: Set the text for the "next" directionNav item
535
+ pausePlay: false, //Boolean: Create pause/play dynamic element
536
+ pauseText: 'Pause', //String: Set the text for the "pause" pausePlay item
537
+ playText: 'Play', //String: Set the text for the "play" pausePlay item
538
+ randomize: false, //Boolean: Randomize slide order
539
+ slideToStart: 0, //Integer: The slide that the slider should start on. Array notation (0 = first slide)
540
+ animationLoop: true, //Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end
541
+ pauseOnAction: true, //Boolean: Pause the slideshow when interacting with control elements, highly recommended.
542
+ pauseOnHover: false, //Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering
543
+ controlsContainer: "", //Selector: Declare which container the navigation elements should be appended too. Default container is the flexSlider element. Example use would be ".flexslider-container", "#container", etc. If the given element is not found, the default action will be taken.
544
+ manualControls: "", //Selector: Declare custom control navigation. Example would be ".flex-control-nav li" or "#tabs-nav li img", etc. The number of elements in your controlNav should match the number of slides/tabs.
545
+ start: function(){}, //Callback: function(slider) - Fires when the slider loads the first slide
546
+ before: function(){}, //Callback: function(slider) - Fires asynchronously with each slider animation
547
+ after: function(){}, //Callback: function(slider) - Fires after each slider animation completes
548
+ end: function(){} //Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)
549
+ }
550
+
551
+ //FlexSlider: Plugin Function
552
+ $.fn.flexslider = function(options) {
553
+ return this.each(function() {
554
+ if ($(this).find('.slides > li').length == 1) {
555
+ $(this).find('.slides > li').fadeIn(400);
556
+ }
557
+ else if ($(this).data('flexsliderInit') != true) {
558
+ new $.flexslider(this, options);
559
+ }
560
+ });
561
+ }
562
+
563
+ })(jQuery);