2008/08/22

Rails 2.1 OSX Finder like ColumnNav.

original google code : http://columnav.googlecode.com/svn/trunk/index.html

Update(22/8/2008):
Since ResponseHeader was "applicatoin/json ;utf8 ",
The original code does not work.

in columnav.js,
Before:
var contentType = o.getResponseHeader['Content-Type'];
if ('application/json' == contentType.replace(/\s+$/,'')) {

After:
var contentType = o.getResponseHeader['Content-Type'];
var compareString = contentType.replace(/\s+$/,'')
if (compareString.include('application/json')) {



It was not easy to implement "finder" with extjs. And furthermore, my codes were getting ugly. Almost hard to see. So I abandoned Extjs on the user-view. I've decided to use it on admin pages.



ColumNav is a hierarchical menu implementation utilizing Bill Scott's Yahoo UI Carousel component. Content is loaded from an unordered list and displayed in a scrollable viewport, similar to Column View in the Mac OS X Finder.


Features include:


  • infinite extensibility using Ajax to build sub-menus
  • instantiation from DOM or JSON data sources
  • a highly customizable look and feel using CSS
  • support for multiple columns
  • support for keyboard-only navigation (CTRL + arrow keys)
  • cross-browser compatibility

App/views/Categories/index.html



<% content_for :head do%>


<%= stylesheet_link_tag 'cssbits_notice' %>
<%= stylesheet_link_tag 'columnav', 'columnav_apply' %>
<%= javascript_include_tag :defaults %>
<%= javascript_include_tag "columnav/yui/yahoo-min" %>
<%= javascript_include_tag "columnav/yui/utilities" %>
<%= javascript_include_tag "columnav/yui/container_core-min" %>

<%= javascript_include_tag "columnav/carousel_min" %>
<%= javascript_include_tag "columnav/columnav" %>
<%= javascript_include_tag "columnav/columnav_json_parsing" %>


<% javascript_tag do %>
try { document.execCommand('BackgroundImageCache', false, true); } catch(e) {}


function init() {
var cn_cfg = {
numVisible: 3,
prevElement: 'columnav-prev',
datasource: '/categories/columntree/1.json'
};
var cn = new YAHOO.extension.ColumNav('columnav', cn_cfg);
}
YAHOO.util.Event.addListener(window, 'load', init);
<% end %>

<% end %>







App/controllers/Categories_controller.rb



def columntree(id = params[:id])
categories = Category.find_all_by_parent_id(id)

data = get_tree(categories, id)
respond_to do |format|
format.json { render :text => data[0].to_json, :layout => false }
end
end


def get_tree(categories, parent_id)
parent = Category.find_by_id(parent_id)
data = Array.new
data.concat([ "ul" => insert(categories, parent) ])
return data
end

def insert(categories, parent)
result = Array.new
result.concat(["li" => insert_data(categories, parent) ])
return result[0]
end

def insert_data(categories, parent)
iterated = Array.new
categories.each { |category|
if !category.leaf?
iterated.concat(["a" => {"#text" => category.text, "@href" => "/categories/columntree/"+category.id.to_s+".json", "@rel" => "ajax"}, "id" => category.id]) # "@rel" => "ajax" 면 폴더로 인식.
else
iterated.concat(["a" => {"#text" => category.text, "@href" => "http://peepcode.com"}, "id" => category.id])
end
}
return iterated
end



app/models/category.rb


class Category < dependent =""> :nullify
has_many :portfolios, :dependent => :nullify

acts_as_nested_set

validates_presence_of :text

has_attached_file :photo,
:styles => { :medium => "220x180#", :thumb => "100x82#" },
:path => "#{RAILS_ROOT}/public/images/category_photos/:id/:style_:basename.:extension",
:url => "/images/category_photos/:id/:style_:basename.:extension",
:default_url => "/images/category_photos/missing.png",
:whiny_thumbnails => true


#liquid
liquid_methods :text

# extjs를 위한 코드임

def self.root_nodes
find(:all, :conditions => 'parent_id IS NULL')
end

def self.find_children(start_id = nil)
start_id.to_i == 0 ? root_nodes : find(start_id).direct_children
end

def children
Category.find_all_by_parent_id(self.id)
end

def self.find_level1
find_all_by_parent_id(1)
end

def leaf
unknown? || children_count == 0
end

def leaf?
unknown? || children_count == 0
end


def to_json_with_leaf(options = {})
self.to_json_without_leaf(options.merge(:methods => :leaf))
end
alias_method_chain :to_json, :leaf
private
end

0 comments:

Post a Comment