refinerycms-blog 2.1.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -23
  3. data/Gemfile +15 -7
  4. data/Rakefile +0 -1
  5. data/app/assets/javascripts/refinery/blog/backend.js +18 -59
  6. data/app/assets/stylesheets/refinery/blog/backend.css.scss +4 -55
  7. data/app/assets/stylesheets/refinery/blog/frontend.css.scss +2 -2
  8. data/app/controllers/refinery/blog/admin/categories_controller.rb +6 -0
  9. data/app/controllers/refinery/blog/admin/posts_controller.rb +25 -3
  10. data/app/controllers/refinery/blog/blog_controller.rb +31 -5
  11. data/app/controllers/refinery/blog/categories_controller.rb +10 -3
  12. data/app/controllers/refinery/blog/posts_controller.rb +16 -6
  13. data/app/helpers/refinery/blog/controller_helper.rb +1 -22
  14. data/app/models/refinery/blog/categorization.rb +0 -1
  15. data/app/models/refinery/blog/category.rb +3 -6
  16. data/app/models/refinery/blog/comment.rb +15 -17
  17. data/app/models/refinery/blog/post.rb +44 -43
  18. data/app/views/refinery/blog/admin/_submenu.html.erb +1 -3
  19. data/app/views/refinery/blog/admin/categories/_category.html.erb +14 -5
  20. data/app/views/refinery/blog/admin/posts/_form.html.erb +13 -6
  21. data/app/views/refinery/blog/admin/posts/_form_part.html.erb +1 -1
  22. data/app/views/refinery/blog/admin/posts/_post.html.erb +12 -5
  23. data/app/views/refinery/blog/admin/posts/_teaser_part.html.erb +1 -1
  24. data/app/views/refinery/blog/posts/index.html.erb +2 -2
  25. data/app/views/refinery/blog/shared/_categories.html.erb +3 -3
  26. data/app/views/refinery/shared/admin/_autocomplete.html.erb +45 -0
  27. data/bin/rails +5 -0
  28. data/bin/refinerycms +62 -0
  29. data/changelog.md +4 -1
  30. data/config/locales/cs.yml +2 -2
  31. data/config/locales/en.yml +3 -0
  32. data/config/locales/fr.yml +6 -4
  33. data/config/locales/nb.yml +154 -14
  34. data/config/locales/nl.yml +21 -0
  35. data/config/locales/pl.yml +2 -2
  36. data/config/locales/ru.yml +25 -14
  37. data/config/locales/zh-CN.yml +32 -1
  38. data/config/locales/zh-TW.yml +160 -0
  39. data/config/routes.rb +6 -3
  40. data/db/migrate/20110803223522_create_blog_structure.rb +4 -4
  41. data/db/migrate/20120531113632_delete_cached_slugs.rb +2 -2
  42. data/db/migrate/20140622132537_add_missing_unique_indices.acts_as_taggable_on_engine.rb +20 -0
  43. data/db/migrate/20140622132538_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +15 -0
  44. data/db/seeds.rb +4 -4
  45. data/lib/refinery/blog.rb +1 -1
  46. data/lib/refinery/blog/configuration.rb +1 -1
  47. data/lib/refinery/blog/engine.rb +8 -3
  48. data/readme.md +21 -6
  49. data/refinerycms-blog.gemspec +9 -7
  50. data/script/rails +1 -3
  51. data/spec/controllers/refinery/blog/admin/comments_controller_spec.rb +23 -19
  52. data/spec/controllers/refinery/blog/admin/posts_controller_spec.rb +35 -0
  53. data/spec/controllers/refinery/blog/posts_controller_spec.rb +3 -3
  54. data/spec/factories/blog_posts.rb +1 -1
  55. data/spec/factories/user.rb +27 -0
  56. data/spec/features/refinery/blog/admin/categories_spec.rb +106 -104
  57. data/spec/features/refinery/blog/admin/comments_spec.rb +18 -18
  58. data/spec/features/refinery/blog/admin/menu_spec.rb +14 -8
  59. data/spec/features/refinery/blog/admin/posts_spec.rb +99 -86
  60. data/spec/features/refinery/blog/categories_spec.rb +20 -18
  61. data/spec/features/refinery/blog/posts_spec.rb +128 -124
  62. data/spec/helpers/refinery/blog/posts_helper_spec.rb +13 -13
  63. data/spec/lib/refinery/blog/engine_spec.rb +1 -11
  64. data/spec/models/refinery/blog/category_spec.rb +10 -10
  65. data/spec/models/refinery/blog/comment_spec.rb +3 -3
  66. data/spec/models/refinery/blog/post_spec.rb +59 -33
  67. data/spec/spec_helper.rb +2 -3
  68. metadata +75 -50
  69. data/app/assets/images/refinery/blog/icons/add.png +0 -0
  70. data/app/assets/images/refinery/blog/icons/cog.png +0 -0
  71. data/app/assets/images/refinery/blog/icons/comment.png +0 -0
  72. data/app/assets/images/refinery/blog/icons/comment_cross.png +0 -0
  73. data/app/assets/images/refinery/blog/icons/comment_tick.png +0 -0
  74. data/app/assets/images/refinery/blog/icons/comments.png +0 -0
  75. data/app/assets/images/refinery/blog/icons/down.gif +0 -0
  76. data/app/assets/images/refinery/blog/icons/folder.png +0 -0
  77. data/app/assets/images/refinery/blog/icons/folder_add.png +0 -0
  78. data/app/assets/images/refinery/blog/icons/folder_edit.png +0 -0
  79. data/app/assets/images/refinery/blog/icons/page.png +0 -0
  80. data/app/assets/images/refinery/blog/icons/page_add.png +0 -0
  81. data/app/assets/images/refinery/blog/icons/page_copy.png +0 -0
  82. data/app/assets/images/refinery/blog/icons/up.gif +0 -0
  83. data/spec/helpers/refinery/blog/controller_helper_spec.rb +0 -27
  84. data/todo.md +0 -5
@@ -2,28 +2,7 @@ module Refinery
2
2
  module Blog
3
3
  module ControllerHelper
4
4
 
5
- protected
6
-
7
- def find_blog_post
8
- unless (@post = Refinery::Blog::Post.with_globalize.find(params[:id])).try(:live?)
9
- if refinery_user? and current_refinery_user.authorized_plugins.include?("refinerycms_blog")
10
- @post = Refinery::Blog::Post.find(params[:id])
11
- else
12
- error_404
13
- end
14
- end
15
- end
16
-
17
- def find_all_blog_posts
18
- @posts = Refinery::Blog::Post.live.includes(:comments, :categories).with_globalize.page(params[:page])
19
- end
20
-
21
- def find_tags
22
- @tags = Refinery::Blog::Post.live.tag_counts_on(:tags)
23
- end
24
- def find_all_blog_categories
25
- @categories = Refinery::Blog::Category.translated
26
- end
5
+
27
6
  end
28
7
  end
29
8
  end
@@ -6,7 +6,6 @@ module Refinery
6
6
  belongs_to :blog_post, :class_name => 'Refinery::Blog::Post', :foreign_key => :blog_post_id
7
7
  belongs_to :blog_category, :class_name => 'Refinery::Blog::Category', :foreign_key => :blog_category_id
8
8
 
9
- attr_accessible :blog_category_id, :blog_post_id
10
9
  end
11
10
  end
12
11
  end
@@ -1,10 +1,10 @@
1
1
  module Refinery
2
2
  module Blog
3
3
  class Category < ActiveRecord::Base
4
+ extend FriendlyId
4
5
 
5
6
  translates :title, :slug
6
7
 
7
- extend FriendlyId
8
8
  friendly_id :title, :use => [:slugged, :globalize]
9
9
 
10
10
  has_many :categorizations, :dependent => :destroy, :foreign_key => :blog_category_id
@@ -12,11 +12,8 @@ module Refinery
12
12
 
13
13
  validates :title, :presence => true, :uniqueness => true
14
14
 
15
- attr_accessible :title
16
- attr_accessor :locale
17
-
18
- class Translation
19
- attr_accessible :locale
15
+ def self.by_title(title)
16
+ joins(:translations).find_by(title: title)
20
17
  end
21
18
 
22
19
  def self.translated
@@ -1,31 +1,29 @@
1
+ require 'filters_spam'
2
+
1
3
  module Refinery
2
4
  module Blog
3
5
  class Comment < ActiveRecord::Base
4
6
 
5
- attr_accessible :name, :email, :message
6
-
7
- filters_spam :author_field => :name,
8
- :email_field => :email,
9
- :message_field => :body
7
+ filters_spam author_field: :name, email_field: :email, message_field: :body
10
8
 
11
- belongs_to :post, :foreign_key => 'blog_post_id'
9
+ belongs_to :post, foreign_key: 'blog_post_id'
12
10
 
13
11
  alias_attribute :message, :body
14
12
 
15
- validates :name, :message, :presence => true
16
- validates :email, :format => { :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i }
13
+ validates :name, :message, presence: true
14
+ validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
17
15
 
18
16
  class << self
19
17
  def unmoderated
20
- where(:state => nil)
18
+ where(state: nil)
21
19
  end
22
20
 
23
21
  def approved
24
- where(:state => 'approved')
22
+ where(state: 'approved')
25
23
  end
26
24
 
27
25
  def rejected
28
- where(:state => 'rejected')
26
+ where(state: 'rejected')
29
27
  end
30
28
  end
31
29
 
@@ -55,7 +53,7 @@ module Refinery
55
53
  currently = Refinery::Setting.find_or_set(:comments_allowed, true, {
56
54
  :scoping => 'blog'
57
55
  })
58
- Refinery::Setting.set(:comments_allowed, {:value => !currently, :scoping => 'blog'})
56
+ Refinery::Setting.set(:comments_allowed, {value: !currently, scoping: 'blog'})
59
57
  end
60
58
 
61
59
  before_create do |comment|
@@ -68,16 +66,16 @@ module Refinery
68
66
  class << self
69
67
  def enabled?
70
68
  Refinery::Setting.find_or_set(:comment_moderation, true, {
71
- :scoping => 'blog',
72
- :restricted => false
69
+ scoping: 'blog',
70
+ restricted: false
73
71
  })
74
72
  end
75
73
 
76
74
  def toggle!
77
75
  new_value = {
78
- :value => !Blog::Comment::Moderation.enabled?,
79
- :scoping => 'blog',
80
- :restricted => false
76
+ value: !Blog::Comment::Moderation.enabled?,
77
+ scoping: 'blog',
78
+ restricted: false
81
79
  }
82
80
  Refinery::Setting.set(:comment_moderation, new_value)
83
81
  end
@@ -4,51 +4,50 @@ require 'seo_meta'
4
4
  module Refinery
5
5
  module Blog
6
6
  class Post < ActiveRecord::Base
7
+ extend FriendlyId
7
8
 
8
9
  translates :title, :body, :custom_url, :custom_teaser, :slug, :include => :seo_meta
9
10
 
10
- extend FriendlyId
11
11
  friendly_id :friendly_id_source, :use => [:slugged, :globalize]
12
12
 
13
- is_seo_meta if self.table_exists?
14
-
15
- default_scope :order => 'published_at DESC'
16
-
17
- belongs_to :author, :class_name => Refinery::Blog.user_class.to_s, :foreign_key => :user_id, :readonly => true
13
+ is_seo_meta
18
14
 
19
- has_many :comments, :dependent => :destroy, :foreign_key => :blog_post_id
20
15
  acts_as_taggable
21
16
 
17
+ belongs_to :author, proc { readonly(true) }, :class_name => Refinery::Blog.user_class.to_s, :foreign_key => :user_id
18
+ has_many :comments, :dependent => :destroy, :foreign_key => :blog_post_id
22
19
  has_many :categorizations, :dependent => :destroy, :foreign_key => :blog_post_id
23
20
  has_many :categories, :through => :categorizations, :source => :blog_category
24
21
 
25
22
  validates :title, :presence => true, :uniqueness => true
26
23
  validates :body, :presence => true
27
- validates :published_at, :author, :presence => true
28
-
24
+ validates :published_at, :presence => true
25
+ validates :author, :presence => true, if: :author_required?
29
26
  validates :source_url, :url => { :if => 'Refinery::Blog.validate_source_url',
30
27
  :update => true,
31
28
  :allow_nil => true,
32
29
  :allow_blank => true,
33
30
  :verify => [:resolve_redirects]}
34
31
 
35
- attr_accessible :title, :body, :custom_teaser, :tag_list, :draft, :published_at, :custom_url, :author
36
- attr_accessible :browser_title, :meta_description, :user_id, :category_ids
37
- attr_accessible :source_url, :source_url_title
38
- attr_accessor :locale
39
-
32
+ class Translation
33
+ is_seo_meta
34
+ end
35
+
36
+ # Override this to disable required authors
37
+ def author_required?
38
+ true
39
+ end
40
40
 
41
- class Translation
42
- is_seo_meta
43
- attr_accessible :browser_title, :meta_description, :locale
44
- end
41
+ # If custom_url or title changes tell friendly_id to regenerate slug when
42
+ # saving record
43
+ def should_generate_new_friendly_id?
44
+ custom_url_changed? || title_changed?
45
+ end
45
46
 
46
- # Delegate SEO Attributes to globalize3 translation
47
+ # Delegate SEO Attributes to globalize translation
47
48
  seo_fields = ::SeoMeta.attributes.keys.map{|a| [a, :"#{a}="]}.flatten
48
49
  delegate(*(seo_fields << {:to => :translation}))
49
50
 
50
- before_save { |m| m.translation.save }
51
-
52
51
  self.per_page = Refinery::Blog.posts_per_page
53
52
 
54
53
  def next
@@ -60,7 +59,7 @@ module Refinery
60
59
  end
61
60
 
62
61
  def live?
63
- !draft and published_at <= Time.now
62
+ !draft && published_at <= Time.now
64
63
  end
65
64
 
66
65
  def friendly_id_source
@@ -79,56 +78,58 @@ module Refinery
79
78
  end
80
79
  end
81
80
  # A join implies readonly which we don't really want.
82
- joins(:translations).where(globalized_conditions).where(conditions).readonly(false)
81
+ where(conditions).joins(:translations).where(globalized_conditions)
82
+ .readonly(false)
83
83
  end
84
84
 
85
- def find_by_slug_or_id(slug_or_id)
86
- if slug_or_id.friendly_id?
87
- find_by_slug(slug_or_id)
88
- else
89
- find(slug_or_id)
90
- end
85
+ def by_month(date)
86
+ newest_first.where(:published_at => date.beginning_of_month..date.end_of_month)
91
87
  end
92
88
 
93
- def by_month(date)
94
- where(:published_at => date.beginning_of_month..date.end_of_month)
89
+ def by_year(date)
90
+ newest_first.where(:published_at => date.beginning_of_year..date.end_of_year).with_globalize
95
91
  end
96
92
 
97
- def by_archive(date)
98
- Refinery.deprecate("Refinery::Blog::Post.by_archive(date)", {:replacement => "Refinery::Blog::Post.by_month(date)", :when => 2.2 })
99
- by_month(date)
93
+ def by_title(title)
94
+ joins(:translations).find_by(:title => title)
100
95
  end
101
96
 
102
- def by_year(date)
103
- where(:published_at => date.beginning_of_year..date.end_of_year).with_globalize
97
+ def newest_first
98
+ order("published_at DESC")
104
99
  end
105
100
 
106
101
  def published_dates_older_than(date)
107
- published_before(date).select(:published_at).map(&:published_at)
102
+ newest_first.published_before(date).select(:published_at).map(&:published_at)
108
103
  end
109
104
 
110
105
  def recent(count)
111
- live.limit(count)
106
+ newest_first.live.limit(count)
112
107
  end
113
108
 
114
109
  def popular(count)
115
- unscoped.order("access_count DESC").limit(count).with_globalize
110
+ order("access_count DESC").limit(count).with_globalize
116
111
  end
117
112
 
118
113
  def previous(item)
119
- published_before(item.published_at).first
114
+ newest_first.published_before(item.published_at).first
120
115
  end
121
116
 
122
117
  def uncategorized
123
- live.includes(:categories).where(Refinery::Blog::Categorization.table_name => { :blog_category_id => nil })
118
+ newest_first.live.includes(:categories).where(
119
+ Refinery::Blog::Categorization.table_name => { :blog_category_id => nil }
120
+ )
124
121
  end
125
122
 
126
123
  def next(current_record)
127
- where(["published_at > ? and draft = ?", current_record.published_at, false]).reorder('published_at ASC').with_globalize.first
124
+ where(arel_table[:published_at].gt(current_record.published_at))
125
+ .where(:draft => false)
126
+ .order('published_at ASC').with_globalize.first
128
127
  end
129
128
 
130
129
  def published_before(date=Time.now)
131
- where("published_at < ? and draft = ?", date, false).with_globalize
130
+ where(arel_table[:published_at].lt(date))
131
+ .where(:draft => false)
132
+ .with_globalize
132
133
  end
133
134
  alias_method :live, :published_before
134
135
 
@@ -1,8 +1,6 @@
1
1
  <nav id='actions' class='multilist'>
2
2
  <ul class='search_list'>
3
- <li class='not_a_link'>
4
- <%= render "/refinery/admin/search", :url => request.path %>
5
- </li>
3
+ <li class='not_a_link'><%= render "/refinery/admin/search", :url => request.path -%></li>
6
4
  </ul>
7
5
 
8
6
  <ul class='collapsible_menu'>
@@ -2,12 +2,21 @@
2
2
  <span class='title'>
3
3
  <%= category.title.presence || category.translations.detect {|t| t.title.present?}.title %>
4
4
  <span class="preview">
5
- <% category.translations.each do |translation| %>
6
- <% if translation.title.present? %>
7
- <%= link_to refinery_icon_tag("flags/#{translation.locale}.png", :size => '16x11'),
8
- refinery.edit_blog_admin_category_path(category, :switch_locale => translation.locale),
9
- :class => 'locale' %>
5
+ <% if Refinery::I18n.frontend_locales.many? %>
6
+ <span class='locales'>
7
+ <% category.translations.sort_by{ |t| Refinery::I18n.frontend_locales.index(t.locale)}.each do |translation| %>
8
+ <% if translation.title.present? %>
9
+ <%= link_to refinery.edit_blog_admin_category_path(category,
10
+ :switch_locale => translation.locale),
11
+ :class => 'locale',
12
+ :title => translation.locale.upcase do %>
13
+ <div class="<%=translation.locale %> locale_marker">
14
+ <%= locale_text_icon(translation.locale.upcase) %>
15
+ </div>
16
+ <% end %>
17
+ <% end %>
10
18
  <% end %>
19
+ </span>
11
20
  <% end %>
12
21
  </span>
13
22
  </span>
@@ -40,14 +40,14 @@
40
40
  </div>
41
41
  </div>
42
42
 
43
- <%= render '/refinery/admin/form_advanced_options_menu', :f => f %>
44
-
45
43
  <div class='field'>
46
44
  <%= f.label :tag_list, t('refinery.blog.shared.tags.title') -%>
47
- <%= f.text_field :tag_list, :class => 'larger' -%>
45
+ <%= f.text_field :tag_list, value: @post.tag_list.to_s, :class => 'larger' -%>
48
46
  </div>
49
47
 
50
- <div id='more_options' style="display:none;">
48
+ <%= render '/refinery/admin/form_advanced_options_menu', :f => f %>
49
+
50
+ <div id='more_options'>
51
51
  <div class="hemisquare">
52
52
  <h3><%= t('title', :scope => 'refinery.blog.admin.submenu.categories') %></h3>
53
53
  <ul class='blog_categories'>
@@ -106,11 +106,18 @@
106
106
  <%= render "/refinery/admin/form_actions",
107
107
  :f => f,
108
108
  :continue_editing => true,
109
- :delete_title => t('delete', :scope => 'refinery.blog.admin.posts.post') %>
109
+ :delete_title => t('delete', :scope => 'refinery.blog.admin.posts.post'),
110
+ :before_delete_button => (link_to(t('delete_translation', :scope => 'refinery.blog.admin.posts.post'),
111
+ refinery.delete_translation_blog_admin_post_path(@post, :locale_to_delete => Globalize.locale),
112
+ :method => :post,
113
+ :data => {
114
+ :confirm => t('delete_translation_confirmation', :scope => 'refinery.blog.admin.posts.post')
115
+ },
116
+ :class => "button confirm-delete") if Refinery::I18n.frontend_locales.many? && @post.translations.size > 1) %>
110
117
  <% end -%>
111
118
 
112
119
  <% content_for :stylesheets, stylesheet_link_tag('refinery/blog/backend') %>
113
120
  <% content_for :javascripts, javascript_include_tag('refinery/blog/backend') %>
114
121
  <%= render 'refinery/shared/admin/autocomplete',
115
- :dom_id => '#blog_post_tag_list',
122
+ :dom_id => '#post_tag_list',
116
123
  :url => refinery.tags_blog_admin_posts_url %>
@@ -1,3 +1,3 @@
1
1
  <div class='page_part' id='page_part_body'>
2
- <%= f.text_area :body, :rows => 20, :class => 'wymeditor widest' -%>
2
+ <%= f.text_area :body, :rows => 20, :class => 'visual_editor widest' -%>
3
3
  </div>
@@ -2,12 +2,19 @@
2
2
  <span class='title'>
3
3
  <%= post.title.presence || post.translations.detect {|t| t.title.present?}.title %>
4
4
  <span class="preview">
5
- <% post.translations.each do |translation| %>
6
- <% if translation.title.present? %>
7
- <%= link_to refinery_icon_tag("flags/#{translation.locale}.png", :size => '16x11'),
8
- refinery.edit_blog_admin_post_path(post, :switch_locale => translation.locale),
9
- :class => 'locale' %>
5
+ <% if Refinery::I18n.frontend_locales.many? %>
6
+ <span class='locales'>
7
+ <% post.translations.sort_by{ |t| Refinery::I18n.frontend_locales.index(t.locale)}.each do |translation| %>
8
+ <% if translation.title.present? %>
9
+ <%= link_to refinery.edit_blog_admin_post_path(post, :switch_locale => translation.locale), :class => 'locale', title: translation.locale.upcase do %>
10
+
11
+ <div class="<%=translation.locale %> locale_marker">
12
+ <%= locale_text_icon(translation.locale.upcase) %>
13
+ </div>
14
+ <% end %>
15
+ <% end %>
10
16
  <% end %>
17
+ </span>
11
18
  <% end %>
12
19
 
13
20
  <%= post.published_at.try(:strftime, '%b %d, %Y') || 'draft' %>
@@ -1,5 +1,5 @@
1
1
  <div class='page_part' id='page_part_teaser'>
2
- <%= f.text_area :custom_teaser, :rows => 20, :class => 'wymeditor widest' -%>
2
+ <%= f.text_area :custom_teaser, :rows => 20, :class => 'visual_editor widest' -%>
3
3
  <p>
4
4
  <span class='clearfix label_inline_with_link'>
5
5
  <%= link_to t('copy_body', :scope => 'refinery.blog.admin.posts.form'), "#",
@@ -1,5 +1,5 @@
1
1
  <% content_for :body do %>
2
- <%= raw @page.content_for(Refinery::Pages.default_parts.first.to_sym) if Refinery::Pages.default_parts.any? %>
2
+ <%= raw @page.content_for(Refinery::Pages.default_parts.first[:slug].to_sym) if Refinery::Pages.default_parts.any? %>
3
3
 
4
4
  <% if @posts.any? %>
5
5
  <section id="blog_posts">
@@ -12,7 +12,7 @@
12
12
  <% end %>
13
13
 
14
14
  <% content_for :side_body_prepend do -%>
15
- <%= raw @page.content_for(Refinery::Pages.default_parts.second.to_sym) %>
15
+ <%= raw @page.content_for(Refinery::Pages.default_parts.second[:slug].to_sym) %>
16
16
  <% end if Refinery::Pages.default_parts.many? -%>
17
17
  <%= render '/refinery/blog/shared/body_content_right' %>
18
18
 
@@ -1,10 +1,10 @@
1
1
  <% if @categories.any? %>
2
2
  <h2><%= t('.title') %></h2>
3
- <ul id='categories'>
3
+ <ul id="categories">
4
4
  <% @categories.each do |category| %>
5
- <li<%= " class='selected'" if @category.present? and @category.id == category.id %>>
5
+ <li<%== ' class="selected"' if @category.present? && @category.id == category.id %>>
6
6
  <%= link_to "#{category.title} (#{category.post_count})", refinery.blog_category_path(category) %>
7
7
  </li>
8
8
  <% end %>
9
9
  </ul>
10
- <% end %>
10
+ <% end %>
@@ -1 +1,46 @@
1
1
  <% content_for :stylesheets, stylesheet_link_tag("refinery/blog/ui-lightness/jquery-ui-1.8.13.custom") %>
2
+ <% content_for :javascripts do %>
3
+ <script>
4
+ function split(val) {
5
+ return val.split(/,\s*/);
6
+ }
7
+ function extractLast(term) {
8
+ return split(term).pop();
9
+ }
10
+ $(document).ready(function(){
11
+ $('<%= dom_id %>').bind("keydown", function(event) {
12
+ if (event.keyCode === $.ui.keyCode.TAB && $(this).data("autocomplete").menu.active) {
13
+ event.preventDefault()
14
+ }
15
+ }).autocomplete({
16
+ source: function(request, response) {
17
+ $.getJSON("<%= url %>", {
18
+ term: extractLast(request.term)
19
+ }, response);
20
+ },
21
+ search: function() {
22
+ // custom minLength
23
+ var term = extractLast(this.value);
24
+ if (term.length < 2) {
25
+ return false;
26
+ }
27
+ },
28
+ focus: function() {
29
+ // prevent value inserted on focus
30
+ return false;
31
+ },
32
+ select: function(event, ui) {
33
+ var terms = split(this.value);
34
+ // remove the current input
35
+ terms.pop();
36
+ // add the selected item
37
+ terms.push(ui.item.value);
38
+ // add placeholder to get the comma-and-space at the end
39
+ terms.push("");
40
+ this.value = terms.join(", ");
41
+ return false;
42
+ }
43
+ });
44
+ })
45
+ </script>
46
+ <% end %>