forked from defunkt/jquery-pjax
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3efcc3c
Showing
3 changed files
with
279 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Copyright (c) Chris Wanstrath | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
Software), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
## pushState + ajax = pjax | ||
|
||
.--. | ||
/ \ | ||
## a a | ||
( '._) | ||
|'-- | | ||
_.\___/_ ___pjax___ | ||
."\> \Y/|<'. '._.-' | ||
/ \ \_\/ / '-' / | ||
| --'\_/|/ | _/ | ||
|___.-' | |`'` | ||
| | | | ||
| / './ | ||
/__./` | | | ||
\ | | | ||
\ | | | ||
; | | | ||
/ | | | ||
jgs |___\_.\_ | ||
`-"--'---' | ||
|
||
|
||
## what is it? | ||
|
||
pjax loads content from your server into an existing page | ||
without reloading that entire page while ensuring permalinks, | ||
titles, and the back button work as expected. It enhances the | ||
browsing experience of your users - nothing more. | ||
|
||
|
||
## three ways to pjax on the client side: | ||
|
||
1. Functionally obtrusive, loading the href with ajax into data-pjax: | ||
|
||
<a href='/explore' data-pjax='#main'>Explore</a> | ||
|
||
$('a[data-pjax]').pjax() | ||
|
||
|
||
2. Slightly obtrusive, passing a container and jQuery ajax options: | ||
|
||
<a href='/explore' class='js-pjax'>Explore</a> | ||
|
||
$('a.js-pjax').pjax('#main', { error: function(){ | ||
$('.error').text('Something went wrong!') | ||
}) | ||
|
||
|
||
3. Unobtrusive, using the pjax 'loading' callback: | ||
|
||
<div id='main'> | ||
<div class='loader' style='display:none'><img src='spin.gif'></div> | ||
<div class='tabs'> | ||
<a href='/explore'>Explore</a> | ||
<a href='/help'>Help</a> | ||
</div> | ||
</div> | ||
|
||
$('a').pjax('#main', { loading: function(){ | ||
this == the target container == #main | ||
$(this).find('.loader').show() | ||
}) | ||
|
||
|
||
## $(link).pjax( container, options ) | ||
|
||
The $(link).pjax() function accepts a container, an options object, | ||
or both. The options are the same as jQuery's ajax options with the | ||
following additions: | ||
|
||
container - The selector of the container to load the reponse body into, or | ||
the container itself. | ||
push - Whether to pushState the URL. Defaults to true (of course). | ||
loading - A callback to fire after it's been too many ms and | ||
you want to ease the user's pain with a loading indicator. | ||
You can also bind to the 'loading.pjax' event on container. | ||
|
||
|
||
## $.pjax( options ) | ||
|
||
You can also just call $.pjax directly. It acts much like $.ajax, even | ||
returning the same thing and accepting the same options. | ||
|
||
The pjax-specific keys listed in the $(link).pjax() section work here | ||
as well. | ||
|
||
This pjax call: | ||
|
||
$.pjax({ | ||
url: '/authors', | ||
container: '#main' | ||
}) | ||
|
||
Roughly translates into this ajax call: | ||
|
||
$.ajax({ | ||
url: '/authors?pjax=true', | ||
dataType: 'html', | ||
success: function(data){ | ||
$('#main').html( data ) | ||
history.pushState( null, $(data).filter('title').text(), '/authors' ) | ||
}) | ||
}) | ||
|
||
|
||
## install it | ||
|
||
$ cd path/to/js | ||
$ curl -O https://github.com/defunkt/jquery-pjax/raw/master/jquery.pjax.js | ||
|
||
Then, in your HTML: | ||
|
||
<script src="path/to/js/jquery.pjax.js"></script> | ||
|
||
Replace 'path/to/js' with the path to your JavaScript directory, | ||
e.g. 'public/javascripts'. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// When called on a link, fetches the href with ajax into the | ||
// container specified as the first parameter or with the data-pjax | ||
// attribute on the link itself. | ||
// | ||
// Tries to make sure the back button and ctrl+click work the way | ||
// you'd expect. | ||
// | ||
// Accepts a jQuery ajax options object that may include these | ||
// pjax specific options: | ||
// | ||
// container - Where to stick the response body. Usually a String selector. | ||
// $(container).html(xhr.responseBody) | ||
// loading - A callback to fire after it's been too many ms and | ||
// you want to ease the user's pain with a loading indicator. | ||
// You can also bind to the 'loading.pjax' event on container. | ||
// push - Whether to pushState the URL. Defaults to true (of course). | ||
// | ||
// For convenience the first parameter can be either the container or | ||
// the options object. | ||
// | ||
// Returns the jQuery object | ||
jQuery.fn.pjax = function( container, options ) { | ||
var $ = jQuery | ||
|
||
if ( options ) | ||
options.container = container | ||
else | ||
options = container | ||
|
||
$(this).live('click', function(){ | ||
// Middle click, cmd click, and ctrl click should open | ||
// links in a new tab as normal. | ||
if ( event.which == 2 || event.metaKey ) | ||
return true | ||
|
||
var defaults = { | ||
url: this.href, | ||
container: $(this).attr('data-pjax') | ||
} | ||
|
||
$.pjax( $.extend({}, defaults, options) ) | ||
|
||
return false | ||
}) | ||
} | ||
|
||
|
||
// Loads a URL with ajax, puts the response body inside a container, | ||
// then pushState()'s the loaded URL. Also ensures the back button | ||
// works the way you'd expect. | ||
// | ||
// Works just like $.ajax in that it accepts a jQuery ajax | ||
// settings object (with keys like url, type, data, etc). | ||
// | ||
// Accepts these extra keys: | ||
// | ||
// container - Where to stick the response body. | ||
// $(container).html(xhr.responseBody) | ||
// loading - A callback to fire after it's been too many ms and | ||
// you want to ease the user's pain with a loading indicator. | ||
// You can also bind to the 'loading.pjax' event on container. | ||
// push - Whether to pushState the URL. Defaults to true (of course). | ||
// | ||
// Use it just like $.ajax: | ||
// | ||
// var xhr = $.pjax({ url: this.href, container: '#main' }) | ||
// console.log( xhr.readyState ) | ||
// | ||
// Returns whatever $.ajax returns. | ||
jQuery.pjax = function( options ) { | ||
// Helper | ||
var $ = jQuery | ||
|
||
var defaults = { | ||
data: { pjax: true }, | ||
type: 'GET', | ||
dataType: 'html', | ||
error: function(){ window.location = options.url }, | ||
success: function(data){ | ||
// If we got no data or an entire web page, go directly | ||
// to the page and let normal error handling happen. | ||
if ( !$.trim(data) || /<html/i.test(data) ) | ||
return window.location = options.url | ||
|
||
// If there's a <title> tag in the response, use it as | ||
// the page's title. | ||
var title = $.trim( $(data).filter('title').remove().text() ) | ||
if ( title ) document.title = title | ||
|
||
// Make it happen. | ||
$(options.container).html( data ) | ||
|
||
// If they didn't explicitly disable `push`, call pushState() | ||
if ( options.push !== false ) { | ||
window.history.pushState( { pjax: options.container }, | ||
document.title, options.url ) | ||
} | ||
|
||
// Invoke their success handler if they gave us one. | ||
success.apply( this, arguments ) | ||
} | ||
} | ||
|
||
// We don't want to let anyone override our success handler. | ||
var success = options.success || $.noop | ||
delete options.success | ||
|
||
options = $.extend( true, {}, defaults, options ) | ||
var xhr = $.ajax( options ) | ||
|
||
// If we haven't found what we're looking for after a buncha ms | ||
// you might want to show a 'Loading...' indicator. | ||
setTimeout(function(){ | ||
if ( xhr.readyState == 4 ) return | ||
$(options.container).trigger('loading.pjax') | ||
if ( options.loading ) options.loading.call( options.container ) | ||
}, 350) | ||
|
||
$(document).trigger('pjax', xhr, options) | ||
return xhr | ||
} | ||
|
||
// Bind our popstate handler which takes care of the back and | ||
// forward buttons, but only once we've called pjax() | ||
jQuery(document).one('pjax', function(){ | ||
jQuery(window).bind('popstate', function(event){ | ||
var state = event.state | ||
if ( state && state.pjax ) | ||
jQuery.pjax({ url: location.href, container: state.pjax, push: false }) | ||
else | ||
window.location = location.href | ||
}) | ||
}) | ||
|
||
// Add the state property to jQuery's event object so we can use it in | ||
// $(window).bind('popstate') | ||
jQuery.event.props.push('state') | ||
|
||
// Fall back to normalcy for older browsers. | ||
if ( !window.history || !window.history.pushState ) { | ||
jQuery.pjax = jQuery.fn.pjax = $.noop | ||
} |