├── doc ├── css │ ├── common.css │ ├── full_list.css │ └── style.css ├── frames.html ├── file_list.html ├── class_list.html ├── top-level-namespace.html ├── Attrtastic │ ├── Railtie.html │ ├── SemanticAttributesHelper.html │ └── SemanticAttributesBuilder.html ├── method_list.html ├── Attrtastic.html ├── _index.html ├── index.html ├── file.README.html └── js │ ├── full_list.js │ └── app.js ├── lib ├── attrtastic │ ├── version.rb │ ├── railtie.rb │ ├── semantic_attributes_helper.rb │ └── semantic_attributes_builder.rb └── attrtastic.rb ├── .gitignore ├── .document ├── init.rb ├── Gemfile ├── Rakefile ├── LICENSE ├── Gemfile.lock ├── attrtastic.gemspec ├── README.md └── test ├── test_semantic_attributes_helper.rb ├── helper.rb ├── test_attrtastic.rb ├── test_attribute.rb └── test_attributes.rb /doc/css/common.css: -------------------------------------------------------------------------------- 1 | /* Override this file with custom rules */ -------------------------------------------------------------------------------- /lib/attrtastic/version.rb: -------------------------------------------------------------------------------- 1 | module Attrtastic 2 | VERSION = "0.4.3" 3 | end 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## PROJECT::SPECIFIC 2 | .yardoc 3 | 4 | pkg/* 5 | *.gem 6 | .bundle 7 | -------------------------------------------------------------------------------- /.document: -------------------------------------------------------------------------------- 1 | README.rdoc 2 | lib/**/*.rb 3 | bin/* 4 | features/**/*.feature 5 | LICENSE 6 | -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | require "attrtastic" 2 | ActionView::Base.send(:include, Attrtastic::SemanticAttributesHelper) 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in attrtastic.gemspec 4 | gemspec 5 | 6 | gem "rake", '~> 0.9.2.2' 7 | -------------------------------------------------------------------------------- /lib/attrtastic/railtie.rb: -------------------------------------------------------------------------------- 1 | require 'attrtastic' 2 | require 'rails' 3 | 4 | module Attrtastic 5 | class Railtie < Rails::Railtie 6 | initializer 'attrtastic.initialize', :after => :after_initialize do 7 | ActionView::Base.send :include, Attrtastic::SemanticAttributesHelper 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /doc/frames.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Documentation by YARD 0.7.2 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler" 2 | Bundler::GemHelper.install_tasks 3 | 4 | require 'rake/testtask' 5 | Rake::TestTask.new(:test) do |test| 6 | test.libs << 'test' 7 | test.pattern = 'test/**/test_*.rb' 8 | test.verbose = true 9 | end 10 | 11 | begin 12 | require 'rcov/rcovtask' 13 | Rcov::RcovTask.new do |test| 14 | test.libs << 'test' 15 | test.pattern = 'test/**/test_*.rb' 16 | test.verbose = true 17 | end 18 | rescue LoadError 19 | task :rcov do 20 | abort "RCov is not available. In order to run rcov, you must: sudo install rcov" 21 | end 22 | end 23 | 24 | require 'yard' 25 | YARD::Rake::YardocTask.new 26 | 27 | task :default => :test 28 | -------------------------------------------------------------------------------- /lib/attrtastic.rb: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require "attrtastic/semantic_attributes_helper" 3 | require "attrtastic/semantic_attributes_builder" 4 | ## 5 | # Attrtastic, in its assumption, should be similar to formtastic and 6 | # ease displaying AR informations, help create scaffolded show and index 7 | # pages. 8 | # 9 | # @author Boruta Mirosław 10 | 11 | require File.join(File.dirname(__FILE__), *%w[attrtastic railtie]) if defined?(::Rails::Railtie) 12 | 13 | module Attrtastic 14 | extend self 15 | 16 | # Set default options for attribute such as :display_empty 17 | # 18 | # @example 19 | # Attrtastic.default_options[:display_empty] = true 20 | attr_accessor :default_options 21 | self.default_options ||= {} 22 | 23 | def reset_default_options 24 | self.default_options = {} 25 | end 26 | end 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2011 Boruta Miroslaw 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | attrtastic (0.4.3) 5 | actionpack (>= 3.0) 6 | activesupport (>= 3.0) 7 | 8 | GEM 9 | remote: http://rubygems.org/ 10 | specs: 11 | abstract (1.0.0) 12 | actionpack (3.0.9) 13 | activemodel (= 3.0.9) 14 | activesupport (= 3.0.9) 15 | builder (~> 2.1.2) 16 | erubis (~> 2.6.6) 17 | i18n (~> 0.5.0) 18 | rack (~> 1.2.1) 19 | rack-mount (~> 0.6.14) 20 | rack-test (~> 0.5.7) 21 | tzinfo (~> 0.3.23) 22 | activemodel (3.0.9) 23 | activesupport (= 3.0.9) 24 | builder (~> 2.1.2) 25 | i18n (~> 0.5.0) 26 | activesupport (3.0.9) 27 | bluecloth (2.0.9) 28 | builder (2.1.2) 29 | erubis (2.6.6) 30 | abstract (>= 1.0.0) 31 | i18n (0.5.0) 32 | rack (1.2.3) 33 | rack-mount (0.6.14) 34 | rack (>= 1.0.0) 35 | rack-test (0.5.7) 36 | rack (>= 1.0) 37 | rake (0.9.2.2) 38 | shoulda-context (1.0.0) 39 | test-unit (2.4.1) 40 | tzinfo (0.3.28) 41 | yard (0.6.3) 42 | 43 | PLATFORMS 44 | ruby 45 | 46 | DEPENDENCIES 47 | attrtastic! 48 | bluecloth (~> 2.0.0) 49 | rake (~> 0.9.2.2) 50 | shoulda-context (~> 1.0.0) 51 | test-unit (~> 2.4.1) 52 | yard (~> 0.6.0) 53 | -------------------------------------------------------------------------------- /attrtastic.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "attrtastic/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "attrtastic" 7 | s.version = Attrtastic::VERSION 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Boruta Mirosław"] 10 | s.email = ["boruta.miroslaw@gmail.com"] 11 | s.homepage = "http://github.com/MBO/attrtastic" 12 | s.summary = %q{Rails view helper for scaffolding show/index pages for objects} 13 | s.description = %q{Rails view helper for scaffolding show/index pages for objects} 14 | 15 | s.rubyforge_project = "attrtastic" 16 | 17 | s.files = `git ls-files`.split("\n") 18 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 19 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 20 | s.require_paths = ["lib"] 21 | 22 | s.add_development_dependency("yard", ["~> 0.6.0"]) 23 | s.add_development_dependency("bluecloth", ["~>2.0.0"]) 24 | s.add_development_dependency("shoulda-context", ["~> 1.0.0"]) 25 | s.add_development_dependency("test-unit", ["~> 2.4.1"]) 26 | 27 | s.add_dependency("activesupport", [">= 3.0"]) 28 | s.add_dependency("actionpack", [">= 3.0"]) 29 | end 30 | -------------------------------------------------------------------------------- /doc/file_list.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 |
28 |

File List

29 | 38 | 39 | 40 | 47 |
48 | 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Attrtastic 2 | 3 | Attrtastic is simple view helper which can be used to create index/show pages 4 | for any objects (for example Active Model objects). It helps you display 5 | all present attributes of object. 6 | 7 | If you need compatibility with Rails 2.x, then please install version 0.2.2 of 8 | this gem. 9 | 10 | ## Using 11 | 12 | Install the gem: 13 | 14 | gem install attrtastic 15 | 16 | Add to your `Gemfile`: 17 | 18 | gem "attrtastic" 19 | 20 | And use in your views, for example in user/show.erb 21 | 22 | <%= semantic_attributes_for @user do |attr| %> 23 | <%= attr.attributes "User" do %> 24 | <%= attr.attribute :first_name %> 25 | <%= attr.attribute :last_name %> 26 | <%= attr.attribute :avatar do %> 27 | <%= image_tag @user.avatar.url %> 28 | <% end %> 29 | <% end %> 30 | <%= attr.attributes "Contact" do %> 31 | <%= attr.attribute :email %> 32 | <%= attr.attribute :tel %> 33 | <%= attr.attribute :fax %> 34 | <% end %> 35 | <% end %> 36 | 37 | By default attributes which returns `#blank?` value are ommited, unless 38 | `:display_empty => true` is added to `#attribute`. 39 | 40 | ## Note on Patches/Pull Requests 41 | 42 | * Fork the project. 43 | * Make your feature addition or bug fix. 44 | * Add tests for it. This is important so I don't break it in a 45 | future version unintentionally. 46 | * Commit, do not mess with rakefile, version, or history. 47 | (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) 48 | * Send me a pull request. Bonus points for topic branches. 49 | 50 | ## Copyright 51 | 52 | Copyright (c) 2009-2011 Boruta Mirosław. See LICENSE for details. 53 | -------------------------------------------------------------------------------- /test/test_semantic_attributes_helper.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class TestSemanticAttributesHelper < TestCase 4 | 5 | context "semantic_attributes_helper" do 6 | 7 | setup do 8 | setup_fixtures 9 | end 10 | 11 | should "generate output event when no block given" do 12 | expected = html <<-EOHTML 13 |
14 |
15 |
    16 |
  1. 17 | Name 18 | IT Pro Blog 19 |
  2. 20 |
  3. 21 | Url 22 | http://www.it.pro.blog 23 |
  4. 24 |
  5. 25 | Author full name 26 | Doe, John 27 |
  6. 28 |
29 |
30 |
31 | EOHTML 32 | actual = @template.semantic_attributes_for(@blog) 33 | 34 | assert_equal expected, actual 35 | end 36 | 37 | should "run block" do 38 | block_run = false 39 | @template.semantic_attributes_for(@user) do |attr| 40 | block_run = true 41 | end 42 | 43 | assert block_run 44 | end 45 | 46 | should "accept options" do 47 | expected = html <<-EOHTML 48 |
49 |
50 | EOHTML 51 | actual = @template.semantic_attributes_for(@user, :html => {:class => 'simple show'}) do |attr| 52 | true 53 | end 54 | 55 | assert_equal expected, actual 56 | end 57 | 58 | end 59 | 60 | end 61 | -------------------------------------------------------------------------------- /lib/attrtastic/semantic_attributes_helper.rb: -------------------------------------------------------------------------------- 1 | module Attrtastic 2 | ## 3 | # Helper which should be included in ActionView. Adds #semantic_attributes_for 4 | # method, which helps printing attributes for given record, similar to 5 | # formtastic's sematnic_form_for 6 | # 7 | # @example 8 | # ActionView::Base.send :include, Attrtastic::SemanticAttributesHelper 9 | # 10 | # @example Example of useage 11 | # <%= semantic_attributes_for @user do |attr| %> 12 | # <%= attr.attributes "User info" do %> 13 | # <%= attr.attribute :name %> 14 | # <%= attr.attribute :email %> 15 | # <% end %> 16 | # <%= attr.attributes "User details" do %> 17 | # <%= attr.attribute :weight %> 18 | # <%= attr.attribute :height %> 19 | # <%= attr.attribute :age %> 20 | # <% end %> 21 | # <% end %> 22 | module SemanticAttributesHelper 23 | 24 | ## 25 | # Creates attributes for given object 26 | # 27 | # @param[ActiveRecord] record AR instance record for which to display attributes 28 | # @param[Hash] options Opions 29 | # @option options [Hash] :html ({}) Hash with optional :class html class name for html block 30 | # @yield [attr] Block which is yield inside of markup 31 | # @yieldparam [SemanticAttributesBuilder] builder Builder for attributes for given AR record 32 | # 33 | # @example 34 | # <%= semantic_attributes_for @user do |attr| %> 35 | # <%= attr.attributes do %> 36 | # <%= attr.attribute :name %> 37 | # <%= attr.attribute :email %> 38 | # <% end %> 39 | # <% end %> 40 | # 41 | # @example 42 | # <%= semantic_attributes_for @user %> 43 | # 44 | def semantic_attributes_for(record, options = {}, &block) 45 | options[:html] ||= {} 46 | 47 | html_class = [ "attrtastic", record.class.to_s.underscore, options[:html][:class] ].compact.join(" ") 48 | 49 | output = tag(:div, { :class => html_class}, true) 50 | if block_given? 51 | output << capture(SemanticAttributesBuilder.new(record, self), &block) 52 | else 53 | output << capture(SemanticAttributesBuilder.new(record, self)) do |attr| 54 | attr.attributes 55 | end 56 | end 57 | output.safe_concat("") 58 | end 59 | 60 | end 61 | end 62 | 63 | -------------------------------------------------------------------------------- /test/helper.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | require 'shoulda-context' 3 | require 'action_view' 4 | require 'bigdecimal' 5 | 6 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 7 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 8 | require 'attrtastic' 9 | 10 | class TestCase < Test::Unit::TestCase 11 | def html(string) 12 | string.split(/\n/m).map(&:strip).join 13 | end 14 | 15 | def setup 16 | Attrtastic.reset_default_options 17 | end 18 | 19 | def setup_fixtures 20 | @user = User.new.tap do |u| 21 | u.first_name,u.last_name = "John","Doe" 22 | u.email = "john@doe.com" 23 | u.created_at = DateTime.parse("2011-06-02 12:06:42") 24 | u.time = Time.at(946702800) 25 | u.birthday = Date.parse("1953-06-03") 26 | u.float = 54424.22 27 | u.decimal = BigDecimal.new('4454.3435') 28 | u.integer = 45453 29 | end 30 | @blog = Blog.new.tap{|b| b.name,b.url,b.author = "IT Pro Blog","http://www.it.pro.blog",@user} 31 | @blog.posts = [ 32 | Post.new.tap{|p| p.title,p.content = "Hello World!","Hello World!\nInitial post"}, 33 | Post.new.tap{|p| p.title,p.content = "Sorry","Sorry for long delay. Had much stuff on my head..."}, 34 | ] 35 | @user.blog = @blog 36 | 37 | ActionView::Base.send :include, Attrtastic::SemanticAttributesHelper 38 | @template = ActionView::Base.new.tap{ |av| av.output_buffer = ActiveSupport::SafeBuffer.new } 39 | @user_builder = Attrtastic::SemanticAttributesBuilder.new(@user, @template) 40 | @blog_builder = Attrtastic::SemanticAttributesBuilder.new(@blog, @template) 41 | end 42 | end 43 | 44 | class User 45 | attr_accessor :first_name, :last_name, :email, :title, :created_at, :time, :birthday, :float, :decimal, :integer, :blog 46 | 47 | def address 48 | { 49 | :street => "Hellway 13", 50 | :city => "New York", 51 | } 52 | end 53 | 54 | def full_name 55 | [last_name,first_name].join(", ") 56 | end 57 | 58 | def attribute_names 59 | %w( first_name last_name email title created_at time birthday float decimal integer address full_name ) 60 | end 61 | end 62 | 63 | class Blog 64 | attr_accessor :name, :url, :author, :posts 65 | delegate :full_name, :to => :author, :prefix => true 66 | 67 | def attribute_names 68 | %w( name url author_full_name ) 69 | end 70 | end 71 | 72 | class Post 73 | attr_accessor :title, :content 74 | 75 | def attribute_names 76 | %w( title content ) 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /doc/class_list.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 |
28 |

Class List

29 | 38 | 39 | 40 | 45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /doc/top-level-namespace.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Top Level Namespace 8 | 9 | — Documentation by YARD 0.7.2 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 56 | 57 | 58 | 59 |

Top Level Namespace 60 | 61 | 62 | 63 |

64 | 65 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
75 |
76 | 77 |

Defined Under Namespace

78 |

79 | 80 | 81 | Modules: Attrtastic 82 | 83 | 84 | 85 | 86 |

87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 |
95 | 96 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /doc/Attrtastic/Railtie.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Class: Attrtastic::Railtie 8 | 9 | — Documentation by YARD 0.7.2 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 56 | 57 | 58 | 59 |

Class: Attrtastic::Railtie 60 | 61 | 62 | 63 |

64 | 65 |
66 | 67 |
Inherits:
68 |
69 | Rails::Railtie 70 | 71 |
    72 |
  • Object
  • 73 | 74 | 75 | 76 | 77 | 78 |
79 | show all 80 | 81 |
82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |
Defined in:
92 |
lib/attrtastic/railtie.rb
93 | 94 |
95 |
96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
108 | 109 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /doc/method_list.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 |
28 |

Method List

29 | 38 | 39 | 40 | 92 |
93 | 94 | 95 | -------------------------------------------------------------------------------- /doc/Attrtastic.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Module: Attrtastic 8 | 9 | — Documentation by YARD 0.7.2 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 56 | 57 | 58 | 59 |

Module: Attrtastic 60 | 61 | 62 | 63 |

64 | 65 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
Defined in:
75 |
lib/attrtastic.rb,
76 | lib/attrtastic/railtie.rb,
lib/attrtastic/version.rb,
lib/attrtastic/semantic_attributes_helper.rb,
lib/attrtastic/semantic_attributes_builder.rb
77 |
78 | 79 |
80 |
81 | 82 |

Defined Under Namespace

83 |

84 | 85 | 86 | Modules: SemanticAttributesHelper 87 | 88 | 89 | 90 | Classes: Railtie, SemanticAttributesBuilder 91 | 92 | 93 |

94 | 95 |

Constant Summary

96 | 97 |
98 | 99 |
VERSION = 100 | 101 |
102 |
"0.4.2"
103 | 104 |
105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 |
114 | 115 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /test/test_attrtastic.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class TestAttrtastic < TestCase 4 | 5 | context "Attrtastic" do 6 | 7 | setup do 8 | setup_fixtures 9 | end 10 | 11 | should "work with verbose syntax version" do 12 | expected = html <<-EOHTML 13 |
14 |
15 |
User
16 |
    17 |
  1. 18 | First name 19 | John 20 |
  2. 21 |
  3. 22 | Last name 23 | Doe 24 |
  4. 25 |
26 |
27 | 28 |
29 |
Contact
30 |
    31 |
  1. 32 | Email 33 | john@doe.com 34 |
  2. 35 |
36 |
37 |
38 | EOHTML 39 | 40 | actual = @template.semantic_attributes_for(@user) do |attr| 41 | @template.output_buffer << attr.attributes("User") do 42 | @template.output_buffer << (attr.attribute :first_name, :html => {:class => :strong}).to_s 43 | @template.output_buffer << (attr.attribute :last_name).to_s 44 | @template.output_buffer << (attr.attribute :title).to_s 45 | end 46 | @template.output_buffer << attr.attributes(:name => "Contact") do 47 | @template.output_buffer << (attr.attribute :email).to_s 48 | end 49 | end 50 | 51 | assert_equal expected, actual 52 | end 53 | 54 | should "work with compact syntax version" do 55 | expected = html <<-EOHTML 56 |
57 |
58 |
User
59 |
    60 |
  1. 61 | First name 62 | John 63 |
  2. 64 |
  3. 65 | Last name 66 | Doe 67 |
  4. 68 |
69 |
70 | 71 |
72 |
Contact
73 |
    74 |
  1. 75 | Email 76 | john@doe.com 77 |
  2. 78 |
79 |
80 |
81 | EOHTML 82 | 83 | actual = @template.semantic_attributes_for(@user) do |attr| 84 | @template.output_buffer << attr.attributes("User", :first_name, :last_name, :title) 85 | @template.output_buffer << attr.attributes("Contact", :email) 86 | end 87 | 88 | assert_equal expected, actual 89 | end 90 | 91 | context "Default Options" do 92 | should "setup default options" do 93 | assert Attrtastic.default_options.is_a?(Hash) 94 | end 95 | 96 | should "set default options" do 97 | Attrtastic.default_options[:display_empty] = true 98 | expected = {:display_empty => true} 99 | 100 | assert_equal expected, Attrtastic.default_options 101 | end 102 | 103 | should "reset default options" do 104 | Attrtastic.default_options[:display_empty] = true 105 | Attrtastic.reset_default_options 106 | assert_equal Hash.new, Attrtastic.default_options 107 | 108 | end 109 | end 110 | 111 | end 112 | 113 | end 114 | -------------------------------------------------------------------------------- /doc/_index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Documentation by YARD 0.7.2 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 52 | 53 | 54 | 55 |

Documentation by YARD 0.7.2

56 |
57 |

Alphabetic Index

58 | 59 |

File Listing

60 | 67 | 68 |
69 |

Namespace Listing A-Z

70 | 71 | 72 | 73 | 74 | 75 | 76 | 129 | 130 |
77 | 78 | 79 |
    80 |
  • A
  • 81 | 89 |
90 | 91 | 92 |
    93 |
  • R
  • 94 |
      95 | 96 |
    • 97 | Railtie 98 | 99 | (Attrtastic) 100 | 101 |
    • 102 | 103 |
    104 |
105 | 106 | 107 | 127 | 128 |
131 | 132 |
133 | 134 |
135 | 136 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | File: README 8 | 9 | — Documentation by YARD 0.7.2 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 54 | 55 | 56 | 57 |

Attrtastic

58 | 59 |

Attrtastic is simple view helper which can be used to create index/show pages 60 | for any objects (for example Active Model objects). It helps you display 61 | all present attributes of object.

62 | 63 |

If you need compatibility with Rails 2.x, then please install version 0.2.2 of 64 | this gem.

65 | 66 |

Using

67 | 68 |

Install the gem:

69 | 70 |
gem install attrtastic
 71 | 
72 | 73 |

Add to your Gemfile:

74 | 75 |
gem "attrtastic"
 76 | 
77 | 78 |

And use in your views, for example in user/show.erb

79 | 80 |
<%= semantic_attributes_for @user do |attr| %>
 81 |   <%= attr.attributes "User" do %>
 82 |     <%= attr.attribute :first_name %>
 83 |     <%= attr.attribute :last_name %>
 84 |     <%= attr.attribute :avatar do %>
 85 |       <%= image_tag @user.avatar.url %>
 86 |     <% end %>
 87 |   <% end %>
 88 |   <%= attr.attributes "Contact" do %>
 89 |     <%= attr.attribute :email %>
 90 |     <%= attr.attribute :tel %>
 91 |     <%= attr.attribute :fax %>
 92 |   <% end %>
 93 | <% end %>
 94 | 
95 | 96 |

By default attributes which returns #blank? value are ommited, unless 97 | :display_empty => true is added to #attribute.

98 | 99 |

Note on Patches/Pull Requests

100 | 101 | 110 | 111 | 112 |

Copyright

113 | 114 |

Copyright (c) 2009-2011 Boruta Mirosław. See LICENSE for details.

115 | 116 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /doc/file.README.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | File: README 8 | 9 | — Documentation by YARD 0.7.2 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 54 | 55 | 56 | 57 |

Attrtastic

58 | 59 |

Attrtastic is simple view helper which can be used to create index/show pages 60 | for any objects (for example Active Model objects). It helps you display 61 | all present attributes of object.

62 | 63 |

If you need compatibility with Rails 2.x, then please install version 0.2.2 of 64 | this gem.

65 | 66 |

Using

67 | 68 |

Install the gem:

69 | 70 |
gem install attrtastic
 71 | 
72 | 73 |

Add to your Gemfile:

74 | 75 |
gem "attrtastic"
 76 | 
77 | 78 |

And use in your views, for example in user/show.erb

79 | 80 |
<%= semantic_attributes_for @user do |attr| %>
 81 |   <%= attr.attributes "User" do %>
 82 |     <%= attr.attribute :first_name %>
 83 |     <%= attr.attribute :last_name %>
 84 |     <%= attr.attribute :avatar do %>
 85 |       <%= image_tag @user.avatar.url %>
 86 |     <% end %>
 87 |   <% end %>
 88 |   <%= attr.attributes "Contact" do %>
 89 |     <%= attr.attribute :email %>
 90 |     <%= attr.attribute :tel %>
 91 |     <%= attr.attribute :fax %>
 92 |   <% end %>
 93 | <% end %>
 94 | 
95 | 96 |

By default attributes which returns #blank? value are ommited, unless 97 | :display_empty => true is added to #attribute.

98 | 99 |

Note on Patches/Pull Requests

100 | 101 | 110 | 111 | 112 |

Copyright

113 | 114 |

Copyright (c) 2009-2011 Boruta Mirosław. See LICENSE for details.

115 | 116 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /doc/js/full_list.js: -------------------------------------------------------------------------------- 1 | var inSearch = null; 2 | var searchIndex = 0; 3 | var searchCache = []; 4 | var searchString = ''; 5 | 6 | function fullListSearch() { 7 | // generate cache 8 | searchCache = []; 9 | $('#full_list li').each(function() { 10 | var link = $(this).find('.object_link a'); 11 | searchCache.push({name:link.text(), node:$(this), link:link}); 12 | }); 13 | 14 | $('#search input').keyup(function() { 15 | searchString = this.value.toLowerCase(); 16 | if (searchString === "") { 17 | clearTimeout(inSearch); 18 | inSearch = null; 19 | $('#full_list, #content').removeClass('insearch'); 20 | $('#full_list li').removeClass('found').each(function() { 21 | 22 | var link = $(this).find('.object_link a'); 23 | link.text(link.text()); 24 | }); 25 | if (clicked) { 26 | clicked.parents('ul').each(function() { 27 | $(this).removeClass('collapsed').prev().removeClass('collapsed'); 28 | }); 29 | } 30 | highlight(); 31 | } 32 | else { 33 | if (inSearch) clearTimeout(inSearch); 34 | searchIndex = 0; 35 | lastRowClass = ''; 36 | $('#full_list, #content').addClass('insearch'); 37 | $('#noresults').text(''); 38 | searchItem(); 39 | } 40 | }); 41 | 42 | $('#search input').focus(); 43 | $('#full_list').after("
"); 44 | } 45 | 46 | var lastRowClass = ''; 47 | function searchItem() { 48 | for (var i = 0; i < searchCache.length / 50; i++) { 49 | var item = searchCache[searchIndex]; 50 | if (item.name.toLowerCase().indexOf(searchString) == -1) { 51 | item.node.removeClass('found'); 52 | } 53 | else { 54 | item.node.css('padding-left', '10px').addClass('found'); 55 | item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1'); 56 | lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2'; 57 | item.link.html(item.name.replace(new RegExp("(" + 58 | searchString.replace(/([\/.*+?|()\[\]{}\\])/g, "\\$1") + ")", "ig"), 59 | '$1')); 60 | } 61 | 62 | if (searchCache.length === searchIndex + 1) { 63 | searchDone(); 64 | return; 65 | } 66 | else { 67 | searchIndex++; 68 | } 69 | } 70 | inSearch = setTimeout('searchItem()', 0); 71 | } 72 | 73 | function searchDone() { 74 | highlight(true); 75 | if ($('#full_list li:visible').size() === 0) { 76 | $('#noresults').text('No results were found.').hide().fadeIn(); 77 | } 78 | else { 79 | $('#noresults').text(''); 80 | } 81 | $('#content').removeClass('insearch'); 82 | clearTimeout(inSearch); 83 | inSearch = null; 84 | } 85 | 86 | clicked = null; 87 | function linkList() { 88 | $('#full_list li, #full_list li a:last').click(function(evt) { 89 | if ($(this).hasClass('toggle')) return true; 90 | if (this.tagName.toLowerCase() == "li") { 91 | var toggle = $(this).children('a.toggle'); 92 | if (toggle.size() > 0 && evt.pageX < toggle.offset().left) { 93 | toggle.click(); 94 | return false; 95 | } 96 | } 97 | if (clicked) clicked.removeClass('clicked'); 98 | var win = window.top.frames.main ? window.top.frames.main : window.parent; 99 | if (this.tagName.toLowerCase() == "a") { 100 | clicked = $(this).parent('li').addClass('clicked'); 101 | win.location = this.href; 102 | } 103 | else { 104 | clicked = $(this).addClass('clicked'); 105 | win.location = $(this).find('a:last').attr('href'); 106 | } 107 | return false; 108 | }); 109 | } 110 | 111 | function collapse() { 112 | if (!$('#full_list').hasClass('class')) return; 113 | $('#full_list.class a.toggle').click(function() { 114 | $(this).parent().toggleClass('collapsed').next().toggleClass('collapsed'); 115 | highlight(); 116 | return false; 117 | }); 118 | $('#full_list.class ul').each(function() { 119 | $(this).addClass('collapsed').prev().addClass('collapsed'); 120 | }); 121 | $('#full_list.class').children().removeClass('collapsed'); 122 | highlight(); 123 | } 124 | 125 | function highlight(no_padding) { 126 | var n = 1; 127 | $('#full_list li:visible').each(function() { 128 | var next = n == 1 ? 2 : 1; 129 | $(this).removeClass("r" + next).addClass("r" + n); 130 | if (!no_padding && $('#full_list').hasClass('class')) { 131 | $(this).css('padding-left', (10 + $(this).parents('ul').size() * 15) + 'px'); 132 | } 133 | n = next; 134 | }); 135 | } 136 | 137 | function escapeShortcut() { 138 | $(document).keydown(function(evt) { 139 | if (evt.which == 27) { 140 | $('#search_frame', window.top.document).slideUp(100); 141 | $('#search a', window.top.document).removeClass('active inactive'); 142 | $(window.top).focus(); 143 | } 144 | }); 145 | } 146 | 147 | $(escapeShortcut); 148 | $(fullListSearch); 149 | $(linkList); 150 | $(collapse); 151 | -------------------------------------------------------------------------------- /doc/css/full_list.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; 4 | font-size: 13px; 5 | height: 101%; 6 | overflow-x: hidden; 7 | } 8 | 9 | h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; } 10 | .clear { clear: both; } 11 | #search { position: absolute; right: 5px; top: 9px; padding-left: 24px; } 12 | #content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; } 13 | #full_list { padding: 0; list-style: none; margin-left: 0; } 14 | #full_list ul { padding: 0; } 15 | #full_list li { padding: 5px; padding-left: 12px; margin: 0; font-size: 1.1em; list-style: none; } 16 | #noresults { padding: 7px 12px; } 17 | #content.insearch #noresults { margin-left: 7px; } 18 | ul.collapsed ul, ul.collapsed li { display: none; } 19 | li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; } 20 | li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; } 21 | li { color: #888; cursor: pointer; } 22 | li.deprecated { text-decoration: line-through; font-style: italic; } 23 | li.r1 { background: #f0f0f0; } 24 | li.r2 { background: #fafafa; } 25 | li:hover { background: #ddd; } 26 | li small:before { content: "("; } 27 | li small:after { content: ")"; } 28 | li small.search_info { display: none; } 29 | a:link, a:visited { text-decoration: none; color: #05a; } 30 | li.clicked { background: #05a; color: #ccc; } 31 | li.clicked a:link, li.clicked a:visited { color: #eee; } 32 | li.clicked a.toggle { opacity: 0.5; background-position: bottom right; } 33 | li.collapsed.clicked a.toggle { background-position: top right; } 34 | #search input { border: 1px solid #bbb; -moz-border-radius: 3px; -webkit-border-radius: 3px; } 35 | #nav { margin-left: 10px; font-size: 0.9em; display: none; color: #aaa; } 36 | #nav a:link, #nav a:visited { color: #358; } 37 | #nav a:hover { background: transparent; color: #5af; } 38 | 39 | .frames #content h1 { margin-top: 0; } 40 | .frames li { white-space: nowrap; cursor: normal; } 41 | .frames li small { display: block; font-size: 0.8em; } 42 | .frames li small:before { content: ""; } 43 | .frames li small:after { content: ""; } 44 | .frames li small.search_info { display: none; } 45 | .frames #search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; } 46 | .frames #content.insearch #search { background-position: center right; } 47 | .frames #search input { width: 110px; } 48 | .frames #nav { display: block; } 49 | 50 | #full_list.insearch li { display: none; } 51 | #full_list.insearch li.found { display: list-item; padding-left: 10px; } 52 | #full_list.insearch li a.toggle { display: none; } 53 | #full_list.insearch li small.search_info { display: block; } 54 | -------------------------------------------------------------------------------- /doc/js/app.js: -------------------------------------------------------------------------------- 1 | function createSourceLinks() { 2 | $('.method_details_list .source_code'). 3 | before("[View source]"); 4 | $('.toggleSource').toggle(function() { 5 | $(this).parent().next().slideDown(100); 6 | $(this).text("Hide source"); 7 | }, 8 | function() { 9 | $(this).parent().next().slideUp(100); 10 | $(this).text("View source"); 11 | }); 12 | } 13 | 14 | function createDefineLinks() { 15 | var tHeight = 0; 16 | $('.defines').after(" more..."); 17 | $('.toggleDefines').toggle(function() { 18 | tHeight = $(this).parent().prev().height(); 19 | $(this).prev().show(); 20 | $(this).parent().prev().height($(this).parent().height()); 21 | $(this).text("(less)"); 22 | }, 23 | function() { 24 | $(this).prev().hide(); 25 | $(this).parent().prev().height(tHeight); 26 | $(this).text("more..."); 27 | }); 28 | } 29 | 30 | function createFullTreeLinks() { 31 | var tHeight = 0; 32 | $('.inheritanceTree').toggle(function() { 33 | tHeight = $(this).parent().prev().height(); 34 | $(this).parent().toggleClass('showAll'); 35 | $(this).text("(hide)"); 36 | $(this).parent().prev().height($(this).parent().height()); 37 | }, 38 | function() { 39 | $(this).parent().toggleClass('showAll'); 40 | $(this).parent().prev().height(tHeight); 41 | $(this).text("show all"); 42 | }); 43 | } 44 | 45 | function fixBoxInfoHeights() { 46 | $('dl.box dd.r1, dl.box dd.r2').each(function() { 47 | $(this).prev().height($(this).height()); 48 | }); 49 | } 50 | 51 | function searchFrameLinks() { 52 | $('#method_list_link').click(function() { 53 | toggleSearchFrame(this, relpath + 'method_list.html'); 54 | }); 55 | 56 | $('#class_list_link').click(function() { 57 | toggleSearchFrame(this, relpath + 'class_list.html'); 58 | }); 59 | 60 | $('#file_list_link').click(function() { 61 | toggleSearchFrame(this, relpath + 'file_list.html'); 62 | }); 63 | } 64 | 65 | function toggleSearchFrame(id, link) { 66 | var frame = $('#search_frame'); 67 | $('#search a').removeClass('active').addClass('inactive'); 68 | if (frame.attr('src') == link && frame.css('display') != "none") { 69 | frame.slideUp(100); 70 | $('#search a').removeClass('active inactive'); 71 | } 72 | else { 73 | $(id).addClass('active').removeClass('inactive'); 74 | frame.attr('src', link).slideDown(100); 75 | } 76 | } 77 | 78 | function linkSummaries() { 79 | $('.summary_signature').click(function() { 80 | document.location = $(this).find('a').attr('href'); 81 | }); 82 | } 83 | 84 | function framesInit() { 85 | if (window.top.frames.main) { 86 | document.body.className = 'frames'; 87 | $('#menu .noframes a').attr('href', document.location); 88 | $('html head title', window.parent.document).text($('html head title').text()); 89 | } 90 | } 91 | 92 | function keyboardShortcuts() { 93 | if (window.top.frames.main) return; 94 | $(document).keypress(function(evt) { 95 | if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return; 96 | if (typeof evt.target !== "undefined" && 97 | (evt.target.nodeName == "INPUT" || 98 | evt.target.nodeName == "TEXTAREA")) return; 99 | switch (evt.charCode) { 100 | case 67: case 99: $('#class_list_link').click(); break; // 'c' 101 | case 77: case 109: $('#method_list_link').click(); break; // 'm' 102 | case 70: case 102: $('#file_list_link').click(); break; // 'f' 103 | default: break; 104 | } 105 | }); 106 | } 107 | 108 | function summaryToggle() { 109 | $('.summary_toggle').click(function() { 110 | localStorage.summaryCollapsed = $(this).text(); 111 | $(this).text($(this).text() == "collapse" ? "expand" : "collapse"); 112 | var next = $(this).parent().parent().next(); 113 | if (next.hasClass('compact')) { 114 | next.toggle(); 115 | next.next().toggle(); 116 | } 117 | else if (next.hasClass('summary')) { 118 | var list = $('