On Mar 26, 10:13 am, “Conrad T.” [email protected] wrote:
Hey, if you post the relevant code, then people within this group can
better assist you. For example, view, partials, and other relevant
code.
Alright
Here goes, but I’m in the middle of making that js function generic,
so it’s not all kosher there
Also, note that I pass along :update, :partial, and
optionally :partial_on_failure on my remote requests. This is because
I need to update more than one thing when rendering the results (I’ve
created a status console div that pops up with error messages for
models, and notices and warnings) - I handle these params myself, and
shouldn’t be considered equivalent to those normally placed in the
options hash for remote requests.
Here’s the code:
<%
Get the controller name from the locals hash (if someone
initialized us), from the params (if we called ourselves),
or from the controller that was called which resulted in this view
being rendered.
controller_name ||= params[:poly_tree_controller_name] ||
request.parameters[‘controller’] || raise(“I need to know what
controller to query when doing stuff with the tree nodes!”)
Get the node from the locals hash, or look for one instantiated in
the controller:
node_instance_name = controller_name.singularize.sub(/^.+//, ‘’)
node = node || instance_variable_get(“@#{node_instance_name}”) ||
raise(“I need a node to start rendering the tree!”)
Get the class for the node:
node_class = Kernel.const_get(node.class.to_s)
Did we get a parent_content_id via params?
parent_content_id = params[:poly_tree_parent_content_id]
Also, when rendering children, we actually send the parent, then
state that we want the children. Let’s remember the parent’s id:
parent_node_id = node.id
Check if we’re supposed to render the children rather than the
node itself:
expanded = (params[:poly_tree_expanded] &&
params[:poly_tree_expanded] == ‘true’)
If we are, we throw the children in an array, otherwise we just
through this node in an array:
nodes = expanded ? node.children : [node]
Get a content_partial and create_partial from the locals hash (if
someone initialized us),
from the params (if we called ourselves), or try defaults in the
appropriate view directory:
content_partial ||= params[:poly_tree_content_partial] || “/
#{controller_name}/tree_node”
create_partial ||= params[:poly_tree_create_partial] || “/
#{controller_name}/edit”
Is this an unsaved model?
model_is_unsaved = node.id.nil?
Is this create mode?
create_new_after_render =
(params[:poly_tree_create_new_after_render] &&
params[:poly_tree_create_new_after_render] == ‘true’)
Render whichever nodes we’re supposed to render:
nodes.each { |node|
content_element_id = model_is_unsaved ?
“new_child_node_#{Time.now.to_f.to_s.gsub(/
./,‘’)}of#{node_instance_name}#{node.parent_id}" :
"tree_node_for#{node_instance_name}_#{node.id}” %>
HERE’S ME CURRENTLY EDITING THIS FUNCTION, SO EXPECT THINGS TO BE
BROKEN
<%= (“function #{reload_function}(target_element_id, model_id) {”
+
(remote_function(:url => {
:controller =>
controller_name,
:action
=> :show,
:id =>
‘model_id’,
:poly_tree_expanded =>
‘false’,
:poly_tree_content_partial =>
content_partial,
:poly_tree_create_partial =>
create_partial,
:update =>
‘target_element_id’,
:partial => ‘/
tree_node’
},
:before =>
“Element.show(‘#{content_element_id}_activity_indicator’)”,
:success =>
“Element.hide(‘#{content_element_id}_collapse_button’);Element.show(‘#{content_element_id}_expand_button’);”,
:complete =>
“Element.hide(‘#{content_element_id}_activity_indicator’)”)) +
“;}”).gsub(/model_id/, “’ + model_id + '”).gsub(/
target_element_id/, “’ + target_element_id +
'”).in_javascript_tags
%>
<div id="<%= content_element_id %>" class="tree_node">
<%= # This one tags this node as having a parent. Later, after
this item is deleted, we can use javascript to check for the existance
of this id.
# Knowing that our siblings will be tagged with the same id,
if we get a positive, then we know that siblings still exist, if not,
we know that
# the parent is now childless and should not be show expand/
collapse buttons anymore.
‘
’ if
parent_content_id
%>
<div class="tools">
<!-- Delete button -->
<span id="<%= content_element_id %>_delete_button"<%= '
style=“display:none;”’ if model_is_unsaved %>>
<%= link_to_remote( icon_for_backend_list_delete,
:url => {
:controller =>
controller_name,
:action
=> :delete,
:id =>
node.id,
:poly_tree_expanded =>
params[:poly_tree_expanded],
:poly_tree_content_partial =>
content_partial,
:poly_tree_create_partial =>
create_partial,
:update =>
content_element_id,
:partial =>
‘/nothing’,
:partial_on_failure =>
‘/tree_node’
},
:before =>
“Element.show(‘#{content_element_id}_activity_indicator’)”,
:complete => “if ($
(‘#{parent_content_id}_child’) == null)
{ Element.hide(‘#{parent_content_id}_collapse_button’); };”
) %>
<!-- Expand button -->
<span id="<%= content_element_id %>_expand_button"<%= '
style=“display:none;”’ unless node.children.size > 0 %>>
<%= link_to_remote( icon_for_backend_list_expand,
:url => {
:controller
=> controller_name,
:action
=> :show,
:id
=> node.id,
:poly_tree_expanded
=> ‘true’,
:poly_tree_content_partial
=> content_partial,
:poly_tree_create_partial
=> create_partial,
:poly_tree_parent_content_id
=> content_element_id,
:update
=> “#{content_element_id}_children”,
:partial
=> ‘/tree_node’,
:insert_at
=> ‘top’
},
:before =>
“Element.show(‘#{content_element_id}_activity_indicator’)”,
:success =>
“Element.show(‘#{content_element_id}_collapse_button’);Element.hide(‘#{content_element_id}_expand_button’);Element.show(‘#{content_element_id}_expanded_create_button’);Element.hide(‘#{content_element_id}_collapsed_create_button’);”,
:complete =>
“Element.hide(‘#{content_element_id}_activity_indicator’)”) %>
<!-- Collapse button -->
<span id="<%= content_element_id %>_collapse_button"
style=“display:none;”>
<%= link_to_remote( icon_for_backend_list_collapse,
:url => {
:controller =>
controller_name,
:action
=> :show,
:id =>
node.id,
:poly_tree_expanded =>
‘false’,
:poly_tree_content_partial =>
content_partial,
:poly_tree_create_partial =>
create_partial,
:update =>
content_element_id,
:partial =>
‘/tree_node’
},
:before =>
“Element.show(‘#{content_element_id}_activity_indicator’)”,
:success =>
“Element.hide(‘#{content_element_id}_collapse_button’);Element.show(‘#{content_element_id}_expand_button’);”,
:complete =>
“Element.hide(‘#{content_element_id}_activity_indicator’)” ) %>
<!-- Create button when expanded -->
<span id="<%= content_element_id %>_expanded_create_button"
style=“display:none;”>
<%= link_to_remote(‘expanded_create’,
:url => {
:controller
=> controller_name,
:action
=> :create,
:poly_tree_expanded
=> ‘false’,
:poly_tree_content_partial
=> content_partial,
:poly_tree_create_partial
=> create_partial,
:poly_tree_parent_content_id
=> parent_content_id,
:update
=> “#{content_element_id}_children”,
:partial
=> ‘/tree_node’,
:partial_on_failure
=> ‘/nothing’,
:insert_at
=> ‘top’
},
:before =>
“Element.show(‘#{content_element_id}_activity_indicator’)”, # We show
the activity indicator in our parent.
:complete =>
“Element.hide(‘#{content_element_id}_activity_indicator’)”, #
Afterwards, we remove this intermediate DIV element.
:with => “‘#{node_instance_name}
[parent_id]=#{node.id}’”)
%>
<!-- Create button when collapsed -->
<span id="<%= content_element_id %>_collapsed_create_button"<
%= ’ style=“display:none;’ if model_is_unsaved %>”>
<%=
link_to_remote( ‘collapsed_create’,#icon_for_backend_list_create,
:url => {
:controller
=> controller_name,
:action
=> :show,
:id
=> node.id,
:poly_tree_expanded
=> ‘true’,
:poly_tree_content_partial
=> content_partial,
:poly_tree_create_partial
=> create_partial,
:poly_tree_parent_content_id
=> content_element_id,
:poly_tree_create_new_after_render
=> ‘true’,
:update
=> “#{content_element_id}_children”,
:partial
=> ‘/tree_node’,
:insert_at
=> ‘top’
},
:before =>
“Element.show(‘#{content_element_id}_activity_indicator’)”,
:success =>
“Element.show(‘#{content_element_id}_collapse_button’);Element.hide(‘#{content_element_id}_expand_button’);Element.show(‘#{content_element_id}_expanded_create_button’);Element.hide(‘#{content_element_id}_collapsed_create_button’);”,
:complete =>
“Element.hide(‘#{content_element_id}_activity_indicator’)”) %>
<!-- Cancel button when creating -->
<span id="<%= content_element_id %>_cancel_create_button"<%= '
style=“display:none;’ unless model_is_unsaved %>”>
<%= link_to_function( icon_for_backend_close,
“Element.remove(‘#{content_element_id}’); if ($
(‘#{parent_content_id}_child’) == null)
{ Element.hide(‘#{parent_content_id}_collapse_button’);
Element.show(‘#{parent_content_id}_collapsed_create_button’);
Element.hide(‘#{parent_content_id}_expanded_create_button’); };”) %>
<%=
activity_indicator(“#{content_element_id}_activity_indicator”) %>
<div class="content">
<% if model_is_unsaved %>
<%= render :partial => create_partial, :locals =>
{ node_instance_name.to_sym => node, :after_save_id_callback_function
=> callback_function_name } %>
<% else %>
<%= render :partial => content_partial, :locals =>
{ node_instance_name.to_sym => node } %>
<% end %>
<% unless model_is_unsaved %>
<div id="<%= content_element_id %>_children" class="children">
</div>
<% end %>
</div>
<% } %>
<% # Here we check if we’re supposed to automatically create a new
node after an expansion.
# - That’s how the “create new” button works when a node is
collapsed, it expands the node
# with an instruction about creating a new node after it’s had
its children expanded into view.
#
# What we do is that we call the create function on the
controller, telling it to use
# whatever create partial has been determined for rendering, and
to insert the results
# at the top of our parent’s children element, then to remove the
intermediate element
# we create to perform this action.
if create_new_after_render
content_element_id =
“new_child_node_caller_#{Time.now.to_f.to_s.gsub(/
./,‘’)}for#{node_instance_name}_#{parent_node_id}” %>
<%= remote_function(:url => {
:controller
=> controller_name,
:action
=> :create,
:poly_tree_expanded
=> ‘false’,
:poly_tree_content_partial
=> content_partial,
:poly_tree_create_partial
=> create_partial,
:poly_tree_parent_content_id
=> parent_content_id,
:update
=> “#{parent_content_id}_children”,
:partial
=> ‘/tree_node’,
:partial_on_failure
=> ‘/nothing’,
:insert_at
=> ‘top’
},
:with => “‘#{node_instance_name}
[parent_id]=#{parent_node_id}’”, # This is the preset values to make
sure the created node has the right parent.
:before =>
“Element.show(‘#{parent_content_id}_activity_indicator’)”, # We show
the activity indicator in our parent.
:complete =>
“Element.hide(‘#{parent_content_id}_activity_indicator’);Element.remove(‘#{content_element_id}’)”)
Afterwards, we remove this intermediate DIV element.
%>;
</script>
</div><%
end
%>