Module: JquerySortableTreeHelper

Defined in:
app/helpers/jquery_sortable_tree_helper/render_tree_helper.rb,
app/helpers/jquery_sortable_tree_helper.rb,
app/helpers/jquery_sortable_tree_helper/render_sortable_tree_helper.rb,
app/helpers/jquery_sortable_tree_helper/render_nested_options_helper.rb,
app/helpers/jquery_sortable_tree_helper/render_expandable_tree_helper.rb,
app/helpers/jquery_sortable_tree_helper/render_indented_options_helper.rb

Overview

SECURITY note Prepare your data on server side for rendering or use h.html_escape(node.content) for escape potentially dangerous content

Defined Under Namespace

Modules: RenderExpandableTreeHelper, RenderIndentedOptionsHelper, RenderNestedOptionsHelper, RenderSortableTreeHelper, RenderTreeHelper

Constant Summary collapse

TREE_RENDERERS =

Ilya Zykin, [email protected], Russia [Ivanovo, Saint Petersburg] 2009-2014 github.com/the-teacher

{
  tree: RenderTreeHelper,
  sortable: RenderSortableTreeHelper,
  expandable: RenderExpandableTreeHelper,
  nested_options: RenderNestedOptionsHelper,
  indented_options: RenderIndentedOptionsHelper
}.freeze

Instance Method Summary collapse

Instance Method Details

#add_new_node_form(options) ⇒ Object



74
75
76
77
78
79
80
81
82
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 74

def add_new_node_form(options)
  capture do
    form_for(options[:model].to_sym, form_for_options(options)) do |f|
      title_field = f.text_field options[:title].to_sym, required: true, class: 'form-control', placeholder: I18n.t('sortable_tree.title_of_new_node', default: "The #{options[:title]} of new #{options[:model]}")
      concat (:div, title_field, class: 'form-group')
      concat f.hidden_field :parent_id, value: options[:parent_id]
    end
  end
end

#base_dataObject



36
37
38
39
40
41
42
43
44
45
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 36

def base_data
  {
    model: params[:controller].singularize,
    title: 'title',
    max_levels: 5,
    parent_id: params[:parent_id],
    rebuild_url: send("rebuild_#{params[:controller]}_url"),
    url: url_for(controller: params[:controller], action: :show, id: ':id', format: :json)
  }
end

#base_optionsObject

Server Side Render Tree Helper



100
101
102
103
104
105
106
107
108
109
110
111
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 100

def base_options
  {
    id: :id,
    title: :title,
    node: nil,
    type: :tree,
    root: false,
    level: 0,
    namespace: [],
    controller: params[:controller]
  }
end

#build_children(tree, opts) ⇒ Object



113
114
115
116
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 113

def build_children(tree, opts)
  children = (opts[:boost][opts[:node].id.to_i] || [])
  children.reduce('') { |r, elem| r + build_server_tree(tree, opts.merge(node: elem, root: false, level: opts[:level].next)) }
end

#build_server_tree(tree, options = {}) ⇒ Object



132
133
134
135
136
137
138
139
140
141
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 132

def build_server_tree(tree, options = {})
  tree = [*tree]
  opts = merge_base_options(tree, options)

  if opts[:node]
    raw build_tree_html(self, opts[:render_module], opts.merge(children: build_children(tree, opts)))
  else
    raw (roots(tree) || []).reduce('') { |r, root| r + build_server_tree(tree, opts.merge(node: root, root: true, level: opts[:level].next)) }
  end
end

#build_tree_html(context, render_module, options = {}) ⇒ Object



24
25
26
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 24

def build_tree_html context, render_module, options = {}
  render_module::Render.new(context, options).render_node
end

#define_class_of_elements_of(tree) ⇒ Object

Common Base Methods



16
17
18
19
20
21
22
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 16

def define_class_of_elements_of tree
  case
    when tree.is_a?(ActiveRecord::Relation) then tree.name.to_s.underscore.downcase
    when tree.empty?                        then nil
    else tree.first.class.to_s.underscore.downcase
  end
end

#expandable_tree(tree, options = {}) ⇒ Object



92
93
94
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 92

def expandable_tree(tree, options = {})
  build_server_tree(tree, { type: :expandable }.merge!(options))
end

#fake_node(options) ⇒ Object



51
52
53
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 51

def fake_node(options)
  OpenStruct.new(options[:title] => '', id: ':id', children: nil)
end

#form_for_options(options) ⇒ Object



65
66
67
68
69
70
71
72
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 65

def form_for_options(options)
  {
    html: { id: "new-#{options[:model]}-form" },
    url: send("#{options[:model].pluralize}_path", format: :json),
    method: :post,
    remote: true
  }
end

#indented_options(tree, options = {}) ⇒ Object



88
89
90
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 88

def indented_options(tree, options = {})
  build_server_tree(tree, { type: :indented_options }.merge!(options))
end

#just_tree(tree, options = {}) ⇒ Object

Shortcuts



32
33
34
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 32

def just_tree(tree, options = {})
  build_server_tree(tree, { type: :tree }.merge!(options))
end

#merge_base_options(tree, options) ⇒ Object



123
124
125
126
127
128
129
130
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 123

def merge_base_options(tree, options)
  opts = base_options.merge(options)
  opts[:namespace] = [*opts[:namespace]]
  opts[:render_module] ||= TREE_RENDERERS[opts[:type]]
  opts[:klass] ||= define_class_of_elements_of(tree)
  opts[:boost] ||= tree.group_by { |item| item.parent_id.to_i }
  opts
end

#nested_options(tree, options = {}) ⇒ Object



84
85
86
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 84

def nested_options(tree, options = {})
  build_server_tree(tree, { type: :nested_options }.merge!(options))
end

#roots(tree) ⇒ Object



118
119
120
121
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 118

def roots(tree)
  min_parent_id = tree.map(&:parent_id).compact.min
  tree.select { |e| e.parent_id == min_parent_id }
end

#sortable_tree(tree, options = {}) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 55

def sortable_tree(tree, options = {})
  space(20) +
  add_new_node_form(base_data.merge(options)) +
  (:ol, build_tree_html(self, TREE_RENDERERS[:sortable], base_options.merge(options).merge({ node: fake_node(options) })), class: 'fake-node hidden', style: 'display: none;') +
  (:ol, build_server_tree(tree, { type: :sortable }.merge!(options)),
              class: 'sortable_tree',
              data: base_data.merge(options.slice(:parent_id, :model, :rebuild_url, :title, :max_levels))
  )
end

#space(height) ⇒ Object



47
48
49
# File 'app/helpers/jquery_sortable_tree_helper.rb', line 47

def space(height)
  (:div, ' '.html_safe, style: "height: #{height}px;")
end