Skip to content

luciuschoi/jstreejs-rails

Repository files navigation

Jstreejs::Rails

This gem was built for the asset pipeline of Ruby on Rails projects.

Gem Version

Installation

Add this line to your application's Gemfile:

gem 'jquery-rails'
gem 'bulma-rails'
gem 'jstreejs-rails', '3.3.5.0'
gem 'ancestry'

And then execute:

$ bundle

Usage

Scaffold Category resource.

$ rails g scaffold Category title description:text favorite_order 
$ rake db:migrate

Add Ancestry attribute to categories table.

$ rails g migration add_ancestry_to_categories ancestry:string:index 
$ rake db:migrate

application.css

/*
 *= require bulma
 *= require jstree/default/style.min
 *= require jstree/default-dark/style.min
 *= require_tree .
 *= require_self
*/

or application.scss

@import 'bulma';
@import 'jstree/default/style.min';
@import 'jstree/default-dark/style.min';

application.js

//= require jquery
//= require jquery_ujs
//= require jstree.min
//= require jstree_init
//= require turbolinks
//= require_tree .

jstree_init.coffee

$(document).on 'dnd_stop.vakata', (e, data) ->
  ref = $('#tree').jstree(true)
  transfer_ids = data.data.nodes
  target_node = ref.get_node(event.toElement)
  target_node_id = if !target_node then "root" else target_node.id
  all_node_hash = data.data.origin._model.data
  transfer_nodes = []
  for node of all_node_hash
    transfer_nodes.push all_node_hash[node].id if transfer_ids.includes node
  console.log transfer_nodes.join(",")
  console.log target_node_id
  $.getScript("/categories/#{transfer_nodes.join(",")}/to/#{target_node_id}").done((script, textStatus) ->
    console.log textStatus
    console.log "transfered to #{target_node_id}"
    return
  ).fail (jqxhr, settings, exception) ->
    $('div.log').text 'Triggered ajaxError handler.'
    return

  return

$(document).on 'turbolinks:load', ->
  $('#tree').jstree 
    'core':
      'themes': 'name': 'default'
      "check_callback": true       
      'data':
        'url': '/categories.json'
        'data': (node) ->
          { 'id': node.id }
    'plugins': ['sort', 'types', 'dnd']     
    'sort': (a, b) ->
      a1 = @get_node(a)
      b1 = @get_node(b)
      if a1.icon == b1.icon
        if a1.order > b1.order then 1 else -1
      else
        if a1.icon > b1.icon then 1 else -1
  return 

category.rb

class Category < ApplicationRecord
  has_ancestry

  attr_accessor :parent_id

  default_scope { order('favorite_order, title collate "C"')}

  def self.transfer(transfer_ids, target_id)
    transfer_nodes = Category.find(transfer_ids.split(","))
    target_node = target_id == 'root' ? nil : Category.find(target_id)
    transfer_nodes.each do |category|
      category.update_attribute :parent, target_node
    end
  end    
end

categories_controller.rb

class CategoriesController < ApplicationController
  before_action :set_category, only: [:show, :edit, :update, :destroy]

  def index
    @categories = if request.xhr?
                    Category.all
                  else
                    Category.roots
                  end
  end

  def transfer
    Category.transfer(params[:transfer_ids], params[:target_id])
    @categories = Category.roots
    respond_to do |format|
      format.js
    end
  end  

  private
  ···
  def category_params
    params.require(:category).permit(:parent_id, :title, :description, :favorite_order)
  end   

transfer.js.erb

$("#categories_table_list").html("<%=j render @categories %>");

_category.json.jbuilder

json.id category.id
json.text "#{category.favorite_order} #{category.title}"
json.parent category.root? ? "#" : category.ancestry.split("/").last
json.order category.favorite_order

index.html

<div class="contaner">
  <div class="navbar">
    <h1 class='title is-3'>Categories</h1>
  </div>
  <div class="columns">
    <div class="column is-4">
      <div id="tree"></div>    
    </div>
    <div class="column is-8">
      <table class='table is-bordered is-striped is-hoverable is-fullwidth'>
        <thead>
          <tr class='has-background-grey-lighter'>
            <th class='has-text-centered'>ID</th>
            <th class='has-text-centered'>Title</th>
            <th class='has-text-centered' colspan="4">Data Actions</th>
          </tr>
        </thead>

        <tbody id="categories_table_list">
          <%= render @categories %>
        </tbody>
      </table>    
    </div>
  </div>
</div>

<br>

<%= link_to 'New Chapter', new_category_path, class: 'button is-primary' %>

_category.html.erb

<tr>
  <td class='has-text-centered'><%= category.id %></td>
  <td><%= indent(category.ancestry) %> <%= category.favorite_order %> <%= category.title %></td>
  <td><%= link_to '서브챕터생성', new_subcategory_path(category) %></td>
  <td><%= link_to 'Show', category %></td>
  <td><%= link_to 'Edit', edit_category_path(category) %></td>
  <td><%= link_to 'Destroy', category, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<%= render category.children %>

routes.rb

Rails.application.routes.draw do
  root "categories#index"
  resources :categories
  get "categories/:parent_id/subcategory/new" => "categories#new", as: :new_subcategory
  get "categories/:transfer_ids/to/:target_id" => "categories#transfer", as: :transfer_categories
end

Themes

Two themes were included by default: default and default-dark.

To change the theme from default to default-dark, you should update two code lines as follows:

application.css

 *= require jstree/default-dark/style.min
···

jstree-init.coffee

$(document).on 'turbolinks:load', ->
  $('#tree').jstree 'core':
    'themes':
      'name': 'default-dark'
      ···

Demo

Development

After checking out the repo, run bin/setup to install dependencies. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/luciuschoi/jstreejs-rails.