<!-- Tags that define higher level interactive 'widgets' --> <!-- An enhanced version of Rapid's `<table>` that has support for column sorting, searching and pagination. This tag calls `<table merge-params>`, so the parameters for `<table>` are also available. An [worked example](/tutorials/agility#improve_the_project_page_with_a_searchable_sortable_table) of this tag is available in the [Agility Tutorial](/tutorials/agility) --> <def tag="table-plus" attrs="sort-field, sort-direction, sort-columns" > <% sort_field ||= @sort_field; sort_direction ||= @sort_direction; sort_columns ||= {} %> <% sort_columns['this'] ||= this.member_class.try.name_attribute %> <div class="table-plus" merge-attrs="&attributes - attrs_for(:with_fields) - attrs_for(:table)"> <div class="header" param="header"> <div class="search"> <form param="search-form" method="get" action=""> <hidden-fields for-query-string skip="page, search"/> <span>Search</span> <input class="search" type="search" name="search" value="¶ms[:search]"/> <submit label="Go" class="search-button" param="search-submit"/> </form> </div> </div> <table merge-attrs="&attributes & (attrs_for(:table) + attrs_for(:with_fields))" empty merge-params> <field-heading-row:> <with-field-names merge-attrs="&all_attributes & attrs_for(:with_fields)"> <% col = sort_columns[scope.field_path] || scope.field_path sort = sort_field == col && sort_direction == 'asc' ? "-#{col}" : col sort_url = url_for(params.merge(:sort => sort) - [:page]) col_heading_name = this.member_class.try.view_hints.try.field_name(scope.field_name) || scope.field_name.titleize %> <th param="#{scope.field-name}-heading"> <a href="&sort_url" class="column-sort" param="#{scope.field-name}-heading-link"><%= col_heading_name %></a> <if test="&col == sort_field"> <do param="up-arrow" if="&sort_direction == 'desc'">↑</do> <do param="down-arrow" if="&sort_direction == 'asc'">↓</do> </if> </th> </with-field-names> <th if="&all_parameters[:controls]" class="controls"></th> </field-heading-row> </table> <do param="empty-message" if="empty?">No <collection-name lowercase/> to display</do> <page-nav param if="&this.respond_to?(:page_count) || this.respond_to?(:total_pages)"/> </div> </def> <!-- An enhanced version of Rapid's `<collection>` tag that supports drag-and-drop re-ordering. Each item in the collection has a `<div class="ordering-handle" param="handle">` added, which can be used to drag the item up and down. ### Attributes - `sortable-options` - a hash of options to pass to the `sortable_elemnt` helper. Default are: { :constraint => :vertical, :overlap => :vertical, :scroll => :window, :handle => 'ordering-handle', :complete => [visual_effect(:highlight, attributes[:id])] } ### Controller support This tag assumes the controller has a `reorder` action. This action is added automatically by Hobo's model-controller if the model declares `acts_as_list`. See also [Drag and Drop Reordering](/manual/controllers#drag_and_drop_reordering) in the [Controllers and Routing](/manual/controllers) chapter of the manual. --> <def tag="sortable-collection" attrs="sortable-options"><% singular_name = this.member_class.name.underscore attributes[:id] ||= "#{singular_name}_ordering" route_method = subsite ? "#{subsite}_reorder_#{singular_name.pluralize}_url" : "reorder_#{singular_name.pluralize}_url" reorder_url = send(route_method) %> <collection class="sortable" merge> <item: id="#{singular_name}_#{this.id}" param> <div class="ordering-handle" param="handle" if="&can_edit?">↑<br/>↓</div> <do param="default"><card param/></do> </item:> </collection> <%= if Hobo::Dryml.last_if opts = { :url => reorder_url, :constraint => :vertical, :overlap => :vertical, :scroll => :window, :handle => 'ordering-handle', :complete => [visual_effect(:highlight, attributes[:id])] } opts.update(sortable_options) if sortable_options sortable_element attributes[:id], opts end # FIXME: Make unobstrusive %> </def> <!-- Captures the common pattern of a list of "the first few" cards, along with a link to the rest. --> <def tag="preview-with-more" attrs="name"> <% name ||= collection_name.pluralize -%> <section class="#{name.gsub(' ', '-').dasherize} preview-with-more" param="default"> <h3 param="heading"><%= name.titleize %></h3> <a param="more">More <type-name plural lowercase/>...</a> <collection param/> </section> </def> <!-- Renders a gravatar (see [gravatar.com](http://gravatar.com)) image in side a link to `this`. Requires `this` to have an `email_address` field. Normally called with a user record in context. ### Attributes - `size` - Size in pixels of the image. Defaults to 80. - `rating` - The rating allowed. Defaults to 'g'. See [gravatar.com](http://gravatar.com) for information on ratings. --> <def tag="gravatar" attrs="size, rating"> <% size ||= 80; rating ||= 'g'; digest = Digest::MD5.hexdigest(this.email_address) -%> <a class="gravatar"><img class="gravatar" src="http://www.gravatar.com/avatar/#{digest}?s=#{size}&r=#{rating}" merge-attrs/></a> </def> <!-- Provides an ajax-powered *find-as-you-type* live search field which is hooked up to Hobo's site-side search feature. At the moment this tag is not very flexible. It is not easy to use if for anything other than Hobo's site-wide search. --> <def tag="live-search"> <div class="search"> <label for="search-field">Search</label><input type="search" class="live-search"/> <spinner id="search-spinner"/> </div> <section class="hidden" id="search-results-panel"> <h2>Search Results</h2><div param="close-button">close</div> <section id="search-results"> </section> </section> </def> <!-- A `<select>` menu intended to act as a filter for index pages. See [Filtering stories by status](/tutorials/agility#filtering_stories_by_status) in the [Agility Tutorial](/tutorials/agility) for an example. ### Attributes - `param-name` - the name of the HTTP parameter to use for the filter - `options` - an array of options for the menu. - `no-filter` - The text of the first option which indicates no filter is in effect. Defaults to 'All' --> <def tag="filter-menu" attrs="param-name, options, no-filter, id"> <% no_filter ||= "All" %> <form action="&request.request_uri" method="get" class="filter-menu" merge-attrs="id"> <div> <% selected = options.detect {|o| o.to_s==params[param_name.gsub('-', '_')] } %> <select-menu name="¶m_name" options="&options" selected="&selected" first-option="&no_filter" merge-params/> </div> </form> </def>