asset collections almost done
This commit is contained in:
parent
8c6e9bd981
commit
13cd09e3af
66
app/controllers/admin/asset_collections_controller.rb
Normal file
66
app/controllers/admin/asset_collections_controller.rb
Normal file
@ -0,0 +1,66 @@
|
||||
module Admin
|
||||
class AssetCollectionsController < BaseController
|
||||
|
||||
sections 'assets'
|
||||
|
||||
before_filter :set_collections
|
||||
|
||||
def index
|
||||
if not @collections.empty?
|
||||
redirect_to(edit_admin_asset_collection_url(@collections.first)) and return
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@collection = current_site.asset_collections.find(params[:id])
|
||||
render :action => 'edit'
|
||||
end
|
||||
|
||||
def new
|
||||
@collection = current_site.asset_collections.build
|
||||
end
|
||||
|
||||
def edit
|
||||
@collection = current_site.asset_collections.find(params[:id])
|
||||
end
|
||||
|
||||
def create
|
||||
@collection = current_site.asset_collections.build(params[:asset_collection])
|
||||
|
||||
if @collection.save
|
||||
flash_success!
|
||||
redirect_to edit_admin_asset_collection_url(@collection)
|
||||
else
|
||||
flash_error!
|
||||
render :action => 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@collection = current_site.asset_collections.find(params[:id])
|
||||
|
||||
if @collection.update_attributes(params[:asset_collection])
|
||||
flash_success!
|
||||
redirect_to edit_admin_asset_collection_url(@collection)
|
||||
else
|
||||
flash_error!
|
||||
render :action => 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@collection = current_site.asset_collections.find(params[:id])
|
||||
@collection.destroy
|
||||
|
||||
flash_success!
|
||||
|
||||
redirect_to admin_asset_collections_url
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def set_collections
|
||||
@collections = current_site.asset_collections
|
||||
end
|
||||
end
|
||||
end
|
48
app/controllers/admin/assets_controller.rb
Normal file
48
app/controllers/admin/assets_controller.rb
Normal file
@ -0,0 +1,48 @@
|
||||
module Admin
|
||||
class AssetsController < BaseController
|
||||
|
||||
sections 'assets'
|
||||
|
||||
before_filter :set_collections_and_current_collection
|
||||
|
||||
def new
|
||||
@asset = @collection.assets.build
|
||||
end
|
||||
|
||||
def edit
|
||||
@asset = @collection.assets.find(params[:id])
|
||||
end
|
||||
|
||||
def create
|
||||
@asset = @collection.assets.build(params[:asset])
|
||||
|
||||
if @asset.save
|
||||
flash_success!
|
||||
redirect_to edit_admin_asset_collection_url(@collection)
|
||||
else
|
||||
flash_error!
|
||||
render :action => 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@asset = @collection.assets.find(params[:id])
|
||||
|
||||
if @asset.update_attributes(params[:asset])
|
||||
flash_success!
|
||||
redirect_to edit_admin_asset_collection_url(@collection)
|
||||
else
|
||||
flash_error!
|
||||
render :action => 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def set_collections_and_current_collection
|
||||
@collections = current_site.asset_collections
|
||||
@collection = @collections.find(params[:collection_id])
|
||||
end
|
||||
|
||||
end
|
||||
end
|
28
app/models/asset.rb
Normal file
28
app/models/asset.rb
Normal file
@ -0,0 +1,28 @@
|
||||
class Asset
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
|
||||
## fields ##
|
||||
field :name, :type => String
|
||||
field :content_type, :type => String
|
||||
field :width, :type => Integer
|
||||
field :height, :type => Integer
|
||||
field :size, :type => Integer
|
||||
field :position, :type => Integer, :default => 0
|
||||
mount_uploader :source, AssetUploader
|
||||
|
||||
## associations ##
|
||||
embedded_in :collection, :class_name => 'AssetCollection', :inverse_of => :assets
|
||||
|
||||
## validations ##
|
||||
validates_presence_of :name, :source
|
||||
|
||||
## methods ##
|
||||
|
||||
%w{image stylesheet javascript pdf video audio}.each do |type|
|
||||
define_method("#{type}?") do
|
||||
self.content_type == type
|
||||
end
|
||||
end
|
||||
|
||||
end
|
57
app/models/asset_collection.rb
Normal file
57
app/models/asset_collection.rb
Normal file
@ -0,0 +1,57 @@
|
||||
class AssetCollection
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
|
||||
## fields ##
|
||||
field :name, :type => String
|
||||
field :slug, :type => String
|
||||
|
||||
## associations ##
|
||||
belongs_to_related :site
|
||||
embeds_many :assets
|
||||
# has_many_related :assets
|
||||
|
||||
## callbacks ##
|
||||
before_validate :normalize_slug
|
||||
before_save :store_asset_positions!
|
||||
|
||||
## validations ##
|
||||
validates_presence_of :site, :name, :slug
|
||||
validates_uniqueness_of :slug, :scope => :site_id
|
||||
|
||||
## methods ##
|
||||
|
||||
def ordered_assets
|
||||
self.assets.sort { |a, b| (a.position || 0) <=> (b.position || 0) }
|
||||
end
|
||||
|
||||
def assets_order
|
||||
self.ordered_assets.collect(&:id).join(',')
|
||||
end
|
||||
|
||||
def assets_order=(order)
|
||||
@assets_order = order
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def normalize_slug
|
||||
self.slug = self.name.clone if self.slug.blank? && self.name.present?
|
||||
self.slug.slugify! if self.slug.present?
|
||||
end
|
||||
|
||||
def store_asset_positions!
|
||||
return if @assets_order.nil?
|
||||
|
||||
@assets_order.split(',').each_with_index do |asset_id, index|
|
||||
self.assets.find(asset_id).position = index
|
||||
end
|
||||
|
||||
self.assets.each do |asset|
|
||||
if !@assets_order.split(',').include?(asset._id)
|
||||
self.assets.delete(asset)
|
||||
asset.send(:delete)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -12,6 +12,7 @@ class Site
|
||||
has_many_related :layouts
|
||||
has_many_related :snippets
|
||||
has_many_related :theme_assets
|
||||
has_many_related :asset_collections
|
||||
embeds_many :memberships
|
||||
|
||||
## validations ##
|
||||
@ -82,7 +83,7 @@ class Site
|
||||
end
|
||||
|
||||
def destroy_in_cascade!
|
||||
%w{pages layouts snippets theme_assets}.each do |association|
|
||||
%w{pages layouts snippets theme_assets asset_collections}.each do |association|
|
||||
self.send(association).destroy_all
|
||||
end
|
||||
end
|
||||
|
@ -20,7 +20,7 @@ class ThemeAsset
|
||||
|
||||
## validations ##
|
||||
validate :extname_can_not_be_changed
|
||||
validates_presence_of :site
|
||||
validates_presence_of :site, :source
|
||||
validates_presence_of :slug, :if => Proc.new { |a| a.new_record? && a.performing_plain_text? }
|
||||
validates_integrity_of :source
|
||||
|
||||
@ -84,9 +84,7 @@ class ThemeAsset
|
||||
|
||||
def extname_can_not_be_changed
|
||||
return if self.new_record?
|
||||
|
||||
Rails.logger.debug "previous = #{self.source.file.original_filename.inspect} / #{self.source_filename.inspect}"
|
||||
|
||||
|
||||
if File.extname(self.source.file.original_filename) != File.extname(self.source_filename)
|
||||
self.errors.add(:source, :extname_changed)
|
||||
end
|
||||
|
64
app/uploaders/asset_uploader.rb
Normal file
64
app/uploaders/asset_uploader.rb
Normal file
@ -0,0 +1,64 @@
|
||||
# encoding: utf-8
|
||||
|
||||
class AssetUploader < CarrierWave::Uploader::Base
|
||||
|
||||
include CarrierWave::RMagick
|
||||
|
||||
def store_dir
|
||||
"sites/#{model.collection.site_id}/assets/#{model.id}"
|
||||
end
|
||||
|
||||
version :thumb do
|
||||
process :resize_to_fill => [50, 50]
|
||||
process :convert => 'png'
|
||||
end
|
||||
|
||||
version :medium do
|
||||
process :resize_to_fill => [80, 80]
|
||||
process :convert => 'png'
|
||||
end
|
||||
|
||||
version :preview do
|
||||
process :resize_to_fit => [880, 1100]
|
||||
process :convert => 'png'
|
||||
end
|
||||
|
||||
process :set_content_type
|
||||
process :set_size
|
||||
process :set_width_and_height
|
||||
|
||||
def set_content_type
|
||||
value = :other
|
||||
|
||||
self.class.content_types.each_pair do |type, rules|
|
||||
rules.each do |rule|
|
||||
case rule
|
||||
when String then value = type if file.content_type == rule
|
||||
when Regexp then value = type if (file.content_type =~ rule) == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
model.content_type = value
|
||||
end
|
||||
|
||||
def set_size
|
||||
model.size = file.size
|
||||
end
|
||||
|
||||
def set_width_and_height
|
||||
if model.image?
|
||||
model.width, model.height = `identify -format "%wx%h" #{file.path}`.split(/x/).collect(&:to_i)
|
||||
end
|
||||
end
|
||||
|
||||
def self.content_types
|
||||
{
|
||||
:image => ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg'],
|
||||
:movie => [/^video/, 'application/x-shockwave-flash', 'application/x-swf'],
|
||||
:audio => [/^audio/, 'application/ogg', 'application/x-mp3'],
|
||||
:pdf => ['application/pdf', 'application/x-pdf']
|
||||
}
|
||||
end
|
||||
|
||||
end
|
@ -71,8 +71,6 @@ class ThemeAssetUploader < CarrierWave::Uploader::Base
|
||||
end
|
||||
|
||||
def filename
|
||||
Rails.logger.debug "slug ===> #{model.slug} / #{model.content_type} / #{original_filename}"
|
||||
|
||||
if model.slug.present?
|
||||
model.filename
|
||||
else
|
||||
@ -80,8 +78,6 @@ class ThemeAssetUploader < CarrierWave::Uploader::Base
|
||||
basename = File.basename(original_filename, extension).slugify(:underscore => true)
|
||||
"#{basename}#{extension}"
|
||||
end
|
||||
#
|
||||
# original_filename
|
||||
end
|
||||
|
||||
end
|
||||
|
7
app/views/admin/asset_collections/_asset.html.haml
Normal file
7
app/views/admin/asset_collections/_asset.html.haml
Normal file
@ -0,0 +1,7 @@
|
||||
%li{ :id => "asset-#{asset.id}", :class => "asset #{'last' if (asset_counter + 1) % 6 == 0}"}
|
||||
%h4= link_to truncate(asset.name, :length => 22), edit_admin_asset_path(@collection, asset)
|
||||
.image
|
||||
.inside
|
||||
= vignette_tag(asset)
|
||||
.actions
|
||||
= link_to image_tag('admin/list/icons/cross.png'), '#', :class => 'remove', :confirm => t('admin.messages.confirm')
|
28
app/views/admin/asset_collections/edit.html.haml
Normal file
28
app/views/admin/asset_collections/edit.html.haml
Normal file
@ -0,0 +1,28 @@
|
||||
- title link_to(@collection.name.blank? ? @collection.name_was : @collection.name, '#', :rel => 'asset_collection_name', :title => t('.ask_for_name'), :class => 'editable')
|
||||
|
||||
- content_for :head do
|
||||
= javascript_include_tag 'admin/asset_collections.js'
|
||||
|
||||
- content_for :submenu do
|
||||
= render 'admin/shared/menu/assets'
|
||||
|
||||
%p= t('.help')
|
||||
|
||||
- content_for :buttons do
|
||||
= admin_button_tag :add_asset, new_admin_asset_url(@collection), :class => 'add'
|
||||
|
||||
%p.no-items{ :style => "#{'display: none' unless @collection.assets.empty? }" }
|
||||
= t('.no_items', :url => new_admin_asset_url(@collection))
|
||||
|
||||
%ul#assets.assets.sortable
|
||||
= render :partial => 'asset', :collection => @collection.ordered_assets
|
||||
%li.clear
|
||||
|
||||
= semantic_form_for @collection, :url => admin_asset_collection_url(@collection), :html => { :multipart => true } do |f|
|
||||
= f.hidden_field :assets_order
|
||||
|
||||
= f.foldable_inputs :name => :options do
|
||||
= f.input :name
|
||||
= f.input :slug, :required => false
|
||||
|
||||
= render 'admin/shared/form_actions', :delete_button => link_to(content_tag(:span, t('.destroy')), admin_asset_collection_url(@collection), :confirm => t('admin.messages.confirm'), :method => :delete, :class => 'button small remove'), :button_label => :update
|
8
app/views/admin/asset_collections/index.html.haml
Normal file
8
app/views/admin/asset_collections/index.html.haml
Normal file
@ -0,0 +1,8 @@
|
||||
- title t('.title')
|
||||
|
||||
- content_for :submenu do
|
||||
= render 'admin/shared/menu/assets'
|
||||
|
||||
%p= t('.help')
|
||||
|
||||
%p.no-items= t('.no_items', :url => new_admin_asset_collection_url)
|
17
app/views/admin/asset_collections/new.html.haml
Normal file
17
app/views/admin/asset_collections/new.html.haml
Normal file
@ -0,0 +1,17 @@
|
||||
- title t('.title')
|
||||
|
||||
- content_for :head do
|
||||
= javascript_include_tag 'admin/asset_collections.js'
|
||||
|
||||
- content_for :submenu do
|
||||
= render 'admin/shared/menu/assets'
|
||||
|
||||
%p= t('.help')
|
||||
|
||||
= semantic_form_for @collection, :url => admin_asset_collections_url do |f|
|
||||
|
||||
= f.inputs :name => :information do
|
||||
= f.input :name
|
||||
= f.input :slug, :required => false
|
||||
|
||||
= render 'admin/shared/form_actions', :back_url => admin_asset_collections_url, :button_label => :create
|
10
app/views/admin/assets/_form.html.haml
Normal file
10
app/views/admin/assets/_form.html.haml
Normal file
@ -0,0 +1,10 @@
|
||||
= f.inputs :name => :information do
|
||||
= f.input :name
|
||||
= f.input :source
|
||||
|
||||
- if @asset.image?
|
||||
= f.foldable_inputs :name => "#{t('formtastic.titles.preview')} #{image_dimensions_and_size(@asset)}", :class => 'preview' do
|
||||
%li
|
||||
.image
|
||||
.inside
|
||||
= image_tag(@asset.source.url(:preview))
|
15
app/views/admin/assets/edit.html.haml
Normal file
15
app/views/admin/assets/edit.html.haml
Normal file
@ -0,0 +1,15 @@
|
||||
- title t('.title')
|
||||
|
||||
- content_for :submenu do
|
||||
= render 'admin/shared/menu/assets'
|
||||
|
||||
- content_for :buttons do
|
||||
= admin_button_tag t('admin.asset_collections.edit.add_asset'), new_admin_asset_url(@collection), :class => 'add'
|
||||
|
||||
%p= t('.help')
|
||||
|
||||
= semantic_form_for @asset, :url => admin_asset_url(@collection, @asset), :html => { :multipart => true } do |form|
|
||||
|
||||
= render 'form', :f => form
|
||||
|
||||
= render 'admin/shared/form_actions', :back_url => edit_admin_asset_collection_url(@collection), :button_label => :update
|
12
app/views/admin/assets/new.html.haml
Normal file
12
app/views/admin/assets/new.html.haml
Normal file
@ -0,0 +1,12 @@
|
||||
- title t('.title')
|
||||
|
||||
- content_for :submenu do
|
||||
= render 'admin/shared/menu/assets'
|
||||
|
||||
%p= t('.help')
|
||||
|
||||
= semantic_form_for @asset, :url => admin_assets_url(@collection), :html => { :multipart => true } do |form|
|
||||
|
||||
= render 'form', :f => form
|
||||
|
||||
= render 'admin/shared/form_actions', :back_url => edit_admin_asset_collection_url(@collection), :button_label => :create
|
@ -3,8 +3,9 @@
|
||||
%p
|
||||
- if defined?(back_url)
|
||||
= link_to escape_once('← ') + t('.back'), back_url
|
||||
- else
|
||||
|
||||
- elsif defined?(delete_button)
|
||||
= delete_button
|
||||
|
||||
|
||||
.span-12.last
|
||||
%p
|
||||
|
@ -1,5 +1,5 @@
|
||||
%ul#menu
|
||||
= admin_menu_item('contents', admin_pages_url)
|
||||
= admin_menu_item('assets', '#')
|
||||
= admin_menu_item('assets', admin_asset_collections_url)
|
||||
= admin_menu_item('settings', edit_admin_current_site_url)
|
||||
%li.clear
|
||||
|
7
app/views/admin/shared/menu/_assets.html.haml
Normal file
7
app/views/admin/shared/menu/_assets.html.haml
Normal file
@ -0,0 +1,7 @@
|
||||
%ul
|
||||
- @collections.each do |c|
|
||||
%li{ :class => "#{'on' if @collection.id == c.id}" }
|
||||
= link_to content_tag(:span, truncate(c.name, :length => 20)), edit_admin_asset_collection_url(c)
|
||||
|
||||
.action
|
||||
= link_to content_tag(:span, t('admin.asset_collections.index.new')), new_admin_asset_collection_url
|
@ -44,5 +44,13 @@ module CarrierWave
|
||||
record.errors.add attr, options[:message] if record.send("#{attr}_integrity_error")
|
||||
end
|
||||
end
|
||||
|
||||
def validates_processing_of(*attrs)
|
||||
options = attrs.last.is_a?(Hash) ? attrs.last : {}
|
||||
options[:message] ||= I18n.t('carrierwave.errors.processing', :default => 'failed to be processed.')
|
||||
validates_each(*attrs) do |record, attr, value|
|
||||
record.errors.add attr, options[:message] if record.send("#{attr}_processing_error")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -68,12 +68,16 @@ en:
|
||||
title: Listing layouts
|
||||
no_items: "There are no layouts for now. Just click <a href=\"{{url}}\">here</a> to create the first one."
|
||||
new: new layout
|
||||
new:
|
||||
title: New layout
|
||||
|
||||
snippets:
|
||||
index:
|
||||
title: Listing snippets
|
||||
no_items: "There are no snippets for now. Just click <a href=\"{{url}}\">here</a> to create the first one."
|
||||
new: new snippet
|
||||
new:
|
||||
title: New snippet
|
||||
|
||||
sites:
|
||||
new:
|
||||
@ -113,6 +117,24 @@ en:
|
||||
choose_file: Choose file
|
||||
choose_plain_text: Choose plain text
|
||||
|
||||
asset_collections:
|
||||
index:
|
||||
title: Asset collections
|
||||
new: new collection
|
||||
no_items: "There are no collections for now. Just click <a href=\"{{url}}\">here</a> to create the first one."
|
||||
new:
|
||||
title: New collection
|
||||
edit:
|
||||
help: "The collection name can be updated by clicking it. Uploading several files at once is possible, just click on the 'upload files' button at the right corner."
|
||||
add_asset: add asset
|
||||
destroy: remove collection
|
||||
no_items: "There are no assets for now. Just click <a href=\"{{url}}\">here</a> to create the first one."
|
||||
|
||||
assets:
|
||||
new:
|
||||
title: New asset
|
||||
|
||||
|
||||
formtastic:
|
||||
titles:
|
||||
information: General information
|
||||
@ -126,6 +148,7 @@ en:
|
||||
membership_email: Account email
|
||||
file: File
|
||||
preview: Preview
|
||||
options: Advanced options
|
||||
labels:
|
||||
theme_asset:
|
||||
new:
|
||||
|
@ -38,9 +38,14 @@ Locomotive::Application.routes.draw do |map|
|
||||
resources :memberships
|
||||
|
||||
resources :theme_assets
|
||||
|
||||
resources :asset_collections
|
||||
|
||||
resources :assets, :path => "asset_collections/:collection_id"
|
||||
|
||||
end
|
||||
|
||||
# magic url
|
||||
# magic urls
|
||||
match '/' => 'pages#show'
|
||||
match '*path' => 'pages#show'
|
||||
end
|
||||
|
7
doc/TODO
7
doc/TODO
@ -41,9 +41,14 @@ x domain scoping when authenticating
|
||||
x can not replace a javascript by a stylesheet
|
||||
- disable version if not image
|
||||
- asset collections
|
||||
x create / update
|
||||
x sort assets
|
||||
x removing assets
|
||||
- assets
|
||||
- destroy
|
||||
- custom resizing
|
||||
|
||||
- assets uploader:
|
||||
- remove old files if new one
|
||||
|
||||
BACKLOG:
|
||||
- liquid rendering engine
|
||||
|
@ -21,7 +21,7 @@ class String
|
||||
# Turn unwanted chars into the seperator
|
||||
s.gsub!(/[^a-zA-Z0-9\-_\+\/]+/i, options[:sep])
|
||||
# Underscore
|
||||
s.gsub!(/[\-]/i, '') if options[:underscore]
|
||||
s.gsub!(/[\-]/i, '_') if options[:underscore]
|
||||
s
|
||||
end
|
||||
|
||||
|
50
public/javascripts/admin/asset_collections.js
Normal file
50
public/javascripts/admin/asset_collections.js
Normal file
@ -0,0 +1,50 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
// automatic slug from snippet name
|
||||
$('#asset_collection_name').keypress(function() {
|
||||
var input = $(this);
|
||||
var slug = $('#asset_collection_slug');
|
||||
|
||||
if (!slug.hasClass('filled')) {
|
||||
setTimeout(function() {
|
||||
slug.val(input.val().replace(/\s/g, '_').toLowerCase());
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
|
||||
$('#asset_collection_slug').keypress(function() { $(this).addClass('filled'); });
|
||||
|
||||
// sortable assets
|
||||
|
||||
var updateAssetsOrder = function() {
|
||||
var list = $('ul.assets.sortable');
|
||||
var ids = jQuery.map(list.sortable('toArray'), function(e) {
|
||||
return e.match(/asset-(\w+)/)[1];
|
||||
}).join(',');
|
||||
$('#asset_collection_assets_order').val(ids || '0');
|
||||
}
|
||||
|
||||
$('ul.assets.sortable').sortable({
|
||||
items: 'li.asset',
|
||||
stop: function(event, ui) { updateAssetsOrder(); }
|
||||
});
|
||||
|
||||
$('ul.assets.sortable li div.actions a.remove').click(function(e) {
|
||||
if (confirm($(this).attr('data-confirm'))) {
|
||||
$(this).parents('li').remove();
|
||||
|
||||
updateAssetsOrder();
|
||||
|
||||
if ($('ul.assets li.asset').size() == 0) $('p.no-items').show();
|
||||
|
||||
$('ul.assets li.last').removeClass('last');
|
||||
var i = parseInt($('ul.assets li.asset').size() / 6);
|
||||
while (i > 0) {
|
||||
$('ul.assets li.asset:eq(' + (i * 6 - 1) + ')').addClass('last');
|
||||
i--;
|
||||
}
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
@ -38,7 +38,7 @@ $(document).ready(function() {
|
||||
|
||||
if (!slug.hasClass('filled')) {
|
||||
setTimeout(function() {
|
||||
slug.val(input.val().replace(' ', '_')).addClass('touched');
|
||||
slug.val(input.val().replace(/\s/g, '_').toLowerCase()).addClass('touched');
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
|
@ -7,7 +7,7 @@ $(document).ready(function() {
|
||||
|
||||
if (!slug.hasClass('filled')) {
|
||||
setTimeout(function() {
|
||||
slug.val(input.val().replace(' ', '_').toLowerCase());
|
||||
slug.val(input.val().replace(/\s/g, '_').toLowerCase());
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
|
@ -426,7 +426,7 @@ form.formtastic fieldset.preview li .inside {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
form.formtastic fieldset.preview li img { }
|
||||
form.formtastic fieldset.preview li img { }
|
||||
|
||||
|
||||
/* ___ main error message ___ */
|
||||
|
Loading…
Reference in New Issue
Block a user