วิธีที่ดีที่สุดในการเพิ่มคลาส "ปัจจุบัน" เพื่อนำทางใน Rails 3


111

ฉันมีหน้าคงที่ในเมนูการนำทาง ฉันต้องการเพิ่มคลาสเช่น "current" ให้กับรายการที่กำลังแสดงอยู่

วิธีที่ฉันทำคือเพิ่มวิธีการช่วยเหลือจำนวนมาก (แต่ละวิธีสำหรับหนึ่งรายการ) เพื่อตรวจสอบตัวควบคุมและการกระทำ

def current_root_class
  'class="current"' if controller_name == "homepage" && action_name == "index" 
end

<ul>
  <li <%= current_root_class %>><%= link_to "Home", root_path %>

จะมีวิธีไหนดีกว่ากัน!? วิธีปัจจุบันของฉันมันโง่มาก ......

คำตอบ:


56

ไม่ใช่คำตอบที่แท้จริงที่นี่เพราะฉันใช้วิธีเดียวกับคุณ ฉันเพิ่งกำหนดวิธีการช่วยเหลือเพื่อทดสอบคอนโทรลเลอร์หรือการดำเนินการหลายอย่าง:

ใน application_helper.rb

  def controller?(*controller)
    controller.include?(params[:controller])
  end

  def action?(*action)
    action.include?(params[:action])
  end

จากนั้นคุณสามารถใช้if controller?("homepage") && action?("index", "show")ในมุมมองของคุณหรือวิธีการช่วยเหลืออื่น ๆ ...


วิธีของคุณเหมาะสมที่สุดเมื่อมีบางหน้าที่จัดการโดยตัวควบคุม / การกระทำที่แตกต่างกัน แต่อยู่ในรายการเมนูเดียวกันใช่ไหม? คุณพบข้อดีมากกว่านี้หรือไม่ ~?
PeterWong

ไม่มีข้อได้เปรียบอีกต่อไปยกเว้นความกระชับของไวยากรณ์ ฉันอยากรู้ว่ามีใครมีทางออกที่ดีกว่านี้บ้างไหม
Yannis

ฉันทำวิธีนี้ประสบความสำเร็จอย่างมาก เพิ่มโค้ดนี้ในมุมมอง: <% = link_to "Users", users_path, class: (controller? ("users")? 'selected': nil)%> เรียบร้อยจริงๆที่ใช้งานได้ทั้ง / users และ / users / new .
Andreas

1
การปรับปรุงอาจเป็นไปได้controller_nameและaction_nameแทนที่จะเป็น params
Francesco Belladonna

ทำได้ดี. ฉันไม่ได้คิดที่จะรักษาความเรียบง่ายนี้ แต่เครื่องชั่งนี้ดีมาก +1
newdark-it

290

ฉันเรียกผู้ช่วยว่าnav_link:

def nav_link(link_text, link_path)
  class_name = current_page?(link_path) ? 'current' : ''

  content_tag(:li, :class => class_name) do
    link_to link_text, link_path
  end
end

ใช้เช่น:

nav_link 'Home', root_path

ซึ่งจะสร้าง HTML เช่น

<li class="current"><a href="/">Home</a></li>

3
ใช้งานได้ดีกับ twitter ootstrap หากคุณใช้ twitter bootstrap navbar twitter.github.com/bootstrap/examples/hero.html
Lee McAlilly

41
เปลี่ยนเป็น class_name = current_page? (link_path)? 'current': ไม่มีถ้าคุณไม่ต้องการให้แท็กชั้นเรียนแสดงเมื่อไม่อยู่ในหน้าปัจจุบัน
Matthew Hui

1
คุณจะแก้ไขสิ่งนี้สำหรับรายการซ้อนที่ใช้ในดรอปดาวน์ได้อย่างไร
doremi

9
แห้งเป็นทะเลทราย
ออร์แลนโด

1
ฉันได้เพิ่มอาร์กิวเมนต์ extra_classes = nil, id = nil แล้วภายใน content_tag content_tag (: li, class: [class_name, extra_classes], id: id) เพื่อให้คุณสามารถเพิ่มคลาสและ id ของคุณเองให้กับองค์ประกอบได้ :)
จอน

72

ใช้ตัวcurrent_page?ช่วยเพื่อพิจารณาว่าคุณควรมอบหมาย"current"ชั้นเรียนหรือไม่ ตัวอย่างเช่น:

<%= 'active' if current_page?(home_about_path) %>

หมายเหตุคุณยังสามารถส่งผ่านเส้นทาง (ไม่เพียง แต่กัญชาของตัวเลือก) current_page?(root_path)เช่น:


3
มีวิธีทำให้สิ่งนี้ละเว้นพารามิเตอร์แบบสอบถามหรือไม่
Mohamad

@ Mohamad คุณสามารถทำได้: current_page? (ตัวควบคุม: 'ผู้ใช้', การกระทำ: 'ดัชนี')
nilid

26

ฉันใช้ฟังก์ชัน nav_link (ข้อความลิงค์) นี้ใน application_helper.rb (Rails 3) เพื่อให้งานเสร็จและมันจะม้วนลิงค์แถบนำทาง bootstrap twitter 2.0 ของฉันให้ฉัน

def nav_link(text, link)
    recognized = Rails.application.routes.recognize_path(link)
    if recognized[:controller] == params[:controller] && recognized[:action] == params[:action]
        content_tag(:li, :class => "active") do
            link_to( text, link)
        end
    else
        content_tag(:li) do
            link_to( text, link)
        end
    end
end

ตัวอย่าง:

<%=nav_link("About Us", about_path) %>

สิ่งนี้สามารถทำให้ง่ายขึ้นโดยใช้current_page?วิธีการเช่นเดียวกับคำตอบอื่น ๆ
Teemu Leisti

10

วิธีที่ฉันทำคือเพิ่มฟังก์ชันตัวช่วยใน application_helper

def current_class?(test_path)
  return 'current' if request.request_uri == test_path
  ''
end

จากนั้นในการนำทาง

<%= link_to 'Home', root_path, :class => current_class?(root_path) %>

ซึ่งจะทดสอบเส้นทางการเชื่อมโยงกับหน้าปัจจุบัน uri และส่งคืนคลาสปัจจุบันของคุณหรือสตริงว่าง

ฉันไม่ได้ทดสอบสิ่งนี้อย่างละเอียดและฉันยังใหม่กับ RoR มาก (หลังจากใช้ PHP มาหลายสิบปีแล้ว) ดังนั้นหากสิ่งนี้มีข้อบกพร่องที่สำคัญฉันชอบที่จะได้ยิน

อย่างน้อยวิธีนี้คุณต้องมีฟังก์ชันตัวช่วย 1 ตัวและการโทรง่ายๆในแต่ละลิงค์


1
เพียงแค่ปัญหา ฉันใช้ request.path แทน request_uri (request_uri ใช้งานไม่ได้อาจเป็นปัญหาเวอร์ชันราง?) คำตอบของคุณสะอาดและสง่างามในความคิดของฉัน
Tony

6

เพื่อสร้างคำตอบของ @Skilldrick ...

หากคุณเพิ่มรหัสนี้ใน application.js จะทำให้แน่ใจว่าเมนูแบบเลื่อนลงใด ๆ ที่มีลูกที่ใช้งานอยู่จะถูกทำเครื่องหมายว่าใช้งานอยู่ ...

$('.active').closest('li.dropdown').addClass('active');

ในการสรุปรหัสสนับสนุน> เพิ่มตัวช่วยที่เรียกว่า nav_link:

def nav_link_to(link_text, link_path)
  class_name = current_page?(link_path) ? 'active' : ''

  content_tag(:li, :class => class_name) do
    link_to link_text, link_path
  end
end

ใช้เช่น:

nav_link_to 'Home', root_path

ซึ่งจะสร้าง HTML เช่น

<li class="active"><a href="/">Home</a></li>

4

ฉันคิดว่าวิธีที่ดีที่สุดคือ

application_helper.rb:

def is_active(controller, action)       
  params[:action] == action && params[:controller] == controller ? "active" : nil        
end

และในเมนู:

<li class="<%= is_active('controller', 'action') %>">

จะเว้นชั้นว่างไว้ "" แบบนั้นได้ไหม
Harsha MV

ใช่. อาจดูแปลกหากคุณดูแหล่งที่มาเห็นแอตทริบิวต์คลาสว่างเปล่ามากมาย แต่เป็น HTML ที่ถูกต้อง
kobaltz

คุณสามารถใช้ได้<%= content_tag(:li, "Click me", class: is_active('controller', 'action')) %>มันจะไม่พิมพ์แอตทริบิวต์คลาสสำหรับศูนย์ apidock.com/rails/ActionView/Helpers/TagHelper/content_tag
neonmate

4

ฉันรู้ว่ามันเป็นคำตอบที่ล้าสมัย แต่คุณสามารถละเว้นการตรวจสอบหน้าปัจจุบันทั้งหมดเหล่านี้ได้โดยใช้ตัวช่วยlink_to ที่เรียกว่าactive_link_to gem ซึ่งทำงานได้ตรงกับที่คุณต้องการเพิ่มคลาสที่ใช้งานอยู่ในลิงก์ของหน้าปัจจุบัน


4

นี่คือตัวอย่างทั้งหมดเกี่ยวกับวิธีการเพิ่มคลาสที่ใช้งานอยู่ในหน้าเมนู bootstrap ในมุมมองราง

    <li class="<%= 'active' if current_page?(root_path) %>"><%= link_to 'Home', controller: "welcome" %></li>
    <li class="<%= 'active' if current_page?(about_path) %>"><%= link_to 'About us', about_path %></li>
   <li class="<%= 'active' if current_page?(contact_path) %>"><%= link_to 'Contact us', contact_path %></li>

3

ผมใช้อัญมณีที่น่ากลัวที่เรียกว่าแท็บ on Rails


1
ขอบคุณสำหรับคำแนะนำ เนื่องจากการนำทางของฉันเรียบง่ายมากและมีเพียงชิ้นเดียวที่มีไอเท็มเล็ก ๆ น้อย ๆ อัญมณีจึงน่าจะใช้พลังงานมากเกินไป
PeterWong

3

ฉันมี nav_link เวอร์ชันที่รวบรัดกว่าซึ่งทำงานเหมือนกับ link_to แต่ได้รับการปรับแต่งให้ส่งออกแท็ก li แบบตัด

ใส่สิ่งต่อไปนี้ใน application_helper.rb ของคุณ

def nav_link(*args, &block)
    if block_given?
      options      = args.first || {}
      html_options = args.second
      nav_link(capture(&block), options, html_options)
    else
      name         = args[0]
      options      = args[1] || {}
      html_options = args[2]

      html_options = convert_options_to_data_attributes(options, html_options)
      url = url_for(options)

      class_name = current_page?(url) ? 'active' : nil

      href = html_options['href']
      tag_options = tag_options(html_options)

      href_attr = "href=\"#{ERB::Util.html_escape(url)}\"" unless href
      "<li class=\"#{class_name}\"><a #{href_attr}#{tag_options}>#{ERB::Util.html_escape(name || url)}</a></li>".html_safe
    end
  end

หากคุณดูโค้ดด้านบนและเปรียบเทียบกับโค้ด link_to ใน url_helper.rb ข้อแตกต่างเพียงอย่างเดียวคือการตรวจสอบว่า url เป็นเพจปัจจุบันหรือไม่และเพิ่มคลาส "active" ลงในแท็ก li แบบตัด นี่เป็นเพราะฉันใช้ตัวช่วย nav_link กับส่วนประกอบ navของ Twitter Bootstrap ซึ่งต้องการให้ลิงก์รวมอยู่ในแท็ก li และคลาส "active" ที่ใช้กับ li ด้านนอก

สิ่งที่ดีเกี่ยวกับโค้ดด้านบนคือช่วยให้คุณสามารถส่งผ่านบล็อกไปยังฟังก์ชันได้เช่นเดียวกับที่คุณทำกับ link_to

ตัวอย่างเช่นรายการการนำทาง bootstrap พร้อมไอคอนจะมีลักษณะดังนี้:

บาง:

ul.nav.nav-list
  =nav_link root_path do
    i.icon-home
    |  Home
  =nav_link "#" do
    i.icon-user
    |  Users

เอาท์พุท:

<ul class="nav nav-list">
  <li class="active">
    <a href="/">
      <i class="icon-home"/>
      Home
    </a>
  </li>
  <li>
    <a href="#">
      <i class="icon-users"/>
      Users
    </a>
  </li>
</ul>

นอกจากนี้เช่นเดียวกับตัวช่วย link_to คุณสามารถส่งผ่านตัวเลือก HTML ไปยัง nav_link ซึ่งจะนำไปใช้กับแท็ก

ตัวอย่างการส่งชื่อสำหรับจุดยึด:

บาง:

ul.nav.nav-list
  =nav_link root_path, title:"Home" do
    i.icon-home
    |  Home
  =nav_link "#", title:"Users" do
    i.icon-user
    |  Users

เอาท์พุท:

<ul class="nav nav-list">
  <li class="active">
    <a href="/" title="Home">
      <i class="icon-home"/>
      Home
    </a>
  </li>
  <li>
    <a href="#" title="Users">
      <i class="icon-users"/>
      Users
    </a>
  </li>
</ul>

น่ากลัว สำหรับฉันนี่เป็นตัวเลือกที่ทำได้ดีที่สุดเพราะอนุญาตให้บล็อกได้ ขอบคุณมาก!
Kasperi

3

สำหรับฉันโดยส่วนตัวฉันใช้คำตอบที่หลากหลายที่นี่

<li class="<%= 'active' if current_page?(inventory_index_path) %>"><a href="#">Menu</a></li>

ฉันใช้ css ที่เป็นรูปธรรมและวิธีการทำให้หมวดหมู่หลักยุบได้โดยใช้โค้ดด้านล่าง

$('.active').closest(".collapsible.collapsible-accordion")
            .find(".collapsible-header")
            .click();

หวังว่ามันจะช่วยใครบางคน


ลืมเรื่องนี้ไป ขอบคุณที่โพสต์ข้อความนี้เพื่อเตือนความจำ
newdark-it

2

current_page?วิธีการไม่เพียงพอมีความยืดหยุ่นสำหรับฉัน (บอกว่าคุณตั้งค่าการควบคุม แต่ไม่ดำเนินการแล้วมันจะกลับจริงในการดำเนินการควบคุมดัชนีฯ ) ดังนั้นฉันได้ทำนี้ขึ้นอยู่กับคำตอบอื่น ๆ :

  def nav_link_to(link_text, link_path, checks=nil)
    active = false
    if not checks.nil?
      active = true
      checks.each do |check,v|
        if not v.include? params[check]
          active = false
          break
        end
      end
    end

    return content_tag :li, :class => (active ? 'active' : '') do
      link_to link_text, link_path
    end
  end

ตัวอย่าง:

nav_link_to "Pages", pages_url, :controller => 'pages'

ขอบคุณสำหรับคำตอบ. ฉันคิดว่าของคุณคล้ายกับคำตอบที่ยอมรับจริง ๆ :)
PeterWong

ฉันเจอคำตอบนี้ผ่าน Google ตั้งแต่ฉันประสบปัญหานี้ดังนั้นฉันคิดว่าฉันจะช่วยคนอื่น ๆ ที่เจอปัญหานี้เช่นกัน :)
สัมพันธ์กัน

2

อ้อ! ดูบทความนี้: วิธีที่ดีกว่าในการเพิ่มคลาส 'ที่เลือก' ไปยังลิงค์ใน Rails

วาง nav_link_helper.rb ลงในแอพ / ตัวช่วยและทำได้ง่ายเหมือน:

<%= nav_link 'My_Page', 'http://example.com/page' %>

ตัวช่วย nav_link ทำงานเหมือนกับ Rails link_to helper มาตรฐาน แต่จะเพิ่มคลาส 'ที่เลือก' ลงในลิงก์ของคุณ (หรือ wrapper) หากตรงตามเกณฑ์ที่กำหนด ตามค่าเริ่มต้นหาก URL ปลายทางของลิงก์เป็น url เดียวกับ url ของหน้าปัจจุบันคลาสเริ่มต้นของ 'selected' จะถูกเพิ่มลงในลิงก์

มีส่วนสำคัญอยู่ที่นี่: https://gist.github.com/3279194

อัปเดต: นี่คืออัญมณี: http://rubygems.org/gems/nav_link_to


นี่เป็นสิ่งที่ดี ฉันนำไปใช้และเพิ่มการปรับเปลี่ยนเพื่อสนับสนุนการตั้งชื่อคลาสให้กับองค์ประกอบที่ไม่ได้เลือกและเป็นความคิดเห็นในส่วนสำคัญ
Teemu Leisti

2

ฉันใช้ตัวช่วยง่ายๆเช่นนี้สำหรับลิงก์ระดับบนสุดเพื่อให้/stories/my-storyหน้าไฮไลต์/storiesลิงก์

def nav_link text, url

  active = (url == request.fullpath || (url != '/' && request.fullpath[0..(url.size-1)] == url))

  "<li#{ active ? " class='selected'" : '' }><a href='#{url}'>#{text}</a></li>".html_safe

end

2

ให้ฉันแสดงวิธีแก้ปัญหาของฉัน:

_header.html.erb :

  <ul class="nav">
    <%= nav_tabs(@tabs) %> 
  </ul>

application_helper.rb :

 def nav_tabs(tabs=[])
    html = []
    tabs.each do |tab| 
      html << (content_tag :li, :class => ("current-page" if request.fullpath.split(/[\??]/)[0] == tab[:path]) do
        link_to tab[:path] do
          content_tag(:i, '', :class => tab[:icon]) +
          tag(:br) +
          "#{tab[:name]}"
        end
      end)        
    end

    html.join.html_safe
  end

application_controller.rb :

before_filter :set_navigation_tabs

private
def set_navigation_tabs
  @tabs = 
    if current_user && manager?
      [
        { :name => "Home", :icon => "icon-home", :path => home_index_path },
        { :name => "Portfolio", :icon => "icon-camera", :path => portfolio_home_index_path },
        { :name => "Contact", :icon => "icon-envelope-alt", :path => contact_home_index_path }
      ]
    elsif current_user && client?
      ...
    end

1

ตามคำตอบของ Skilldrickฉันจะเปลี่ยนเป็นดังต่อไปนี้:

def nav_link(*args, &block)
  is_active = current_page?(args[0]) || current_page?(args[1])
  class_name = is_active ? 'active' : nil

  content_tag(:li, class: class_name) do
    link_to *args, &block
  end
end

เพื่อให้มีประโยชน์มากขึ้น


1

เวอร์ชันนี้มีพื้นฐานมาจาก @ Skilldrick แต่อนุญาตให้คุณเพิ่มเนื้อหา html

ดังนั้นคุณสามารถทำได้:

nav_link "A Page", a_page_path

แต่ยัง:

nav_link a_page_path do
  <strong>A Page</strong>
end

หรือเนื้อหา html อื่น ๆ (คุณสามารถเพิ่มไอคอนได้เช่น)

ผู้ช่วยคือ:

  def nav_link(name = nil, options = nil, html_options = nil, &block)
    html_options, options, name = options, name, block if block_given?
    options ||= {}

    html_options = convert_options_to_data_attributes(options, html_options)

    url = url_for(options)
    html_options['href'] ||= url

    class_name = current_page?(url) ? 'current' : ''
    content_tag(:li, :class => class_name) do  
      content_tag(:a, name || url, html_options, &block)
    end
  end

1

ฉันคิดว่าฉันคิดวิธีง่ายๆที่อาจเป็นประโยชน์สำหรับกรณีการใช้งานจำนวนมาก สิ่งนี้ช่วยให้ฉัน:

  • สนับสนุนไม่เพียง แต่ข้อความธรรมดา แต่มี HTML อยู่ภายใน link_to (เช่นเพิ่มไอคอนภายในลิงก์)
  • เพิ่มโค้ดเพียงไม่กี่บรรทัด application_helper.rb
  • ต่อท้ายactiveชื่อคลาสทั้งหมดขององค์ประกอบลิงก์แทนที่จะเป็นคลาสเดียว

ดังนั้นเพิ่มสิ่งนี้ในapplication_helper.rb:

def active_class?(class_name = nil, path)
  class_name ||= ""
  class_name += " active" if current_page?(path)
  class_name.strip!
  return class_name
end

และในเทมเพลตของคุณคุณสามารถมีสิ่งนี้:

<div class="col-xs-3">
  <%= link_to root_path, :class => active_class?("btn btn-outline-primary", root_path) do %>
    <i class="fa fa-list-alt fa-fw"></i>
  <% end %>
</div>

ในฐานะโบนัสคุณสามารถระบุหรือไม่class_nameใช้มันได้ดังนี้:<div class="<%= current_page?(root_path) %>">

ขอบคุณคำตอบก่อนหน้า1 , 2และทรัพยากร


0

ทั้งหมดนี้ใช้งานได้กับแถบนำทางธรรมดา แต่เมนูย่อยแบบเลื่อนลงล่ะ เมื่อเลือกเมนูย่อยรายการเมนูด้านบนควรทำให้เป็น 'ปัจจุบัน' ในกรณีนี้ tabs_on_rails ฉันจะเป็นทางออก


0

นี่คือวิธีที่ฉันแก้ไขในโครงการปัจจุบันของฉัน

def class_if_current_page(current_page = {}, *my_class)
    if current_page?(current_page)
      my_class.each do |klass|
        "#{klass} "
      end
    end
  end

จากนั้น ..

li = link_to company_path 
    class: %w{ class_if_current_page( { status: "pending" }, "active" ), "company" } do  
      Current Company

0

วิธีง่ายๆของฉัน -

application.html.erb,

<div class="navbar">
    <div class="<%= @menu1_current %> first-item"><a href="/menu1"> MENU1 </a></div>
    <div class="<%= @menu2_current %>"><a href="/menu2"> MENU2 </a></div>
    <div class="<%= @menu3_current %>"><a href="/menu3"> MENU3 </a></div>
    <div class="<%= @menu4_current %> last-item"><a href="/menu4"> MENU4 </a></div>
</div>

main_controller.erb,

class MainController < ApplicationController
    def menu1
        @menu1_current = "current"
    end

    def menu2
        @menu2_current = "current"
    end

    def menu3
        @menu3_current = "current"
    end

    def menu4
        @menu4_current = "current"
    end
end

ขอบคุณ


0

หากคุณต้องการสนับสนุนแฮชตัวเลือก html ในมุมมอง ตัวอย่างเช่นหากคุณต้องการเรียกใช้ด้วยคลาส CSS หรือ id อื่นคุณสามารถกำหนดฟังก์ชันตัวช่วยได้เช่นนี้

def nav_link_to(text, url, options = {})
  options[:class] ||= ""
  options[:class] += " active"
  options[:class].strip!
  link_to text, url, options
end

ดังนั้นในมุมมองให้เรียกตัวช่วยนี้แบบเดียวกับที่คุณเรียก link_to helper

<%= nav_link_to "About", about_path, class: "my-css-class" %>

0

สร้างวิธีการApplicationHelperดังต่อไปนี้

def active controllers, action_names = nil
  class_name = controllers.split(",").any? { |c| controller.controller_name == c.strip } ? "active" : ""
  if class_name.present? && action_names.present?
    return action_names.split(",").any? { |an| controller.action_name == an.strip } ? "active" : ""
  end
  class_name
end

ตอนนี้ใช้ในมุมมองด้านล่างกรณีการใช้งาน

1.สำหรับการกระทำทั้งหมดของคอนโทรลเลอร์เฉพาะใด ๆ

<li class="<%= active('controller_name')%>">
....
</li>

2.สำหรับการกระทำทั้งหมดของคอนโทรลเลอร์หลายตัว (โดยคั่นด้วยเครื่องหมายจุลภาค)

<li class="<%= active('controller_name1,controller_name2')%>">
....
</li>

3.สำหรับการดำเนินการเฉพาะของคอนโทรลเลอร์เฉพาะใด ๆ

<li class="<%= active('controller_name', 'action_name')%>">
....
</li>

4.สำหรับการดำเนินการเฉพาะของคอนโทรลเลอร์หลายตัว (โดยคั่นด้วยเครื่องหมายจุลภาค)

<li class="<%= active('controller_name1,controller_name2', 'action_name')%>">
....
</li>

5.สำหรับการกระทำบางอย่างของคอนโทรลเลอร์เฉพาะใด ๆ

<li class="<%= active('controller_name', 'index, show')%>">
....
</li>

6.สำหรับการกระทำบางอย่างของคอนโทรลเลอร์หลายตัว (โดยคั่นด้วยเครื่องหมายจุลภาค)

<li class="<%= active('controller_name1,controller_name2', 'index, show')%>">
....
</li>

หวังว่าจะช่วยได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.