GithubHelp home page GithubHelp logo

ncri / ajaxify_rails Goto Github PK

View Code? Open in Web Editor NEW
116.0 7.0 16.0 475 KB

Rails gem for automatically turning internal links into ajax links that load content without a full page reload.

License: MIT License

Ruby 56.84% CoffeeScript 29.75% JavaScript 1.40% CSS 3.78% HTML 8.23%

ajaxify_rails's Introduction

Ajaxify Rails Build Status

No more full page reloads for your Rails app! Yay!

Automatically makes your app loading content in the background via Ajax.

Works by turning all internal links into Ajax links that trigger an update of the page's content area. Also form submissions are automatically turned into Ajax requests.

Features:

  • Uses the html5 history interface for changing the url and making the browser's back and forward buttons work with Ajax.
  • Falls back to a hash based URL approach for browsers without the history interface (like Internet Explorer version <10).
  • Hash based and non-hash URLs are interchangeable.
  • Transparently handles redirects and supports page titles and flash messages.
  • Tested with Chrome, Firefox, Safari and Internet Explorer 8+.

Demo: http://ajaxify-demo.herokuapp.com/ (the first page load might take a while, as heroku needs to spin up a dyno)

Demo source: https://github.com/ncri/ajaxify_rails_demo_app

Inspired by the pjax_rails gem (https://github.com/rails/pjax_rails).

Requirements

  • Ruby 1.9 and the asset pipeline,
  • jQuery,
  • Your app doesn't use named anchors (#). Named anchors can't be correctly represented in the fallback hash based url scheme.

Installation

Add this line to your application's Gemfile:

gem 'ajaxify_rails'

And then execute:

$ bundle

In your application.js file add:

//= require ajaxify_rails

Usage

Call Ajaxify.init() in your layout's javascript. Do this as early as possible to ensure Ajaxify's interchangeable url schemes (history api vs. hash based urls) work most effectively.

The later you call init(), the later potential redirects from one scheme to another are performed, which means the more unnecessary work the browser has to do.

Content Area

Ajaxify assumes that your app has a content container html tag with the id main. This tag is the container wrapping the yield statement in your layout. If yield doesn't have a wrapper in your app yet, you need to supply one to get ajaxification working:

#main
  = yield

You can set the content container of your app when initializing Ajaxify:

Ajaxify.init
  content_container: 'content_container_id'

or later using set_content_container:

Ajaxify.set_content_container('content_container_id')

Loader Animation

You probably like to have a loader image to be displayed to the user while content loads via Ajax. This is simple. Ajaxify automatically inserts a loader div with the class ajaxify_loader into the content wrapper before starting an Ajax request. So just supply styles for .ajaxify_loader in your css, with an animated gif as a background.

Page Title

If you define a method called page_title in your application controller, returning the current page's title, Ajaxify will use it to automatically update the title tag after the main content has changed.

Navigation and other Layout Updates

It's a common use case to have a navigation that needs to change its appearence and possibly functioning when the user navigates to a different section of the page. Ajaxify provides a success callback that is triggered after successful updates of the page's main content. Just bind to the `ajaxify:content_loaded' event and make your layout changes:

$(document).on 'ajaxify:content_loaded', ->
  # update navigation and/or other layout elements

Flash Messages

Ajaxify correctly displays your flash messages after ajaxified requests. By default, only flash[:notice] is supported. If you are using for example flash[:warning] as well you have to add the flash_types option to the Ajaxify.init() call:

Ajaxify.init
  flash_types: ['notice', 'warning']

Also make sure that you supply invisible wrapper tags in your layout for each flash type you use, with the id set to the type, e.g.:

#notice{ style: "#{'display:none' unless flash[:notice]}" }
  = flash[:notice]

Full Page Reloads

Sometimes requests change the layout of the page so significantly that loading only the main content via Ajax and doing some minor layout tweaks here and there are simply not sufficient.

There might also be links and forms which already have their own Ajax functionality.

For these cases you can turn off Ajaxify, by simply adding the class no_ajaxify directly to links or forms:

= link_to 'Change everything!', re_render_it_all_path, class: 'no_ajaxify'

Root Redirects

Sometimes you need to redirect on the root url.

For example you might have a localized application with the locale inside the url. When a user navigates to your_domain.com he/she gets redirected to e.g. your_domain.com/en/. This works fine in browsers supporting the html 5 history api. However, for browsers without the history api like Internet Explorer before version 10, Ajaxify needs hints about your url structure to not get confused (it creates endless redirects otherwise!). You need to explicitly supply all possible root paths.

Example: if your app's root url potentially redirects to your_domain.com/en/ and your_domain.com/de/ you need to hint Ajaxify like this:

Ajaxify.init
  base_paths = ['de', 'en']

Important: Ajaxify.base_paths need to be set before Ajaxify.init() is called!

Extra Content

Sometimes you need to do non trivial modifications of the layout whenever the content in the main content area of your site changes. Ajaxify allows you to attach arbitrary html to ajaxified requests. This extra html is then stripped from the main content that is inserted into the content area. But before that a callback is triggered which can be used to grab the extra content and do something with it. To use this feature you need to provide a method ajaxify_extra_content in your ApplicationController:

def ajaxify_extra_content
  ... your extra html ...
end

For example you could provide html for a widget in the layout like this:

def ajaxify_extra_content
  "<div id='my_fancy_widget_html'> some html </div>"
end

And then, on the client side bind to the ajaxify:content_inserted event and select the widget html via #ajaxify_content:

$(document).on 'ajaxify:content_inserted', ->
  $('#my_fancy_widget').html $('#ajaxify_content #my_fancy_widget_html').html()

Tip: you can call view helpers to render extra content from within your controller using the view_context:

def ajaxify_extra_content
  view_context.my_fancy_widget
end

Ajaxify Events

Ajaxify provides a few jQuery events you can bind to:

  • ajaxify:before_load => Triggered before the ajaxify request is started. Params: url.
  • ajaxify:content_loaded => Triggered after an ajaxify request finished successfully. Params: data, status, jqXHR, url.
  • ajaxify:content_inserted => Triggered after an ajaxify request finished but before extra content is stripped from the response.
  • ajaxify:flash_displayed => Triggered after a flash message is displayed. Parameters: flash_type.
  • ajaxify:load_error => Triggered if the ajaxify request goes wrong. Parameters: data, status, jqXHR, url.

Javascript

In addition to calling your javascript e.g. in a dom ready event handler (or in your layout), you should also call it in an ajaxify:content_loaded event handler, to make sure it is executed after content has loaded via Ajaxify.

Toggle Ajaxify

You can temporarily deactivate Ajaxify by calling Ajaxify.activate(false). You can switch it on again with Ajaxify.activate(). Note that Ajaxify.activate has to be called before the DOM is ready. Alternatively, you can set the active option to false when initializing Ajaxify to temporarily disable ajaxification, e.g.

Ajaxify.init
  active: false

Scrolling

By default, ajaxify scrolls to the top of the screen when you click on a link or submit a form. You can change this default behavior by setting 'scroll_to_top' to false on init.

Ajaxify.init
  scroll_to_top: false

You can also change the setting for individual links by adding classes:

= link_to "Scroll to top", scroll_to_top_path, class: 'scroll_to_top'
= link_to "Don't scroll", no_scroll_path, class: 'no_scroll_to_top'

Loader animation

By default, ajaxify displays a loader animation when you click on a link or submit a form. You can change this default behavior by setting 'display_loader' to false on init.

Ajaxify.init
  display_loader: false

You can also change the setting for individual links by adding classes:

= link_to "Display loader", display_loader_path, class: 'display_loader'
= link_to "Don't display loader", no_display_loader_path, class: 'no_display_loader'

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

ajaxify_rails's People

Contributors

johannlejeune avatar kbparagua avatar lexagosto avatar ncri avatar vptcnt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

ajaxify_rails's Issues

Link detecting inside main

I want to make work ajaxify with links that appears in "changing content - class main". Can I refresh ajaxify in some way ? I was trying initialize Ajaxify again in content_inserted event but it was just unlucky shot.

confirm and $.rails.confirm

Hi

line 118 and 119, it will be better to use the buil-in rails confirm function in place of the standard confirm function, like this

if options.confirm
  return false unless $.rails.confirm(options.confirm, element)

it should permit to customize the dialog of the confirmation.

But how to pass the element (link) parameter

Vincent

Cannot deactivate ajaxify / fail gracefully to fulll page load

I have a sitaution where I need to deactivate ajaxify.
I tried Ajaxify.activate(false) as stated in the readme, but it doesn't seem to do anything.
Ajaxify works just fine even after calling Ajaxify.activate(false).

So I tried just not initializing Ajaxify at all for specific situations.
I expected it to do fail gracefully and do a full page load, but it returned an error at line 184.
TypeError: current_url is null
options.url = current_url.replace(/(&|&|?)ajaxify_redirect=true/, '');

And then I went do the demo site to see if it does full page load when the check box is not checked. Everything was still ajaxified when 'ajaxify' checkbox was not checked.

It would be great if deactivating works properly and it fails gracefully to do full page load when Ajaxify is not initialized.

Thank you.

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

is it some hack for it

In requirments there is :
Your app doesn't use named anchors (#). Named anchors can't be correctly represented in the fallback hash based url scheme.

Is it some hack for it ?

Auto-refresh when assets are precompiled (v. 0.7.*)

We have installed ajaxify_rails 0.7.5.
It is working perfectly on development environment, wherein assets are not precompiled.

Then when we deployed our app on staging and production environment. Something weird is happening. It appears that ajaxify_rails is processing the request twice. When you click a link, ajaxify will happen, then after the response is rendered the page will refresh. I'm not sure if ajaxify_rails is processing the request twice, or there is something on ajaxify_rails code that initiate a refresh action after rendering.

I downgraded to v 0.5.* then the issue was gone. The issue is also not present on v. 0.2.*.

There is something on v 0.7.* and the precompiled assets that is triggering this auto-refresh thing. I still don't have an idea what is happening on the code. Maybe these will give you some clues where to look at. Thanks and Goodluck!

Clicking on a link always scrolls to the top

When I click on a link, the screen always scrolls to the top.
It can be reproduced on the demo site. Decrease the height of the browser window and you will see that screen scrolls to the top when a link is clicked.
I want my screen to stay where it is, but there are situations where it needs to scroll to the top. It would be great if its scrolling behavior can be configurable.

Problem with ajaxify's response

Hello !

I am having a problem with ajaxify's response, when i try to access to a link and so to update only #main, the response contains the html code of the whole page (with js sources / metadata / footer ... ) and put it in the #main div. I really dont understand why, even after analyzing your demo source code.
If anyone had this problem before or knows how to solve it, it would be very nice !
Thank you :-)

Is there a way to do full page reloads from a ajaxified request?

For example:

Login required before filter redirects to login page but when a ajaxified link is clicked and the filter halts the execution, the redirect_to is also ajaxified but I want it to load the full page instead of ajaxified div.

Is there any way to do so?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.