adding taggable images
git-svn-id: http://svn.barleysodas.com/barleysodas/trunk@103 0f7b21a7-9e3a-4941-bbeb-ce5c7c368fa7master
parent
543d65ebb6
commit
044824947b
|
@ -0,0 +1,78 @@
|
||||||
|
class GalleriesController < ApplicationController
|
||||||
|
append_before_filter :fetch_image, :only => [ :show, :destroy,
|
||||||
|
:download_original ]
|
||||||
|
|
||||||
|
# GET /images
|
||||||
|
# GET /images.xml
|
||||||
|
def index
|
||||||
|
@content_title = 'Image Gallery'
|
||||||
|
cond_ary = []
|
||||||
|
cond_var = {
|
||||||
|
:people_id => params[:id]
|
||||||
|
}
|
||||||
|
@secondary_title = "Everybody's Images"
|
||||||
|
if params[:id]
|
||||||
|
cond_ary << 'images.people_id = :people_id'
|
||||||
|
@people = People.find(params[:id])
|
||||||
|
@secondary_title = "Images from #{@people.title}"
|
||||||
|
end
|
||||||
|
cond_ary << '1 = 1' if cond_ary.empty?
|
||||||
|
@pages, @images = paginate :images, :per_page => per_page,
|
||||||
|
:order => 'images.created_at DESC', :include => [ 'people' ],
|
||||||
|
:conditions => [ cond_ary.join(' AND '), cond_var ]
|
||||||
|
flash.now[:notice] = 'There are no images yet.' if @images.empty?
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # index.rhtml
|
||||||
|
format.xml { render :xml => @images.to_xml }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /galleries/1
|
||||||
|
# GET /galleries/1.xml
|
||||||
|
def show
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # show.rhtml
|
||||||
|
format.xml { render :xml => @image.to_xml }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /galleries/new
|
||||||
|
def new
|
||||||
|
@image = Image.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /images
|
||||||
|
# POST /images.xml
|
||||||
|
def create
|
||||||
|
@image = Image.new(params[:image])
|
||||||
|
if @image.save
|
||||||
|
flash[:notice] = 'Great success!'
|
||||||
|
redirect_to gallery_url(@image)
|
||||||
|
else
|
||||||
|
render :action => :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /galleries/1
|
||||||
|
# DELETE /galleries/1.xml
|
||||||
|
def destroy
|
||||||
|
@image.destroy
|
||||||
|
flash[:notice] = 'Destroyed the image.'
|
||||||
|
redirect_to galleries_url(:id => @image.people_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Sends a copy of the original Image to the People.
|
||||||
|
#
|
||||||
|
def download_original
|
||||||
|
send_file("#{RAILS_ROOT}/public/images/" +
|
||||||
|
@image.filename_for_version(:original),
|
||||||
|
:disposition => 'inline', :type => @image.content_type)
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def fetch_image
|
||||||
|
@image = Image.find(params[:id])
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,88 @@
|
||||||
|
class TagImagesController < ApplicationController
|
||||||
|
# GET /tag_images
|
||||||
|
# GET /tag_images.xml
|
||||||
|
def index
|
||||||
|
redirect_to images_url
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /tag_images/1
|
||||||
|
# GET /tag_images/1.xml
|
||||||
|
def show
|
||||||
|
@content_title = 'Tag your friends and beers!'
|
||||||
|
@image = Image.find(params[:id], :include => [ :tag_images ])
|
||||||
|
@tag_images = @image.tag_images
|
||||||
|
respond_to do |format|
|
||||||
|
format.html # show.rhtml
|
||||||
|
format.xml { render :xml => @tag_images.to_xml }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /tag_images
|
||||||
|
# POST /tag_images.xml
|
||||||
|
def create
|
||||||
|
@tag_image = TagImage.new(params[:tag_image])
|
||||||
|
@image = @tag_image.image
|
||||||
|
if @tag_image.save
|
||||||
|
@tag_images = @image.tag_images
|
||||||
|
render :partial => 'tag_images'
|
||||||
|
else
|
||||||
|
render :partial => 'tag_image_errors', :status => 500
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /tag_images/1
|
||||||
|
# DELETE /tag_images/1.xml
|
||||||
|
def destroy
|
||||||
|
@tag_image = TagImage.find params[:id], :include => [ :image ]
|
||||||
|
@image = @tag_image.image
|
||||||
|
@tag_image.destroy
|
||||||
|
@image.tag_images.reload
|
||||||
|
@tag_images = @image.tag_images
|
||||||
|
render :partial => 'tag_images'
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Searches for all known models that support image tagging. Sticks all of
|
||||||
|
# the matching results into a hash that is indexed by the type.
|
||||||
|
#
|
||||||
|
def taggable_search
|
||||||
|
@results = {}
|
||||||
|
cond_ary = [ 'title ILIKE :title' ]
|
||||||
|
cond_var = { :title => "%#{params[:name]}%" }
|
||||||
|
TagImage.types_for_select.flatten.each do |ctype|
|
||||||
|
klass = Class.class_eval(ctype)
|
||||||
|
@results[ctype] = klass.find :all, :order => 'title ASC',
|
||||||
|
:conditions => [ cond_ary.join(' AND '), cond_var ]
|
||||||
|
end
|
||||||
|
render :partial => 'taggable_results'
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Renders an Ajax browser of all tagged Image models for any +:taggable_type+
|
||||||
|
#
|
||||||
|
def tagged_images
|
||||||
|
images_per_page = 4
|
||||||
|
@page_count, @current_page, @tagged_type, @tagged_images = nil, nil, nil, nil
|
||||||
|
@tagged_type = params[:tagged_type]
|
||||||
|
if TagImage.types_for_select.flatten.include?(@tagged_type)
|
||||||
|
cond_ary = [
|
||||||
|
'tagged_type = :tt',
|
||||||
|
'tagged_id = :tid'
|
||||||
|
]
|
||||||
|
cond_var = { :tt => @tagged_type, :tid => params[:id] }
|
||||||
|
conditions = [ cond_ary.join(' AND '), cond_var ]
|
||||||
|
@current_page = params[:page].to_i
|
||||||
|
@current_page = 1 if @current_page == 0
|
||||||
|
image_count = TagImage.count(conditions)
|
||||||
|
@page_count = (image_count.to_f / per_page.to_f + 0.5).to_i
|
||||||
|
@page_count = 1 if @page_count == 0 and image_count >= 0
|
||||||
|
@tagged_images = TagImage.find :all, :limit => images_per_page,
|
||||||
|
:conditions => conditions, :order => 'created_at ASC',
|
||||||
|
:offset => ((@current_page - 1) * images_per_page),
|
||||||
|
:include => [ 'image' ]
|
||||||
|
render :partial => 'tag_images/tagged_images'
|
||||||
|
else
|
||||||
|
render :nothing => true, :status => 500
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -91,4 +91,48 @@ module ApplicationHelper
|
||||||
res
|
res
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Captures a block output and renders it in a partial as <tt>body</tt>
|
||||||
|
#
|
||||||
|
def block_to_partial(partial_name, options = {}, &block)
|
||||||
|
options.merge!(:body => capture(&block))
|
||||||
|
concat(render(:partial => partial_name, :locals => options), block.binding)
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Helper to build a prototype dialog.
|
||||||
|
#
|
||||||
|
def lightbox(options = {}, &block)
|
||||||
|
options = {
|
||||||
|
:title => 'DialogTitle',
|
||||||
|
:window_id => 'DialogId',
|
||||||
|
:modal => false
|
||||||
|
}.merge(options)
|
||||||
|
block_to_partial('shared/lightbox', options, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Pagination link image browser thingey for the tagged image lightbox.
|
||||||
|
#
|
||||||
|
def image_browser_navigation_link(image_name, page_number, total_pages,
|
||||||
|
tagged_class, tagged_id)
|
||||||
|
if page_number == 0 or
|
||||||
|
(page_number == 1 and total_pages == 1) or
|
||||||
|
(page_number > total_pages)
|
||||||
|
image_tag(image_name)
|
||||||
|
else
|
||||||
|
link_to_remote image_tag(image_name), :update => 'browser_box',
|
||||||
|
:url => { :controller => 'tag_images', :action => 'tagged_images',
|
||||||
|
:id => :tagged_id, :tagged_class => tagged_class }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Link to open the dialog box for the tagged image browser.
|
||||||
|
#
|
||||||
|
def tagged_image_browser_link
|
||||||
|
link_to_function 'Tagged Images',
|
||||||
|
"lightboxes['tagged_image_browser'].open()"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
module GalleriesHelper
|
||||||
|
def new_image_link
|
||||||
|
link_to 'Upload Image', new_gallery_url
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
module TagImagesHelper
|
||||||
|
end
|
|
@ -6,6 +6,7 @@ class Beer < ActiveRecord::Base
|
||||||
has_one_tuxwiki_page :owner_class => 'Beer'
|
has_one_tuxwiki_page :owner_class => 'Beer'
|
||||||
belongs_to :style
|
belongs_to :style
|
||||||
validates_presence_of :style_id
|
validates_presence_of :style_id
|
||||||
|
has_many_tagged_images
|
||||||
|
|
||||||
##
|
##
|
||||||
# Returns a list of attributes for the Page partial.
|
# Returns a list of attributes for the Page partial.
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
require 'mini_magick'
|
||||||
|
|
||||||
|
class Image < ActiveRecord::Base
|
||||||
|
attr_accessor :file
|
||||||
|
belongs_to :people
|
||||||
|
validates_presence_of :people_id
|
||||||
|
before_validation_on_create :set_people_id
|
||||||
|
before_create :validate_image_sanity
|
||||||
|
after_create :setup_directories
|
||||||
|
before_destroy :destroy_directories
|
||||||
|
has_many :tag_images, :dependent => :destroy
|
||||||
|
has_many :tagged_items, :through => :tag_images
|
||||||
|
|
||||||
|
##
|
||||||
|
# Builds the filename for this model for a particular version of the file.
|
||||||
|
#
|
||||||
|
def filename_for_version(ver = :screen)
|
||||||
|
if respond_to?(ver)
|
||||||
|
"community/#{id}/#{self.send(ver)}"
|
||||||
|
else
|
||||||
|
"/images/image-missing.png"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
##
|
||||||
|
# Determines the base directory for all files in this model.
|
||||||
|
#
|
||||||
|
def base_directory
|
||||||
|
"#{RAILS_ROOT}/public/images/community/#{id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Sets the People marker for ownership on creation.
|
||||||
|
#
|
||||||
|
def set_people_id
|
||||||
|
self[:people_id] = ApplicationController.current_people_id rescue nil
|
||||||
|
self[:people_id] ||= People.penguincoder.id rescue nil
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Checks to make sure that the file exists and is an image.
|
||||||
|
#
|
||||||
|
def validate_image_sanity
|
||||||
|
if @file.nil? or @file.to_s.empty?
|
||||||
|
errors.add(:file, 'is not a file')
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
errors.add(:file, 'is too big (3MB max)') if @file.size > 3 * 1048576
|
||||||
|
begin
|
||||||
|
@magick_image = MiniMagick::Image.from_blob(@file.read,
|
||||||
|
File.extname(@file.original_filename))
|
||||||
|
rescue
|
||||||
|
logger.debug("Caught an exception saving an image:")
|
||||||
|
logger.debug("* #{$!}")
|
||||||
|
errors.add(:file, 'is not an image')
|
||||||
|
end
|
||||||
|
return false if self.errors.size > 0
|
||||||
|
self.content_type = @file.content_type.chomp
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Makes the directories and writes the different versions for the uploaded
|
||||||
|
# files if applicable.
|
||||||
|
#
|
||||||
|
def setup_directories
|
||||||
|
Dir.mkdir(base_directory) unless File.exist?(base_directory)
|
||||||
|
self.original = File.basename(@file.original_filename).gsub(/[^\w._-]/, '')
|
||||||
|
@magick_image.write("#{base_directory}/#{self.original}")
|
||||||
|
@magick_image.thumbnail("600x600>")
|
||||||
|
self.screen = "screen_#{self.original}"
|
||||||
|
@magick_image.write("#{base_directory}/#{self.screen}")
|
||||||
|
if @magick_image.output =~ / (\d+)x(\d+) /
|
||||||
|
self.screen_width = $1
|
||||||
|
self.screen_height = $2
|
||||||
|
end
|
||||||
|
@magick_image.thumbnail("50x50>")
|
||||||
|
self.thumbnail = "thumbnail_#{self.original}"
|
||||||
|
@magick_image.write("#{base_directory}/#{self.thumbnail}")
|
||||||
|
self.save
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Removes the directories and files associated with this model on destroy.
|
||||||
|
#
|
||||||
|
def destroy_directories
|
||||||
|
return unless File.exists?(base_directory)
|
||||||
|
Dir.foreach(base_directory) do |file|
|
||||||
|
next if file =~ /^\.\.?$/
|
||||||
|
File.delete(base_directory + '/' + file)
|
||||||
|
end
|
||||||
|
Dir.delete(base_directory)
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,6 +7,8 @@ class People < ActiveRecord::Base
|
||||||
attr_protected :role_id
|
attr_protected :role_id
|
||||||
has_many :created_pages, :class_name => 'Page', :foreign_key => 'created_by'
|
has_many :created_pages, :class_name => 'Page', :foreign_key => 'created_by'
|
||||||
has_many :updated_pages, :class_name => 'Page', :foreign_key => 'updated_by'
|
has_many :updated_pages, :class_name => 'Page', :foreign_key => 'updated_by'
|
||||||
|
has_many :images, :dependent => :destroy
|
||||||
|
has_many_tagged_images
|
||||||
validates_uniqueness_of :title
|
validates_uniqueness_of :title
|
||||||
|
|
||||||
make_authenticatable
|
make_authenticatable
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
class TagImage < ActiveRecord::Base
|
||||||
|
belongs_to :image
|
||||||
|
belongs_to :tagged, :polymorphic => true
|
||||||
|
validates_presence_of :image_id, :tagged_id, :tagged_type
|
||||||
|
validates_uniqueness_of :tagged_id, :scope => :tagged_type
|
||||||
|
|
||||||
|
def self.types_for_select
|
||||||
|
[ 'Beer', 'People', 'Brewery' ].collect { |x| [x] }
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,10 @@
|
||||||
|
<%= render :partial => 'shared/tagged_image_browser', :locals => { :obj => @beer } %>
|
||||||
|
|
||||||
<%= render :partial => 'pages/page' %>
|
<%= render :partial => 'pages/page' %>
|
||||||
|
|
||||||
<% content_for :sidebar do -%>
|
<% content_for :sidebar do -%>
|
||||||
<%= new_beer_link -%><br />
|
<%= new_beer_link -%><br />
|
||||||
<%= edit_beer_link(@beer) -%><br />
|
<%= edit_beer_link(@beer) -%><br />
|
||||||
<%= link_to 'Destroy', beer_path(@beer.page.title_for_url), :confirm => 'Are you sure?', :method => :delete %><br />
|
<%= link_to 'Destroy', beer_path(@beer.page.title_for_url), :confirm => 'Are you sure?', :method => :delete %><br />
|
||||||
|
<% unless @beer.tagged_images.empty? -%><%= tagged_image_browser_link -%><br /><% end -%>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
<%= new_brewery_link -%><br />
|
<%= new_brewery_link -%><br />
|
||||||
<%= edit_brewery_link(@brewery) -%><br />
|
<%= edit_brewery_link(@brewery) -%><br />
|
||||||
<%= link_to 'Destroy', brewery_path(@brewery.page.title_for_url), :confirm => 'Are you sure?', :method => :delete %><br />
|
<%= link_to 'Destroy', brewery_path(@brewery.page.title_for_url), :confirm => 'Are you sure?', :method => :delete %><br />
|
||||||
|
<%= tagged_image_browser_link -%><br />
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<br />
|
||||||
|
<% version ||= :screen -%>
|
||||||
|
<div class="people_image" id="image_<%= image.id -%>">
|
||||||
|
<%= link_to_unless_current(image_tag(image.filename_for_version(version), :alt => image.original), gallery_url(image)) %>
|
||||||
|
<p class="author">Uploaded by <%= link_to(image.people.title, galleries_url(:id => image.people_id)) -%></p>
|
||||||
|
</div>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<fieldset>
|
||||||
|
<h2>Upload an image</h2>
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
File:
|
||||||
|
<%= file_field 'image', 'file' %>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<h1>Editing images</h1>
|
||||||
|
|
||||||
|
<%= error_messages_for :images %>
|
||||||
|
|
||||||
|
<% form_for(:images, :url => images_path(@images), :html => { :method => :put }) do |f| %>
|
||||||
|
<p>
|
||||||
|
<%= submit_tag "Update" %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= link_to 'Show', images_path(@images) %> |
|
||||||
|
<%= link_to 'Back', images_path %>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<%= render :partial => 'image', :collection => @images, :locals => { :version => :thumbnail } %>
|
||||||
|
|
||||||
|
<%= render :partial => 'shared/pagination_links' %>
|
||||||
|
|
||||||
|
<% content_for :sidebar do -%>
|
||||||
|
<%= new_image_link -%><br />
|
||||||
|
<% end -%>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<%= error_messages_for :image %>
|
||||||
|
|
||||||
|
<% form_for(:images, :url => galleries_path, :html => { :multipart => true, :onsubmit => "$('spinner').style.display = 'inline';" }) do |f| %>
|
||||||
|
<fieldset>
|
||||||
|
<h2>Upload an image</h2>
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
File:
|
||||||
|
<%= file_field 'image', 'file' %>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
|
<p>
|
||||||
|
<%= submit_tag "Create" %> <%= image_tag '/images/spinner.gif', :id => 'spinner', :style => 'display:none' %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% content_for :sidebar do -%>
|
||||||
|
<%= new_image_link -%><br />
|
||||||
|
<% end -%>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<%= render :partial => 'image', :locals => { :image => @image } %>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<% content_for :sidebar do -%>
|
||||||
|
<%= link_to "#{@image.people.title}'s images (#{@image.people.images.size})", galleries_path(:id => @image.people_id) -%><br />
|
||||||
|
<%= link_to "Download original", :action => 'download_original', :id => @image.id -%><br />
|
||||||
|
<%= link_to 'Destroy', gallery_path(@image), :confirm => 'Are you sure?', :method => :delete %><br />
|
||||||
|
<%= link_to 'Tag Image', :controller => :tag_images, :action => :show, :id => @image.id -%><br />
|
||||||
|
<% end -%>
|
|
@ -5,6 +5,7 @@
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||||
<%= stylesheet_link_tag 'application', :media => 'all' %>
|
<%= stylesheet_link_tag 'application', :media => 'all' %>
|
||||||
<%= javascript_include_tag :defaults %>
|
<%= javascript_include_tag :defaults %>
|
||||||
|
<%= javascript_include_tag 'control.modal.js' %>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
<%= yield :script %>
|
<%= yield :script %>
|
||||||
</script>
|
</script>
|
||||||
|
@ -53,4 +54,5 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<div id="<%= window_id -%>_dialog">
|
||||||
|
<div class="dialogBox">
|
||||||
|
<div class="dialogHeader"><%= title -%></div>
|
||||||
|
<br />
|
||||||
|
<div class="dialogContent"><%= body -%></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%= link_to(title, "##{window_id}_dialog", { :class => "#{modal ? '' : 'non'}modal_controls", :onclick => "return false;", :id => "#{window_id}_id_key", :style => 'display: none;' }) %>
|
||||||
|
<% content_for :script do -%>
|
||||||
|
addLoadEvent(function(){
|
||||||
|
if(!window.lightboxes)
|
||||||
|
lightboxes = {};
|
||||||
|
if(!window.after_opens)
|
||||||
|
after_opens = {};
|
||||||
|
if(!window.before_closes)
|
||||||
|
before_closes = {}
|
||||||
|
var link = $("<%= window_id -%>_id_key");
|
||||||
|
var key = '<%= window_id -%>';
|
||||||
|
var ao = after_opens[key];
|
||||||
|
var bc = before_closes[key];
|
||||||
|
if(ao == undefined)
|
||||||
|
ao = function(){};
|
||||||
|
if(bc == undefined)
|
||||||
|
bc = function(){};
|
||||||
|
lightboxes[key] = new Control.Modal(link, {
|
||||||
|
afterOpen: ao, beforeClose: bc,
|
||||||
|
overlayCloseOnClick: <%= modal ? 'false' : 'true' -%>
|
||||||
|
});
|
||||||
|
});
|
||||||
|
<% end -%>
|
|
@ -0,0 +1,46 @@
|
||||||
|
<% content_for :stylesheet do -%>
|
||||||
|
#browser_box {
|
||||||
|
}
|
||||||
|
|
||||||
|
#browser_box img {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#browser_controls {
|
||||||
|
padding: 3px 10px 3px 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
|
<% content_for :script do -%>
|
||||||
|
if(!window.after_opens)
|
||||||
|
after_opens = {};
|
||||||
|
if(!window.before_closes)
|
||||||
|
before_closes = {}
|
||||||
|
|
||||||
|
after_opens['tagged_image_browser'] = function(){
|
||||||
|
$('browser_box').hide();
|
||||||
|
new Ajax.Updater('browser_box',
|
||||||
|
'<%= url_for(:controller => :tag_images, :action => :tagged_images, :id => ((obj ||= nil).nil? ? nil : obj.id), :tagged_type => obj.class) -%>',
|
||||||
|
{
|
||||||
|
onFailure: function() {
|
||||||
|
lightboxes['tagged_image_browser'].close();
|
||||||
|
},
|
||||||
|
onSuccess: function() {
|
||||||
|
$('browser_spinner').hide();
|
||||||
|
new Effect.Appear('browser_box', { duration: 1.5 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
before_closes['tagged_image_browser'] = function(){
|
||||||
|
$('browser_box').hide();
|
||||||
|
$('browser_spinner').show();
|
||||||
|
}
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
|
<% lightbox :title => 'Tagged Images', :window_id => 'tagged_image_browser' do -%>
|
||||||
|
<div id="browser_spinner"><div class="centered"><%= image_tag('spinner.gif') -%></div></div>
|
||||||
|
<div id="browser_box"></div>
|
||||||
|
<% end -%>
|
|
@ -0,0 +1 @@
|
||||||
|
<%= error_messages_for 'tag_image' %>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<p>
|
||||||
|
<strong>Tagged items:</strong>
|
||||||
|
<% if @tag_images.empty? -%>
|
||||||
|
None.
|
||||||
|
<% else -%>
|
||||||
|
<%= @tag_images.collect { |t| "<span onmouseover=\"show_tag_at(#{t.x}, #{t.y})\" onmouseout=\"hide_tag_box()\">#{t.tagged.title} (<em>#{t.tagged_type}</em> | #{link_to_remote('Remove', :url => tag_image_path(t), :update => 'tag_images', :method => :delete)})</span>" }.join(', ') -%>
|
||||||
|
<% end -%>
|
||||||
|
</p>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<% @results.keys.each do |ctype| -%>
|
||||||
|
<% next if @results[ctype].empty? -%>
|
||||||
|
<h3><%= ctype.pluralize -%></h3>
|
||||||
|
<p>
|
||||||
|
<%= @results[ctype].collect { |r| link_to_function(r.title, "set_taggable_item(#{r.id}, '#{r.title}', '#{ctype}');") }.join(', ') %>
|
||||||
|
</p>
|
||||||
|
<% end -%>
|
||||||
|
<% unless @results.detect { |key, val| !val.empty? } -%>
|
||||||
|
<small>No results found...</small>
|
||||||
|
<% end -%>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="centered">
|
||||||
|
<% @tagged_images.each do |tag_image| -%>
|
||||||
|
<%= link_to(image_tag(tag_image.image.filename_for_version(:thumbnail)), gallery_path(tag_image.image), :popup => true) %>
|
||||||
|
<% end -%>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div id="browser_controls" class="centered">
|
||||||
|
<%= image_browser_navigation_link('go-first.png', 1, @page_count, @tagged_type, params[:id]) -%> <%= image_browser_navigation_link('go-previous.png', @current_page - 1, @page_count, @tagged_type, params[:id]) -%> <%= @current_page -%> / <%= @page_count -%> <%= image_browser_navigation_link('go-next.png', @current_page + 1, @page_count, @tagged_type, params[:id]) -%> <%= image_browser_navigation_link('go-last.png', @page_count, @page_count, @tagged_type, params[:id]) -%>
|
||||||
|
</div>
|
|
@ -0,0 +1,110 @@
|
||||||
|
<% content_for :stylesheet do -%>
|
||||||
|
#image_block {
|
||||||
|
z-index: 0;
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 0px;
|
||||||
|
width: <%= @image.screen_width -%>px;
|
||||||
|
height: <%= @image.screen_height -%>px;
|
||||||
|
background-image: url('/images/<%= @image.filename_for_version -%>');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
#image_block_container {
|
||||||
|
margin: 10px <%= (605 - @image.screen_width) / 2 -%>px 20px <%= (605 - @image.screen_width) / 2 -%>px;
|
||||||
|
}
|
||||||
|
#image_tag_box {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border: 5px solid #db3333;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
|
<% content_for :script do -%>
|
||||||
|
function show_tag_at(xcoord, ycoord)
|
||||||
|
{
|
||||||
|
$('image_tag_box').style.top = (ycoord - 50) + 'px';
|
||||||
|
$('image_tag_box').style.left = (xcoord - 50) + 'px';
|
||||||
|
$('image_tag_box').style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide_tag_box()
|
||||||
|
{
|
||||||
|
$('image_tag_box').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_coordinates(event)
|
||||||
|
{
|
||||||
|
xcoord = (event.offsetX ? event.offsetX : (event.pageX - $('image_block').offsetLeft));
|
||||||
|
ycoord = (event.offsetY ? event.offsetY : (event.pageY - $('image_block').offsetTop));
|
||||||
|
show_tag_at(xcoord, ycoord);
|
||||||
|
lightboxes['taggedContentDialog'].open();
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_taggable_item(id, title, type)
|
||||||
|
{
|
||||||
|
$('tag_image_tagged_id').value = id;
|
||||||
|
$('tag_image_title').innerHTML = title;
|
||||||
|
$('tag_image_tagged_type').value = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!window.after_opens)
|
||||||
|
after_opens = {};
|
||||||
|
if(!window.before_closes)
|
||||||
|
before_closes = {};
|
||||||
|
after_opens['taggedContentDialog'] = function(){
|
||||||
|
$('tag_image_x').value = xcoord;
|
||||||
|
$('tag_image_y').value = ycoord;
|
||||||
|
$('tag_image_image_id').value = <%= params[:id] -%>;
|
||||||
|
$('search').focus();
|
||||||
|
}
|
||||||
|
before_closes['taggedContentDialog'] = function(){
|
||||||
|
hide_tag_box();
|
||||||
|
}
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
|
<div id="image_block_container" class="centered">
|
||||||
|
<div id="image_block" onclick='set_coordinates(event);'>
|
||||||
|
<div id="image_tag_box" style="display: none;"></div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div id="tag_images">
|
||||||
|
<%= render :partial => 'tag_images' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% lightbox :title => 'Search for a taggable item', :window_id => 'taggedContentDialog' do -%>
|
||||||
|
<div id="tag_image_errors" class="errorExplanation"></div>
|
||||||
|
<form id="tag_image_fields">
|
||||||
|
<%= hidden_field 'tag_image', 'x' %>
|
||||||
|
<%= hidden_field 'tag_image', 'y' %>
|
||||||
|
<%= hidden_field 'tag_image', 'image_id' %>
|
||||||
|
<%= hidden_field 'tag_image', 'tagged_id' %>
|
||||||
|
<%= hidden_field 'tag_image', 'tagged_type' %>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="centered">
|
||||||
|
<%= link_to_function(image_tag('edit-clear.png'), "$('search').value = '';") -%> <%= text_field_tag 'search', '', :size => 30 -%><br />
|
||||||
|
Selected: <span id="tag_image_title">None</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="taggable_results" class="dialogSearchResults"></div>
|
||||||
|
|
||||||
|
<%= observe_field 'search',
|
||||||
|
:url => { :action => 'taggable_search' },
|
||||||
|
:frequency => 2,
|
||||||
|
:update => 'taggable_results',
|
||||||
|
:with => "'name='+escape(value)" %>
|
||||||
|
|
||||||
|
<div class="dialogControls">
|
||||||
|
<%= link_to_remote('Save', { :url => tag_images_path, :with => "Form.serialize($('tag_image_fields'))", :success => 'Control.Modal.close()', :update => { :success => 'tag_images', :failure => 'tag_image_errors' } }, { :method => :post }) -%>
|
||||||
|
<%= link_to_function 'Cancel', "Control.Modal.close()" -%>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
|
<% content_for :sidebar do -%>
|
||||||
|
<%= link_to 'Image Details', gallery_path(@image) -%><br />
|
||||||
|
<% end -%>
|
|
@ -9,3 +9,4 @@ end
|
||||||
|
|
||||||
require 'redcloth'
|
require 'redcloth'
|
||||||
require 'has_one_page'
|
require 'has_one_page'
|
||||||
|
require 'has_many_tagged_images'
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
ActionController::Routing::Routes.draw do |map|
|
ActionController::Routing::Routes.draw do |map|
|
||||||
|
map.resources :tag_images
|
||||||
|
|
||||||
map.resources :beers, :breweries, :pages, :discussions, :peoples, :roles,
|
map.resources :beers, :breweries, :pages, :discussions, :peoples, :roles,
|
||||||
:sessions, :styles, :galleries
|
:sessions, :styles, :galleries, :tag_images
|
||||||
|
|
||||||
map.connect ':controller/:action/:id.:format'
|
map.connect ':controller/:action/:id.:format'
|
||||||
map.connect ':controller/:action/:id'
|
map.connect ':controller/:action/:id'
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
class CreateImages < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
create_table :images do |t|
|
||||||
|
t.column :people_id, :integer
|
||||||
|
t.column :created_at, :datetime
|
||||||
|
t.column :original, :string
|
||||||
|
t.column :thumbnail, :string
|
||||||
|
t.column :screen, :string
|
||||||
|
t.column :screen_width, :integer
|
||||||
|
t.column :screen_height, :integer
|
||||||
|
t.column :content_type, :string
|
||||||
|
end
|
||||||
|
add_index :images, :people_id
|
||||||
|
create_table :images_pages, :id => false do |t|
|
||||||
|
t.column :image_id, :integer
|
||||||
|
t.column :page_id, :integer
|
||||||
|
end
|
||||||
|
add_index :images_pages, :image_id
|
||||||
|
add_index :images_pages, :page_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
drop_table :images
|
||||||
|
drop_table :images_pages
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
class CreateTagImages < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
create_table :tag_images do |t|
|
||||||
|
t.column :image_id, :integer
|
||||||
|
t.column :tagged_id, :integer
|
||||||
|
t.column :tagged_type, :string, :limit => 32
|
||||||
|
t.column :primary, :boolean
|
||||||
|
t.column :x, :integer
|
||||||
|
t.column :y, :integer
|
||||||
|
end
|
||||||
|
add_index :tag_images, :image_id
|
||||||
|
add_index :tag_images, :tagged_id
|
||||||
|
add_index :tag_images, :tagged_type
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
drop_table :tag_images
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,7 +5,7 @@ base_actions = ApplicationController.action_methods
|
||||||
# rather than defining them here.
|
# rather than defining them here.
|
||||||
controllers = [ PagesController, DiscussionsController, StylesController,
|
controllers = [ PagesController, DiscussionsController, StylesController,
|
||||||
PeoplesController, BeersController, BreweriesController, RolesController,
|
PeoplesController, BeersController, BreweriesController, RolesController,
|
||||||
GalleriesController ]
|
GalleriesController, TagImagesController ]
|
||||||
controllers.each do |c|
|
controllers.each do |c|
|
||||||
actions = c.action_methods - base_actions
|
actions = c.action_methods - base_actions
|
||||||
cname = c.controller_name
|
cname = c.controller_name
|
||||||
|
@ -28,6 +28,11 @@ Permission.find(:all,
|
||||||
next if [ 'new', 'create', 'edit', 'update', 'destroy' ].include?(p.action)
|
next if [ 'new', 'create', 'edit', 'update', 'destroy' ].include?(p.action)
|
||||||
r.permissions << p
|
r.permissions << p
|
||||||
end
|
end
|
||||||
|
Permission.find(:all,
|
||||||
|
:conditions => [ 'controller = ?', 'tag_images' ]).each do |p|
|
||||||
|
next if [ 'show', 'create', 'destroy', 'taggable_search' ].include?(p.action)
|
||||||
|
r.permissions << p
|
||||||
|
end
|
||||||
|
|
||||||
r2 = Role.admin_role
|
r2 = Role.admin_role
|
||||||
Permission.find(:all).each do |p|
|
Permission.find(:all).each do |p|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
module ActiveRecord # :nodoc:
|
||||||
|
class Base # :nodoc:
|
||||||
|
class << self
|
||||||
|
##
|
||||||
|
# This method will add a has_one :page association and a few useful
|
||||||
|
# callbacks to the requested model. It expects to have a
|
||||||
|
# :owner_class parameter given so that it knows what the owner class
|
||||||
|
# name should be. The associated model will automatically be deleted
|
||||||
|
# when this model is deleted.
|
||||||
|
#
|
||||||
|
# The Page will automatically have the title updated from the owner's
|
||||||
|
# title field and be saved after a successful save. When a Page errors
|
||||||
|
# on validation, the errors are automatically copied into the owner so
|
||||||
|
# that the user doesn't even have to know what is going on.
|
||||||
|
#
|
||||||
|
def has_many_tagged_images(options = {})
|
||||||
|
class_eval do
|
||||||
|
has_many :tagged_images, :source_type => self.base_class.to_s,
|
||||||
|
:source => :tagged, :through => :tag_images
|
||||||
|
has_many :tag_images, :dependent => :destroy, :as => :tagged
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Binary file not shown.
After Width: | Height: | Size: 773 B |
Binary file not shown.
After Width: | Height: | Size: 666 B |
Binary file not shown.
After Width: | Height: | Size: 685 B |
Binary file not shown.
After Width: | Height: | Size: 676 B |
Binary file not shown.
After Width: | Height: | Size: 655 B |
|
@ -1,3 +1,15 @@
|
||||||
|
function addLoadEvent(func) {
|
||||||
|
var oldonload = window.onload;
|
||||||
|
if (typeof window.onload != 'function') {
|
||||||
|
window.onload = func;
|
||||||
|
} else {
|
||||||
|
window.onload = function() {
|
||||||
|
oldonload();
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function set_all_checkboxes(form_name, field_name, check_value)
|
function set_all_checkboxes(form_name, field_name, check_value)
|
||||||
{
|
{
|
||||||
if(!document.forms[form_name])
|
if(!document.forms[form_name])
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
@import 'layout.css';
|
@import 'layout.css';
|
||||||
@import 'content.css';
|
@import 'content.css';
|
||||||
@import 'syntax.css';
|
@import 'syntax.css';
|
||||||
|
@import 'lightboxes.css';
|
||||||
|
|
||||||
@media print { #sidebar { display: none; }
|
@media print { #sidebar { display: none; }
|
||||||
#content { float: none; width: 90%; }
|
#content { float: none; width: 90%; }
|
||||||
|
@ -22,10 +23,10 @@ textarea { font: normal 12px "bitstream vera sans", verdana, sans-serif; }
|
||||||
|
|
||||||
abbr { border: none; }
|
abbr { border: none; }
|
||||||
cite { font-style: normal; }
|
cite { font-style: normal; }
|
||||||
a img { border: none; padding: 0; margin: 0; }
|
a img { border: none; padding: 0; margin: 0; vertical-align: middle; text-decoration: none; }
|
||||||
|
|
||||||
a:link, a:visited { color: #000; }
|
a:link, a:visited { color: #000; text-decoration: none; }
|
||||||
a:hover, a:active { color: #fff; background: #000; }
|
a:hover, a:active { text-decoration: underline; }
|
||||||
|
|
||||||
/* http://longren.org/2006/09/27/wrapping-text-inside-pre-tags */
|
/* http://longren.org/2006/09/27/wrapping-text-inside-pre-tags */
|
||||||
pre {
|
pre {
|
||||||
|
@ -35,3 +36,5 @@ pre {
|
||||||
white-space: -o-pre-wrap;
|
white-space: -o-pre-wrap;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.centered { text-align: center; }
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
Header
|
Header
|
||||||
--------------------------------------------------------------*/
|
--------------------------------------------------------------*/
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
background: url(/images/header_shadow.gif) repeat-x left bottom;
|
background: url(/images/header_shadow.gif) repeat-x left bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header a:link,
|
#header a:link,
|
||||||
#header a:visited {
|
#header a:visited {
|
||||||
color: #000;
|
color: #000;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#header h1 {
|
#header h1 {
|
||||||
font: bold 410% georgia, serif;
|
font: bold 410% georgia, serif;
|
||||||
letter-spacing: -1px;
|
letter-spacing: -1px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header h2 {
|
#header h2 {
|
||||||
font: normal 12px verdana, arial, sans-serif;
|
font: normal 12px verdana, arial, sans-serif;
|
||||||
margin: 2.35em 0.2em 0 0;
|
margin: 2.35em 0.2em 0 0;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
@ -41,37 +41,37 @@
|
||||||
#content h2,
|
#content h2,
|
||||||
#content h3,
|
#content h3,
|
||||||
#content h4,
|
#content h4,
|
||||||
#content h5 {
|
#content h5 {
|
||||||
font-family: georgia, times;
|
font-family: georgia, times;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
letter-spacing: -1px;
|
letter-spacing: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content h1 {
|
#content h1 {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
margin: 0 0 0.3em;
|
margin: 0 0 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content h2 {
|
#content h2 {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
margin: 0 0 0.3em;
|
margin: 0 0 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content h3 {
|
#content h3 {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
margin: 1.2em 0 0.3em;
|
margin: 1.2em 0 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content h4 {
|
#content h4 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin: 1.2em 0 0.3em;
|
margin: 1.2em 0 0.3em;
|
||||||
border-bottom: 1px dotted #bbb;
|
border-bottom: 1px dotted #bbb;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content h5 {
|
#content h5 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
background: #ffd;
|
background: #ffd;
|
||||||
margin: 1.2em 0 0.3em;
|
margin: 1.2em 0 0.3em;
|
||||||
border-bottom: 1px dotted #aaa;
|
border-bottom: 1px dotted #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,17 +91,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#content li {
|
#content li {
|
||||||
line-height: 15px;
|
line-height: 15px;
|
||||||
margin: 0 0 0 1em; padding: 0;
|
margin: 0 0 0 1em; padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content blockquote {
|
#content blockquote {
|
||||||
color: #555;
|
color: #555;
|
||||||
border-left: 5px solid #ccc;
|
border-left: 5px solid #ccc;
|
||||||
margin: 1.3em 1em; padding: 0 1em;
|
margin: 1.3em 1em; padding: 0 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content code {
|
#content code {
|
||||||
font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif;
|
font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,25 +114,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Article Entries - class names based on http://microformats.org/wiki/hatom] */
|
/* Article Entries - class names based on http://microformats.org/wiki/hatom] */
|
||||||
#content .hentry {
|
#content .hentry {
|
||||||
margin: 0 0 3em 0;
|
margin: 0 0 3em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content .hentry .entry-title {
|
#content .hentry .entry-title {
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
line-height: 99%;
|
line-height: 99%;
|
||||||
letter-spacing: -1.5px;
|
letter-spacing: -1.5px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content .hentry .entry-title a:link,
|
#content .hentry .entry-title a:link,
|
||||||
#content .hentry .entry-title a:visited {
|
#content .hentry .entry-title a:visited {
|
||||||
color: #111;
|
color: #111;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content .hentry .entry-title a:hover,
|
#content .hentry .entry-title a:hover,
|
||||||
#content .hentry .entry-title a:active {
|
#content .hentry .entry-title a:active {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@
|
||||||
|
|
||||||
#content .hentry .entry-content { }
|
#content .hentry .entry-content { }
|
||||||
|
|
||||||
#content .hentry ul.meta {
|
#content .hentry ul.meta {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
background: #eee;
|
background: #eee;
|
||||||
margin: 0; padding: 5px;
|
margin: 0; padding: 5px;
|
||||||
|
@ -171,7 +171,7 @@
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content .hentry ul.meta li {
|
#content .hentry ul.meta li {
|
||||||
line-height: 13px;
|
line-height: 13px;
|
||||||
margin: 0; padding: 0;
|
margin: 0; padding: 0;
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@
|
||||||
margin: 0 0 1.5em; padding: 1em;
|
margin: 0 0 1.5em; padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content li.discussion.preview {
|
#content li.discussion.preview {
|
||||||
background: #ffc;
|
background: #ffc;
|
||||||
border: 3px solid #fab444;
|
border: 3px solid #fab444;
|
||||||
margin: 0 0 1.5em; padding: 1em;
|
margin: 0 0 1.5em; padding: 1em;
|
||||||
|
@ -239,19 +239,19 @@
|
||||||
padding: 1em 0.5em;
|
padding: 1em 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content form.discussions fieldset {
|
#content form.discussions fieldset {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content form.discussions legend {
|
#content form.discussions legend {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content form.discussions label {
|
#content form.discussions label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content form.discussions textarea {
|
#content form.discussions textarea {
|
||||||
width: 90%; height: 150px;
|
width: 90%; height: 150px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
@ -263,24 +263,32 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#content .people_image .author {
|
#content .people_image .author {
|
||||||
margin: 0 0 0.5em 0.5em;
|
margin: 0 2.5em 0.5em 0.5em;
|
||||||
width: 60px; height: 60px;
|
|
||||||
float: right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#content .people_image .meta {
|
#content .people_image .meta {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.people_image img {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
/*--------------------------------------------------------------
|
||||||
Sidebar
|
Sidebar
|
||||||
--------------------------------------------------------------*/
|
--------------------------------------------------------------*/
|
||||||
|
|
||||||
#sidebar {
|
#sidebar {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar h3 {
|
#sidebar a:hover, #sidebar a:active {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #000;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar h3 {
|
||||||
font: bold 14px "lucidamac bold", "lucida grande", verdana, arial, helvetica, sans-serif;
|
font: bold 14px "lucidamac bold", "lucida grande", verdana, arial, helvetica, sans-serif;
|
||||||
margin: 0 0 0.5em;
|
margin: 0 0 0.5em;
|
||||||
}
|
}
|
||||||
|
@ -296,11 +304,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar ul {
|
#sidebar ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin: 0 0 2em; padding: 0;
|
margin: 0 0 2em; padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar li {
|
#sidebar li {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 1px 0;
|
padding: 1px 0;
|
||||||
}
|
}
|
||||||
|
@ -308,7 +316,7 @@
|
||||||
#sidebar em { font-style: normal; }
|
#sidebar em { font-style: normal; }
|
||||||
|
|
||||||
/* Live-search and results */
|
/* Live-search and results */
|
||||||
#sidebar .search p {
|
#sidebar .search p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +330,7 @@
|
||||||
height: 15px;
|
height: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar .search .results {
|
#sidebar .search .results {
|
||||||
margin: 0 0 1.25em;
|
margin: 0 0 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,12 +338,12 @@
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar .search .results p {
|
#sidebar .search .results p {
|
||||||
font: bold 14px "lucidamac bold", "lucida grande", verdana, arial, helvetica, sans-serif;
|
font: bold 14px "lucidamac bold", "lucida grande", verdana, arial, helvetica, sans-serif;
|
||||||
margin: 0 0 0.5em;
|
margin: 0 0 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar .search .results ul {
|
#sidebar .search .results ul {
|
||||||
margin: 0; padding: 3px;
|
margin: 0; padding: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,53 +354,30 @@
|
||||||
color: #222;
|
color: #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar .search .results a:hover,
|
#sidebar .search .results a:hover,
|
||||||
#sidebar .search .results a:active {
|
#sidebar .search .results a:active {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flickr sidebar-node */
|
|
||||||
#sidebar #flickr {
|
|
||||||
margin: 0 0 2em;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar #flickr div {
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar #flickr img {
|
|
||||||
margin: 0 0 5px;
|
|
||||||
padding: 5px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar #flickr img:hover {
|
|
||||||
background: #ffc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sidebar #flickr a {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
/*--------------------------------------------------------------
|
||||||
Footer
|
Footer
|
||||||
--------------------------------------------------------------*/
|
--------------------------------------------------------------*/
|
||||||
|
|
||||||
#footer {
|
#footer {
|
||||||
border-top: 1px solid #ccc;
|
border-top: 1px solid #ccc;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer a:link,
|
#footer a:link,
|
||||||
#footer a:visited {
|
#footer a:visited {
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer a:hover,
|
#footer a:hover,
|
||||||
#footer a:active {
|
#footer a:active {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: #000;
|
background: #000;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer hr {
|
#footer hr {
|
||||||
|
@ -401,21 +386,21 @@
|
||||||
|
|
||||||
#footer p {
|
#footer p {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
float: left;
|
float: left;
|
||||||
margin: 0; padding: 0;
|
margin: 0; padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer ul {
|
#footer ul {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
margin: 0; padding: 0;
|
margin: 0; padding: 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer li {
|
#footer li {
|
||||||
margin: 0; padding: 0 0 0 1em;
|
margin: 0; padding: 0 0 0 1em;
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tag Cloud Styles */
|
/* Tag Cloud Styles */
|
||||||
|
@ -442,11 +427,11 @@
|
||||||
/* flash hash styles */
|
/* flash hash styles */
|
||||||
#notice {
|
#notice {
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
background-color: #F7F4D5;
|
background-color: #F7F4D5;
|
||||||
border-top: 1px solid #666;
|
border-top: 1px solid #666;
|
||||||
border-bottom: 1px solid #666;
|
border-bottom: 1px solid #666;
|
||||||
color: #333;
|
color: #333;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
@ -454,11 +439,11 @@
|
||||||
|
|
||||||
#error {
|
#error {
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
background-color: #FFCCCC;
|
background-color: #FFCCCC;
|
||||||
border-top: 1px solid #666;
|
border-top: 1px solid #666;
|
||||||
border-bottom: 1px solid #666;
|
border-bottom: 1px solid #666;
|
||||||
color: #333;
|
color: #333;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
|
@ -15,7 +15,7 @@ body {
|
||||||
|
|
||||||
#container {
|
#container {
|
||||||
max-width: 795px;
|
max-width: 795px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin: 0 auto; padding: 10px 0 0 0;
|
margin: 0 auto; padding: 10px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
.dialogBox {
|
||||||
|
background-color: #eee;
|
||||||
|
border: 1px solid #444;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
padding: 4px;
|
||||||
|
height: auto;
|
||||||
|
min-height: 75px;
|
||||||
|
max-height: 450px;
|
||||||
|
width: auto;
|
||||||
|
min-width: 275px;
|
||||||
|
max-width: 550px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogHeader {
|
||||||
|
background: #999;
|
||||||
|
padding: 2px 5px 2px 5px;
|
||||||
|
text-align: center;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
border: 1px solid #444;
|
||||||
|
color: #FFF;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogControls {
|
||||||
|
height: auto;
|
||||||
|
text-align: center;
|
||||||
|
width: auto;
|
||||||
|
font-size: 1.1em;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.dialogControls a {
|
||||||
|
background-color: #CCC;
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 0.25em 1.0em 0.25em 1.0em;
|
||||||
|
text-decoration: none;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
}
|
||||||
|
.dialogControls a:hover, .dialogControls a.over {
|
||||||
|
text-decoration: none;
|
||||||
|
border: 1px solid black;
|
||||||
|
background-color: #999;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogContent {
|
||||||
|
padding: 0px 10px 0px 10px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogSearchResults {
|
||||||
|
padding: 0.25em;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 1.1em;
|
||||||
|
min-height: 50px;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.dialogSearchResults li {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal_overlay {
|
||||||
|
/* konqueror doesn't like these styles. omit for now.
|
||||||
|
background-color: #727272;
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||||
|
one:
|
||||||
|
id: 1
|
||||||
|
two:
|
||||||
|
id: 2
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||||
|
one:
|
||||||
|
id: 1
|
||||||
|
two:
|
||||||
|
id: 2
|
|
@ -0,0 +1,57 @@
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
require 'images_controller'
|
||||||
|
|
||||||
|
# Re-raise errors caught by the controller.
|
||||||
|
class GalleriesController; def rescue_action(e) raise e end; end
|
||||||
|
|
||||||
|
class GalleriesControllerTest < Test::Unit::TestCase
|
||||||
|
fixtures :images
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@controller = GalleriesController.new
|
||||||
|
@request = ActionController::TestRequest.new
|
||||||
|
@response = ActionController::TestResponse.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_get_index
|
||||||
|
get :index
|
||||||
|
assert_response :success
|
||||||
|
assert assigns(:images)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_get_new
|
||||||
|
get :new
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_create_images
|
||||||
|
old_count = Images.count
|
||||||
|
post :create, :images => { }
|
||||||
|
assert_equal old_count+1, Images.count
|
||||||
|
|
||||||
|
assert_redirected_to images_path(assigns(:images))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_show_images
|
||||||
|
get :show, :id => 1
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_get_edit
|
||||||
|
get :edit, :id => 1
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_update_images
|
||||||
|
put :update, :id => 1, :images => { }
|
||||||
|
assert_redirected_to images_path(assigns(:images))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_destroy_images
|
||||||
|
old_count = Images.count
|
||||||
|
delete :destroy, :id => 1
|
||||||
|
assert_equal old_count-1, Images.count
|
||||||
|
|
||||||
|
assert_redirected_to images_path
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,57 @@
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
require 'tag_images_controller'
|
||||||
|
|
||||||
|
# Re-raise errors caught by the controller.
|
||||||
|
class TagImagesController; def rescue_action(e) raise e end; end
|
||||||
|
|
||||||
|
class TagImagesControllerTest < Test::Unit::TestCase
|
||||||
|
fixtures :tag_images
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@controller = TagImagesController.new
|
||||||
|
@request = ActionController::TestRequest.new
|
||||||
|
@response = ActionController::TestResponse.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_get_index
|
||||||
|
get :index
|
||||||
|
assert_response :success
|
||||||
|
assert assigns(:tag_images)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_get_new
|
||||||
|
get :new
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_create_tag_image
|
||||||
|
old_count = TagImage.count
|
||||||
|
post :create, :tag_image => { }
|
||||||
|
assert_equal old_count+1, TagImage.count
|
||||||
|
|
||||||
|
assert_redirected_to tag_image_path(assigns(:tag_image))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_show_tag_image
|
||||||
|
get :show, :id => 1
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_get_edit
|
||||||
|
get :edit, :id => 1
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_update_tag_image
|
||||||
|
put :update, :id => 1, :tag_image => { }
|
||||||
|
assert_redirected_to tag_image_path(assigns(:tag_image))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_destroy_tag_image
|
||||||
|
old_count = TagImage.count
|
||||||
|
delete :destroy, :id => 1
|
||||||
|
assert_equal old_count-1, TagImage.count
|
||||||
|
|
||||||
|
assert_redirected_to tag_images_path
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
|
||||||
|
class ImageTest < Test::Unit::TestCase
|
||||||
|
fixtures :images
|
||||||
|
|
||||||
|
# Replace this with your real tests.
|
||||||
|
def test_truth
|
||||||
|
assert true
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,10 @@
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
|
||||||
|
class TagImageTest < Test::Unit::TestCase
|
||||||
|
fixtures :tag_images
|
||||||
|
|
||||||
|
# Replace this with your real tests.
|
||||||
|
def test_truth
|
||||||
|
assert true
|
||||||
|
end
|
||||||
|
end
|
Reference in New Issue