├── Rakefile ├── Gemfile ├── lib ├── ljax_rails │ ├── action_dispatch_monkey.rb │ ├── action_controller_monkey.rb │ └── action_view_monkey.rb └── ljax_rails.rb ├── .gitignore ├── app └── assets │ └── javascripts │ └── ljax_rails.js.coffee ├── ljax_rails.gemspec ├── README.md └── MIT_LICENSE /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in ljax_rails.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/ljax_rails/action_dispatch_monkey.rb: -------------------------------------------------------------------------------- 1 | ActionDispatch::Request.class_eval do 2 | def ljax? 3 | xhr? && headers['X-LJAX'] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | log 19 | -------------------------------------------------------------------------------- /lib/ljax_rails/action_controller_monkey.rb: -------------------------------------------------------------------------------- 1 | module LjaxRails::LjaxActionProcessor 2 | def default_render(*) 3 | if request.ljax? 4 | partial = LjaxRails.encryptor.decrypt_and_verify request.headers['X-LJAX-Partial'] 5 | render partial: partial 6 | else 7 | super 8 | end 9 | end 10 | end 11 | 12 | ActionController::Base.send :prepend, LjaxRails::LjaxActionProcessor 13 | -------------------------------------------------------------------------------- /app/assets/javascripts/ljax_rails.js.coffee: -------------------------------------------------------------------------------- 1 | $ -> 2 | $('.ljax-container').each (index, container) => 3 | $.ajax 4 | type: 'GET' 5 | dataType: 'html' 6 | url: $(container).data('remote-url') 7 | cache: false 8 | headers: {'X-LJAX': 'true', 'X-LJAX-Container': container.id, 'X-LJAX-Partial': $(container).data('ljax-partial')} 9 | success: (data) -> 10 | $(container).replaceWith(data).trigger('ljax:success') 11 | error: -> 12 | $(container).trigger('ljax:error') 13 | complete: -> 14 | $(container).trigger('ljax:complete') 15 | -------------------------------------------------------------------------------- /lib/ljax_rails/action_view_monkey.rb: -------------------------------------------------------------------------------- 1 | require 'securerandom' 2 | 3 | module LjaxRails 4 | module LjaxRenderer 5 | def render_partial(context, options, &block) 6 | if options[:locals] && options[:locals].delete(:remote) 7 | partial = options.delete :partial 8 | encrypted_partial = LjaxRails.encryptor.encrypt_and_sign partial 9 | 10 | url = options[:locals].delete :remote_url 11 | id = "ljax-#{SecureRandom.uuid}" 12 | loading = block.call if block 13 | 14 | %Q!
#{loading}
!.html_safe 15 | else 16 | super 17 | end 18 | end 19 | end 20 | end 21 | 22 | ActionView::Renderer.send :prepend, LjaxRails::LjaxRenderer 23 | -------------------------------------------------------------------------------- /lib/ljax_rails.rb: -------------------------------------------------------------------------------- 1 | module LjaxRails 2 | VERSION = Gem.loaded_specs['ljax_rails'].version.to_s 3 | 4 | class Engine < ::Rails::Engine 5 | initializer 'ljax_rails.add_controller' do 6 | ActiveSupport.on_load :action_controller do 7 | require_relative 'ljax_rails/action_dispatch_monkey' 8 | require_relative 'ljax_rails/action_view_monkey' 9 | require_relative 'ljax_rails/action_controller_monkey' 10 | end 11 | end 12 | end 13 | 14 | def self.encryptor 15 | @encryptor ||= begin 16 | key = if Rails.application.config.respond_to? :secret_key_base 17 | Rails.application.config.secret_key_base || Rails.application.config.secret_token 18 | else 19 | Rails.application.config.secret_token 20 | end 21 | ActiveSupport::MessageEncryptor.new key 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /ljax_rails.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "ljax_rails" 7 | spec.version = '0.0.1' 8 | spec.authors = ["Akira Matsuda"] 9 | spec.email = ["ronnie@dio.jp"] 10 | spec.description = '"LJAX" (= Lazy load Ajax) on Rails' 11 | spec.summary = '"LJAX" (= Lazy load Ajax) on Rails' 12 | spec.homepage = 'https://github.com/amatsuda/ljax_rails' 13 | spec.license = "MIT" 14 | 15 | spec.files = `git ls-files`.split($/) 16 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 17 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 18 | spec.require_paths = ["lib"] 19 | 20 | spec.add_development_dependency "rake" 21 | end 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LJAX 2 | 3 | Lazy-load AJAX on Rails 4 | 5 | ## Installation 6 | 7 | Bundle `ljax_rails` gem: 8 | 9 | gem 'ljax_rails' 10 | 11 | Then add this to your app/assets/javascripts/application.js (or whatever bundle you use): 12 | 13 | //=require ljax_rails 14 | 15 | ## Usage 16 | 17 | ### Views 18 | 19 | Add `remote: true` option to your `render :partial` call, then the partial will be lazily rendered in a separate HTTP request. 20 | 21 | ```erb 22 | <%= render 'users', remote: true %> 23 | ``` 24 | 25 | Also, you can give `remote_url` option for specifying request target URL. 26 | 27 | ```erb 28 | <%= render 'sidebar', remote: true, remote_url: '/shared/sidebar' %> 29 | ``` 30 | 31 | ### Controllers 32 | 33 | `request.ljax?` tells you whether the request was sent via LJAX or not. 34 | 35 | ```ruby 36 | def index 37 | if request.ljax? 38 | @users = User.all 39 | end 40 | end 41 | ``` 42 | 43 | ## TODO 44 | 45 | * JS error handling 46 | * JS event hook 47 | * spinner? 48 | * tests 49 | * documentation 50 | * tutorial 51 | 52 | ## Contributing 53 | 54 | Send me your PRs! 55 | -------------------------------------------------------------------------------- /MIT_LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Akira Matsuda 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | --------------------------------------------------------------------------------