Commit 04f381eb by Paul Klimov

Merge branch 'master' of github.com:yiisoft/yii2

parents 518954da afefcd6e
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
// the options object. // the options object.
// //
// Returns the jQuery object // Returns the jQuery object
function fnPjax(selector, container, options) { function fnPjax(selector, container, options) {
var context = this var context = this
return this.on('click.pjax', selector, function(event) { return this.on('click.pjax', selector, function(event) {
var opts = $.extend({}, optionsFor(container, options)) var opts = $.extend({}, optionsFor(container, options))
...@@ -35,7 +35,7 @@ function fnPjax(selector, container, options) { ...@@ -35,7 +35,7 @@ function fnPjax(selector, container, options) {
opts.container = $(this).attr('data-pjax') || context opts.container = $(this).attr('data-pjax') || context
handleClick(event, opts) handleClick(event, opts)
}) })
} }
// Public: pjax on click handler // Public: pjax on click handler
// //
...@@ -56,7 +56,7 @@ function fnPjax(selector, container, options) { ...@@ -56,7 +56,7 @@ function fnPjax(selector, container, options) {
// }) // })
// //
// Returns nothing. // Returns nothing.
function handleClick(event, container, options) { function handleClick(event, container, options) {
options = optionsFor(container, options) options = optionsFor(container, options)
var link = event.currentTarget var link = event.currentTarget
...@@ -95,8 +95,9 @@ function handleClick(event, container, options) { ...@@ -95,8 +95,9 @@ function handleClick(event, container, options) {
if (!clickEvent.isDefaultPrevented()) { if (!clickEvent.isDefaultPrevented()) {
pjax(opts) pjax(opts)
event.preventDefault() event.preventDefault()
$(link).trigger('pjax:clicked', [opts])
}
} }
}
// Public: pjax on form submit handler // Public: pjax on form submit handler
// //
...@@ -113,7 +114,7 @@ function handleClick(event, container, options) { ...@@ -113,7 +114,7 @@ function handleClick(event, container, options) {
// }) // })
// //
// Returns nothing. // Returns nothing.
function handleSubmit(event, container, options) { function handleSubmit(event, container, options) {
options = optionsFor(container, options) options = optionsFor(container, options)
var form = event.currentTarget var form = event.currentTarget
...@@ -132,7 +133,7 @@ function handleSubmit(event, container, options) { ...@@ -132,7 +133,7 @@ function handleSubmit(event, container, options) {
pjax($.extend({}, defaults, options)) pjax($.extend({}, defaults, options))
event.preventDefault() event.preventDefault()
} }
// Loads a URL with ajax, puts the response body inside a container, // Loads a URL with ajax, puts the response body inside a container,
// then pushState()'s the loaded URL. // then pushState()'s the loaded URL.
...@@ -153,7 +154,7 @@ function handleSubmit(event, container, options) { ...@@ -153,7 +154,7 @@ function handleSubmit(event, container, options) {
// console.log( xhr.readyState ) // console.log( xhr.readyState )
// //
// Returns whatever $.ajax returns. // Returns whatever $.ajax returns.
function pjax(options) { function pjax(options) {
options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options) options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
if ($.isFunction(options.url)) { if ($.isFunction(options.url)) {
...@@ -344,12 +345,12 @@ function pjax(options) { ...@@ -344,12 +345,12 @@ function pjax(options) {
} }
return pjax.xhr return pjax.xhr
} }
// Public: Reload current page with pjax. // Public: Reload current page with pjax.
// //
// Returns whatever $.pjax returns. // Returns whatever $.pjax returns.
function pjaxReload(container, options) { function pjaxReload(container, options) {
var defaults = { var defaults = {
url: window.location.href, url: window.location.href,
push: false, push: false,
...@@ -358,7 +359,7 @@ function pjaxReload(container, options) { ...@@ -358,7 +359,7 @@ function pjaxReload(container, options) {
} }
return pjax($.extend(defaults, optionsFor(container, options))) return pjax($.extend(defaults, optionsFor(container, options)))
} }
// Internal: Hard replace current state with url. // Internal: Hard replace current state with url.
// //
...@@ -366,33 +367,33 @@ function pjaxReload(container, options) { ...@@ -366,33 +367,33 @@ function pjaxReload(container, options) {
// https://bugs.webkit.org/show_bug.cgi?id=93506 // https://bugs.webkit.org/show_bug.cgi?id=93506
// //
// Returns nothing. // Returns nothing.
function locationReplace(url) { function locationReplace(url) {
window.history.replaceState(null, "", "#") window.history.replaceState(null, "", "#")
window.location.replace(url) window.location.replace(url)
} }
var initialPop = true var initialPop = true
var initialURL = window.location.href var initialURL = window.location.href
var initialState = window.history.state var initialState = window.history.state
// Initialize $.pjax.state if possible // Initialize $.pjax.state if possible
// Happens when reloading a page and coming forward from a different // Happens when reloading a page and coming forward from a different
// session history. // session history.
if (initialState && initialState.container) { if (initialState && initialState.container) {
pjax.state = initialState pjax.state = initialState
} }
// Non-webkit browsers don't fire an initial popstate event // Non-webkit browsers don't fire an initial popstate event
if ('state' in window.history) { if ('state' in window.history) {
initialPop = false initialPop = false
} }
// popstate handler takes care of the back and forward buttons // popstate handler takes care of the back and forward buttons
// //
// You probably shouldn't use pjax on pages with other pushState // You probably shouldn't use pjax on pages with other pushState
// stuff yet. // stuff yet.
function onPjaxPopstate(event) { function onPjaxPopstate(event) {
var state = event.state var state = event.state
if (state && state.container) { if (state && state.container) {
...@@ -455,13 +456,13 @@ function onPjaxPopstate(event) { ...@@ -455,13 +456,13 @@ function onPjaxPopstate(event) {
} }
} }
initialPop = false initialPop = false
} }
// Fallback version of main pjax function for browsers that don't // Fallback version of main pjax function for browsers that don't
// support pushState. // support pushState.
// //
// Returns nothing since it retriggers a hard form submission. // Returns nothing since it retriggers a hard form submission.
function fallbackPjax(options) { function fallbackPjax(options) {
var url = $.isFunction(options.url) ? options.url() : options.url, var url = $.isFunction(options.url) ? options.url() : options.url,
method = options.type ? options.type.toUpperCase() : 'GET' method = options.type ? options.type.toUpperCase() : 'GET'
...@@ -492,7 +493,7 @@ function fallbackPjax(options) { ...@@ -492,7 +493,7 @@ function fallbackPjax(options) {
$(document.body).append(form) $(document.body).append(form)
form.submit() form.submit()
} }
// Internal: Generate unique id for state object. // Internal: Generate unique id for state object.
// //
...@@ -500,32 +501,32 @@ function fallbackPjax(options) { ...@@ -500,32 +501,32 @@ function fallbackPjax(options) {
// unique across page loads. // unique across page loads.
// //
// Returns Number. // Returns Number.
function uniqueId() { function uniqueId() {
return (new Date).getTime() return (new Date).getTime()
} }
// Internal: Strips _pjax param from url // Internal: Strips _pjax param from url
// //
// url - String // url - String
// //
// Returns String. // Returns String.
function stripPjaxParam(url) { function stripPjaxParam(url) {
return url return url
.replace(/\?_pjax=[^&]+&?/, '?') .replace(/\?_pjax=[^&]+&?/, '?')
.replace(/_pjax=[^&]+&?/, '') .replace(/_pjax=[^&]+&?/, '')
.replace(/[\?&]$/, '') .replace(/[\?&]$/, '')
} }
// Internal: Parse URL components and returns a Locationish object. // Internal: Parse URL components and returns a Locationish object.
// //
// url - String URL // url - String URL
// //
// Returns HTMLAnchorElement that acts like Location. // Returns HTMLAnchorElement that acts like Location.
function parseURL(url) { function parseURL(url) {
var a = document.createElement('a') var a = document.createElement('a')
a.href = url a.href = url
return a return a
} }
// Internal: Build options Object for arguments. // Internal: Build options Object for arguments.
// //
...@@ -544,7 +545,7 @@ function parseURL(url) { ...@@ -544,7 +545,7 @@ function parseURL(url) {
// // => {container: '#container', push: true} // // => {container: '#container', push: true}
// //
// Returns options Object. // Returns options Object.
function optionsFor(container, options) { function optionsFor(container, options) {
// Both container and options // Both container and options
if ( container && options ) if ( container && options )
options.container = container options.container = container
...@@ -562,7 +563,7 @@ function optionsFor(container, options) { ...@@ -562,7 +563,7 @@ function optionsFor(container, options) {
options.container = findContainerFor(options.container) options.container = findContainerFor(options.container)
return options return options
} }
// Internal: Find container element for a variety of inputs. // Internal: Find container element for a variety of inputs.
// //
...@@ -572,7 +573,7 @@ function optionsFor(container, options) { ...@@ -572,7 +573,7 @@ function optionsFor(container, options) {
// container - A selector String, jQuery object, or DOM Element. // container - A selector String, jQuery object, or DOM Element.
// //
// Returns a jQuery object whose context is `document` and has a selector. // Returns a jQuery object whose context is `document` and has a selector.
function findContainerFor(container) { function findContainerFor(container) {
container = $(container) container = $(container)
if ( !container.length ) { if ( !container.length ) {
...@@ -584,7 +585,7 @@ function findContainerFor(container) { ...@@ -584,7 +585,7 @@ function findContainerFor(container) {
} else { } else {
throw "cant get selector for pjax container!" throw "cant get selector for pjax container!"
} }
} }
// Internal: Filter and find all elements matching the selector. // Internal: Filter and find all elements matching the selector.
// //
...@@ -595,13 +596,13 @@ function findContainerFor(container) { ...@@ -595,13 +596,13 @@ function findContainerFor(container) {
// selector - String selector to match // selector - String selector to match
// //
// Returns a jQuery object. // Returns a jQuery object.
function findAll(elems, selector) { function findAll(elems, selector) {
return elems.filter(selector).add(elems.find(selector)); return elems.filter(selector).add(elems.find(selector));
} }
function parseHTML(html) { function parseHTML(html) {
return $.parseHTML(html, document, true) return $.parseHTML(html, document, true)
} }
// Internal: Extracts container and metadata from response. // Internal: Extracts container and metadata from response.
// //
...@@ -614,7 +615,7 @@ function parseHTML(html) { ...@@ -614,7 +615,7 @@ function parseHTML(html) {
// options - pjax options Object // options - pjax options Object
// //
// Returns an Object with url, title, and contents keys. // Returns an Object with url, title, and contents keys.
function extractContainer(data, xhr, options) { function extractContainer(data, xhr, options) {
var obj = {} var obj = {}
// Prefer X-PJAX-URL header if it was set, otherwise fallback to // Prefer X-PJAX-URL header if it was set, otherwise fallback to
...@@ -676,7 +677,7 @@ function extractContainer(data, xhr, options) { ...@@ -676,7 +677,7 @@ function extractContainer(data, xhr, options) {
if (obj.title) obj.title = $.trim(obj.title) if (obj.title) obj.title = $.trim(obj.title)
return obj return obj
} }
// Load an execute scripts using standard script request. // Load an execute scripts using standard script request.
// //
...@@ -686,7 +687,7 @@ function extractContainer(data, xhr, options) { ...@@ -686,7 +687,7 @@ function extractContainer(data, xhr, options) {
// scripts - jQuery object of script Elements // scripts - jQuery object of script Elements
// //
// Returns nothing. // Returns nothing.
function executeScriptTags(scripts) { function executeScriptTags(scripts) {
if (!scripts) return if (!scripts) return
var existingScripts = $('script[src]') var existingScripts = $('script[src]')
...@@ -703,12 +704,12 @@ function executeScriptTags(scripts) { ...@@ -703,12 +704,12 @@ function executeScriptTags(scripts) {
script.src = $(this).attr('src') script.src = $(this).attr('src')
document.head.appendChild(script) document.head.appendChild(script)
}) })
} }
// Internal: History DOM caching class. // Internal: History DOM caching class.
var cacheMapping = {} var cacheMapping = {}
var cacheForwardStack = [] var cacheForwardStack = []
var cacheBackStack = [] var cacheBackStack = []
// Push previous state id and container contents into the history // Push previous state id and container contents into the history
// cache. Should be called in conjunction with `pushState` to save the // cache. Should be called in conjunction with `pushState` to save the
...@@ -718,7 +719,7 @@ var cacheBackStack = [] ...@@ -718,7 +719,7 @@ var cacheBackStack = []
// value - DOM Element to cache // value - DOM Element to cache
// //
// Returns nothing. // Returns nothing.
function cachePush(id, value) { function cachePush(id, value) {
cacheMapping[id] = value cacheMapping[id] = value
cacheBackStack.push(id) cacheBackStack.push(id)
...@@ -730,7 +731,7 @@ function cachePush(id, value) { ...@@ -730,7 +731,7 @@ function cachePush(id, value) {
// Trim back history stack to max cache length. // Trim back history stack to max cache length.
while (cacheBackStack.length > pjax.defaults.maxCacheLength) while (cacheBackStack.length > pjax.defaults.maxCacheLength)
delete cacheMapping[cacheBackStack.shift()] delete cacheMapping[cacheBackStack.shift()]
} }
// Shifts cache from directional history cache. Should be // Shifts cache from directional history cache. Should be
// called on `popstate` with the previous state id and container // called on `popstate` with the previous state id and container
...@@ -741,7 +742,7 @@ function cachePush(id, value) { ...@@ -741,7 +742,7 @@ function cachePush(id, value) {
// value - DOM Element to cache // value - DOM Element to cache
// //
// Returns nothing. // Returns nothing.
function cachePop(direction, id, value) { function cachePop(direction, id, value) {
var pushStack, popStack var pushStack, popStack
cacheMapping[id] = value cacheMapping[id] = value
...@@ -756,17 +757,17 @@ function cachePop(direction, id, value) { ...@@ -756,17 +757,17 @@ function cachePop(direction, id, value) {
pushStack.push(id) pushStack.push(id)
if (id = popStack.pop()) if (id = popStack.pop())
delete cacheMapping[id] delete cacheMapping[id]
} }
// Public: Find version identifier for the initial page load. // Public: Find version identifier for the initial page load.
// //
// Returns String version or undefined. // Returns String version or undefined.
function findVersion() { function findVersion() {
return $('meta').filter(function() { return $('meta').filter(function() {
var name = $(this).attr('http-equiv') var name = $(this).attr('http-equiv')
return name && name.toUpperCase() === 'X-PJAX-VERSION' return name && name.toUpperCase() === 'X-PJAX-VERSION'
}).attr('content') }).attr('content')
} }
// Install pjax functions on $.pjax to enable pushState behavior. // Install pjax functions on $.pjax to enable pushState behavior.
// //
...@@ -777,7 +778,7 @@ function findVersion() { ...@@ -777,7 +778,7 @@ function findVersion() {
// $.pjax.enable() // $.pjax.enable()
// //
// Returns nothing. // Returns nothing.
function enable() { function enable() {
$.fn.pjax = fnPjax $.fn.pjax = fnPjax
$.pjax = pjax $.pjax = pjax
$.pjax.enable = $.noop $.pjax.enable = $.noop
...@@ -796,7 +797,7 @@ function enable() { ...@@ -796,7 +797,7 @@ function enable() {
version: findVersion version: findVersion
} }
$(window).on('popstate.pjax', onPjaxPopstate) $(window).on('popstate.pjax', onPjaxPopstate)
} }
// Disable pushState behavior. // Disable pushState behavior.
// //
...@@ -809,7 +810,7 @@ function enable() { ...@@ -809,7 +810,7 @@ function enable() {
// $.pjax.disable() // $.pjax.disable()
// //
// Returns nothing. // Returns nothing.
function disable() { function disable() {
$.fn.pjax = function() { return this } $.fn.pjax = function() { return this }
$.pjax = fallbackPjax $.pjax = fallbackPjax
$.pjax.enable = enable $.pjax.enable = enable
...@@ -819,20 +820,20 @@ function disable() { ...@@ -819,20 +820,20 @@ function disable() {
$.pjax.reload = function() { window.location.reload() } $.pjax.reload = function() { window.location.reload() }
$(window).off('popstate.pjax', onPjaxPopstate) $(window).off('popstate.pjax', onPjaxPopstate)
} }
// Add the state property to jQuery's event object so we can use it in // Add the state property to jQuery's event object so we can use it in
// $(window).bind('popstate') // $(window).bind('popstate')
if ( $.inArray('state', $.event.props) < 0 ) if ( $.inArray('state', $.event.props) < 0 )
$.event.props.push('state') $.event.props.push('state')
// Is pjax supported by this browser? // Is pjax supported by this browser?
$.support.pjax = $.support.pjax =
window.history && window.history.pushState && window.history.replaceState && window.history && window.history.pushState && window.history.replaceState &&
// pushState isn't reliable on iOS until 5. // pushState isn't reliable on iOS until 5.
!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/) !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/)
$.support.pjax ? enable() : disable() $.support.pjax ? enable() : disable()
})(jQuery); })(jQuery);
...@@ -50,10 +50,16 @@ class Pjax extends Widget ...@@ -50,10 +50,16 @@ class Pjax extends Widget
/** /**
* @var string the jQuery selector of the links that should trigger pjax requests. * @var string the jQuery selector of the links that should trigger pjax requests.
* If not set, all links within the enclosed content of Pjax will trigger pjax requests. * If not set, all links within the enclosed content of Pjax will trigger pjax requests.
* Note that the pjax response to a link is a full page, a normal request will be sent again. * Note that if the response to the pjax request is a full page, a normal request will be sent again.
*/ */
public $linkSelector; public $linkSelector;
/** /**
* @var string the jQuery selector of the forms whose submissions should trigger pjax requests.
* If not set, all forms with `data-pjax` attribute within the enclosed content of Pjax will trigger pjax requests.
* Note that if the response to the pjax request is a full page, a normal request will be sent again.
*/
public $formSelector;
/**
* @var boolean whether to enable push state. * @var boolean whether to enable push state.
*/ */
public $enablePushState = true; public $enablePushState = true;
...@@ -148,9 +154,11 @@ class Pjax extends Widget ...@@ -148,9 +154,11 @@ class Pjax extends Widget
$this->clientOptions['timeout'] = $this->timeout; $this->clientOptions['timeout'] = $this->timeout;
$options = Json::encode($this->clientOptions); $options = Json::encode($this->clientOptions);
$linkSelector = Json::encode($this->linkSelector !== null ? $this->linkSelector : '#' . $id . ' a'); $linkSelector = Json::encode($this->linkSelector !== null ? $this->linkSelector : '#' . $id . ' a');
$formSelector = Json::encode($this->formSelector !== null ? $this->formSelector : '#' . $id . ' form[data-pjax]');
$view = $this->getView(); $view = $this->getView();
PjaxAsset::register($view); PjaxAsset::register($view);
$js = "jQuery(document).pjax($linkSelector, \"#$id\", $options);"; $js = "jQuery(document).pjax($linkSelector, \"#$id\", $options);";
$js .= "jQuery(document).on('submit', $formSelector, function (event) {jQuery.pjax.submit(event, '#$id');});";
$view->registerJs($js); $view->registerJs($js);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment