ajax_pagination 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/CHANGELOG.md +4 -0
- data/README.md +30 -3
- data/Rakefile +10 -0
- data/ajax_pagination.gemspec +1 -1
- data/lib/ajax_pagination/version.rb +1 -1
- data/lib/generators/ajax_pagination/assets_generator.rb +37 -0
- data/spec/R30PORT +1 -0
- data/spec/ajax_pagination/integration/ajaxpaginate_spec.rb +85 -75
- data/spec/ajax_pagination/integration/rails30_spec.rb +35 -0
- data/spec/rails30_app/.gitignore +8 -0
- data/spec/rails30_app/Gemfile +28 -0
- data/spec/rails30_app/Gemfile.lock +96 -0
- data/spec/rails30_app/Rakefile +7 -0
- data/spec/rails30_app/app/controllers/application_controller.rb +13 -0
- data/spec/rails30_app/app/controllers/changelog_controller.rb +12 -0
- data/spec/rails30_app/app/controllers/pages_controller.rb +28 -0
- data/spec/rails30_app/app/controllers/sessions_controller.rb +9 -0
- data/spec/rails30_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails30_app/app/helpers/posts_helper.rb +2 -0
- data/spec/rails30_app/app/mailers/.gitkeep +0 -0
- data/spec/rails30_app/app/models/.gitkeep +0 -0
- data/spec/rails30_app/app/models/changelog.rb +19 -0
- data/spec/rails30_app/app/views/changelog/_page.html.erb +10 -0
- data/spec/rails30_app/app/views/changelog/index.html.erb +3 -0
- data/spec/rails30_app/app/views/layouts/ajax.html.erb +8 -0
- data/spec/rails30_app/app/views/layouts/application.html.erb +49 -0
- data/spec/rails30_app/app/views/layouts/flash.html.erb +7 -0
- data/spec/rails30_app/app/views/pages/about.html.erb +4 -0
- data/spec/rails30_app/app/views/pages/readme.html.erb +4 -0
- data/spec/rails30_app/app/views/pages/warnings.html.erb +43 -0
- data/spec/rails30_app/app/views/pages/welcome.html.erb +6 -0
- data/spec/rails30_app/app/views/sessions/count.html.erb +7 -0
- data/spec/rails30_app/config.ru +4 -0
- data/spec/rails30_app/config/application.rb +53 -0
- data/spec/rails30_app/config/boot.rb +10 -0
- data/spec/rails30_app/config/database.yml +25 -0
- data/spec/rails30_app/config/environment.rb +6 -0
- data/spec/rails30_app/config/environments/development.rb +25 -0
- data/spec/rails30_app/config/environments/production.rb +43 -0
- data/spec/rails30_app/config/environments/test.rb +30 -0
- data/spec/rails30_app/config/initializers/ajax_pagination.rb +12 -0
- data/spec/rails30_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails30_app/config/initializers/inflections.rb +15 -0
- data/spec/rails30_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails30_app/config/initializers/secret_token.rb +7 -0
- data/spec/rails30_app/config/initializers/session_store.rb +8 -0
- data/spec/rails30_app/config/locales/en.yml +5 -0
- data/spec/rails30_app/config/routes.rb +71 -0
- data/spec/rails30_app/log/.gitkeep +0 -0
- data/spec/rails30_app/public/404.html +26 -0
- data/spec/rails30_app/public/422.html +26 -0
- data/spec/rails30_app/public/500.html +25 -0
- data/spec/rails30_app/public/favicon.ico +0 -0
- data/spec/rails30_app/public/images/ajax-loader.gif +0 -0
- data/spec/rails30_app/public/javascripts/ajax_pagination.js +380 -0
- data/spec/rails30_app/public/javascripts/history.js +4 -0
- data/spec/rails30_app/public/javascripts/history_adapter_jquery.js +77 -0
- data/spec/rails30_app/public/javascripts/history_core.js +1943 -0
- data/spec/rails30_app/public/javascripts/history_html4.js +621 -0
- data/spec/rails30_app/public/javascripts/jquery-ui.js +11767 -0
- data/spec/rails30_app/public/javascripts/jquery-ui.min.js +791 -0
- data/spec/rails30_app/public/javascripts/jquery.ba-bbq.js +18 -0
- data/spec/rails30_app/public/javascripts/jquery.js +9266 -0
- data/spec/rails30_app/public/javascripts/jquery.min.js +4 -0
- data/spec/rails30_app/public/javascripts/jquery.url.js +160 -0
- data/spec/rails30_app/public/javascripts/jquery_ujs.js +373 -0
- data/spec/rails30_app/public/javascripts/json2.js +487 -0
- data/spec/rails30_app/public/stylesheets/ajax_pagination.css +24 -0
- data/spec/rails30_app/public/stylesheets/application.css +12 -0
- data/spec/rails30_app/public/stylesheets/scaffold.css +56 -0
- data/spec/rails30_app/script/rails +6 -0
- data/spec/rails_app/Gemfile.lock +107 -0
- data/spec/spec_helper.rb +16 -1
- metadata +72 -10
- data/spec/rails_app/test/fixtures/posts.yml +0 -9
- data/spec/rails_app/test/functional/posts_controller_test.rb +0 -49
- data/spec/rails_app/test/unit/helpers/posts_helper_test.rb +0 -4
- data/spec/rails_app/test/unit/post_test.rb +0 -7
@@ -0,0 +1,30 @@
|
|
1
|
+
RailsApp::Application.configure do
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb
|
3
|
+
|
4
|
+
# The test environment is used exclusively to run your application's
|
5
|
+
# test suite. You never need to work with it otherwise. Remember that
|
6
|
+
# your test database is "scratch space" for the test suite and is wiped
|
7
|
+
# and recreated between test runs. Don't rely on the data there!
|
8
|
+
config.cache_classes = true
|
9
|
+
|
10
|
+
# Log error messages when you accidentally call methods on nil
|
11
|
+
config.whiny_nils = true
|
12
|
+
|
13
|
+
# Show full error reports and disable caching
|
14
|
+
config.consider_all_requests_local = true
|
15
|
+
config.action_controller.perform_caching = false
|
16
|
+
|
17
|
+
# Raise exceptions instead of rendering exception templates
|
18
|
+
config.action_dispatch.show_exceptions = false
|
19
|
+
|
20
|
+
# Disable request forgery protection in test environment
|
21
|
+
config.action_controller.allow_forgery_protection = false
|
22
|
+
|
23
|
+
# Tell Action Mailer not to deliver emails to the real world.
|
24
|
+
# The :test delivery method accumulates sent emails in the
|
25
|
+
# ActionMailer::Base.deliveries array.
|
26
|
+
config.action_mailer.delivery_method = :test
|
27
|
+
|
28
|
+
# Print deprecation notices to the stderr
|
29
|
+
config.active_support.deprecation = :stderr
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
AjaxPagination.config do |config|
|
2
|
+
# uncomment to change default loading image file, located in assets/images.
|
3
|
+
# config.loading_image = "ajax-loader.gif"
|
4
|
+
|
5
|
+
# whether javascript warnings are on, these present themselves as alerts
|
6
|
+
# by default, warnings are active only if the environment is development
|
7
|
+
# to configure by environment otherwise, this configuration needs to be added to the environment specific files
|
8
|
+
# uncomment to turn warnings on in all environments
|
9
|
+
config.warnings = true
|
10
|
+
# or to turn off in all environments
|
11
|
+
# config.warnings = false
|
12
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
4
|
+
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
5
|
+
|
6
|
+
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
7
|
+
# Rails.backtrace_cleaner.remove_silencers!
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Add new inflection rules using the following format
|
4
|
+
# (all these examples are active by default):
|
5
|
+
# ActiveSupport::Inflector.inflections do |inflect|
|
6
|
+
# inflect.plural /^(ox)$/i, '\1en'
|
7
|
+
# inflect.singular /^(ox)en/i, '\1'
|
8
|
+
# inflect.irregular 'person', 'people'
|
9
|
+
# inflect.uncountable %w( fish sheep )
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# These inflection rules are supported but not enabled by default:
|
13
|
+
# ActiveSupport::Inflector.inflections do |inflect|
|
14
|
+
# inflect.acronym 'RESTful'
|
15
|
+
# end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Your secret key for verifying the integrity of signed cookies.
|
4
|
+
# If you change this key, all old signed cookies will become invalid!
|
5
|
+
# Make sure the secret is at least 30 characters and all random,
|
6
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
7
|
+
RailsApp::Application.config.secret_token = 'a706a86b3637055b5983373afe5113e107ef65d626a4c1763ec9017948fb7d640b5bcb7c541bab0bc52761e0c8aa78fcc43e24182440cd21b866330739e97169'
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
RailsApp::Application.config.session_store :cookie_store, :key => '_rails_app_session'
|
4
|
+
|
5
|
+
# Use the database for sessions instead of the cookie-based default,
|
6
|
+
# which shouldn't be used to store highly confidential information
|
7
|
+
# (create the session table with "rails generate session_migration")
|
8
|
+
# RailsApp::Application.config.session_store :active_record_store
|
@@ -0,0 +1,71 @@
|
|
1
|
+
RailsApp::Application.routes.draw do
|
2
|
+
|
3
|
+
namespace :pages do
|
4
|
+
get 'about'
|
5
|
+
get 'readme'
|
6
|
+
end
|
7
|
+
|
8
|
+
get 'changelog' => 'changelog#index'
|
9
|
+
|
10
|
+
namespace :sessions do
|
11
|
+
get 'count'
|
12
|
+
post 'count'
|
13
|
+
end
|
14
|
+
|
15
|
+
# The priority is based upon order of creation:
|
16
|
+
# first created -> highest priority.
|
17
|
+
|
18
|
+
# Sample of regular route:
|
19
|
+
# match 'products/:id' => 'catalog#view'
|
20
|
+
# Keep in mind you can assign values other than :controller and :action
|
21
|
+
|
22
|
+
# Sample of named route:
|
23
|
+
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
|
24
|
+
# This route can be invoked with purchase_url(:id => product.id)
|
25
|
+
|
26
|
+
# Sample resource route (maps HTTP verbs to controller actions automatically):
|
27
|
+
# resources :products
|
28
|
+
|
29
|
+
# Sample resource route with options:
|
30
|
+
# resources :products do
|
31
|
+
# member do
|
32
|
+
# get 'short'
|
33
|
+
# post 'toggle'
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# collection do
|
37
|
+
# get 'sold'
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
|
41
|
+
# Sample resource route with sub-resources:
|
42
|
+
# resources :products do
|
43
|
+
# resources :comments, :sales
|
44
|
+
# resource :seller
|
45
|
+
# end
|
46
|
+
|
47
|
+
# Sample resource route with more complex sub-resources
|
48
|
+
# resources :products do
|
49
|
+
# resources :comments
|
50
|
+
# resources :sales do
|
51
|
+
# get 'recent', :on => :collection
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
|
55
|
+
# Sample resource route within a namespace:
|
56
|
+
# namespace :admin do
|
57
|
+
# # Directs /admin/products/* to Admin::ProductsController
|
58
|
+
# # (app/controllers/admin/products_controller.rb)
|
59
|
+
# resources :products
|
60
|
+
# end
|
61
|
+
|
62
|
+
# You can have the root of your site routed with "root"
|
63
|
+
# just remember to delete public/index.html.
|
64
|
+
root :to => 'pages#welcome'
|
65
|
+
|
66
|
+
# See how all your routes lay out with "rake routes"
|
67
|
+
|
68
|
+
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
69
|
+
# Note: This route will make all actions in every controller accessible via GET requests.
|
70
|
+
# match ':controller(/:action(/:id))(.:format)'
|
71
|
+
end
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The page you were looking for doesn't exist (404)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<!-- This file lives in public/404.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
23
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
24
|
+
</div>
|
25
|
+
</body>
|
26
|
+
</html>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<!-- This file lives in public/422.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>The change you wanted was rejected.</h1>
|
23
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
24
|
+
</div>
|
25
|
+
</body>
|
26
|
+
</html>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
5
|
+
<style type="text/css">
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
7
|
+
div.dialog {
|
8
|
+
width: 25em;
|
9
|
+
padding: 0 4em;
|
10
|
+
margin: 4em auto 0 auto;
|
11
|
+
border: 1px solid #ccc;
|
12
|
+
border-right-color: #999;
|
13
|
+
border-bottom-color: #999;
|
14
|
+
}
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
|
19
|
+
<body>
|
20
|
+
<!-- This file lives in public/500.html -->
|
21
|
+
<div class="dialog">
|
22
|
+
<h1>We're sorry, but something went wrong.</h1>
|
23
|
+
</div>
|
24
|
+
</body>
|
25
|
+
</html>
|
File without changes
|
Binary file
|
@@ -0,0 +1,380 @@
|
|
1
|
+
//= require jquery.ba-bbq
|
2
|
+
//= require jquery.url
|
3
|
+
|
4
|
+
/*
|
5
|
+
* AJAX Pagination: Ajaxifying your pagination links
|
6
|
+
* https://github.com/ronalchn/ajax_pagination
|
7
|
+
*
|
8
|
+
* Copyright (c) 2012 Ronald Ping Man Chan
|
9
|
+
* Distributed under the LGPL license
|
10
|
+
*
|
11
|
+
* Although the ajax_pagination gem as a whole is distributed under LGPL, I am expressly permitting users to minify and concatenate this javascript file
|
12
|
+
* with other javascript files, as long as it is through an automatic asset management process (eg. Sprockets), and the automatic asset
|
13
|
+
* management process obtains this javascript file as a separate file via dynamically linked means (ie. with this file left in the separately
|
14
|
+
* installed ajax_pagination gem).
|
15
|
+
* ~ Ronald Chan
|
16
|
+
*/
|
17
|
+
jQuery(document).ready(function () {
|
18
|
+
function minVersion(version) {
|
19
|
+
var $vrs = window.jQuery.fn.jquery.split('.'),
|
20
|
+
min = version.split('.');
|
21
|
+
for (var i=0, len=min.length; i<len; i++) {
|
22
|
+
if ($vrs[i]) {
|
23
|
+
min[i] = parseInt(min[i],10);
|
24
|
+
$vrs[i] = parseInt($vrs[i],10);
|
25
|
+
if ($vrs[i] < min[i]) return false;
|
26
|
+
else if ($vrs[i] > min[i]) return true;
|
27
|
+
}
|
28
|
+
else return false;
|
29
|
+
}
|
30
|
+
return true;
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
if (!(History && minVersion('1.7'))) { // dependencies missing
|
35
|
+
var missing = "";
|
36
|
+
if (!History) missing += "\nHistory.js not installed";
|
37
|
+
if (!minVersion('1.7')) missing += "\njQuery version 1.7+ not installed. Currently installed: jQuery " + window.jQuery.fn.jquery;
|
38
|
+
alert("AJAX Pagination MISSING_DEPENDENCIES:" + missing);
|
39
|
+
}
|
40
|
+
|
41
|
+
(function( $ ) { // on document ready
|
42
|
+
if (History && History.enabled && minVersion('1.7')) {
|
43
|
+
///////////////////////////////////
|
44
|
+
////// $.ajax_pagination API //////
|
45
|
+
///////////////////////////////////
|
46
|
+
// selector function for pagination object
|
47
|
+
$.ajax_pagination = function (pagination_name) {
|
48
|
+
return new pagination_object(pagination_name);
|
49
|
+
};
|
50
|
+
$.ajax_pagination.version = '0.5.1';
|
51
|
+
$.ajax_pagination.enabled = true;
|
52
|
+
function pagination_object(pagination_name) {
|
53
|
+
this.get = function(url,options) {
|
54
|
+
if (options === undefined) options = {};
|
55
|
+
if (options.history === undefined) options.history = true;
|
56
|
+
swapPage(pagination_name,url,options.history);
|
57
|
+
}
|
58
|
+
this.exists = function() {
|
59
|
+
return $('#' + pagination_name + '_paginated_section').length == 1;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
/////////////////////////////
|
63
|
+
////// Basic Internals //////
|
64
|
+
/////////////////////////////
|
65
|
+
var pagination_loader_state = new Array(); // the page we are waiting for
|
66
|
+
var pagination_url = location.href; // url we came from, so we can see transitions of the url
|
67
|
+
var history_state = {ajax_pagination_set:true}; // current history state
|
68
|
+
|
69
|
+
function display_pagination_loader(pagination_name) {
|
70
|
+
var paginated_section = getSection(pagination_name);
|
71
|
+
if (pagination_loader_state[pagination_name] === undefined) { // show loader if not already shown
|
72
|
+
if ($.rails.fire(getSection(pagination_name),"ajaxp:loading")) {
|
73
|
+
var paginated_content;
|
74
|
+
if (paginated_section.hasClass("paginated_content")) paginated_content = paginated_section; // if the whole section is a loading zone
|
75
|
+
else paginated_content = paginated_section.children(".paginated_content").first(); // don't want to support multiple loader images
|
76
|
+
var height = paginated_content.height();
|
77
|
+
// setup loading look
|
78
|
+
var img = document.createElement("IMG");
|
79
|
+
if (paginated_section.data("pagination") !== undefined && paginated_section.data("pagination").image !== undefined) img.src = paginated_section.data("pagination").image;
|
80
|
+
else img.src = "/images/ajax-loader.gif";
|
81
|
+
var margin = Math.round(height>400?50:(height/8));
|
82
|
+
$(img).addClass('ajaxpagination-loader');
|
83
|
+
var div = document.createElement("DIV");
|
84
|
+
$(div).addClass('ajaxpagination-loadzone');
|
85
|
+
$(div).append("<div class=\"margin-top\" />").append(img);
|
86
|
+
paginated_content.wrapInner("<div class=\"ajaxpagination-oldcontent\" />");
|
87
|
+
paginated_content.append(div);
|
88
|
+
}
|
89
|
+
}
|
90
|
+
if ($.rails.fire(getSection(pagination_name),"ajaxp:focus")) {
|
91
|
+
// scroll to top of paginated_section if it is not visible
|
92
|
+
if ($(document).scrollTop() > paginated_section.offset().top - 20) {
|
93
|
+
$(document).scrollTop(paginated_section.offset().top - 20);
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
function getSection(pagination_name) {
|
98
|
+
var id = "#" + pagination_name + "_paginated_section"; // element id we are looking for
|
99
|
+
return $(id);
|
100
|
+
}
|
101
|
+
function getSectionName(section) {
|
102
|
+
var id = section.attr("id");
|
103
|
+
if (id === undefined) return undefined; // no name
|
104
|
+
var pagination_name = /^(.*)_paginated_section$/.exec(id)[1];
|
105
|
+
if (pagination_name == null || pagination_name === undefined) return undefined; // pagination not set up properly
|
106
|
+
return pagination_name;
|
107
|
+
}
|
108
|
+
function getSectionNames(sections) {
|
109
|
+
var names = new Array();
|
110
|
+
sections.each(function () {
|
111
|
+
names.push(getSectionName($(this)));
|
112
|
+
});
|
113
|
+
return names;
|
114
|
+
}
|
115
|
+
function intersects(a,b) { // do the arrays a and b intersect?
|
116
|
+
var i=0, j=0;
|
117
|
+
while (i < a.length && j < b.length) {
|
118
|
+
if (a[i]<b[j]) i++;
|
119
|
+
else if (a[i]>b[j]) j++;
|
120
|
+
else return true; // intersects
|
121
|
+
}
|
122
|
+
return false; // doesn't intersect
|
123
|
+
}
|
124
|
+
// whether change of state is a reload
|
125
|
+
function isReload(pagination_name,from,to) {
|
126
|
+
if (from == to) return true; // same url - always a reload
|
127
|
+
var section = getSection(pagination_name);
|
128
|
+
if (section.length == 0) return false;
|
129
|
+
|
130
|
+
// if data-pagination is not defined, then no reload can be detected
|
131
|
+
if (section.data('pagination') === undefined || section.data('pagination').reload === undefined) return false;
|
132
|
+
|
133
|
+
var reload = section.data('pagination').reload;
|
134
|
+
if (!(reload instanceof Array)) reload = new Array(reload);
|
135
|
+
for (i=0;i<reload.length;i++) {
|
136
|
+
if (reload[i].query !== undefined) {
|
137
|
+
if ($.deparam.querystring(from)[reload[i].query] !== $.deparam.querystring(to)[reload[i].query]) return false;
|
138
|
+
}
|
139
|
+
if (reload[i].urlregex !== undefined) {
|
140
|
+
var fstr = from, tstr = to;
|
141
|
+
if (reload[i].urlpart !== undefined) {
|
142
|
+
fstr = $.url(from,true).attr(reload[i].urlpart);
|
143
|
+
tstr = $.url(to,true).attr(reload[i].urlpart);
|
144
|
+
if (typeof(fstr)!="string" || typeof(tstr)!="string") continue; // skip
|
145
|
+
}
|
146
|
+
var index = 0;
|
147
|
+
if (reload[i].regexindex !== undefined) index = reload[i].regexindex;
|
148
|
+
var regex = new RegExp(reload[i].urlregex);
|
149
|
+
var frommatch = regex.exec(fstr), tomatch = regex.exec(tstr);
|
150
|
+
if (frommatch != null && frommatch.length>=index) frommatch = frommatch[index];
|
151
|
+
if (tomatch != null && tomatch.length>=index) tomatch = tomatch[index];
|
152
|
+
if (frommatch !== tomatch) return false;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
return true;
|
156
|
+
}
|
157
|
+
// when this function is used beforeSend of an AJAX request, will use the resulting content in a section of the page
|
158
|
+
// this event handler has the same arguments as for jquery and jquery-ujs, except it also takes the name of the section to put the content into as first argument
|
159
|
+
// adapter functions will be used to reconcile the differences in arguments, this is required because jquery and jquery-ujs has different ways to get the pagination_name argument
|
160
|
+
function beforeSendHandler(pagination_name,jqXHR,settings) {
|
161
|
+
var id = "#" + pagination_name + "_paginated_section"; // element id we are looking for
|
162
|
+
var requesturl = settings.url;
|
163
|
+
var countid = $('[id="' + pagination_name + '_paginated_section"]').length;
|
164
|
+
if (countid != 1) { // something wrong, cannot find unique section to load page into
|
165
|
+
|
166
|
+
alert("AJAX Pagination UNIQUE_SECTION_NOT_FOUND:\nExpected one pagination section called " + pagination_name + ", found " + countid);
|
167
|
+
|
168
|
+
return false; // continue AJAX normally
|
169
|
+
}
|
170
|
+
if (!$.rails.fire(getSection(pagination_name),"ajaxp:beforeSend",[jqXHR,settings])) return false;
|
171
|
+
display_pagination_loader(pagination_name);
|
172
|
+
// register callbacks for other events
|
173
|
+
jqXHR.done(function(data, textStatus, jqXHR) {
|
174
|
+
if (requesturl != pagination_loader_state[pagination_name]) return; // ignore stale content
|
175
|
+
if (jqXHR.status == 200 && jqXHR.getResponseHeader('Location') !== null) { // special AJAX redirect
|
176
|
+
var redirecturl = jqXHR.getResponseHeader('Location');
|
177
|
+
swapPage(pagination_name,redirecturl);
|
178
|
+
pagination_url = redirecturl;
|
179
|
+
History.replaceState(history_state,document.title,redirecturl); // state not changed
|
180
|
+
return;
|
181
|
+
}
|
182
|
+
// find matching element id in data, after removing script tags
|
183
|
+
var page = $("<div />");
|
184
|
+
page[0].innerHTML = data; // put response in DOM without executing scripts
|
185
|
+
|
186
|
+
// if page contains a title, use it
|
187
|
+
var title = page.find("title");
|
188
|
+
if (title.length>0) History.replaceState(history_state,title.html(),location.href);
|
189
|
+
|
190
|
+
// get page contents
|
191
|
+
var content = page.find(id);
|
192
|
+
if (content.length>0) {
|
193
|
+
content = content.html();
|
194
|
+
|
195
|
+
alert("AJAX Pagination EXTRA_CONTENT_DISCARDED:\nExtra content returned by AJAX request ignored. Only a portion of the page content returned by the server was required. To fix this, explicitly call ajax_respond :pagination => \"" + pagination_name + "\" to render only the partial view required. This warning can be turned off in the ajax_pagination initializer file.");
|
196
|
+
|
197
|
+
}
|
198
|
+
else { // otherwise use all the content, including any scripts - we consider scripts specifically returned in the partial probably should be re-run
|
199
|
+
content = page.find("body"); // does not tend to work since browsers strip out the html, head, body tags
|
200
|
+
if (content.length>0) content = content.html(); // if it has a body tag, only include its contents (for full html structure), leaving out <head> etc sections.
|
201
|
+
else content = page.html(); // otherwise include the whole html snippet
|
202
|
+
}
|
203
|
+
|
204
|
+
if ($.rails.fire(getSection(pagination_name),"ajaxp:done",[content])) $(id).html(content);
|
205
|
+
|
206
|
+
delete pagination_loader_state[pagination_name]; // not waiting for page anymore
|
207
|
+
|
208
|
+
$.rails.fire(getSection(pagination_name),"ajaxp:loaded");
|
209
|
+
});
|
210
|
+
jqXHR.fail(function(jqXHR, textStatus, errorThrown) {
|
211
|
+
if (requesturl != pagination_loader_state[pagination_name]) return; // ignore stale content
|
212
|
+
if ($.rails.fire(getSection(pagination_name),"ajaxp:fail",[jqXHR.responseText])) $(id).html(jqXHR.responseText);
|
213
|
+
|
214
|
+
delete pagination_loader_state[pagination_name]; // not waiting for page anymore
|
215
|
+
|
216
|
+
$.rails.fire(getSection(pagination_name),"ajaxp:loaded");
|
217
|
+
});
|
218
|
+
return true;
|
219
|
+
}
|
220
|
+
function swapPage(pagination_name, requesturl, history) { // swaps the page at pagination_name to that from requesturl (used by History.popState, therefore no remote link has been clicked)
|
221
|
+
if (history === undefined) history = false;
|
222
|
+
// send our own ajax request, and tie it into the beforeSendHandler used for jquery-ujs as well
|
223
|
+
if (!$.rails.fire(getSection(pagination_name),"ajaxp:before",[requesturl,undefined])) return false;
|
224
|
+
$.ajax({url: requesturl, data: {pagination:pagination_name},
|
225
|
+
dataType: 'html',
|
226
|
+
beforeSend: function (jqXHR,settings) {
|
227
|
+
var result = beforeSendHandler(pagination_name,jqXHR,settings);
|
228
|
+
if (result) {
|
229
|
+
if (history) pushHistory(pagination_name,settings.url);
|
230
|
+
pagination_loader_state[pagination_name] = settings.url; // remember which page number we are waiting for
|
231
|
+
}
|
232
|
+
return result;
|
233
|
+
}
|
234
|
+
});
|
235
|
+
}
|
236
|
+
function pushHistory(pagination_name,url) {
|
237
|
+
var data = $("#" + pagination_name + "_paginated_section").data("pagination");
|
238
|
+
if (data === undefined || data.history === undefined || data.history) { // check that history is not disabled
|
239
|
+
// construct visible url
|
240
|
+
var data = $.deparam.querystring($.url(url).attr('query'));
|
241
|
+
delete data['pagination'];
|
242
|
+
pagination_url = $.param.querystring(url,data,2);
|
243
|
+
if (isReload(pagination_name,url,location.href)) History.replaceState(history_state,document.title,pagination_url);
|
244
|
+
else { // not just a reload of current page, so do actual pushState
|
245
|
+
// change current history state, and push it on
|
246
|
+
if (history_state.ajax_pagination === undefined) history_state.ajax_pagination = new Array();
|
247
|
+
var fieldname = "_" + pagination_name;
|
248
|
+
if (history_state.ajax_pagination[fieldname] === undefined) history_state.ajax_pagination[fieldname]=1;
|
249
|
+
else history_state.ajax_pagination[fieldname]++;
|
250
|
+
History.pushState(history_state,document.title,pagination_url); // push state
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
// these special containers are for convenience only, to apply the required data-remote, data-pagination attributes to all links inside
|
255
|
+
$(document).on("click", ".pagination a, .ajaxpagination a, a.ajaxpagination", function(e) {
|
256
|
+
// ignore if already selected by jquery-ujs
|
257
|
+
if ($(this).filter($.rails.linkClickSelector).length>0) return true; // continue with jquery-ujs - this behaviour is necessary because we do not know if the jquery-ujs handler executes before or after this handler
|
258
|
+
// find out what data-pagination should be set to
|
259
|
+
var pagination_container = $(this).closest(".pagination, .ajaxpagination"); // container of links (use to check for data-pagination first)
|
260
|
+
var pagination_name = pagination_container.data('pagination');
|
261
|
+
if (pagination_name === undefined) {
|
262
|
+
pagination_name = /^(.*)_paginated_section$/.exec($(this).closest(".paginated_section").attr("id")); // if data-pagination not present, search up the tree for a suitable section
|
263
|
+
if (pagination_name == null) {
|
264
|
+
|
265
|
+
alert("AJAX Pagination MISSING_REFERENCE:\nNo pagination section name given for link, and none could be implicitly assigned, AJAX cancelled for this request");
|
266
|
+
|
267
|
+
return true; // pagination not set up properly
|
268
|
+
}
|
269
|
+
pagination_name = pagination_name[1];
|
270
|
+
}
|
271
|
+
|
272
|
+
// set data-remote, data-pagination
|
273
|
+
$(this).attr({'data-remote':'true'}); // needs to be set so that the jquery-ujs selectors work
|
274
|
+
$(this).data({'remote':'true','pagination':pagination_name}); // needs to be set because attributes only read into jquery's data memory once
|
275
|
+
if ($(this).data('type') === undefined) { // to be moved to ajax:before filter when https://github.com/rails/jquery-ujs/pull/241 is successful, and jquery-rails minimum version updated
|
276
|
+
$(this).data('type','html'); // AJAX Pagination requests return html be default
|
277
|
+
}
|
278
|
+
// stop this event from having further effect (because we do not know if jquery-ujs's event handler executed before or after us)
|
279
|
+
e.preventDefault();
|
280
|
+
e.stopImmediatePropagation();
|
281
|
+
// pass it on the jquery-ujs
|
282
|
+
$.rails.handleRemote($(this));
|
283
|
+
return false;
|
284
|
+
});
|
285
|
+
$(document).on("ajax:before","a, " + $.rails.inputChangeSelector, function() {
|
286
|
+
var pagination_name = $(this).data('pagination');
|
287
|
+
if (pagination_name === undefined) return true; // this is not an AJAX Pagination AJAX request
|
288
|
+
$(this).data('params',$.extend($(this).data('params'),{'pagination':pagination_name})); // add data-pagination to the params data
|
289
|
+
return $.rails.fire(getSection(pagination_name),"ajaxp:before",[this.href,$(this).data('method')]);
|
290
|
+
});
|
291
|
+
$(document).on("ajax:before","form", function() {
|
292
|
+
var pagination_name = $(this).data('pagination');
|
293
|
+
if (pagination_name === undefined) return true; // this is not an AJAX Pagination AJAX request
|
294
|
+
// alter action to include pagination parameter in the GET part of the action url
|
295
|
+
$(this).attr('action',$.param.querystring($(this).attr('action'),{pagination:pagination_name}));
|
296
|
+
return $.rails.fire(getSection(pagination_name),"ajaxp:before",[$(this).attr('action'),$(this).data('method')]);
|
297
|
+
});
|
298
|
+
$(document).on("ajax:beforeSend","a, form, " + $.rails.inputChangeSelector, function (e,jqXHR,settings) {
|
299
|
+
var pagination_name = $(this).data('pagination');
|
300
|
+
if (pagination_name === undefined) return true; // this is not an AJAX Pagination AJAX request
|
301
|
+
if (beforeSendHandler(pagination_name,jqXHR,settings)) {
|
302
|
+
pushHistory(pagination_name,settings.url);
|
303
|
+
pagination_loader_state[pagination_name] = settings.url;
|
304
|
+
}
|
305
|
+
return true;
|
306
|
+
});
|
307
|
+
History.Adapter.bind(window,'popstate',function(e){ // popstate, but can work with hash changes as well
|
308
|
+
//var from = pagination_url, to = location.href; // from what state to what other state
|
309
|
+
var state = History.getState().data || {};
|
310
|
+
state.ajax_pagination = state.ajax_pagination || {};
|
311
|
+
history_state.ajax_pagination = history_state.ajax_pagination || {};
|
312
|
+
if (!state.ajax_pagination_set) { // page first visited (if refresh, state remains)
|
313
|
+
state.ajax_pagination = history_state.ajax_pagination; // put current known state in
|
314
|
+
state.ajax_pagination_set = true; // special flag so that we know its touched
|
315
|
+
History.replaceState(state,document.title,location.href);
|
316
|
+
return;
|
317
|
+
}
|
318
|
+
var allsections = {};
|
319
|
+
for (var field in state.ajax_pagination) {
|
320
|
+
//if (getSection(field.substr(1)).length == 0) delete state.ajax_pagination[field]; // section no longer exists in current page, so can be deleted
|
321
|
+
// edit it cannot be deleted anymore, because if history changes, section tree node not necessarily reloaded
|
322
|
+
allsections[field] = true;
|
323
|
+
}
|
324
|
+
for (var field in history_state.ajax_pagination) allsections[field] = true;
|
325
|
+
|
326
|
+
var changedsections = new Array();
|
327
|
+
for (var section in allsections) {
|
328
|
+
var from = history_state.ajax_pagination[section] || 0;
|
329
|
+
var to = state.ajax_pagination[section] || 0;
|
330
|
+
if (from != to) {
|
331
|
+
// schedule for loading only if not a refresh (changing browser history does not cause a refresh unless it is explicitly requested)
|
332
|
+
//alert('testing ' + section);
|
333
|
+
if (!isReload(section.substr(1),location.href,pagination_url)) changedsections.push(section.substr(1)); // this section changed
|
334
|
+
}
|
335
|
+
}
|
336
|
+
history_state = state; // we can update our view of the state now
|
337
|
+
|
338
|
+
changedsections.sort(); // sort the pagination_names stored in array
|
339
|
+
for (var i = 0; i < changedsections.length; i++) {
|
340
|
+
var section = getSection(changedsections[i]);
|
341
|
+
if (section.length == 0) continue; // no longer exists on page (meaning it does not need reloading)
|
342
|
+
var parentsections = getSectionNames(section.parents(".paginated_section"));
|
343
|
+
parentsections.sort();
|
344
|
+
// check for intersection
|
345
|
+
if (!intersects(changedsections,parentsections)) { // no intersection, load new content in this section
|
346
|
+
swapPage(changedsections[i],location.href);
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
pagination_url = location.href; // update url (new url recognised)
|
351
|
+
});
|
352
|
+
|
353
|
+
History.Adapter.trigger(window,"popstate"); // update stuff on page load
|
354
|
+
|
355
|
+
// trigger a loaded event on each section on initial page load
|
356
|
+
$.rails.fire($(".paginated_section"),"ajaxp:loaded");
|
357
|
+
}
|
358
|
+
else {
|
359
|
+
// AJAX Pagination is disabled, we need to tidy up a few things to keep things working
|
360
|
+
|
361
|
+
// remove remote attribute globally
|
362
|
+
$("a[data-pagination]").removeData('remote');
|
363
|
+
$("a[data-pagination]").removeAttr('data-remote');
|
364
|
+
$("form[data-pagination]").removeData('remote');
|
365
|
+
$("form[data-pagination]").removeAttr('data-remote');
|
366
|
+
|
367
|
+
// set an event handler to remove the remote attribute if new content is loaded with AJAX Pagination
|
368
|
+
$(document).children().add(".paginated_section").delegate("a, input, form","click.rails change.rails submit.rails", function(event) {
|
369
|
+
var element = $(event.target);
|
370
|
+
if (element.data('pagination') === undefined) return true;
|
371
|
+
else {
|
372
|
+
element.removeData('remote');
|
373
|
+
element.removeAttr('data-remote');
|
374
|
+
}
|
375
|
+
}); // note using delegate for this instance for backwards compatibility, since might be disabled due to old jQuery version
|
376
|
+
|
377
|
+
}
|
378
|
+
})( jQuery );
|
379
|
+
});
|
380
|
+
|