Commit 0d83548d28565bbeb031215da71ed44f5b4d2389

Authored by Victor Costa
2 parents b9b6e81c f9835ac9

Merge branch 'AI3279-new_block_store' into stable

Conflicts:
	app/controllers/box_organizer_controller.rb
	app/controllers/my_profile/profile_design_controller.rb
	app/helpers/box_organizer_helper.rb
	app/helpers/boxes_helper.rb
	app/helpers/layout_helper.rb
	app/models/block.rb
	app/models/communities_block.rb
	app/models/theme.rb
	app/views/box_organizer/index.html.erb
	app/views/box_organizer/show_block_type_info.html.erb
	test/functional/environment_design_controller_test.rb
	test/functional/profile_design_controller_test.rb
app/controllers/box_organizer_controller.rb
@@ -3,9 +3,11 @@ class BoxOrganizerController < ApplicationController @@ -3,9 +3,11 @@ class BoxOrganizerController < ApplicationController
3 before_filter :login_required 3 before_filter :login_required
4 4
5 def index 5 def index
  6 + @available_blocks = available_blocks.uniq
6 end 7 end
7 8
8 - def add_or_move_block 9 + def move_block
  10 + @block = params[:id] ? boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) : nil
9 11
10 target_position = nil 12 target_position = nil
11 13
@@ -17,23 +19,15 @@ class BoxOrganizerController < ApplicationController @@ -17,23 +19,15 @@ class BoxOrganizerController < ApplicationController
17 else 19 else
18 (params[:target] =~ /end-of-box-([0-9]+)/) 20 (params[:target] =~ /end-of-box-([0-9]+)/)
19 21
20 - @target_box = boxes_holder.boxes.find($1) 22 + @target_box = boxes_holder.boxes.find_by_id($1)
21 end 23 end
22 24
23 - type = params[:id].gsub(/^block-/,'') 25 + @block = new_block(params[:type], @target_box) if @block.nil?
  26 + @source_box = @block.box
24 27
25 - if available_blocks.map(&:name).include?(type)  
26 - @block = type.constantize.new 28 + if (@source_box != @target_box)
  29 + @block.remove_from_list
27 @block.box = @target_box 30 @block.box = @target_box
28 - @block.position = target_position  
29 - else  
30 - @block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))  
31 - @source_box = @block.box  
32 -  
33 - if (@source_box != @target_box)  
34 - @block.remove_from_list  
35 - @block.box = @target_box  
36 - end  
37 end 31 end
38 32
39 if target_position.nil? 33 if target_position.nil?
@@ -49,12 +43,9 @@ class BoxOrganizerController < ApplicationController @@ -49,12 +43,9 @@ class BoxOrganizerController < ApplicationController
49 43
50 @target_box.reload 44 @target_box.reload
51 45
52 - if available_blocks.map(&:name).include?(type)  
53 - render :action => 'add_block'  
54 - else  
55 - render :action => 'move_block' 46 + unless request.xhr?
  47 + redirect_to :action => 'index'
56 end 48 end
57 -  
58 end 49 end
59 50
60 def move_block_down 51 def move_block_down
@@ -69,20 +60,6 @@ class BoxOrganizerController < ApplicationController @@ -69,20 +60,6 @@ class BoxOrganizerController < ApplicationController
69 redirect_to :action => 'index' 60 redirect_to :action => 'index'
70 end 61 end
71 62
72 - def show_block_type_info  
73 - type = params[:type]  
74 - if ! type.blank?  
75 - if available_blocks.map(&:name).include?(type)  
76 - @block = type.constantize  
77 - else  
78 - raise ArgumentError.new("Type %s is not allowed. Go away." % type)  
79 - end  
80 - render :action => 'show_block_type_info', :layout => false  
81 - else  
82 - redirect_to :action => 'index'  
83 - end  
84 - end  
85 -  
86 def edit 63 def edit
87 @block = boxes_holder.blocks.find(params[:id]) 64 @block = boxes_holder.blocks.find(params[:id])
88 render :action => 'edit', :layout => false 65 render :action => 'edit', :layout => false
@@ -94,7 +71,7 @@ class BoxOrganizerController < ApplicationController @@ -94,7 +71,7 @@ class BoxOrganizerController < ApplicationController
94 path_list = if boxes_holder.is_a?(Environment) && boxes_holder.enabled?('use_portal_community') && boxes_holder.portal_community 71 path_list = if boxes_holder.is_a?(Environment) && boxes_holder.enabled?('use_portal_community') && boxes_holder.portal_community
95 boxes_holder.portal_community.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{portal}/"+content.path } 72 boxes_holder.portal_community.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{portal}/"+content.path }
96 elsif boxes_holder.is_a?(Profile) 73 elsif boxes_holder.is_a?(Profile)
97 - boxes_holder.articles.find(:all, :conditions=>"articles.name ILIKE '%#{search}%' or articles.path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{profile}/"+content.path } 74 + boxes_holder.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{profile}/"+content.path }
98 else 75 else
99 [] 76 []
100 end 77 end
@@ -129,6 +106,27 @@ class BoxOrganizerController < ApplicationController @@ -129,6 +106,27 @@ class BoxOrganizerController < ApplicationController
129 redirect_to :action => 'index' 106 redirect_to :action => 'index'
130 end 107 end
131 108
  109 + def show_block_type_info
  110 + type = params[:type]
  111 + if type.blank? || !available_blocks.map(&:name).include?(type)
  112 + raise ArgumentError.new("Type %s is not allowed. Go away." % type)
  113 + end
  114 + @block = type.constantize.new
  115 + @block.box = Box.new(:owner => boxes_holder)
  116 + render :action => 'show_block_type_info', :layout => false
  117 + end
  118 +
132 protected :boxes_editor? 119 protected :boxes_editor?
133 120
  121 + protected
  122 +
  123 + def new_block(type, box)
  124 + if !available_blocks.map(&:name).include?(type)
  125 + raise ArgumentError.new("Type %s is not allowed. Go away." % type)
  126 + end
  127 + block = type.constantize.new
  128 + box.blocks << block
  129 + block
  130 + end
  131 +
134 end 132 end
app/controllers/my_profile/profile_design_controller.rb
@@ -7,59 +7,56 @@ class ProfileDesignController &lt; BoxOrganizerController @@ -7,59 +7,56 @@ class ProfileDesignController &lt; BoxOrganizerController
7 before_filter :protect_fixed_block, :only => [:save, :move_block] 7 before_filter :protect_fixed_block, :only => [:save, :move_block]
8 8
9 def protect_fixed_block 9 def protect_fixed_block
  10 + return if params[:id].blank?
10 block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) 11 block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
11 - if !block.nil? && block.fixed && !current_person.is_admin? 12 + if block.present? && block.fixed && !current_person.is_admin?
12 render_access_denied 13 render_access_denied
13 end 14 end
14 end 15 end
15 16
16 def available_blocks 17 def available_blocks
17 - @available_blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ]  
18 - @available_blocks += plugins.dispatch(:extra_blocks) 18 + blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ]
  19 +
  20 + blocks += plugins.dispatch(:extra_blocks)
19 21
20 # blocks exclusive to people 22 # blocks exclusive to people
21 if profile.person? 23 if profile.person?
22 - @available_blocks << FavoriteEnterprisesBlock  
23 - @available_blocks << CommunitiesBlock  
24 - @available_blocks << EnterprisesBlock  
25 - @available_blocks += plugins.dispatch(:extra_blocks, :type => Person) 24 + blocks << FavoriteEnterprisesBlock
  25 + blocks << CommunitiesBlock
  26 + blocks << EnterprisesBlock
  27 + blocks += plugins.dispatch(:extra_blocks, :type => Person)
26 end 28 end
27 29
28 # blocks exclusive to communities 30 # blocks exclusive to communities
29 if profile.community? 31 if profile.community?
30 - @available_blocks += plugins.dispatch(:extra_blocks, :type => Community) 32 + blocks += plugins.dispatch(:extra_blocks, :type => Community)
31 end 33 end
32 34
33 # blocks exclusive for enterprises 35 # blocks exclusive for enterprises
34 if profile.enterprise? 36 if profile.enterprise?
35 - @available_blocks << DisabledEnterpriseMessageBlock  
36 - @available_blocks << HighlightsBlock  
37 - @available_blocks << ProductCategoriesBlock  
38 - @available_blocks << FeaturedProductsBlock  
39 - @available_blocks << FansBlock  
40 - @available_blocks += plugins.dispatch(:extra_blocks, :type => Enterprise) 37 + blocks << DisabledEnterpriseMessageBlock
  38 + blocks << HighlightsBlock
  39 + blocks << ProductCategoriesBlock
  40 + blocks << FeaturedProductsBlock
  41 + blocks << FansBlock
  42 + blocks += plugins.dispatch(:extra_blocks, :type => Enterprise)
41 end 43 end
42 44
43 # product block exclusive for enterprises in environments that permits it 45 # product block exclusive for enterprises in environments that permits it
44 if profile.enterprise? && profile.environment.enabled?('products_for_enterprises') 46 if profile.enterprise? && profile.environment.enabled?('products_for_enterprises')
45 - @available_blocks << ProductsBlock 47 + blocks << ProductsBlock
46 end 48 end
47 49
48 # block exclusive to profiles that have blog 50 # block exclusive to profiles that have blog
49 if profile.has_blog? 51 if profile.has_blog?
50 - @available_blocks << BlogArchivesBlock 52 + blocks << BlogArchivesBlock
51 end 53 end
52 54
53 if user.is_admin?(profile.environment) 55 if user.is_admin?(profile.environment)
54 - @available_blocks << RawHTMLBlock 56 + blocks << RawHTMLBlock
55 end 57 end
56 58
57 - @available_blocks  
58 -  
59 - end  
60 -  
61 - def index  
62 - available_blocks 59 + blocks
63 end 60 end
64 61
65 end 62 end
app/helpers/box_organizer_helper.rb
1 module BoxOrganizerHelper 1 module BoxOrganizerHelper
2 2
3 - def max_number_of_blocks_per_line  
4 - 7  
5 - end  
6 -  
7 def display_icon(block) 3 def display_icon(block)
8 image_path = nil 4 image_path = nil
9 plugin = @plugins.fetch_first_plugin(:has_block?, block) 5 plugin = @plugins.fetch_first_plugin(:has_block?, block)
app/helpers/boxes_helper.rb
@@ -191,7 +191,9 @@ module BoxesHelper @@ -191,7 +191,9 @@ module BoxesHelper
191 "before-block-#{block.id}" 191 "before-block-#{block.id}"
192 end 192 end
193 if block.nil? or modifiable?(block) 193 if block.nil? or modifiable?(block)
194 - content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'add_or_move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') 194 + draggable_id = "encodeURIComponent(jQuery(ui.draggable).attr('id'))"
  195 + draggable_type = "encodeURIComponent(jQuery(ui.draggable).attr('data-block-type'))"
  196 + content_tag('div', _('Drop Here'), :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover', :with => "'type='+"+draggable_type+"+'&id=' + "+draggable_id, :activeClass => 'block-target-active')
195 else 197 else
196 "" 198 ""
197 end 199 end
@@ -199,7 +201,25 @@ module BoxesHelper @@ -199,7 +201,25 @@ module BoxesHelper
199 201
200 # makes the given block draggable so it can be moved away. 202 # makes the given block draggable so it can be moved away.
201 def block_handle(block) 203 def block_handle(block)
202 - modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" 204 + return "" unless modifiable?(block)
  205 + icon = "<div><div>#{display_icon(block.class)}</div><span>#{_(block.class.pretty_name)}</span></div>"
  206 + block_draggable("block-#{block.id}",
  207 + :helper => "function() {return cloneDraggableBlock($(this), '#{icon}')}")
  208 + end
  209 +
  210 + def block_draggable(element_id, options={})
  211 + draggable_options = {
  212 + :revert => "'invalid'",
  213 + :appendTo => "'#block-store-draggables'",
  214 + :helper => '"clone"',
  215 + :revertDuration => 200,
  216 + :scroll => false,
  217 + :start => "startDragBlock",
  218 + :stop => "stopDragBlock",
  219 + :cursor => "'move'",
  220 + :cursorAt => '{ left: 0, top:0, right:0, bottom:0 }',
  221 + }.merge(options)
  222 + draggable_element(element_id, draggable_options)
203 end 223 end
204 224
205 def block_edit_buttons(block) 225 def block_edit_buttons(block)
@@ -224,9 +244,9 @@ module BoxesHelper @@ -224,9 +244,9 @@ module BoxesHelper
224 # FIXME too much hardcoded stuff 244 # FIXME too much hardcoded stuff
225 if holder.layout_template == 'default' 245 if holder.layout_template == 'default'
226 if block.box.position == 2 # area 2, left side => move to right side 246 if block.box.position == 2 # area 2, left side => move to right side
227 - buttons << icon_button('right', _('Move to the opposite side'), { :action => 'add_or_move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' ) 247 + buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )
228 elsif block.box.position == 3 # area 3, right side => move to left side 248 elsif block.box.position == 3 # area 3, right side => move to left side
229 - buttons << icon_button('left', _('Move to the opposite side'), { :action => 'add_or_move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) 249 + buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
230 end 250 end
231 end 251 end
232 252
@@ -251,8 +271,8 @@ module BoxesHelper @@ -251,8 +271,8 @@ module BoxesHelper
251 content_tag('h2', _('Embed block code')) + 271 content_tag('h2', _('Embed block code')) +
252 content_tag('div', _('Below, you''ll see a field containing embed code for the block. Just copy the code and paste it into your website or blogging software.'), :style => 'margin-bottom: 1em;') + 272 content_tag('div', _('Below, you''ll see a field containing embed code for the block. Just copy the code and paste it into your website or blogging software.'), :style => 'margin-bottom: 1em;') +
253 content_tag('textarea', embed_code, :style => 'margin-bottom: 1em; width:100%; height:40%;', :readonly => 'readonly') + 273 content_tag('textarea', embed_code, :style => 'margin-bottom: 1em; width:100%; height:40%;', :readonly => 'readonly') +
254 - thickbox_close_button(_('Close')), :style => 'display: none;', :id => "embed-code-box-#{block.id}")  
255 - buttons << thickbox_inline_popup_icon(:embed, _('Embed code'), {}, "embed-code-box-#{block.id}") << html 274 + modal_close_button(_('Close')), :style => 'display: none;', :id => "embed-code-box-#{block.id}")
  275 + buttons << modal_inline_icon(:embed, _('Embed code'), {}, "embed-code-box-#{block.id}") << html
256 end 276 end
257 277
258 content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar') 278 content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar')
app/helpers/layout_helper.rb
@@ -49,7 +49,7 @@ module LayoutHelper @@ -49,7 +49,7 @@ module LayoutHelper
49 'selectordie', 49 'selectordie',
50 'inputosaurus', 50 'inputosaurus',
51 'chat', 51 'chat',
52 - 'block_store', 52 + 'block-store',
53 pngfix_stylesheet_path, 53 pngfix_stylesheet_path,
54 ] + tokeninput_stylesheets 54 ] + tokeninput_stylesheets
55 plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') } 55 plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') }
app/models/block.rb
@@ -122,19 +122,36 @@ class Block &lt; ActiveRecord::Base @@ -122,19 +122,36 @@ class Block &lt; ActiveRecord::Base
122 '(dummy)' 122 '(dummy)'
123 end 123 end
124 124
125 - # returns a short description of the block, used when the user sees a list of  
126 - # blocks to choose one to include in the design.  
127 - #  
128 - # Must be redefined in subclasses to match the short description of each block  
129 - # type.  
130 def self.short_description 125 def self.short_description
131 self.pretty_name 126 self.pretty_name
132 end 127 end
133 128
  129 + def self.icon
  130 + "/images/icon_block.png"
  131 + end
  132 +
  133 + def self.icon_path
  134 + basename = self.name.split('::').last.underscore
  135 + File.join('blocks', basename, 'icon.png')
  136 + end
  137 +
134 def self.pretty_name 138 def self.pretty_name
135 self.name.split('::').last.gsub('Block','') 139 self.name.split('::').last.gsub('Block','')
136 end 140 end
137 141
  142 + def self.default_icon_path
  143 + 'icon_block.png'
  144 + end
  145 +
  146 + def self.preview_path
  147 + base_name = self.name.split('::').last.underscore
  148 + File.join('blocks', base_name,'previews')
  149 + end
  150 +
  151 + def self.default_preview_path
  152 + "block_preview.png"
  153 + end
  154 +
138 # Returns the content to be used for this block. 155 # Returns the content to be used for this block.
139 # 156 #
140 # This method can return several types of objects: 157 # This method can return several types of objects:
@@ -247,33 +264,10 @@ class Block &lt; ActiveRecord::Base @@ -247,33 +264,10 @@ class Block &lt; ActiveRecord::Base
247 duplicated_block.created_at = nil 264 duplicated_block.created_at = nil
248 duplicated_block.updated_at = nil 265 duplicated_block.updated_at = nil
249 duplicated_block.save! 266 duplicated_block.save!
250 - duplicated_block.insert_at((self.position || 0) + 1) 267 + duplicated_block.insert_at(self.position + 1)
251 duplicated_block 268 duplicated_block
252 end 269 end
253 270
254 - def self.preview_path  
255 - base_name = self.name.split('::').last.underscore  
256 - File.join('blocks', base_name,'previews')  
257 - end  
258 -  
259 - def self.icon_path  
260 - basename = self.name.split('::').last.underscore  
261 - File.join('blocks', basename, 'icon.png')  
262 - end  
263 -  
264 - def self.default_icon_path  
265 - 'icon_block.png'  
266 - end  
267 -  
268 - def self.default_preview_path  
269 - "block_preview.png"  
270 - end  
271 -  
272 - def copy_from(block)  
273 - self.settings = block.settings  
274 - self.position = block.position  
275 - end  
276 -  
277 def copy_from(block) 271 def copy_from(block)
278 self.settings = block.settings 272 self.settings = block.settings
279 self.position = block.position 273 self.position = block.position
app/models/communities_block.rb
@@ -6,7 +6,6 @@ class CommunitiesBlock &lt; ProfileListBlock @@ -6,7 +6,6 @@ class CommunitiesBlock &lt; ProfileListBlock
6 _("<p>Display all of your communities.</p><p>You could choose the amount of communities will be displayed and you could priorize that profiles with images.</p> <p>The view all button is always present in the block.</p>") 6 _("<p>Display all of your communities.</p><p>You could choose the amount of communities will be displayed and you could priorize that profiles with images.</p> <p>The view all button is always present in the block.</p>")
7 end 7 end
8 8
9 -  
10 def self.short_description 9 def self.short_description
11 _('Communities') 10 _('Communities')
12 end 11 end
app/models/theme.rb
@@ -13,14 +13,8 @@ class Theme @@ -13,14 +13,8 @@ class Theme
13 Rails.root.join('public', 'user_themes') 13 Rails.root.join('public', 'user_themes')
14 end 14 end
15 15
16 - #FIXME make this test changed  
17 def system_themes_dir 16 def system_themes_dir
18 - Rails.root.join('public', relative_themes_dir)  
19 - end  
20 -  
21 - #FIXME make this test  
22 - def relative_themes_dir  
23 - File.join('designs', 'themes') 17 + Rails.root.join('public', 'designs', 'themes')
24 end 18 end
25 19
26 def create(id, attributes = {}) 20 def create(id, attributes = {})
@@ -100,11 +94,6 @@ class Theme @@ -100,11 +94,6 @@ class Theme
100 end 94 end
101 95
102 #FIXME make this test 96 #FIXME make this test
103 - def public_path  
104 - File.join('/', self.class.relative_themes_dir, self.id)  
105 - end  
106 -  
107 - #FIXME make this test  
108 def filesystem_path 97 def filesystem_path
109 File.join(self.class.system_themes_dir, self.id) 98 File.join(self.class.system_themes_dir, self.id)
110 end 99 end
app/views/box_organizer/index.html.erb
1 -<%= stylesheet_link_tag 'circlepop.css' %> 1 +<%= stylesheet_link_tag 'slick.css' %>
  2 +<%= stylesheet_link_tag 'slick-theme.css' %>
2 3
3 <h1><%= _('Editing sideboxes')%></h1> 4 <h1><%= _('Editing sideboxes')%></h1>
4 5
@@ -6,53 +7,23 @@ @@ -6,53 +7,23 @@
6 <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> 7 <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %>
7 <% end %> 8 <% end %>
8 9
9 -<% n_blocks_in_line = 0 %>  
10 -<% last_block = @available_blocks.last %>  
11 -  
12 -<div id="block-types-container"> 10 +<div id="block-store">
13 <div id="block-types"> 11 <div id="block-types">
14 -  
15 <% @available_blocks.each do |block| %> 12 <% @available_blocks.each do |block| %>
16 -  
17 - <% if n_blocks_in_line == 0 %>  
18 - <div class="block-types-group">  
19 - <% end %>  
20 -  
21 - <% n_blocks_in_line += 1 %>  
22 -  
23 - <div id="block-<%=block.name%>" class="block-type <%= block.name.to_css_class %> drag"> 13 + <div id="block-<%= block.name.to_css_class %>" class="block-type <%= block.name.to_css_class %>" data-block-type="<%= block.name %>">
24 <div class="button-bar"> 14 <div class="button-bar">
25 - <%= link_to content_tag('span', _('Help on this block')),  
26 - {:action => 'show_block_type_info', :type => block.name},  
27 - :class => "button icon-button icon-help colorbox",  
28 - :title => _('Help on this block') %>  
29 - <br style="clear: left"> 15 + <%= modal_button 'help', _('Help on this block'),
  16 + {:action => 'show_block_type_info', :type => block.name},
  17 + :title => _('Help on this block') %>
30 </div> 18 </div>
31 <div> 19 <div>
32 <%= display_icon(block) %> 20 <%= display_icon(block) %>
33 </div> 21 </div>
34 <span><%= _(block.pretty_name) %></span> 22 <span><%= _(block.pretty_name) %></span>
  23 + <%= block_draggable("block-#{block.name.to_css_class}",
  24 + :cursorAt => '{bottom: 30, left: 0}') %>
35 </div> 25 </div>
36 -  
37 - <%= draggable_element("block-#{block.name}", :revert => true) %>  
38 -  
39 - <% if n_blocks_in_line == max_number_of_blocks_per_line || last_block == block %>  
40 - <% n_blocks_in_line = 0 %>  
41 - </div>  
42 - <% end %>  
43 -  
44 <% end %> 26 <% end %>
45 -  
46 </div> 27 </div>
47 </div> 28 </div>
48 -  
49 -<section id="block-types-navigation">  
50 - <nav class="nav-circlepop">  
51 - <a class="previous" href="javascript:void(0);"><span class="icon-wrap"></span></a>  
52 - <a class="next" href="javascript:void(0);"><span class="icon-wrap"></span></a>  
53 - </nav>  
54 -</section>  
55 -  
56 -<div style="clear:both;"></div>  
57 -  
58 -<%= javascript_include_tag('block_store') %> 29 +<div id="block-store-draggables"></div>
app/views/box_organizer/show_block_type_info.html.erb
1 <div id="block-info-container"> 1 <div id="block-info-container">
2 2
3 <div id="block-info-header"> 3 <div id="block-info-header">
4 - <%= display_icon(@block) %>  
5 - <h1><%= @block.pretty_name %></h1>  
6 - <p><%= @block.short_description %></p> 4 + <%= display_icon(@block.class) %>
  5 + <h1><%= @block.class.pretty_name %></h1>
  6 + <p><%= @block.class.short_description %></p>
7 </div> 7 </div>
8 8
9 <div id="block-info-images"> 9 <div id="block-info-images">
10 <div style="white-space: nowrap;"> 10 <div style="white-space: nowrap;">
11 - <%= display_previews(@block) %> 11 + <%= display_previews(@block.class) %>
12 </div> 12 </div>
13 </div> 13 </div>
14 14
15 <div id="block-info-description"> 15 <div id="block-info-description">
16 <h2><%= _('Description') %></h2> 16 <h2><%= _('Description') %></h2>
17 - <p><%= @block.description %></p>  
18 - <p><%= @block.new.help if @block.method_defined?(:help) %></p> 17 + <p><%= @block.class.description %></p>
  18 + <p><%= @block.help if @block.class.method_defined?(:help) %></p>
19 </div> 19 </div>
20 20
21 </div> 21 </div>
app/views/layouts/_javascript.html.erb
@@ -3,8 +3,9 @@ @@ -3,8 +3,9 @@
3 'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate', 3 'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate',
4 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', 'jquery.typewatch', 'jquery.textchange', 4 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', 'jquery.typewatch', 'jquery.textchange',
5 'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'inputosaurus.js', 'select-or-die/_src/selectordie', 5 'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'inputosaurus.js', 'select-or-die/_src/selectordie',
  6 + 'slick.js',
6 # noosfero libraries 7 # noosfero libraries
7 - 'application.js', 'modal.js', 8 + 'application.js', 'modal.js', 'block-store.js',
8 'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow', 9 'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow',
9 :cache => 'cache/application' %> 10 :cache => 'cache/application' %>
10 11
lib/noosfero/plugin.rb
@@ -183,13 +183,11 @@ class Noosfero::Plugin @@ -183,13 +183,11 @@ class Noosfero::Plugin
183 def api_mount_points 183 def api_mount_points
184 end 184 end
185 end 185 end
186 -  
187 - 186 +
188 #FIXME make this test 187 #FIXME make this test
189 def has_block?(block) 188 def has_block?(block)
190 self.class.extra_blocks.keys.include?(block) 189 self.class.extra_blocks.keys.include?(block)
191 end 190 end
192 -  
193 191
194 def expanded_template(file_path, locals = {}) 192 def expanded_template(file_path, locals = {})
195 views_path = Rails.root.join('plugins', "#{self.class.public_name}", 'views') 193 views_path = Rails.root.join('plugins', "#{self.class.public_name}", 'views')
plugins/container_block/public/style.css
@@ -57,3 +57,6 @@ @@ -57,3 +57,6 @@
57 .container-block-plugin_container-block .block-target { 57 .container-block-plugin_container-block .block-target {
58 background: #afd; 58 background: #afd;
59 } 59 }
  60 +#box-organizer.shadow .container-block-plugin_container-block {
  61 + opacity: 1;
  62 +}
public/fonts/slick.eot 0 → 100644
No preview for this file type
public/fonts/slick.svg 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +<?xml version="1.0" standalone="no"?>
  2 +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
  3 +<svg xmlns="http://www.w3.org/2000/svg">
  4 +<metadata>Generated by Fontastic.me</metadata>
  5 +<defs>
  6 +<font id="slick" horiz-adv-x="512">
  7 +<font-face font-family="slick" units-per-em="512" ascent="480" descent="-32"/>
  8 +<missing-glyph horiz-adv-x="512" />
  9 +
  10 +<glyph unicode="&#8594;" d="M241 113l130 130c4 4 6 8 6 13 0 5-2 9-6 13l-130 130c-3 3-7 5-12 5-5 0-10-2-13-5l-29-30c-4-3-6-7-6-12 0-5 2-10 6-13l87-88-87-88c-4-3-6-8-6-13 0-5 2-9 6-12l29-30c3-3 8-5 13-5 5 0 9 2 12 5z m234 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
  11 +<glyph unicode="&#8592;" d="M296 113l29 30c4 3 6 7 6 12 0 5-2 10-6 13l-87 88 87 88c4 3 6 8 6 13 0 5-2 9-6 12l-29 30c-3 3-8 5-13 5-5 0-9-2-12-5l-130-130c-4-4-6-8-6-13 0-5 2-9 6-13l130-130c3-3 7-5 12-5 5 0 10 2 13 5z m179 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
  12 +<glyph unicode="&#8226;" d="M475 256c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
  13 +<glyph unicode="&#97;" d="M475 439l0-128c0-5-1-9-5-13-4-4-8-5-13-5l-128 0c-8 0-13 3-17 11-3 7-2 14 4 20l40 39c-28 26-62 39-100 39-20 0-39-4-57-11-18-8-33-18-46-32-14-13-24-28-32-46-7-18-11-37-11-57 0-20 4-39 11-57 8-18 18-33 32-46 13-14 28-24 46-32 18-7 37-11 57-11 23 0 44 5 64 15 20 9 38 23 51 42 2 1 4 3 7 3 3 0 5-1 7-3l39-39c2-2 3-3 3-6 0-2-1-4-2-6-21-25-46-45-76-59-29-14-60-20-93-20-30 0-58 5-85 17-27 12-51 27-70 47-20 19-35 43-47 70-12 27-17 55-17 85 0 30 5 58 17 85 12 27 27 51 47 70 19 20 43 35 70 47 27 12 55 17 85 17 28 0 55-5 81-15 26-11 50-26 70-45l37 37c6 6 12 7 20 4 8-4 11-9 11-17z"/>
  14 +</font></defs></svg>
public/fonts/slick.ttf 0 → 100644
No preview for this file type
public/fonts/slick.woff 0 → 100644
No preview for this file type
public/javascripts/block-store.js 0 → 100644
@@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
  1 +function cloneDraggableBlock(el, blockIcon) {
  2 + el.addClass('ui-draggable-dragging');
  3 + return blockIcon;
  4 +}
  5 +
  6 +function startDragBlock() {
  7 + $('#box-organizer').addClass('shadow');
  8 +}
  9 +
  10 +function stopDragBlock() {
  11 + $('#box-organizer').removeClass('shadow');
  12 + $('.ui-draggable-dragging').removeClass('ui-draggable-dragging');
  13 +}
  14 +
  15 +jQuery(document).ready(function($) {
  16 + var store = $('#block-store #block-types').slick({
  17 + infinite: true,
  18 + dots: true,
  19 + draggable: false,
  20 + respondTo: 'slider',
  21 + slidesToShow: 7,
  22 + slidesToScroll: 4,
  23 + responsive: [
  24 + {
  25 + breakpoint: 2048,
  26 + settings: {
  27 + slidesToShow: 10,
  28 + slidesToScroll: 4,
  29 + }
  30 + },
  31 + {
  32 + breakpoint: 1024,
  33 + settings: {
  34 + slidesToShow: 8,
  35 + slidesToScroll: 4,
  36 + }
  37 + }
  38 + ]
  39 + });
  40 +});
public/javascripts/slick.js 0 → 100644
@@ -0,0 +1,2249 @@ @@ -0,0 +1,2249 @@
  1 +/*
  2 + _ _ _ _
  3 + ___| (_) ___| | __ (_)___
  4 +/ __| | |/ __| |/ / | / __|
  5 +\__ \ | | (__| < _ | \__ \
  6 +|___/_|_|\___|_|\_(_)/ |___/
  7 + |__/
  8 +
  9 + Version: 1.5.0
  10 + Author: Ken Wheeler
  11 + Website: http://kenwheeler.github.io
  12 + Docs: http://kenwheeler.github.io/slick
  13 + Repo: http://github.com/kenwheeler/slick
  14 + Issues: http://github.com/kenwheeler/slick/issues
  15 +
  16 + */
  17 +/* global window, document, define, jQuery, setInterval, clearInterval */
  18 +(function(factory) {
  19 + 'use strict';
  20 + if (typeof define === 'function' && define.amd) {
  21 + define(['jquery'], factory);
  22 + } else if (typeof exports !== 'undefined') {
  23 + module.exports = factory(require('jquery'));
  24 + } else {
  25 + factory(jQuery);
  26 + }
  27 +
  28 +}(function($) {
  29 + 'use strict';
  30 + var Slick = window.Slick || {};
  31 +
  32 + Slick = (function() {
  33 +
  34 + var instanceUid = 0;
  35 +
  36 + function Slick(element, settings) {
  37 +
  38 + var _ = this,
  39 + dataSettings, responsiveSettings, breakpoint;
  40 +
  41 + _.defaults = {
  42 + accessibility: true,
  43 + adaptiveHeight: false,
  44 + appendArrows: $(element),
  45 + appendDots: $(element),
  46 + arrows: true,
  47 + asNavFor: null,
  48 + prevArrow: '<button type="button" data-role="none" class="slick-prev" aria-label="previous">Previous</button>',
  49 + nextArrow: '<button type="button" data-role="none" class="slick-next" aria-label="next">Next</button>',
  50 + autoplay: false,
  51 + autoplaySpeed: 3000,
  52 + centerMode: false,
  53 + centerPadding: '50px',
  54 + cssEase: 'ease',
  55 + customPaging: function(slider, i) {
  56 + return '<button type="button" data-role="none">' + (i + 1) + '</button>';
  57 + },
  58 + dots: false,
  59 + dotsClass: 'slick-dots',
  60 + draggable: true,
  61 + easing: 'linear',
  62 + edgeFriction: 0.35,
  63 + fade: false,
  64 + focusOnSelect: false,
  65 + infinite: true,
  66 + initialSlide: 0,
  67 + lazyLoad: 'ondemand',
  68 + mobileFirst: false,
  69 + pauseOnHover: true,
  70 + pauseOnDotsHover: false,
  71 + respondTo: 'window',
  72 + responsive: null,
  73 + rtl: false,
  74 + slide: '',
  75 + slidesToShow: 1,
  76 + slidesToScroll: 1,
  77 + speed: 500,
  78 + swipe: true,
  79 + swipeToSlide: false,
  80 + touchMove: true,
  81 + touchThreshold: 5,
  82 + useCSS: true,
  83 + variableWidth: false,
  84 + vertical: false,
  85 + waitForAnimate: true
  86 + };
  87 +
  88 + _.initials = {
  89 + animating: false,
  90 + dragging: false,
  91 + autoPlayTimer: null,
  92 + currentDirection: 0,
  93 + currentLeft: null,
  94 + currentSlide: 0,
  95 + direction: 1,
  96 + $dots: null,
  97 + listWidth: null,
  98 + listHeight: null,
  99 + loadIndex: 0,
  100 + $nextArrow: null,
  101 + $prevArrow: null,
  102 + slideCount: null,
  103 + slideWidth: null,
  104 + $slideTrack: null,
  105 + $slides: null,
  106 + sliding: false,
  107 + slideOffset: 0,
  108 + swipeLeft: null,
  109 + $list: null,
  110 + touchObject: {},
  111 + transformsEnabled: false,
  112 + verticalScrolling: false
  113 + };
  114 +
  115 + $.extend(_, _.initials);
  116 +
  117 + _.activeBreakpoint = null;
  118 + _.animType = null;
  119 + _.animProp = null;
  120 + _.breakpoints = [];
  121 + _.breakpointSettings = [];
  122 + _.cssTransitions = false;
  123 + _.hidden = 'hidden';
  124 + _.paused = false;
  125 + _.positionProp = null;
  126 + _.respondTo = null;
  127 + _.shouldClick = true;
  128 + _.$slider = $(element);
  129 + _.$slidesCache = null;
  130 + _.transformType = null;
  131 + _.transitionType = null;
  132 + _.visibilityChange = 'visibilitychange';
  133 + _.windowWidth = 0;
  134 + _.windowTimer = null;
  135 +
  136 + dataSettings = $(element).data('slick') || {};
  137 +
  138 + _.options = $.extend({}, _.defaults, dataSettings, settings);
  139 +
  140 + _.currentSlide = _.options.initialSlide;
  141 +
  142 + _.originalSettings = _.options;
  143 + responsiveSettings = _.options.responsive || null;
  144 +
  145 + if (responsiveSettings && responsiveSettings.length > -1) {
  146 + _.respondTo = _.options.respondTo || 'window';
  147 + for (breakpoint in responsiveSettings) {
  148 + if (responsiveSettings.hasOwnProperty(breakpoint)) {
  149 + _.breakpoints.push(responsiveSettings[
  150 + breakpoint].breakpoint);
  151 + _.breakpointSettings[responsiveSettings[
  152 + breakpoint].breakpoint] =
  153 + responsiveSettings[breakpoint].settings;
  154 + }
  155 + }
  156 + _.breakpoints.sort(function(a, b) {
  157 + if (_.options.mobileFirst === true) {
  158 + return a - b;
  159 + } else {
  160 + return b - a;
  161 + }
  162 + });
  163 + }
  164 +
  165 + if (typeof document.mozHidden !== 'undefined') {
  166 + _.hidden = 'mozHidden';
  167 + _.visibilityChange = 'mozvisibilitychange';
  168 + } else if (typeof document.msHidden !== 'undefined') {
  169 + _.hidden = 'msHidden';
  170 + _.visibilityChange = 'msvisibilitychange';
  171 + } else if (typeof document.webkitHidden !== 'undefined') {
  172 + _.hidden = 'webkitHidden';
  173 + _.visibilityChange = 'webkitvisibilitychange';
  174 + }
  175 +
  176 + _.autoPlay = $.proxy(_.autoPlay, _);
  177 + _.autoPlayClear = $.proxy(_.autoPlayClear, _);
  178 + _.changeSlide = $.proxy(_.changeSlide, _);
  179 + _.clickHandler = $.proxy(_.clickHandler, _);
  180 + _.selectHandler = $.proxy(_.selectHandler, _);
  181 + _.setPosition = $.proxy(_.setPosition, _);
  182 + _.swipeHandler = $.proxy(_.swipeHandler, _);
  183 + _.dragHandler = $.proxy(_.dragHandler, _);
  184 + _.keyHandler = $.proxy(_.keyHandler, _);
  185 + _.autoPlayIterator = $.proxy(_.autoPlayIterator, _);
  186 +
  187 + _.instanceUid = instanceUid++;
  188 +
  189 + // A simple way to check for HTML strings
  190 + // Strict HTML recognition (must start with <)
  191 + // Extracted from jQuery v1.11 source
  192 + _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/;
  193 +
  194 + _.init();
  195 +
  196 + _.checkResponsive(true);
  197 +
  198 + }
  199 +
  200 + return Slick;
  201 +
  202 + }());
  203 +
  204 + Slick.prototype.addSlide = Slick.prototype.slickAdd = function(markup, index, addBefore) {
  205 +
  206 + var _ = this;
  207 +
  208 + if (typeof(index) === 'boolean') {
  209 + addBefore = index;
  210 + index = null;
  211 + } else if (index < 0 || (index >= _.slideCount)) {
  212 + return false;
  213 + }
  214 +
  215 + _.unload();
  216 +
  217 + if (typeof(index) === 'number') {
  218 + if (index === 0 && _.$slides.length === 0) {
  219 + $(markup).appendTo(_.$slideTrack);
  220 + } else if (addBefore) {
  221 + $(markup).insertBefore(_.$slides.eq(index));
  222 + } else {
  223 + $(markup).insertAfter(_.$slides.eq(index));
  224 + }
  225 + } else {
  226 + if (addBefore === true) {
  227 + $(markup).prependTo(_.$slideTrack);
  228 + } else {
  229 + $(markup).appendTo(_.$slideTrack);
  230 + }
  231 + }
  232 +
  233 + _.$slides = _.$slideTrack.children(this.options.slide);
  234 +
  235 + _.$slideTrack.children(this.options.slide).detach();
  236 +
  237 + _.$slideTrack.append(_.$slides);
  238 +
  239 + _.$slides.each(function(index, element) {
  240 + $(element).attr('data-slick-index', index);
  241 + });
  242 +
  243 + _.$slidesCache = _.$slides;
  244 +
  245 + _.reinit();
  246 +
  247 + };
  248 +
  249 + Slick.prototype.animateHeight = function() {
  250 + var _ = this;
  251 + if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
  252 + var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
  253 + _.$list.animate({
  254 + height: targetHeight
  255 + }, _.options.speed);
  256 + }
  257 + };
  258 +
  259 + Slick.prototype.animateSlide = function(targetLeft, callback) {
  260 +
  261 + var animProps = {},
  262 + _ = this;
  263 +
  264 + _.animateHeight();
  265 +
  266 + if (_.options.rtl === true && _.options.vertical === false) {
  267 + targetLeft = -targetLeft;
  268 + }
  269 + if (_.transformsEnabled === false) {
  270 + if (_.options.vertical === false) {
  271 + _.$slideTrack.animate({
  272 + left: targetLeft
  273 + }, _.options.speed, _.options.easing, callback);
  274 + } else {
  275 + _.$slideTrack.animate({
  276 + top: targetLeft
  277 + }, _.options.speed, _.options.easing, callback);
  278 + }
  279 +
  280 + } else {
  281 +
  282 + if (_.cssTransitions === false) {
  283 + if (_.options.rtl === true) {
  284 + _.currentLeft = -(_.currentLeft);
  285 + }
  286 + $({
  287 + animStart: _.currentLeft
  288 + }).animate({
  289 + animStart: targetLeft
  290 + }, {
  291 + duration: _.options.speed,
  292 + easing: _.options.easing,
  293 + step: function(now) {
  294 + now = Math.ceil(now);
  295 + if (_.options.vertical === false) {
  296 + animProps[_.animType] = 'translate(' +
  297 + now + 'px, 0px)';
  298 + _.$slideTrack.css(animProps);
  299 + } else {
  300 + animProps[_.animType] = 'translate(0px,' +
  301 + now + 'px)';
  302 + _.$slideTrack.css(animProps);
  303 + }
  304 + },
  305 + complete: function() {
  306 + if (callback) {
  307 + callback.call();
  308 + }
  309 + }
  310 + });
  311 +
  312 + } else {
  313 +
  314 + _.applyTransition();
  315 + targetLeft = Math.ceil(targetLeft);
  316 +
  317 + if (_.options.vertical === false) {
  318 + animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)';
  319 + } else {
  320 + animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)';
  321 + }
  322 + _.$slideTrack.css(animProps);
  323 +
  324 + if (callback) {
  325 + setTimeout(function() {
  326 +
  327 + _.disableTransition();
  328 +
  329 + callback.call();
  330 + }, _.options.speed);
  331 + }
  332 +
  333 + }
  334 +
  335 + }
  336 +
  337 + };
  338 +
  339 + Slick.prototype.asNavFor = function(index) {
  340 + var _ = this,
  341 + asNavFor = _.options.asNavFor !== null ? $(_.options.asNavFor).slick('getSlick') : null;
  342 + if (asNavFor !== null) asNavFor.slideHandler(index, true);
  343 + };
  344 +
  345 + Slick.prototype.applyTransition = function(slide) {
  346 +
  347 + var _ = this,
  348 + transition = {};
  349 +
  350 + if (_.options.fade === false) {
  351 + transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase;
  352 + } else {
  353 + transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase;
  354 + }
  355 +
  356 + if (_.options.fade === false) {
  357 + _.$slideTrack.css(transition);
  358 + } else {
  359 + _.$slides.eq(slide).css(transition);
  360 + }
  361 +
  362 + };
  363 +
  364 + Slick.prototype.autoPlay = function() {
  365 +
  366 + var _ = this;
  367 +
  368 + if (_.autoPlayTimer) {
  369 + clearInterval(_.autoPlayTimer);
  370 + }
  371 +
  372 + if (_.slideCount > _.options.slidesToShow && _.paused !== true) {
  373 + _.autoPlayTimer = setInterval(_.autoPlayIterator,
  374 + _.options.autoplaySpeed);
  375 + }
  376 +
  377 + };
  378 +
  379 + Slick.prototype.autoPlayClear = function() {
  380 +
  381 + var _ = this;
  382 + if (_.autoPlayTimer) {
  383 + clearInterval(_.autoPlayTimer);
  384 + }
  385 +
  386 + };
  387 +
  388 + Slick.prototype.autoPlayIterator = function() {
  389 +
  390 + var _ = this;
  391 +
  392 + if (_.options.infinite === false) {
  393 +
  394 + if (_.direction === 1) {
  395 +
  396 + if ((_.currentSlide + 1) === _.slideCount -
  397 + 1) {
  398 + _.direction = 0;
  399 + }
  400 +
  401 + _.slideHandler(_.currentSlide + _.options.slidesToScroll);
  402 +
  403 + } else {
  404 +
  405 + if ((_.currentSlide - 1 === 0)) {
  406 +
  407 + _.direction = 1;
  408 +
  409 + }
  410 +
  411 + _.slideHandler(_.currentSlide - _.options.slidesToScroll);
  412 +
  413 + }
  414 +
  415 + } else {
  416 +
  417 + _.slideHandler(_.currentSlide + _.options.slidesToScroll);
  418 +
  419 + }
  420 +
  421 + };
  422 +
  423 + Slick.prototype.buildArrows = function() {
  424 +
  425 + var _ = this;
  426 +
  427 + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
  428 +
  429 + _.$prevArrow = $(_.options.prevArrow);
  430 + _.$nextArrow = $(_.options.nextArrow);
  431 +
  432 + if (_.htmlExpr.test(_.options.prevArrow)) {
  433 + _.$prevArrow.appendTo(_.options.appendArrows);
  434 + }
  435 +
  436 + if (_.htmlExpr.test(_.options.nextArrow)) {
  437 + _.$nextArrow.appendTo(_.options.appendArrows);
  438 + }
  439 +
  440 + if (_.options.infinite !== true) {
  441 + _.$prevArrow.addClass('slick-disabled');
  442 + }
  443 +
  444 + }
  445 +
  446 + };
  447 +
  448 + Slick.prototype.buildDots = function() {
  449 +
  450 + var _ = this,
  451 + i, dotString;
  452 +
  453 + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
  454 +
  455 + dotString = '<ul class="' + _.options.dotsClass + '">';
  456 +
  457 + for (i = 0; i <= _.getDotCount(); i += 1) {
  458 + dotString += '<li>' + _.options.customPaging.call(this, _, i) + '</li>';
  459 + }
  460 +
  461 + dotString += '</ul>';
  462 +
  463 + _.$dots = $(dotString).appendTo(
  464 + _.options.appendDots);
  465 +
  466 + _.$dots.find('li').first().addClass('slick-active').attr('aria-hidden', 'false');
  467 +
  468 + }
  469 +
  470 + };
  471 +
  472 + Slick.prototype.buildOut = function() {
  473 +
  474 + var _ = this;
  475 +
  476 + _.$slides = _.$slider.children(_.options.slide +
  477 + ':not(.slick-cloned)').addClass(
  478 + 'slick-slide');
  479 + _.slideCount = _.$slides.length;
  480 +
  481 + _.$slides.each(function(index, element) {
  482 + $(element).attr('data-slick-index', index);
  483 + });
  484 +
  485 + _.$slidesCache = _.$slides;
  486 +
  487 + _.$slider.addClass('slick-slider');
  488 +
  489 + _.$slideTrack = (_.slideCount === 0) ?
  490 + $('<div class="slick-track"/>').appendTo(_.$slider) :
  491 + _.$slides.wrapAll('<div class="slick-track"/>').parent();
  492 +
  493 + _.$list = _.$slideTrack.wrap(
  494 + '<div aria-live="polite" class="slick-list"/>').parent();
  495 + _.$slideTrack.css('opacity', 0);
  496 +
  497 + if (_.options.centerMode === true || _.options.swipeToSlide === true) {
  498 + _.options.slidesToScroll = 1;
  499 + }
  500 +
  501 + $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading');
  502 +
  503 + _.setupInfinite();
  504 +
  505 + _.buildArrows();
  506 +
  507 + _.buildDots();
  508 +
  509 + _.updateDots();
  510 +
  511 + if (_.options.accessibility === true) {
  512 + _.$list.prop('tabIndex', 0);
  513 + }
  514 +
  515 + _.setSlideClasses(typeof this.currentSlide === 'number' ? this.currentSlide : 0);
  516 +
  517 + if (_.options.draggable === true) {
  518 + _.$list.addClass('draggable');
  519 + }
  520 +
  521 + };
  522 +
  523 + Slick.prototype.checkResponsive = function(initial) {
  524 +
  525 + var _ = this,
  526 + breakpoint, targetBreakpoint, respondToWidth;
  527 + var sliderWidth = _.$slider.width();
  528 + var windowWidth = window.innerWidth || $(window).width();
  529 + if (_.respondTo === 'window') {
  530 + respondToWidth = windowWidth;
  531 + } else if (_.respondTo === 'slider') {
  532 + respondToWidth = sliderWidth;
  533 + } else if (_.respondTo === 'min') {
  534 + respondToWidth = Math.min(windowWidth, sliderWidth);
  535 + }
  536 +
  537 + if (_.originalSettings.responsive && _.originalSettings
  538 + .responsive.length > -1 && _.originalSettings.responsive !== null) {
  539 +
  540 + targetBreakpoint = null;
  541 +
  542 + for (breakpoint in _.breakpoints) {
  543 + if (_.breakpoints.hasOwnProperty(breakpoint)) {
  544 + if (_.originalSettings.mobileFirst === false) {
  545 + if (respondToWidth < _.breakpoints[breakpoint]) {
  546 + targetBreakpoint = _.breakpoints[breakpoint];
  547 + }
  548 + } else {
  549 + if (respondToWidth > _.breakpoints[breakpoint]) {
  550 + targetBreakpoint = _.breakpoints[breakpoint];
  551 + }
  552 + }
  553 + }
  554 + }
  555 +
  556 + if (targetBreakpoint !== null) {
  557 + if (_.activeBreakpoint !== null) {
  558 + if (targetBreakpoint !== _.activeBreakpoint) {
  559 + _.activeBreakpoint =
  560 + targetBreakpoint;
  561 + if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
  562 + _.unslick();
  563 + } else {
  564 + _.options = $.extend({}, _.originalSettings,
  565 + _.breakpointSettings[
  566 + targetBreakpoint]);
  567 + if (initial === true)
  568 + _.currentSlide = _.options.initialSlide;
  569 + _.refresh();
  570 + }
  571 + }
  572 + } else {
  573 + _.activeBreakpoint = targetBreakpoint;
  574 + if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
  575 + _.unslick();
  576 + } else {
  577 + _.options = $.extend({}, _.originalSettings,
  578 + _.breakpointSettings[
  579 + targetBreakpoint]);
  580 + if (initial === true)
  581 + _.currentSlide = _.options.initialSlide;
  582 + _.refresh();
  583 + }
  584 + }
  585 + } else {
  586 + if (_.activeBreakpoint !== null) {
  587 + _.activeBreakpoint = null;
  588 + _.options = _.originalSettings;
  589 + if (initial === true)
  590 + _.currentSlide = _.options.initialSlide;
  591 + _.refresh();
  592 + }
  593 + }
  594 +
  595 + }
  596 +
  597 + };
  598 +
  599 + Slick.prototype.changeSlide = function(event, dontAnimate) {
  600 +
  601 + var _ = this,
  602 + $target = $(event.target),
  603 + indexOffset, slideOffset, unevenOffset;
  604 +
  605 + // If target is a link, prevent default action.
  606 + $target.is('a') && event.preventDefault();
  607 +
  608 + unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0);
  609 + indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll;
  610 +
  611 + switch (event.data.message) {
  612 +
  613 + case 'previous':
  614 + slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset;
  615 + if (_.slideCount > _.options.slidesToShow) {
  616 + _.slideHandler(_.currentSlide - slideOffset, false, dontAnimate);
  617 + }
  618 + break;
  619 +
  620 + case 'next':
  621 + slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset;
  622 + if (_.slideCount > _.options.slidesToShow) {
  623 + _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate);
  624 + }
  625 + break;
  626 +
  627 + case 'index':
  628 + var index = event.data.index === 0 ? 0 :
  629 + event.data.index || $(event.target).parent().index() * _.options.slidesToScroll;
  630 +
  631 + _.slideHandler(_.checkNavigable(index), false, dontAnimate);
  632 + break;
  633 +
  634 + default:
  635 + return;
  636 + }
  637 +
  638 + };
  639 +
  640 + Slick.prototype.checkNavigable = function(index) {
  641 +
  642 + var _ = this,
  643 + navigables, prevNavigable;
  644 +
  645 + navigables = _.getNavigableIndexes();
  646 + prevNavigable = 0;
  647 + if (index > navigables[navigables.length - 1]) {
  648 + index = navigables[navigables.length - 1];
  649 + } else {
  650 + for (var n in navigables) {
  651 + if (index < navigables[n]) {
  652 + index = prevNavigable;
  653 + break;
  654 + }
  655 + prevNavigable = navigables[n];
  656 + }
  657 + }
  658 +
  659 + return index;
  660 + };
  661 +
  662 + Slick.prototype.cleanUpEvents = function() {
  663 +
  664 + var _ = this;
  665 +
  666 + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
  667 + $('li', _.$dots).off('click.slick', _.changeSlide);
  668 + }
  669 +
  670 + if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.options.autoplay === true) {
  671 + $('li', _.$dots)
  672 + .off('mouseenter.slick', _.setPaused.bind(_, true))
  673 + .off('mouseleave.slick', _.setPaused.bind(_, false));
  674 + }
  675 +
  676 + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
  677 + _.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide);
  678 + _.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide);
  679 + }
  680 +
  681 + _.$list.off('touchstart.slick mousedown.slick', _.swipeHandler);
  682 + _.$list.off('touchmove.slick mousemove.slick', _.swipeHandler);
  683 + _.$list.off('touchend.slick mouseup.slick', _.swipeHandler);
  684 + _.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler);
  685 +
  686 + _.$list.off('click.slick', _.clickHandler);
  687 +
  688 + if (_.options.autoplay === true) {
  689 + $(document).off(_.visibilityChange, _.visibility);
  690 + }
  691 +
  692 + _.$list.off('mouseenter.slick', _.setPaused.bind(_, true));
  693 + _.$list.off('mouseleave.slick', _.setPaused.bind(_, false));
  694 +
  695 + if (_.options.accessibility === true) {
  696 + _.$list.off('keydown.slick', _.keyHandler);
  697 + }
  698 +
  699 + if (_.options.focusOnSelect === true) {
  700 + $(_.$slideTrack).children().off('click.slick', _.selectHandler);
  701 + }
  702 +
  703 + $(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange);
  704 +
  705 + $(window).off('resize.slick.slick-' + _.instanceUid, _.resize);
  706 +
  707 + $('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault);
  708 +
  709 + $(window).off('load.slick.slick-' + _.instanceUid, _.setPosition);
  710 + $(document).off('ready.slick.slick-' + _.instanceUid, _.setPosition);
  711 + };
  712 +
  713 + Slick.prototype.clickHandler = function(event) {
  714 +
  715 + var _ = this;
  716 +
  717 + if (_.shouldClick === false) {
  718 + event.stopImmediatePropagation();
  719 + event.stopPropagation();
  720 + event.preventDefault();
  721 + }
  722 +
  723 + };
  724 +
  725 + Slick.prototype.destroy = function() {
  726 +
  727 + var _ = this;
  728 +
  729 + _.autoPlayClear();
  730 +
  731 + _.touchObject = {};
  732 +
  733 + _.cleanUpEvents();
  734 +
  735 + $('.slick-cloned', _.$slider).remove();
  736 +
  737 + if (_.$dots) {
  738 + _.$dots.remove();
  739 + }
  740 + if (_.$prevArrow && (typeof _.options.prevArrow !== 'object')) {
  741 + _.$prevArrow.remove();
  742 + }
  743 + if (_.$nextArrow && (typeof _.options.nextArrow !== 'object')) {
  744 + _.$nextArrow.remove();
  745 + }
  746 +
  747 + if (_.$slides) {
  748 + _.$slides.removeClass('slick-slide slick-active slick-center slick-visible')
  749 + .attr('aria-hidden', 'true')
  750 + .removeAttr('data-slick-index')
  751 + .css({
  752 + position: '',
  753 + left: '',
  754 + top: '',
  755 + zIndex: '',
  756 + opacity: '',
  757 + width: ''
  758 + });
  759 +
  760 + _.$slider.html(_.$slides);
  761 + }
  762 +
  763 + _.$slider.removeClass('slick-slider');
  764 + _.$slider.removeClass('slick-initialized');
  765 +
  766 + };
  767 +
  768 + Slick.prototype.disableTransition = function(slide) {
  769 +
  770 + var _ = this,
  771 + transition = {};
  772 +
  773 + transition[_.transitionType] = '';
  774 +
  775 + if (_.options.fade === false) {
  776 + _.$slideTrack.css(transition);
  777 + } else {
  778 + _.$slides.eq(slide).css(transition);
  779 + }
  780 +
  781 + };
  782 +
  783 + Slick.prototype.fadeSlide = function(slideIndex, callback) {
  784 +
  785 + var _ = this;
  786 +
  787 + if (_.cssTransitions === false) {
  788 +
  789 + _.$slides.eq(slideIndex).css({
  790 + zIndex: 1000
  791 + });
  792 +
  793 + _.$slides.eq(slideIndex).animate({
  794 + opacity: 1
  795 + }, _.options.speed, _.options.easing, callback);
  796 +
  797 + } else {
  798 +
  799 + _.applyTransition(slideIndex);
  800 +
  801 + _.$slides.eq(slideIndex).css({
  802 + opacity: 1,
  803 + zIndex: 1000
  804 + });
  805 +
  806 + if (callback) {
  807 + setTimeout(function() {
  808 +
  809 + _.disableTransition(slideIndex);
  810 +
  811 + callback.call();
  812 + }, _.options.speed);
  813 + }
  814 +
  815 + }
  816 +
  817 + };
  818 +
  819 + Slick.prototype.filterSlides = Slick.prototype.slickFilter = function(filter) {
  820 +
  821 + var _ = this;
  822 +
  823 + if (filter !== null) {
  824 +
  825 + _.unload();
  826 +
  827 + _.$slideTrack.children(this.options.slide).detach();
  828 +
  829 + _.$slidesCache.filter(filter).appendTo(_.$slideTrack);
  830 +
  831 + _.reinit();
  832 +
  833 + }
  834 +
  835 + };
  836 +
  837 + Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function() {
  838 +
  839 + var _ = this;
  840 + return _.currentSlide;
  841 +
  842 + };
  843 +
  844 + Slick.prototype.getDotCount = function() {
  845 +
  846 + var _ = this;
  847 +
  848 + var breakPoint = 0;
  849 + var counter = 0;
  850 + var pagerQty = 0;
  851 +
  852 + if (_.options.infinite === true) {
  853 + pagerQty = Math.ceil(_.slideCount / _.options.slidesToScroll);
  854 + } else if (_.options.centerMode === true) {
  855 + pagerQty = _.slideCount;
  856 + } else {
  857 + while (breakPoint < _.slideCount) {
  858 + ++pagerQty;
  859 + breakPoint = counter + _.options.slidesToShow;
  860 + counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
  861 + }
  862 + }
  863 +
  864 + return pagerQty - 1;
  865 +
  866 + };
  867 +
  868 + Slick.prototype.getLeft = function(slideIndex) {
  869 +
  870 + var _ = this,
  871 + targetLeft,
  872 + verticalHeight,
  873 + verticalOffset = 0,
  874 + targetSlide;
  875 +
  876 + _.slideOffset = 0;
  877 + verticalHeight = _.$slides.first().outerHeight();
  878 +
  879 + if (_.options.infinite === true) {
  880 + if (_.slideCount > _.options.slidesToShow) {
  881 + _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1;
  882 + verticalOffset = (verticalHeight * _.options.slidesToShow) * -1;
  883 + }
  884 + if (_.slideCount % _.options.slidesToScroll !== 0) {
  885 + if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) {
  886 + if (slideIndex > _.slideCount) {
  887 + _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1;
  888 + verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1;
  889 + } else {
  890 + _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1;
  891 + verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1;
  892 + }
  893 + }
  894 + }
  895 + } else {
  896 + if (slideIndex + _.options.slidesToShow > _.slideCount) {
  897 + _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth;
  898 + verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight;
  899 + }
  900 + }
  901 +
  902 + if (_.slideCount <= _.options.slidesToShow) {
  903 + _.slideOffset = 0;
  904 + verticalOffset = 0;
  905 + }
  906 +
  907 + if (_.options.centerMode === true && _.options.infinite === true) {
  908 + _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth;
  909 + } else if (_.options.centerMode === true) {
  910 + _.slideOffset = 0;
  911 + _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2);
  912 + }
  913 +
  914 + if (_.options.vertical === false) {
  915 + targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset;
  916 + } else {
  917 + targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset;
  918 + }
  919 +
  920 + if (_.options.variableWidth === true) {
  921 +
  922 + if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
  923 + targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
  924 + } else {
  925 + targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow);
  926 + }
  927 +
  928 + targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
  929 +
  930 + if (_.options.centerMode === true) {
  931 + if (_.options.infinite === false) {
  932 + targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
  933 + } else {
  934 + targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1);
  935 + }
  936 + targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
  937 + targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2;
  938 + }
  939 + }
  940 +
  941 + return targetLeft;
  942 +
  943 + };
  944 +
  945 + Slick.prototype.getOption = Slick.prototype.slickGetOption = function(option) {
  946 +
  947 + var _ = this;
  948 +
  949 + return _.options[option];
  950 +
  951 + };
  952 +
  953 + Slick.prototype.getNavigableIndexes = function() {
  954 +
  955 + var _ = this,
  956 + breakPoint = 0,
  957 + counter = 0,
  958 + indexes = [],
  959 + max;
  960 +
  961 + if (_.options.infinite === false) {
  962 + max = _.slideCount - _.options.slidesToShow + 1;
  963 + if (_.options.centerMode === true) max = _.slideCount;
  964 + } else {
  965 + breakPoint = _.slideCount * -1;
  966 + counter = _.slideCount * -1;
  967 + max = _.slideCount * 2;
  968 + }
  969 +
  970 + while (breakPoint < max) {
  971 + indexes.push(breakPoint);
  972 + breakPoint = counter + _.options.slidesToScroll;
  973 + counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
  974 + }
  975 +
  976 + return indexes;
  977 +
  978 + };
  979 +
  980 + Slick.prototype.getSlick = function() {
  981 +
  982 + return this;
  983 +
  984 + };
  985 +
  986 + Slick.prototype.getSlideCount = function() {
  987 +
  988 + var _ = this,
  989 + slidesTraversed, swipedSlide, centerOffset;
  990 +
  991 + centerOffset = _.options.centerMode === true ? _.slideWidth * Math.floor(_.options.slidesToShow / 2) : 0;
  992 +
  993 + if (_.options.swipeToSlide === true) {
  994 + _.$slideTrack.find('.slick-slide').each(function(index, slide) {
  995 + if (slide.offsetLeft - centerOffset + ($(slide).outerWidth() / 2) > (_.swipeLeft * -1)) {
  996 + swipedSlide = slide;
  997 + return false;
  998 + }
  999 + });
  1000 +
  1001 + slidesTraversed = Math.abs($(swipedSlide).attr('data-slick-index') - _.currentSlide) || 1;
  1002 +
  1003 + return slidesTraversed;
  1004 +
  1005 + } else {
  1006 + return _.options.slidesToScroll;
  1007 + }
  1008 +
  1009 + };
  1010 +
  1011 + Slick.prototype.goTo = Slick.prototype.slickGoTo = function(slide, dontAnimate) {
  1012 +
  1013 + var _ = this;
  1014 +
  1015 + _.changeSlide({
  1016 + data: {
  1017 + message: 'index',
  1018 + index: parseInt(slide)
  1019 + }
  1020 + }, dontAnimate);
  1021 +
  1022 + };
  1023 +
  1024 + Slick.prototype.init = function() {
  1025 +
  1026 + var _ = this;
  1027 +
  1028 + if (!$(_.$slider).hasClass('slick-initialized')) {
  1029 +
  1030 + $(_.$slider).addClass('slick-initialized');
  1031 + _.buildOut();
  1032 + _.setProps();
  1033 + _.startLoad();
  1034 + _.loadSlider();
  1035 + _.initializeEvents();
  1036 + _.updateArrows();
  1037 + _.updateDots();
  1038 + }
  1039 +
  1040 + _.$slider.trigger('init', [_]);
  1041 +
  1042 + };
  1043 +
  1044 + Slick.prototype.initArrowEvents = function() {
  1045 +
  1046 + var _ = this;
  1047 +
  1048 + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
  1049 + _.$prevArrow.on('click.slick', {
  1050 + message: 'previous'
  1051 + }, _.changeSlide);
  1052 + _.$nextArrow.on('click.slick', {
  1053 + message: 'next'
  1054 + }, _.changeSlide);
  1055 + }
  1056 +
  1057 + };
  1058 +
  1059 + Slick.prototype.initDotEvents = function() {
  1060 +
  1061 + var _ = this;
  1062 +
  1063 + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
  1064 + $('li', _.$dots).on('click.slick', {
  1065 + message: 'index'
  1066 + }, _.changeSlide);
  1067 + }
  1068 +
  1069 + if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.options.autoplay === true) {
  1070 + $('li', _.$dots)
  1071 + .on('mouseenter.slick', _.setPaused.bind(_, true))
  1072 + .on('mouseleave.slick', _.setPaused.bind(_, false));
  1073 + }
  1074 +
  1075 + };
  1076 +
  1077 + Slick.prototype.initializeEvents = function() {
  1078 +
  1079 + var _ = this;
  1080 +
  1081 + _.initArrowEvents();
  1082 +
  1083 + _.initDotEvents();
  1084 +
  1085 + _.$list.on('touchstart.slick mousedown.slick', {
  1086 + action: 'start'
  1087 + }, _.swipeHandler);
  1088 + _.$list.on('touchmove.slick mousemove.slick', {
  1089 + action: 'move'
  1090 + }, _.swipeHandler);
  1091 + _.$list.on('touchend.slick mouseup.slick', {
  1092 + action: 'end'
  1093 + }, _.swipeHandler);
  1094 + _.$list.on('touchcancel.slick mouseleave.slick', {
  1095 + action: 'end'
  1096 + }, _.swipeHandler);
  1097 +
  1098 + _.$list.on('click.slick', _.clickHandler);
  1099 +
  1100 + if (_.options.autoplay === true) {
  1101 + $(document).on(_.visibilityChange, _.visibility.bind(_));
  1102 + }
  1103 +
  1104 + _.$list.on('mouseenter.slick', _.setPaused.bind(_, true));
  1105 + _.$list.on('mouseleave.slick', _.setPaused.bind(_, false));
  1106 +
  1107 + if (_.options.accessibility === true) {
  1108 + _.$list.on('keydown.slick', _.keyHandler);
  1109 + }
  1110 +
  1111 + if (_.options.focusOnSelect === true) {
  1112 + $(_.$slideTrack).children().on('click.slick', _.selectHandler);
  1113 + }
  1114 +
  1115 + $(window).on('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange.bind(_));
  1116 +
  1117 + $(window).on('resize.slick.slick-' + _.instanceUid, _.resize.bind(_));
  1118 +
  1119 + //$('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault);
  1120 +
  1121 + $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition);
  1122 + $(document).on('ready.slick.slick-' + _.instanceUid, _.setPosition);
  1123 +
  1124 + };
  1125 +
  1126 + Slick.prototype.initUI = function() {
  1127 +
  1128 + var _ = this;
  1129 +
  1130 + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
  1131 +
  1132 + _.$prevArrow.show();
  1133 + _.$nextArrow.show();
  1134 +
  1135 + }
  1136 +
  1137 + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
  1138 +
  1139 + _.$dots.show();
  1140 +
  1141 + }
  1142 +
  1143 + if (_.options.autoplay === true) {
  1144 +
  1145 + _.autoPlay();
  1146 +
  1147 + }
  1148 +
  1149 + };
  1150 +
  1151 + Slick.prototype.keyHandler = function(event) {
  1152 +
  1153 + var _ = this;
  1154 +
  1155 + if (event.keyCode === 37 && _.options.accessibility === true) {
  1156 + _.changeSlide({
  1157 + data: {
  1158 + message: 'previous'
  1159 + }
  1160 + });
  1161 + } else if (event.keyCode === 39 && _.options.accessibility === true) {
  1162 + _.changeSlide({
  1163 + data: {
  1164 + message: 'next'
  1165 + }
  1166 + });
  1167 + }
  1168 +
  1169 + };
  1170 +
  1171 + Slick.prototype.lazyLoad = function() {
  1172 +
  1173 + var _ = this,
  1174 + loadRange, cloneRange, rangeStart, rangeEnd;
  1175 +
  1176 + function loadImages(imagesScope) {
  1177 + $('img[data-lazy]', imagesScope).each(function() {
  1178 + var image = $(this),
  1179 + imageSource = $(this).attr('data-lazy');
  1180 +
  1181 + image
  1182 + .load(function() {
  1183 + image.animate({
  1184 + opacity: 1
  1185 + }, 200);
  1186 + })
  1187 + .css({
  1188 + opacity: 0
  1189 + })
  1190 + .attr('src', imageSource)
  1191 + .removeAttr('data-lazy')
  1192 + .removeClass('slick-loading');
  1193 + });
  1194 + }
  1195 +
  1196 + if (_.options.centerMode === true) {
  1197 + if (_.options.infinite === true) {
  1198 + rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1);
  1199 + rangeEnd = rangeStart + _.options.slidesToShow + 2;
  1200 + } else {
  1201 + rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1));
  1202 + rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide;
  1203 + }
  1204 + } else {
  1205 + rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide;
  1206 + rangeEnd = rangeStart + _.options.slidesToShow;
  1207 + if (_.options.fade === true) {
  1208 + if (rangeStart > 0) rangeStart--;
  1209 + if (rangeEnd <= _.slideCount) rangeEnd++;
  1210 + }
  1211 + }
  1212 +
  1213 + loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd);
  1214 + loadImages(loadRange);
  1215 +
  1216 + if (_.slideCount <= _.options.slidesToShow) {
  1217 + cloneRange = _.$slider.find('.slick-slide');
  1218 + loadImages(cloneRange);
  1219 + } else
  1220 + if (_.currentSlide >= _.slideCount - _.options.slidesToShow) {
  1221 + cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow);
  1222 + loadImages(cloneRange);
  1223 + } else if (_.currentSlide === 0) {
  1224 + cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1);
  1225 + loadImages(cloneRange);
  1226 + }
  1227 +
  1228 + };
  1229 +
  1230 + Slick.prototype.loadSlider = function() {
  1231 +
  1232 + var _ = this;
  1233 +
  1234 + _.setPosition();
  1235 +
  1236 + _.$slideTrack.css({
  1237 + opacity: 1
  1238 + });
  1239 +
  1240 + _.$slider.removeClass('slick-loading');
  1241 +
  1242 + _.initUI();
  1243 +
  1244 + if (_.options.lazyLoad === 'progressive') {
  1245 + _.progressiveLazyLoad();
  1246 + }
  1247 +
  1248 + };
  1249 +
  1250 + Slick.prototype.next = Slick.prototype.slickNext = function() {
  1251 +
  1252 + var _ = this;
  1253 +
  1254 + _.changeSlide({
  1255 + data: {
  1256 + message: 'next'
  1257 + }
  1258 + });
  1259 +
  1260 + };
  1261 +
  1262 + Slick.prototype.orientationChange = function() {
  1263 +
  1264 + var _ = this;
  1265 +
  1266 + _.checkResponsive();
  1267 + _.setPosition();
  1268 +
  1269 + };
  1270 +
  1271 + Slick.prototype.pause = Slick.prototype.slickPause = function() {
  1272 +
  1273 + var _ = this;
  1274 +
  1275 + _.autoPlayClear();
  1276 + _.paused = true;
  1277 +
  1278 + };
  1279 +
  1280 + Slick.prototype.play = Slick.prototype.slickPlay = function() {
  1281 +
  1282 + var _ = this;
  1283 +
  1284 + _.paused = false;
  1285 + _.autoPlay();
  1286 +
  1287 + };
  1288 +
  1289 + Slick.prototype.postSlide = function(index) {
  1290 +
  1291 + var _ = this;
  1292 +
  1293 + _.$slider.trigger('afterChange', [_, index]);
  1294 +
  1295 + _.animating = false;
  1296 +
  1297 + _.setPosition();
  1298 +
  1299 + _.swipeLeft = null;
  1300 +
  1301 + if (_.options.autoplay === true && _.paused === false) {
  1302 + _.autoPlay();
  1303 + }
  1304 +
  1305 + };
  1306 +
  1307 + Slick.prototype.prev = Slick.prototype.slickPrev = function() {
  1308 +
  1309 + var _ = this;
  1310 +
  1311 + _.changeSlide({
  1312 + data: {
  1313 + message: 'previous'
  1314 + }
  1315 + });
  1316 +
  1317 + };
  1318 +
  1319 + Slick.prototype.preventDefault = function(e) {
  1320 + e.preventDefault();
  1321 + };
  1322 +
  1323 + Slick.prototype.progressiveLazyLoad = function() {
  1324 +
  1325 + var _ = this,
  1326 + imgCount, targetImage;
  1327 +
  1328 + imgCount = $('img[data-lazy]', _.$slider).length;
  1329 +
  1330 + if (imgCount > 0) {
  1331 + targetImage = $('img[data-lazy]', _.$slider).first();
  1332 + targetImage.attr('src', targetImage.attr('data-lazy')).removeClass('slick-loading').load(function() {
  1333 + targetImage.removeAttr('data-lazy');
  1334 + _.progressiveLazyLoad();
  1335 +
  1336 + if (_.options.adaptiveHeight === true) {
  1337 + _.setPosition();
  1338 + }
  1339 + })
  1340 + .error(function() {
  1341 + targetImage.removeAttr('data-lazy');
  1342 + _.progressiveLazyLoad();
  1343 + });
  1344 + }
  1345 +
  1346 + };
  1347 +
  1348 + Slick.prototype.refresh = function() {
  1349 +
  1350 + var _ = this,
  1351 + currentSlide = _.currentSlide;
  1352 +
  1353 + _.destroy();
  1354 +
  1355 + $.extend(_, _.initials);
  1356 +
  1357 + _.init();
  1358 +
  1359 + _.changeSlide({
  1360 + data: {
  1361 + message: 'index',
  1362 + index: currentSlide
  1363 + }
  1364 + }, true);
  1365 +
  1366 + };
  1367 +
  1368 + Slick.prototype.reinit = function() {
  1369 +
  1370 + var _ = this;
  1371 +
  1372 + _.$slides = _.$slideTrack.children(_.options.slide).addClass(
  1373 + 'slick-slide');
  1374 +
  1375 + _.slideCount = _.$slides.length;
  1376 +
  1377 + if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) {
  1378 + _.currentSlide = _.currentSlide - _.options.slidesToScroll;
  1379 + }
  1380 +
  1381 + if (_.slideCount <= _.options.slidesToShow) {
  1382 + _.currentSlide = 0;
  1383 + }
  1384 +
  1385 + _.setProps();
  1386 +
  1387 + _.setupInfinite();
  1388 +
  1389 + _.buildArrows();
  1390 +
  1391 + _.updateArrows();
  1392 +
  1393 + _.initArrowEvents();
  1394 +
  1395 + _.buildDots();
  1396 +
  1397 + _.updateDots();
  1398 +
  1399 + _.initDotEvents();
  1400 +
  1401 + if (_.options.focusOnSelect === true) {
  1402 + $(_.$slideTrack).children().on('click.slick', _.selectHandler);
  1403 + }
  1404 +
  1405 + _.setSlideClasses(0);
  1406 +
  1407 + _.setPosition();
  1408 +
  1409 + _.$slider.trigger('reInit', [_]);
  1410 +
  1411 + };
  1412 +
  1413 + Slick.prototype.resize = function() {
  1414 +
  1415 + var _ = this;
  1416 +
  1417 + if ($(window).width() !== _.windowWidth) {
  1418 + clearTimeout(_.windowDelay);
  1419 + _.windowDelay = window.setTimeout(function() {
  1420 + _.windowWidth = $(window).width();
  1421 + _.checkResponsive();
  1422 + _.setPosition();
  1423 + }, 50);
  1424 + }
  1425 + };
  1426 +
  1427 + Slick.prototype.removeSlide = Slick.prototype.slickRemove = function(index, removeBefore, removeAll) {
  1428 +
  1429 + var _ = this;
  1430 +
  1431 + if (typeof(index) === 'boolean') {
  1432 + removeBefore = index;
  1433 + index = removeBefore === true ? 0 : _.slideCount - 1;
  1434 + } else {
  1435 + index = removeBefore === true ? --index : index;
  1436 + }
  1437 +
  1438 + if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) {
  1439 + return false;
  1440 + }
  1441 +
  1442 + _.unload();
  1443 +
  1444 + if (removeAll === true) {
  1445 + _.$slideTrack.children().remove();
  1446 + } else {
  1447 + _.$slideTrack.children(this.options.slide).eq(index).remove();
  1448 + }
  1449 +
  1450 + _.$slides = _.$slideTrack.children(this.options.slide);
  1451 +
  1452 + _.$slideTrack.children(this.options.slide).detach();
  1453 +
  1454 + _.$slideTrack.append(_.$slides);
  1455 +
  1456 + _.$slidesCache = _.$slides;
  1457 +
  1458 + _.reinit();
  1459 +
  1460 + };
  1461 +
  1462 + Slick.prototype.setCSS = function(position) {
  1463 +
  1464 + var _ = this,
  1465 + positionProps = {},
  1466 + x, y;
  1467 +
  1468 + if (_.options.rtl === true) {
  1469 + position = -position;
  1470 + }
  1471 + x = _.positionProp == 'left' ? Math.ceil(position) + 'px' : '0px';
  1472 + y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px';
  1473 +
  1474 + positionProps[_.positionProp] = position;
  1475 +
  1476 + if (_.transformsEnabled === false) {
  1477 + _.$slideTrack.css(positionProps);
  1478 + } else {
  1479 + positionProps = {};
  1480 + if (_.cssTransitions === false) {
  1481 + positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';
  1482 + _.$slideTrack.css(positionProps);
  1483 + } else {
  1484 + positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)';
  1485 + _.$slideTrack.css(positionProps);
  1486 + }
  1487 + }
  1488 +
  1489 + };
  1490 +
  1491 + Slick.prototype.setDimensions = function() {
  1492 +
  1493 + var _ = this;
  1494 +
  1495 + if (_.options.vertical === false) {
  1496 + if (_.options.centerMode === true) {
  1497 + _.$list.css({
  1498 + padding: ('0px ' + _.options.centerPadding)
  1499 + });
  1500 + }
  1501 + } else {
  1502 + _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow);
  1503 + if (_.options.centerMode === true) {
  1504 + _.$list.css({
  1505 + padding: (_.options.centerPadding + ' 0px')
  1506 + });
  1507 + }
  1508 + }
  1509 +
  1510 + _.listWidth = _.$list.width();
  1511 + _.listHeight = _.$list.height();
  1512 +
  1513 +
  1514 + if (_.options.vertical === false && _.options.variableWidth === false) {
  1515 + _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow);
  1516 + _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length)));
  1517 +
  1518 + } else if (_.options.variableWidth === true) {
  1519 + _.$slideTrack.width(5000 * _.slideCount);
  1520 + } else {
  1521 + _.slideWidth = Math.ceil(_.listWidth);
  1522 + _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length)));
  1523 + }
  1524 +
  1525 + var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width();
  1526 + if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset);
  1527 +
  1528 + };
  1529 +
  1530 + Slick.prototype.setFade = function() {
  1531 +
  1532 + var _ = this,
  1533 + targetLeft;
  1534 +
  1535 + _.$slides.each(function(index, element) {
  1536 + targetLeft = (_.slideWidth * index) * -1;
  1537 + if (_.options.rtl === true) {
  1538 + $(element).css({
  1539 + position: 'relative',
  1540 + right: targetLeft,
  1541 + top: 0,
  1542 + zIndex: 800,
  1543 + opacity: 0
  1544 + });
  1545 + } else {
  1546 + $(element).css({
  1547 + position: 'relative',
  1548 + left: targetLeft,
  1549 + top: 0,
  1550 + zIndex: 800,
  1551 + opacity: 0
  1552 + });
  1553 + }
  1554 + });
  1555 +
  1556 + _.$slides.eq(_.currentSlide).css({
  1557 + zIndex: 900,
  1558 + opacity: 1
  1559 + });
  1560 +
  1561 + };
  1562 +
  1563 + Slick.prototype.setHeight = function() {
  1564 +
  1565 + var _ = this;
  1566 +
  1567 + if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
  1568 + var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
  1569 + _.$list.css('height', targetHeight);
  1570 + }
  1571 +
  1572 + };
  1573 +
  1574 + Slick.prototype.setOption = Slick.prototype.slickSetOption = function(option, value, refresh) {
  1575 +
  1576 + var _ = this;
  1577 + _.options[option] = value;
  1578 +
  1579 + if (refresh === true) {
  1580 + _.unload();
  1581 + _.reinit();
  1582 + }
  1583 +
  1584 + };
  1585 +
  1586 + Slick.prototype.setPosition = function() {
  1587 +
  1588 + var _ = this;
  1589 +
  1590 + _.setDimensions();
  1591 +
  1592 + _.setHeight();
  1593 +
  1594 + if (_.options.fade === false) {
  1595 + _.setCSS(_.getLeft(_.currentSlide));
  1596 + } else {
  1597 + _.setFade();
  1598 + }
  1599 +
  1600 + _.$slider.trigger('setPosition', [_]);
  1601 +
  1602 + };
  1603 +
  1604 + Slick.prototype.setProps = function() {
  1605 +
  1606 + var _ = this,
  1607 + bodyStyle = document.body.style;
  1608 +
  1609 + _.positionProp = _.options.vertical === true ? 'top' : 'left';
  1610 +
  1611 + if (_.positionProp === 'top') {
  1612 + _.$slider.addClass('slick-vertical');
  1613 + } else {
  1614 + _.$slider.removeClass('slick-vertical');
  1615 + }
  1616 +
  1617 + if (bodyStyle.WebkitTransition !== undefined ||
  1618 + bodyStyle.MozTransition !== undefined ||
  1619 + bodyStyle.msTransition !== undefined) {
  1620 + if (_.options.useCSS === true) {
  1621 + _.cssTransitions = true;
  1622 + }
  1623 + }
  1624 +
  1625 + if (bodyStyle.OTransform !== undefined) {
  1626 + _.animType = 'OTransform';
  1627 + _.transformType = '-o-transform';
  1628 + _.transitionType = 'OTransition';
  1629 + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
  1630 + }
  1631 + if (bodyStyle.MozTransform !== undefined) {
  1632 + _.animType = 'MozTransform';
  1633 + _.transformType = '-moz-transform';
  1634 + _.transitionType = 'MozTransition';
  1635 + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false;
  1636 + }
  1637 + if (bodyStyle.webkitTransform !== undefined) {
  1638 + _.animType = 'webkitTransform';
  1639 + _.transformType = '-webkit-transform';
  1640 + _.transitionType = 'webkitTransition';
  1641 + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
  1642 + }
  1643 + if (bodyStyle.msTransform !== undefined) {
  1644 + _.animType = 'msTransform';
  1645 + _.transformType = '-ms-transform';
  1646 + _.transitionType = 'msTransition';
  1647 + if (bodyStyle.msTransform === undefined) _.animType = false;
  1648 + }
  1649 + if (bodyStyle.transform !== undefined && _.animType !== false) {
  1650 + _.animType = 'transform';
  1651 + _.transformType = 'transform';
  1652 + _.transitionType = 'transition';
  1653 + }
  1654 + _.transformsEnabled = (_.animType !== null && _.animType !== false);
  1655 +
  1656 + };
  1657 +
  1658 +
  1659 + Slick.prototype.setSlideClasses = function(index) {
  1660 +
  1661 + var _ = this,
  1662 + centerOffset, allSlides, indexOffset, remainder;
  1663 +
  1664 + _.$slider.find('.slick-slide').removeClass('slick-active').attr('aria-hidden', 'true').removeClass('slick-center');
  1665 + allSlides = _.$slider.find('.slick-slide');
  1666 +
  1667 + if (_.options.centerMode === true) {
  1668 +
  1669 + centerOffset = Math.floor(_.options.slidesToShow / 2);
  1670 +
  1671 + if (_.options.infinite === true) {
  1672 +
  1673 + if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) {
  1674 + _.$slides.slice(index - centerOffset, index + centerOffset + 1).addClass('slick-active').attr('aria-hidden', 'false');
  1675 + } else {
  1676 + indexOffset = _.options.slidesToShow + index;
  1677 + allSlides.slice(indexOffset - centerOffset + 1, indexOffset + centerOffset + 2).addClass('slick-active').attr('aria-hidden', 'false');
  1678 + }
  1679 +
  1680 + if (index === 0) {
  1681 + allSlides.eq(allSlides.length - 1 - _.options.slidesToShow).addClass('slick-center');
  1682 + } else if (index === _.slideCount - 1) {
  1683 + allSlides.eq(_.options.slidesToShow).addClass('slick-center');
  1684 + }
  1685 +
  1686 + }
  1687 +
  1688 + _.$slides.eq(index).addClass('slick-center');
  1689 +
  1690 + } else {
  1691 +
  1692 + if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) {
  1693 + _.$slides.slice(index, index + _.options.slidesToShow).addClass('slick-active').attr('aria-hidden', 'false');
  1694 + } else if (allSlides.length <= _.options.slidesToShow) {
  1695 + allSlides.addClass('slick-active').attr('aria-hidden', 'false');
  1696 + } else {
  1697 + remainder = _.slideCount % _.options.slidesToShow;
  1698 + indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index;
  1699 + if (_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) {
  1700 + allSlides.slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder).addClass('slick-active').attr('aria-hidden', 'false');
  1701 + } else {
  1702 + allSlides.slice(indexOffset, indexOffset + _.options.slidesToShow).addClass('slick-active').attr('aria-hidden', 'false');
  1703 + }
  1704 + }
  1705 +
  1706 + }
  1707 +
  1708 + if (_.options.lazyLoad === 'ondemand') {
  1709 + _.lazyLoad();
  1710 + }
  1711 +
  1712 + };
  1713 +
  1714 + Slick.prototype.setupInfinite = function() {
  1715 +
  1716 + var _ = this,
  1717 + i, slideIndex, infiniteCount;
  1718 +
  1719 + if (_.options.fade === true) {
  1720 + _.options.centerMode = false;
  1721 + }
  1722 +
  1723 + if (_.options.infinite === true && _.options.fade === false) {
  1724 +
  1725 + slideIndex = null;
  1726 +
  1727 + if (_.slideCount > _.options.slidesToShow) {
  1728 +
  1729 + if (_.options.centerMode === true) {
  1730 + infiniteCount = _.options.slidesToShow + 1;
  1731 + } else {
  1732 + infiniteCount = _.options.slidesToShow;
  1733 + }
  1734 +
  1735 + for (i = _.slideCount; i > (_.slideCount -
  1736 + infiniteCount); i -= 1) {
  1737 + slideIndex = i - 1;
  1738 + $(_.$slides[slideIndex]).clone(true).attr('id', '')
  1739 + .attr('data-slick-index', slideIndex - _.slideCount)
  1740 + .prependTo(_.$slideTrack).addClass('slick-cloned');
  1741 + }
  1742 + for (i = 0; i < infiniteCount; i += 1) {
  1743 + slideIndex = i;
  1744 + $(_.$slides[slideIndex]).clone(true).attr('id', '')
  1745 + .attr('data-slick-index', slideIndex + _.slideCount)
  1746 + .appendTo(_.$slideTrack).addClass('slick-cloned');
  1747 + }
  1748 + _.$slideTrack.find('.slick-cloned').find('[id]').each(function() {
  1749 + $(this).attr('id', '');
  1750 + });
  1751 +
  1752 + }
  1753 +
  1754 + }
  1755 +
  1756 + };
  1757 +
  1758 + Slick.prototype.setPaused = function(paused) {
  1759 +
  1760 + var _ = this;
  1761 +
  1762 + if (_.options.autoplay === true && _.options.pauseOnHover === true) {
  1763 + _.paused = paused;
  1764 + _.autoPlayClear();
  1765 + }
  1766 + };
  1767 +
  1768 + Slick.prototype.selectHandler = function(event) {
  1769 +
  1770 + var _ = this;
  1771 +
  1772 + var targetElement = $(event.target).is('.slick-slide') ?
  1773 + $(event.target) :
  1774 + $(event.target).parents('.slick-slide');
  1775 +
  1776 + var index = parseInt(targetElement.attr('data-slick-index'));
  1777 +
  1778 + if (!index) index = 0;
  1779 +
  1780 + if (_.slideCount <= _.options.slidesToShow) {
  1781 + _.$slider.find('.slick-slide').removeClass('slick-active').attr('aria-hidden', 'true');
  1782 + _.$slides.eq(index).addClass('slick-active').attr("aria-hidden", "false");
  1783 + if (_.options.centerMode === true) {
  1784 + _.$slider.find('.slick-slide').removeClass('slick-center');
  1785 + _.$slides.eq(index).addClass('slick-center');
  1786 + }
  1787 + _.asNavFor(index);
  1788 + return;
  1789 + }
  1790 + _.slideHandler(index);
  1791 +
  1792 + };
  1793 +
  1794 + Slick.prototype.slideHandler = function(index, sync, dontAnimate) {
  1795 +
  1796 + var targetSlide, animSlide, oldSlide, slideLeft, targetLeft = null,
  1797 + _ = this;
  1798 +
  1799 + sync = sync || false;
  1800 +
  1801 + if (_.animating === true && _.options.waitForAnimate === true) {
  1802 + return;
  1803 + }
  1804 +
  1805 + if (_.options.fade === true && _.currentSlide === index) {
  1806 + return;
  1807 + }
  1808 +
  1809 + if (_.slideCount <= _.options.slidesToShow) {
  1810 + return;
  1811 + }
  1812 +
  1813 + if (sync === false) {
  1814 + _.asNavFor(index);
  1815 + }
  1816 +
  1817 + targetSlide = index;
  1818 + targetLeft = _.getLeft(targetSlide);
  1819 + slideLeft = _.getLeft(_.currentSlide);
  1820 +
  1821 + _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft;
  1822 +
  1823 + if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) {
  1824 + if (_.options.fade === false) {
  1825 + targetSlide = _.currentSlide;
  1826 + if (dontAnimate !== true) {
  1827 + _.animateSlide(slideLeft, function() {
  1828 + _.postSlide(targetSlide);
  1829 + });
  1830 + } else {
  1831 + _.postSlide(targetSlide);
  1832 + }
  1833 + }
  1834 + return;
  1835 + } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) {
  1836 + if (_.options.fade === false) {
  1837 + targetSlide = _.currentSlide;
  1838 + if (dontAnimate !== true) {
  1839 + _.animateSlide(slideLeft, function() {
  1840 + _.postSlide(targetSlide);
  1841 + });
  1842 + } else {
  1843 + _.postSlide(targetSlide);
  1844 + }
  1845 + }
  1846 + return;
  1847 + }
  1848 +
  1849 + if (_.options.autoplay === true) {
  1850 + clearInterval(_.autoPlayTimer);
  1851 + }
  1852 +
  1853 + if (targetSlide < 0) {
  1854 + if (_.slideCount % _.options.slidesToScroll !== 0) {
  1855 + animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll);
  1856 + } else {
  1857 + animSlide = _.slideCount + targetSlide;
  1858 + }
  1859 + } else if (targetSlide >= _.slideCount) {
  1860 + if (_.slideCount % _.options.slidesToScroll !== 0) {
  1861 + animSlide = 0;
  1862 + } else {
  1863 + animSlide = targetSlide - _.slideCount;
  1864 + }
  1865 + } else {
  1866 + animSlide = targetSlide;
  1867 + }
  1868 +
  1869 + _.animating = true;
  1870 +
  1871 + _.$slider.trigger("beforeChange", [_, _.currentSlide, animSlide]);
  1872 +
  1873 + oldSlide = _.currentSlide;
  1874 + _.currentSlide = animSlide;
  1875 +
  1876 + _.setSlideClasses(_.currentSlide);
  1877 +
  1878 + _.updateDots();
  1879 + _.updateArrows();
  1880 +
  1881 + if (_.options.fade === true) {
  1882 + if (dontAnimate !== true) {
  1883 + _.fadeSlide(animSlide, function() {
  1884 + _.postSlide(animSlide);
  1885 + });
  1886 + } else {
  1887 + _.postSlide(animSlide);
  1888 + }
  1889 + _.animateHeight();
  1890 + return;
  1891 + }
  1892 +
  1893 + if (dontAnimate !== true) {
  1894 + _.animateSlide(targetLeft, function() {
  1895 + _.postSlide(animSlide);
  1896 + });
  1897 + } else {
  1898 + _.postSlide(animSlide);
  1899 + }
  1900 +
  1901 + };
  1902 +
  1903 + Slick.prototype.startLoad = function() {
  1904 +
  1905 + var _ = this;
  1906 +
  1907 + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
  1908 +
  1909 + _.$prevArrow.hide();
  1910 + _.$nextArrow.hide();
  1911 +
  1912 + }
  1913 +
  1914 + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
  1915 +
  1916 + _.$dots.hide();
  1917 +
  1918 + }
  1919 +
  1920 + _.$slider.addClass('slick-loading');
  1921 +
  1922 + };
  1923 +
  1924 + Slick.prototype.swipeDirection = function() {
  1925 +
  1926 + var xDist, yDist, r, swipeAngle, _ = this;
  1927 +
  1928 + xDist = _.touchObject.startX - _.touchObject.curX;
  1929 + yDist = _.touchObject.startY - _.touchObject.curY;
  1930 + r = Math.atan2(yDist, xDist);
  1931 +
  1932 + swipeAngle = Math.round(r * 180 / Math.PI);
  1933 + if (swipeAngle < 0) {
  1934 + swipeAngle = 360 - Math.abs(swipeAngle);
  1935 + }
  1936 +
  1937 + if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
  1938 + return (_.options.rtl === false ? 'left' : 'right');
  1939 + }
  1940 + if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
  1941 + return (_.options.rtl === false ? 'left' : 'right');
  1942 + }
  1943 + if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
  1944 + return (_.options.rtl === false ? 'right' : 'left');
  1945 + }
  1946 + if (_.options.verticalScrolling === true) {
  1947 + if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
  1948 + return 'left';
  1949 + } else {
  1950 + return 'right';
  1951 + }
  1952 + }
  1953 +
  1954 + return 'vertical';
  1955 +
  1956 + };
  1957 +
  1958 + Slick.prototype.swipeEnd = function(event) {
  1959 +
  1960 + var _ = this,
  1961 + slideCount;
  1962 +
  1963 + _.dragging = false;
  1964 +
  1965 + _.shouldClick = (_.touchObject.swipeLength > 10) ? false : true;
  1966 +
  1967 + if (_.touchObject.curX === undefined) {
  1968 + return false;
  1969 + }
  1970 +
  1971 + if (_.touchObject.edgeHit === true) {
  1972 + _.$slider.trigger("edge", [_, _.swipeDirection()]);
  1973 + }
  1974 +
  1975 + if (_.touchObject.swipeLength >= _.touchObject.minSwipe) {
  1976 +
  1977 + switch (_.swipeDirection()) {
  1978 + case 'left':
  1979 + slideCount = _.options.swipeToSlide ? _.checkNavigable(_.currentSlide + _.getSlideCount()) : _.currentSlide + _.getSlideCount();
  1980 + _.slideHandler(slideCount);
  1981 + _.currentDirection = 0;
  1982 + _.touchObject = {};
  1983 + _.$slider.trigger("swipe", [_, "left"]);
  1984 + break;
  1985 +
  1986 + case 'right':
  1987 + slideCount = _.options.swipeToSlide ? _.checkNavigable(_.currentSlide - _.getSlideCount()) : _.currentSlide - _.getSlideCount();
  1988 + _.slideHandler(slideCount);
  1989 + _.currentDirection = 1;
  1990 + _.touchObject = {};
  1991 + _.$slider.trigger("swipe", [_, "right"]);
  1992 + break;
  1993 + }
  1994 + } else {
  1995 + if (_.touchObject.startX !== _.touchObject.curX) {
  1996 + _.slideHandler(_.currentSlide);
  1997 + _.touchObject = {};
  1998 + }
  1999 + }
  2000 +
  2001 + };
  2002 +
  2003 + Slick.prototype.swipeHandler = function(event) {
  2004 +
  2005 + var _ = this;
  2006 +
  2007 + if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) {
  2008 + return;
  2009 + } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) {
  2010 + return;
  2011 + }
  2012 +
  2013 + _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ?
  2014 + event.originalEvent.touches.length : 1;
  2015 +
  2016 + _.touchObject.minSwipe = _.listWidth / _.options
  2017 + .touchThreshold;
  2018 +
  2019 + if (_.options.verticalScrolling === true) {
  2020 + _.touchObject.minSwipe = _.listHeight / _.options
  2021 + .touchThreshold;
  2022 + }
  2023 +
  2024 + switch (event.data.action) {
  2025 +
  2026 + case 'start':
  2027 + _.swipeStart(event);
  2028 + break;
  2029 +
  2030 + case 'move':
  2031 + _.swipeMove(event);
  2032 + break;
  2033 +
  2034 + case 'end':
  2035 + _.swipeEnd(event);
  2036 + break;
  2037 +
  2038 + }
  2039 +
  2040 + };
  2041 +
  2042 + Slick.prototype.swipeMove = function(event) {
  2043 +
  2044 + var _ = this,
  2045 + edgeWasHit = false,
  2046 + curLeft, swipeDirection, swipeLength, positionOffset, touches;
  2047 +
  2048 + touches = event.originalEvent !== undefined ? event.originalEvent.touches : null;
  2049 +
  2050 + if (!_.dragging || touches && touches.length !== 1) {
  2051 + return false;
  2052 + }
  2053 +
  2054 + curLeft = _.getLeft(_.currentSlide);
  2055 +
  2056 + _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX;
  2057 + _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY;
  2058 +
  2059 + _.touchObject.swipeLength = Math.round(Math.sqrt(
  2060 + Math.pow(_.touchObject.curX - _.touchObject.startX, 2)));
  2061 +
  2062 + if (_.options.verticalScrolling === true) {
  2063 + _.touchObject.swipeLength = Math.round(Math.sqrt(
  2064 + Math.pow(_.touchObject.curY - _.touchObject.startY, 2)));
  2065 + }
  2066 +
  2067 + swipeDirection = _.swipeDirection();
  2068 +
  2069 + if (swipeDirection === 'vertical') {
  2070 + return;
  2071 + }
  2072 +
  2073 + if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) {
  2074 + event.preventDefault();
  2075 + }
  2076 +
  2077 + positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1);
  2078 + if (_.options.verticalScrolling === true) {
  2079 + positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1;
  2080 + }
  2081 +
  2082 +
  2083 + swipeLength = _.touchObject.swipeLength;
  2084 +
  2085 + _.touchObject.edgeHit = false;
  2086 +
  2087 + if (_.options.infinite === false) {
  2088 + if ((_.currentSlide === 0 && swipeDirection === "right") || (_.currentSlide >= _.getDotCount() && swipeDirection === "left")) {
  2089 + swipeLength = _.touchObject.swipeLength * _.options.edgeFriction;
  2090 + _.touchObject.edgeHit = true;
  2091 + }
  2092 + }
  2093 +
  2094 + if (_.options.vertical === false) {
  2095 + _.swipeLeft = curLeft + swipeLength * positionOffset;
  2096 + } else {
  2097 + _.swipeLeft = curLeft + (swipeLength * (_.$list.height() / _.listWidth)) * positionOffset;
  2098 + }
  2099 + if (_.options.verticalScrolling === true) {
  2100 + _.swipeLeft = curLeft + swipeLength * positionOffset;
  2101 + }
  2102 +
  2103 + if (_.options.fade === true || _.options.touchMove === false) {
  2104 + return false;
  2105 + }
  2106 +
  2107 + if (_.animating === true) {
  2108 + _.swipeLeft = null;
  2109 + return false;
  2110 + }
  2111 +
  2112 + _.setCSS(_.swipeLeft);
  2113 +
  2114 + };
  2115 +
  2116 + Slick.prototype.swipeStart = function(event) {
  2117 +
  2118 + var _ = this,
  2119 + touches;
  2120 +
  2121 + if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) {
  2122 + _.touchObject = {};
  2123 + return false;
  2124 + }
  2125 +
  2126 + if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) {
  2127 + touches = event.originalEvent.touches[0];
  2128 + }
  2129 +
  2130 + _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX;
  2131 + _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY;
  2132 +
  2133 + _.dragging = true;
  2134 +
  2135 + };
  2136 +
  2137 + Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function() {
  2138 +
  2139 + var _ = this;
  2140 +
  2141 + if (_.$slidesCache !== null) {
  2142 +
  2143 + _.unload();
  2144 +
  2145 + _.$slideTrack.children(this.options.slide).detach();
  2146 +
  2147 + _.$slidesCache.appendTo(_.$slideTrack);
  2148 +
  2149 + _.reinit();
  2150 +
  2151 + }
  2152 +
  2153 + };
  2154 +
  2155 + Slick.prototype.unload = function() {
  2156 +
  2157 + var _ = this;
  2158 +
  2159 + $('.slick-cloned', _.$slider).remove();
  2160 + if (_.$dots) {
  2161 + _.$dots.remove();
  2162 + }
  2163 + if (_.$prevArrow && (typeof _.options.prevArrow !== 'object')) {
  2164 + _.$prevArrow.remove();
  2165 + }
  2166 + if (_.$nextArrow && (typeof _.options.nextArrow !== 'object')) {
  2167 + _.$nextArrow.remove();
  2168 + }
  2169 + _.$slides.removeClass('slick-slide slick-active slick-visible').attr("aria-hidden", "true").css('width', '');
  2170 +
  2171 + };
  2172 +
  2173 + Slick.prototype.unslick = function() {
  2174 +
  2175 + var _ = this;
  2176 + _.destroy();
  2177 +
  2178 + };
  2179 +
  2180 + Slick.prototype.updateArrows = function() {
  2181 +
  2182 + var _ = this,
  2183 + centerOffset;
  2184 +
  2185 + centerOffset = Math.floor(_.options.slidesToShow / 2);
  2186 +
  2187 + if (_.options.arrows === true && _.options.infinite !==
  2188 + true && _.slideCount > _.options.slidesToShow) {
  2189 + _.$prevArrow.removeClass('slick-disabled');
  2190 + _.$nextArrow.removeClass('slick-disabled');
  2191 + if (_.currentSlide === 0) {
  2192 + _.$prevArrow.addClass('slick-disabled');
  2193 + _.$nextArrow.removeClass('slick-disabled');
  2194 + } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) {
  2195 + _.$nextArrow.addClass('slick-disabled');
  2196 + _.$prevArrow.removeClass('slick-disabled');
  2197 + } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) {
  2198 + _.$nextArrow.addClass('slick-disabled');
  2199 + _.$prevArrow.removeClass('slick-disabled');
  2200 + }
  2201 + }
  2202 +
  2203 + };
  2204 +
  2205 + Slick.prototype.updateDots = function() {
  2206 +
  2207 + var _ = this;
  2208 +
  2209 + if (_.$dots !== null) {
  2210 +
  2211 + _.$dots.find('li').removeClass('slick-active').attr("aria-hidden", "true");
  2212 + _.$dots.find('li').eq(Math.floor(_.currentSlide / _.options.slidesToScroll)).addClass('slick-active').attr("aria-hidden", "false");
  2213 +
  2214 + }
  2215 +
  2216 + };
  2217 +
  2218 + Slick.prototype.visibility = function() {
  2219 +
  2220 + var _ = this;
  2221 +
  2222 + if (document[_.hidden]) {
  2223 + _.paused = true;
  2224 + _.autoPlayClear();
  2225 + } else {
  2226 + _.paused = false;
  2227 + _.autoPlay();
  2228 + }
  2229 +
  2230 + };
  2231 +
  2232 + $.fn.slick = function() {
  2233 + var _ = this,
  2234 + opt = arguments[0],
  2235 + args = Array.prototype.slice.call(arguments, 1),
  2236 + l = _.length,
  2237 + i = 0,
  2238 + ret;
  2239 + for (i; i < l; i++) {
  2240 + if (typeof opt == 'object' || typeof opt == 'undefined')
  2241 + _[i].slick = new Slick(_[i], opt);
  2242 + else
  2243 + ret = _[i].slick[opt].apply(_[i].slick, args);
  2244 + if (typeof ret != 'undefined') return ret;
  2245 + }
  2246 + return _;
  2247 + };
  2248 +
  2249 +}));
public/stylesheets/application.css
@@ -1795,23 +1795,6 @@ a.button.disabled, input.disabled { @@ -1795,23 +1795,6 @@ a.button.disabled, input.disabled {
1795 .invisible-block a.icon-button { 1795 .invisible-block a.icon-button {
1796 position: relative; 1796 position: relative;
1797 } 1797 }
1798 -/************************************************  
1799 - * the handles to where you can drag the blocks *  
1800 - ************************************************/  
1801 -  
1802 -.block-target {  
1803 - padding: 2px;  
1804 - background: #ffd;  
1805 - margin-bottom: 5px;  
1806 - opacity: 0.8;  
1807 - filter: alpha(opacity=80);  
1808 -}  
1809 -.block-target-hover {  
1810 - background: #ffd;  
1811 - border: 1px solid #000;  
1812 - height: 30px;  
1813 - box-shadow: 0 0 15px #888 inset;  
1814 -}  
1815 /************************************************************* 1798 /*************************************************************
1816 * put borders around boxes and blocks when organizing boxes * 1799 * put borders around boxes and blocks when organizing boxes *
1817 *************************************************************/ 1800 *************************************************************/
@@ -1820,15 +1803,6 @@ a.button.disabled, input.disabled { @@ -1820,15 +1803,6 @@ a.button.disabled, input.disabled {
1820 background-repeat: no-repeat; 1803 background-repeat: no-repeat;
1821 background-position: top right; 1804 background-position: top right;
1822 } 1805 }
1823 -#box-organizer div.box-1 {  
1824 - background-image: url(../images/blocks/1.png);  
1825 -}  
1826 -#box-organizer div.box-2 {  
1827 - background-image: url(../images/blocks/2.png);  
1828 -}  
1829 -#box-organizer div.box-3 {  
1830 - background-image: url(../images/blocks/3.png);  
1831 -}  
1832 #box-organizer .block { 1806 #box-organizer .block {
1833 cursor: move; 1807 cursor: move;
1834 } 1808 }
public/stylesheets/block-store.css 0 → 100644
@@ -0,0 +1,154 @@ @@ -0,0 +1,154 @@
  1 +/************************************************
  2 + * the handles to where you can drag the blocks *
  3 + ************************************************/
  4 +
  5 +.block-target {
  6 + padding: 2px;
  7 + background: #81FF9B;
  8 + margin-bottom: 5px;
  9 + opacity: 0.8;
  10 + visibility: hidden;
  11 + height: 0;
  12 + font-size: 20px;
  13 + font-weight: bold;
  14 + color: white;
  15 + text-align: center;
  16 +}
  17 +.block-target-hover {
  18 + border: 1px solid #000;
  19 + box-shadow: 0 0 15px #888 inset;
  20 + opacity: 1;
  21 +}
  22 +.shadow .block-target-hover, .shadow .block-target-active {
  23 + visibility: visible;
  24 + height: 30px;
  25 +}
  26 +
  27 +/************************************************
  28 + * block store styles
  29 + ************************************************/
  30 +#content #block-store .block-type {
  31 + position: relative;
  32 + border: 0px solid #AAA;
  33 + margin: 4px 0;
  34 + padding: 0;
  35 + text-align: center;
  36 + height: auto;
  37 + float: none;
  38 + display: inline-block;
  39 + overflow: hidden;
  40 + width: 112px;
  41 + cursor: move;
  42 + vertical-align: top;
  43 +}
  44 +#block-store .block-type:hover {
  45 + box-shadow: 0px 0px 0px 2px #FFF, 0px 0px 0px 2px #FFF, 0px 0px 10px rgba(0,0,0,0.6);
  46 + outline: none;
  47 +}
  48 +#block-store .block-type:hover .button-bar {
  49 + display: inline;
  50 +}
  51 +#block-store .button-bar {
  52 + margin: 0;
  53 + display: none;
  54 + position: absolute;
  55 + right: 0%;
  56 + border: 0px solid #AAA;
  57 + margin: 0px;
  58 + padding: 0px;
  59 +}
  60 +#block-store .button-bar .icon-help {
  61 + font-size: 0;
  62 + width: 0;
  63 +}
  64 +
  65 +#block-store .block-type .block-type-icon {
  66 + margin-right: auto;
  67 + margin-left: auto;
  68 +}
  69 +#block-store-draggables .block-type, #block-store-draggables .block, #block-store-draggables .block-type-icon, #block-store-draggables .ui-draggable-dragging {
  70 + display: inline-block;
  71 + height: auto;
  72 + z-index: 100;
  73 +}
  74 +#block-store-draggables .block-type .button-bar {
  75 + visibility: hidden;
  76 +}
  77 +#box-organizer.shadow .block {
  78 + opacity: 0.2;
  79 +}
  80 +#box-organizer.shadow .ui-draggable-dragging {
  81 + opacity: 1;
  82 + border: 5px solid red;
  83 + box-shadow: 0px 0px 10px 2px red, inset 0px 0px 10px 2px red;
  84 +}
  85 +#box-organizer .block {
  86 + transition: opacity 0.3s ease-in-out;
  87 +}
  88 +
  89 +/************************************************
  90 + * block info styles
  91 + ************************************************/
  92 +#block-info-container {
  93 + width: 770px;
  94 + padding: 15px;
  95 + color: #444;
  96 +}
  97 +
  98 +#block-info-container #block-info-icon {
  99 + float: left;
  100 + padding-right: 10px;
  101 +}
  102 +
  103 +#block-info-container #block-info-header {
  104 + float: left;
  105 +}
  106 +
  107 +#block-info-container #block-info-header .block-type-icon{
  108 + float: left;
  109 +}
  110 +
  111 +#block-info-container #block-info-header h1 {
  112 + margin: 0;
  113 + font-weight: normal;
  114 + font-family: "Arial Black", Liberation Sans, Arial, sans-serif;
  115 + margin-left: 5px;
  116 + white-space: nowrap;
  117 +}
  118 +
  119 +#block-info-container #block-info-header p{
  120 + margin-left: 55px;
  121 +}
  122 +
  123 +
  124 +#block-info-container h2 {
  125 + margin: 0;
  126 + margin-top: 10px;
  127 + font-weight: normal;
  128 + font-family: "Arial Black", Liberation Sans, Arial, sans-serif;
  129 +}
  130 +
  131 +#block-info-container p {
  132 + margin: 0;
  133 +}
  134 +
  135 +#block-info-images {
  136 + clear: both;
  137 + overflow-x: auto;
  138 + padding-top: 15px;
  139 +}
  140 +
  141 +#block-info-images ul{
  142 + margin: 0px;
  143 + padding: 0px;
  144 +}
  145 +#block-info-images li{
  146 + list-style: none;
  147 + display: inline;
  148 +
  149 +}
  150 +
  151 +
  152 +#block-info-description {
  153 + margin-top: 20px;
  154 +}
public/stylesheets/slick-theme.css 0 → 100644
@@ -0,0 +1,201 @@ @@ -0,0 +1,201 @@
  1 +@charset 'UTF-8';
  2 +/* Slider */
  3 +.slick-loading .slick-list
  4 +{
  5 + background: #fff url('./ajax-loader.gif') center center no-repeat;
  6 +}
  7 +
  8 +/* Icons */
  9 +@font-face
  10 +{
  11 + font-family: 'slick';
  12 + font-weight: normal;
  13 + font-style: normal;
  14 +
  15 + src: url('/fonts/slick.eot');
  16 + src: url('/fonts/slick.eot?#iefix') format('embedded-opentype'), url('/fonts/slick.woff') format('woff'), url('/fonts/slick.ttf') format('truetype'), url('/fonts/slick.svg#slick') format('svg');
  17 +}
  18 +/* Arrows */
  19 +.slick-prev,
  20 +.slick-next
  21 +{
  22 + font-size: 0;
  23 + line-height: 0;
  24 +
  25 + position: absolute;
  26 + top: 50%;
  27 +
  28 + display: block;
  29 +
  30 + width: 40px;
  31 + height: 40px;
  32 + margin-top: -10px;
  33 + padding: 0;
  34 +
  35 + cursor: pointer;
  36 +
  37 + color: transparent;
  38 + border: none;
  39 + outline: none;
  40 + background: transparent;
  41 +}
  42 +.slick-prev:hover,
  43 +.slick-prev:focus,
  44 +.slick-next:hover,
  45 +.slick-next:focus
  46 +{
  47 + color: transparent;
  48 + outline: none;
  49 + background: transparent;
  50 +}
  51 +.slick-prev:hover:before,
  52 +.slick-prev:focus:before,
  53 +.slick-next:hover:before,
  54 +.slick-next:focus:before
  55 +{
  56 + opacity: 1;
  57 +}
  58 +.slick-prev.slick-disabled:before,
  59 +.slick-next.slick-disabled:before
  60 +{
  61 + opacity: .25;
  62 +}
  63 +
  64 +.slick-prev:before,
  65 +.slick-next:before
  66 +{
  67 + font-family: 'slick';
  68 + font-size: 30px;
  69 + line-height: 1;
  70 +
  71 + opacity: .75;
  72 + color: rgb(174, 174, 174);
  73 +
  74 + -webkit-font-smoothing: antialiased;
  75 + -moz-osx-font-smoothing: grayscale;
  76 +}
  77 +
  78 +.slick-prev
  79 +{
  80 + left: -10px;
  81 +}
  82 +[dir='rtl'] .slick-prev
  83 +{
  84 + right: -10px;
  85 + left: auto;
  86 +}
  87 +.slick-prev:before
  88 +{
  89 + content: '←';
  90 +}
  91 +[dir='rtl'] .slick-prev:before
  92 +{
  93 + content: '→';
  94 +}
  95 +
  96 +.slick-next
  97 +{
  98 + right: -10px;
  99 +}
  100 +[dir='rtl'] .slick-next
  101 +{
  102 + right: auto;
  103 + left: -10px;
  104 +}
  105 +.slick-next:before
  106 +{
  107 + content: '→';
  108 +}
  109 +[dir='rtl'] .slick-next:before
  110 +{
  111 + content: '←';
  112 +}
  113 +
  114 +/* Dots */
  115 +.slick-slider
  116 +{
  117 + margin-bottom: 40px;
  118 +}
  119 +
  120 +.slick-dots
  121 +{
  122 + position: absolute;
  123 + bottom: -40px;
  124 +
  125 + display: block;
  126 +
  127 + width: 100%;
  128 + padding: 0;
  129 +
  130 + list-style: none;
  131 +
  132 + text-align: center;
  133 +}
  134 +.slick-dots li
  135 +{
  136 + position: relative;
  137 +
  138 + display: inline-block;
  139 +
  140 + width: 20px;
  141 + height: 20px;
  142 + margin: 0 5px;
  143 + padding: 0;
  144 +
  145 + cursor: pointer;
  146 +}
  147 +.slick-dots li button
  148 +{
  149 + font-size: 0;
  150 + line-height: 0;
  151 +
  152 + display: block;
  153 +
  154 + width: 20px;
  155 + height: 20px;
  156 + padding: 5px;
  157 +
  158 + cursor: pointer;
  159 +
  160 + color: transparent;
  161 + border: 0;
  162 + outline: none;
  163 + background: transparent;
  164 +}
  165 +.slick-dots li button:hover,
  166 +.slick-dots li button:focus
  167 +{
  168 + outline: none;
  169 +}
  170 +.slick-dots li button:hover:before,
  171 +.slick-dots li button:focus:before
  172 +{
  173 + opacity: 1;
  174 +}
  175 +.slick-dots li button:before
  176 +{
  177 + font-family: 'slick';
  178 + font-size: 6px;
  179 + line-height: 20px;
  180 +
  181 + position: absolute;
  182 + top: 0;
  183 + left: 0;
  184 +
  185 + width: 20px;
  186 + height: 20px;
  187 +
  188 + content: '•';
  189 + text-align: center;
  190 +
  191 + opacity: .25;
  192 + color: black;
  193 +
  194 + -webkit-font-smoothing: antialiased;
  195 + -moz-osx-font-smoothing: grayscale;
  196 +}
  197 +.slick-dots li.slick-active button:before
  198 +{
  199 + opacity: .75;
  200 + color: black;
  201 +}
public/stylesheets/slick.css 0 → 100644
@@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
  1 +/* Slider */
  2 +.slick-slider
  3 +{
  4 + position: relative;
  5 +
  6 + display: block;
  7 +
  8 + -moz-box-sizing: border-box;
  9 + box-sizing: border-box;
  10 +
  11 + -webkit-user-select: none;
  12 + -moz-user-select: none;
  13 + -ms-user-select: none;
  14 + user-select: none;
  15 +
  16 + -webkit-touch-callout: none;
  17 + -khtml-user-select: none;
  18 + -ms-touch-action: pan-y;
  19 + touch-action: pan-y;
  20 + -webkit-tap-highlight-color: transparent;
  21 +}
  22 +
  23 +.slick-list
  24 +{
  25 + position: relative;
  26 +
  27 + display: block;
  28 + overflow: hidden;
  29 +
  30 + margin: 0;
  31 + padding: 0;
  32 +}
  33 +.slick-list:focus
  34 +{
  35 + outline: none;
  36 +}
  37 +.slick-list.dragging
  38 +{
  39 + cursor: pointer;
  40 + cursor: hand;
  41 +}
  42 +
  43 +.slick-slider .slick-track,
  44 +.slick-slider .slick-list
  45 +{
  46 + -webkit-transform: translate3d(0, 0, 0);
  47 + -moz-transform: translate3d(0, 0, 0);
  48 + -ms-transform: translate3d(0, 0, 0);
  49 + -o-transform: translate3d(0, 0, 0);
  50 + transform: translate3d(0, 0, 0);
  51 +}
  52 +
  53 +.slick-track
  54 +{
  55 + position: relative;
  56 + top: 0;
  57 + left: 0;
  58 +
  59 + display: block;
  60 +}
  61 +.slick-track:before,
  62 +.slick-track:after
  63 +{
  64 + display: table;
  65 +
  66 + content: '';
  67 +}
  68 +.slick-track:after
  69 +{
  70 + clear: both;
  71 +}
  72 +.slick-loading .slick-track
  73 +{
  74 + visibility: hidden;
  75 +}
  76 +
  77 +.slick-slide
  78 +{
  79 + display: none;
  80 + float: left;
  81 +
  82 + height: 100%;
  83 + min-height: 1px;
  84 +}
  85 +[dir='rtl'] .slick-slide
  86 +{
  87 + float: right;
  88 +}
  89 +.slick-slide img
  90 +{
  91 + display: block;
  92 +}
  93 +.slick-slide.slick-loading img
  94 +{
  95 + display: none;
  96 +}
  97 +.slick-slide.dragging img
  98 +{
  99 + pointer-events: none;
  100 +}
  101 +.slick-initialized .slick-slide
  102 +{
  103 + display: block;
  104 +}
  105 +.slick-loading .slick-slide
  106 +{
  107 + visibility: hidden;
  108 +}
  109 +.slick-vertical .slick-slide
  110 +{
  111 + display: block;
  112 +
  113 + height: auto;
  114 +
  115 + border: 1px solid transparent;
  116 +}
0 \ No newline at end of file 117 \ No newline at end of file
test/functional/environment_design_controller_test.rb
@@ -165,14 +165,6 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -165,14 +165,6 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
165 assert_tag :tag => 'a', :attributes => {:href => '/admin'}, :child => {:tag => 'span', :content => "Back to control panel"} 165 assert_tag :tag => 'a', :attributes => {:href => '/admin'}, :child => {:tag => 'span', :content => "Back to control panel"}
166 end 166 end
167 167
168 - should 'render block types container to add/move block functionality' do  
169 - login_as(create_admin_user(Environment.default))  
170 - get :index  
171 -  
172 - assert_response :success  
173 - assert_tag :tag => 'div', :attributes => {:id => 'block-types-container'}  
174 - end  
175 -  
176 should 'a environment block plugin add new blocks for environments' do 168 should 'a environment block plugin add new blocks for environments' do
177 class CustomBlock1 < Block; end; 169 class CustomBlock1 < Block; end;
178 170
@@ -212,7 +204,7 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -212,7 +204,7 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
212 assert !@controller.available_blocks.include?(CustomBlock4) 204 assert !@controller.available_blocks.include?(CustomBlock4)
213 end 205 end
214 206
215 - should 'a block plugin add new blocks in any position' do 207 + should 'a block plugin add new blocks' do
216 class CustomBlock1 < Block; end; 208 class CustomBlock1 < Block; end;
217 class CustomBlock2 < Block; end; 209 class CustomBlock2 < Block; end;
218 class CustomBlock3 < Block; end; 210 class CustomBlock3 < Block; end;
@@ -242,17 +234,9 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -242,17 +234,9 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
242 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestBlockPlugin.new]) 234 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestBlockPlugin.new])
243 login_as(create_admin_user(Environment.default)) 235 login_as(create_admin_user(Environment.default))
244 get :index 236 get :index
245 -  
246 assert_response :success 237 assert_response :success
247 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock1)  
248 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock2)  
249 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock3)  
250 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock4)  
251 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock5)  
252 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock6)  
253 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock7)  
254 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock8)  
255 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock9) 238 +
  239 + (1..9).each {|i| assert_tag :tag => 'div', :attributes => { 'data-block-type' => "EnvironmentDesignControllerTest::CustomBlock#{i}" }}
256 end 240 end
257 241
258 should 'a block plugin cannot be listed for unspecified types' do 242 should 'a block plugin cannot be listed for unspecified types' do
@@ -285,14 +269,8 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -285,14 +269,8 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
285 get :index 269 get :index
286 assert_response :success 270 assert_response :success
287 271
288 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock1)  
289 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock2)  
290 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock3)  
291 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock4)  
292 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock5)  
293 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock6)  
294 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock7)  
295 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock8) 272 + [4, 8].each {|i| assert_tag :tag => 'div', :attributes => { 'data-block-type' => "EnvironmentDesignControllerTest::CustomBlock#{i}" }}
  273 + [1, 2, 3, 5, 6, 7].each {|i| assert_no_tag :tag => 'div', :attributes => { 'data-block-type' => "EnvironmentDesignControllerTest::CustomBlock#{i}" }}
296 end 274 end
297 275
298 should 'clone a block' do 276 should 'clone a block' do
@@ -338,21 +316,4 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -338,21 +316,4 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
338 assert_equal json_response, [] 316 assert_equal json_response, []
339 end 317 end
340 318
341 - should 'display all available blocks in groups' do  
342 - login_as(create_admin_user(Environment.default))  
343 - get :index  
344 - assert_select 'div.block-types-group', 2  
345 -  
346 - assert_select 'div.block-types-group' do |elements|  
347 - assert_select 'div.block-type', 14  
348 - end  
349 - end  
350 -  
351 - should 'paginate the block store with 7 elements per line' do  
352 - assert_equal 14, @controller.available_blocks.length  
353 - login_as(create_admin_user(Environment.default))  
354 - get :index  
355 - assert_select 'div.block-types-group', 2, "something wrong happens with the pagination of the block store"  
356 - end  
357 -  
358 end 319 end
test/functional/profile_design_controller_test.rb
@@ -78,29 +78,8 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -78,29 +78,8 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
78 ###################################################### 78 ######################################################
79 # BEGIN - tests for BoxOrganizerController features 79 # BEGIN - tests for BoxOrganizerController features
80 ###################################################### 80 ######################################################
81 -  
82 - def test_should_add_block_to_end_of_another_block  
83 - get :add_or_move_block, :profile => 'designtestuser', :id => "block-#{@b1.class.name}", :target => "end-of-box-#{@box2.id}"  
84 - @box2.reload  
85 - block = @box2.blocks.last  
86 -  
87 - assert_equal @b1.class.name, block.class.name  
88 - assert_equal @box2.blocks.size, block.position  
89 - end  
90 -  
91 - def test_should_add_block_to_begin_of_another_block  
92 - get :add_or_move_block, :profile => 'designtestuser', :id => "block-#{@b1.class.name}", :target => "before-block-#{@b4.id}"  
93 -  
94 - previous_position = @b4.position  
95 -  
96 - @b4.box.reload  
97 - @b4.reload  
98 -  
99 - assert_equal @b4.position, previous_position + 1  
100 - end  
101 -  
102 def test_should_move_block_to_the_end_of_another_block 81 def test_should_move_block_to_the_end_of_another_block
103 - get :add_or_move_block, :profile => 'designtestuser', :id => "block-#{@b1.id}", :target => "end-of-box-#{@box2.id}" 82 + get :move_block, :profile => 'designtestuser', :id => "block-#{@b1.id}", :target => "end-of-box-#{@box2.id}"
104 83
105 @b1.reload 84 @b1.reload
106 @box2.reload 85 @box2.reload
@@ -112,7 +91,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -112,7 +91,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
112 91
113 def test_should_move_block_to_the_middle_of_another_block 92 def test_should_move_block_to_the_middle_of_another_block
114 # block 4 is in box 2 93 # block 4 is in box 2
115 - get :add_or_move_block, :profile => 'designtestuser', :id => "block-#{@b1.id}", :target => "before-block-#{@b4.id}" 94 + get :move_block, :profile => 'designtestuser', :id => "block-#{@b1.id}", :target => "before-block-#{@b4.id}"
116 95
117 @b1.reload 96 @b1.reload
118 @b4.reload 97 @b4.reload
@@ -123,7 +102,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -123,7 +102,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
123 end 102 end
124 103
125 def test_block_can_be_moved_up 104 def test_block_can_be_moved_up
126 - get :add_or_move_block, :profile => 'designtestuser', :id => "block-#{@b4.id}", :target => "before-block-#{@b3.id}" 105 + get :move_block, :profile => 'designtestuser', :id => "block-#{@b4.id}", :target => "before-block-#{@b3.id}"
127 106
128 @b4.reload 107 @b4.reload
129 @b3.reload 108 @b3.reload
@@ -135,7 +114,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -135,7 +114,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
135 assert_equal [1,2,3], [@b3,@b4,@b5].map {|item| item.position} 114 assert_equal [1,2,3], [@b3,@b4,@b5].map {|item| item.position}
136 115
137 # b3 -> before b5 116 # b3 -> before b5
138 - get :add_or_move_block, :profile => 'designtestuser', :id => "block-#{@b3.id}", :target => "before-block-#{@b5.id}" 117 + get :move_block, :profile => 'designtestuser', :id => "block-#{@b3.id}", :target => "before-block-#{@b5.id}"
139 118
140 [@b3,@b4,@b5].each do |item| 119 [@b3,@b4,@b5].each do |item|
141 item.reload 120 item.reload
@@ -144,8 +123,13 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -144,8 +123,13 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
144 assert_equal [1,2,3], [@b4, @b3, @b5].map {|item| item.position} 123 assert_equal [1,2,3], [@b4, @b3, @b5].map {|item| item.position}
145 end 124 end
146 125
  126 + def test_move_block_should_redirect_when_not_called_via_ajax
  127 + get :move_block, :profile => 'designtestuser', :id => "block-#{@b3.id}", :target => "before-block-#{@b5.id}"
  128 + assert_redirected_to :action => 'index'
  129 + end
  130 +
147 def test_move_block_should_render_when_called_via_ajax 131 def test_move_block_should_render_when_called_via_ajax
148 - xml_http_request :get, :add_or_move_block, :profile => 'designtestuser', :id => "block-#{@b3.id}", :target => "before-block-#{@b5.id}" 132 + xml_http_request :get, :move_block, :profile => 'designtestuser', :id => "block-#{@b3.id}", :target => "before-block-#{@b5.id}"
149 assert_template 'move_block' 133 assert_template 'move_block'
150 end 134 end
151 135
@@ -185,7 +169,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -185,7 +169,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
185 end 169 end
186 end 170 end
187 171
188 - should 'a block plugin add new blocks in any position' do 172 + should 'a block plugin add new blocks' do
189 class CustomBlock1 < Block; end; 173 class CustomBlock1 < Block; end;
190 class CustomBlock2 < Block; end; 174 class CustomBlock2 < Block; end;
191 class CustomBlock3 < Block; end; 175 class CustomBlock3 < Block; end;
@@ -216,15 +200,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -216,15 +200,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
216 get :index, :profile => 'designtestuser' 200 get :index, :profile => 'designtestuser'
217 assert_response :success 201 assert_response :success
218 202
219 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock1)  
220 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock2)  
221 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock3)  
222 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock4)  
223 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock5)  
224 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock6)  
225 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock7)  
226 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock8)  
227 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock9) 203 + (1..9).each {|i| assert_tag :tag => 'div', :attributes => { 'data-block-type' => "ProfileDesignControllerTest::CustomBlock#{i}" } }
228 end 204 end
229 205
230 should 'a block plugin cannot be listed for unspecified types' do 206 should 'a block plugin cannot be listed for unspecified types' do
@@ -256,14 +232,8 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -256,14 +232,8 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
256 get :index, :profile => 'designtestuser' 232 get :index, :profile => 'designtestuser'
257 assert_response :success 233 assert_response :success
258 234
259 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock1)  
260 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock2)  
261 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock3)  
262 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock4)  
263 - assert @controller.instance_variable_get('@available_blocks').include?(CustomBlock5)  
264 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock6)  
265 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock7)  
266 - assert !@controller.instance_variable_get('@available_blocks').include?(CustomBlock8) 235 + [1, 5].each {|i| assert_tag :tag => 'div', :attributes => { 'data-block-type' => "ProfileDesignControllerTest::CustomBlock#{i}" }}
  236 + [2, 3, 4, 6, 7, 8].each {|i| assert_no_tag :tag => 'div', :attributes => { 'data-block-type' => "ProfileDesignControllerTest::CustomBlock#{i}" }}
267 end 237 end
268 238
269 should 'not edit main block with never option' do 239 should 'not edit main block with never option' do
@@ -305,12 +275,6 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -305,12 +275,6 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
305 assert_equal json_response.include?("/{profile}/"+article3.path), false 275 assert_equal json_response.include?("/{profile}/"+article3.path), false
306 end 276 end
307 277
308 - should 'display popup for show block information' do  
309 - get :show_block_type_info, :profile => 'designtestuser', :type => ArticleBlock.name  
310 - assert_response :success  
311 - assert_no_tag :tag => 'body'  
312 - end  
313 -  
314 ###################################################### 278 ######################################################
315 # END - tests for BoxOrganizerController features 279 # END - tests for BoxOrganizerController features
316 ###################################################### 280 ######################################################
@@ -319,6 +283,21 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -319,6 +283,21 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
319 # BEGIN - tests for ProfileDesignController features 283 # BEGIN - tests for ProfileDesignController features
320 ###################################################### 284 ######################################################
321 285
  286 + should 'actually add a new block' do
  287 + assert_difference 'Block.count' do
  288 + post :move_block, :profile => 'designtestuser', :target => "end-of-box-#{@box1.id}", :type => RecentDocumentsBlock.name
  289 + assert_redirected_to :action => 'index'
  290 + end
  291 + end
  292 +
  293 + should 'not allow to create unknown types' do
  294 + assert_no_difference 'Block.count' do
  295 + assert_raise ArgumentError do
  296 + post :move_block, :profile => 'designtestuser', :box_id => @box1.id, :type => "PleaseLetMeCrackYourSite"
  297 + end
  298 + end
  299 + end
  300 +
322 should 'provide edit screen for blocks' do 301 should 'provide edit screen for blocks' do
323 get :edit, :profile => 'designtestuser', :id => @b1.id 302 get :edit, :profile => 'designtestuser', :id => @b1.id
324 assert_template 'edit' 303 assert_template 'edit'
@@ -393,7 +372,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -393,7 +372,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
393 372
394 get :index, :profile => 'test_ent' 373 get :index, :profile => 'test_ent'
395 374
396 - assert_no_tag :tag => 'input', :attributes => {:type => 'radio', :value => 'ProductsBlock'} 375 + assert_no_tag :tag => 'div', :attributes => { 'data-block-type' => 'ProductsBlock' }
397 end 376 end
398 377
399 should 'create back link to profile control panel' do 378 should 'create back link to profile control panel' do
@@ -408,17 +387,17 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -408,17 +387,17 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
408 should 'offer to create blog archives block only if has blog' do 387 should 'offer to create blog archives block only if has blog' do
409 holder.articles << Blog.new(:name => 'Blog test', :profile => holder) 388 holder.articles << Blog.new(:name => 'Blog test', :profile => holder)
410 get :index, :profile => 'designtestuser' 389 get :index, :profile => 'designtestuser'
411 - assert_tag :tag => 'div', :attributes => { :id => 'block-BlogArchivesBlock' } 390 + assert_tag :tag => 'div', :attributes => { 'data-block-type' => 'BlogArchivesBlock' }
412 end 391 end
413 392
414 should 'not offer to create blog archives block if user dont have blog' do 393 should 'not offer to create blog archives block if user dont have blog' do
415 get :index, :profile => 'designtestuser' 394 get :index, :profile => 'designtestuser'
416 - assert_no_tag :tag => 'div', :attributes => { :id => 'block-BlogArchivesBlock' } 395 + assert_no_tag :tag => 'div', :attributes => { 'data-block-type' => 'BlogArchivesBlock' }
417 end 396 end
418 397
419 should 'offer to create feed reader block' do 398 should 'offer to create feed reader block' do
420 get :index, :profile => 'designtestuser' 399 get :index, :profile => 'designtestuser'
421 - assert_tag :tag => 'div', :attributes => { :id => 'block-FeedReaderBlock' } 400 + assert_tag :tag => 'div', :attributes => { 'data-block-type' => 'FeedReaderBlock' }
422 end 401 end
423 402
424 should 'be able to edit FeedReaderBlock' do 403 should 'be able to edit FeedReaderBlock' do
@@ -528,15 +507,17 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -528,15 +507,17 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
528 end 507 end
529 508
530 should 'allow admins to add RawHTMLBlock' do 509 should 'allow admins to add RawHTMLBlock' do
531 - profile.stubs(:is_admin?).with(anything).returns(true) 510 + profile.stubs(:is_admin?).returns(true)
532 @controller.stubs(:user).returns(profile) 511 @controller.stubs(:user).returns(profile)
533 get :index, :profile => 'designtestuser' 512 get :index, :profile => 'designtestuser'
534 - assert_tag :tag => 'div', :attributes => { :id => 'block-RawHTMLBlock' } 513 + assert_tag :tag => 'div', :attributes => { 'data-block-type' => 'RawHTMLBlock' }
535 end 514 end
536 515
537 should 'not allow normal users to add RawHTMLBlock' do 516 should 'not allow normal users to add RawHTMLBlock' do
  517 + profile.stubs(:is_admin?).returns(false)
  518 + @controller.stubs(:user).returns(profile)
538 get :index, :profile => 'designtestuser' 519 get :index, :profile => 'designtestuser'
539 - assert_no_tag :tag => 'div', :attributes => { :id => 'block-RawHTMLBlock' } 520 + assert_no_tag :tag => 'div', :attributes => { 'data-block-type' => 'RawHTMLBlock' }
540 end 521 end
541 522
542 should 'editing article block displays right selected article' do 523 should 'editing article block displays right selected article' do