Merge pull request #3020 from githubjeka/patch-1

Fix compatible PJAX  with jQuery 3
This commit is contained in:
buddh4 2018-02-27 15:26:48 +01:00 committed by GitHub
commit cdf3764f28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -5,28 +5,28 @@
*/
/**
*
*
* This modified version removed pjaxs asynchronous script loading mechanism.
* Now the script management is handled by yii.js which assures scripts beeing loades synchronously.
*
*
* This was required since the humhub:ready event is was triggered before scripts of pjax results were loaded.
* Since those scripts possibly contain widgets or additions required in the page.
*
*
* Therefore we removed the:
*
*
* executeScriptTags(container.scripts, context) call
*
*
* and
*
*
* obj.scripts = findAll(obj.contents, 'script').remove()
* obj.contents = obj.contents.not(obj.scripts)
*
*
*
*
* see:
*
*
* https://github.com/defunkt/jquery-pjax/issues/331
* https://github.com/defunkt/jquery-pjax/pull/479
*
*
**/
(function($){
@ -64,11 +64,13 @@
//
// Returns the jQuery object
function fnPjax(selector, container, options) {
var context = this
options = optionsFor(container, options)
return this.on('click.pjax', selector, function(event) {
var opts = $.extend({history: true}, optionsFor(container, options))
if (!opts.container)
opts.container = $(this).attr('data-pjax') || context
var opts = options
if (!opts.container) {
opts = $.extend({}, options)
opts.container = $(this).attr('data-pjax')
}
handleClick(event, opts)
})
}
@ -98,9 +100,9 @@ function handleClick(event, container, options) {
options = optionsFor(container, options)
var link = event.currentTarget
var $link = $(link)
// Ignore links with data-pjax="0"
if ($(link).data('pjax') == 0) {
if ($link.data('pjax') == 0) {
return;
}
@ -126,18 +128,18 @@ function handleClick(event, container, options) {
var defaults = {
url: link.href,
container: $(link).attr('data-pjax'),
container: $link.attr('data-pjax'),
target: link
}
var opts = $.extend({}, defaults, options)
var clickEvent = $.Event('pjax:click')
$(link).trigger(clickEvent, [opts])
$link.trigger(clickEvent, [opts])
if (!clickEvent.isDefaultPrevented()) {
pjax(opts)
event.preventDefault()
$(link).trigger('pjax:clicked', [opts])
$link.trigger('pjax:clicked', [opts])
}
}
@ -151,8 +153,7 @@ function handleClick(event, container, options) {
// Examples
//
// $(document).on('submit', 'form', function(event) {
// var container = $(this).closest('[data-pjax-container]')
// $.pjax.submit(event, container)
// $.pjax.submit(event, '[data-pjax-container]')
// })
//
// Returns nothing.
@ -173,17 +174,17 @@ function handleSubmit(event, container, options) {
}
if (defaults.type !== 'GET' && window.FormData !== undefined) {
defaults.data = new FormData(form);
defaults.processData = false;
defaults.contentType = false;
defaults.data = new FormData(form)
defaults.processData = false
defaults.contentType = false
} else {
// Can't handle file uploads, exit
if ($(form).find(':file').length) {
return;
if ($form.find(':file').length) {
return
}
// Fallback to manually serializing the fields
defaults.data = $(form).serializeArray();
defaults.data = $form.serializeArray()
}
pjax($.extend({}, defaults, options))
@ -199,8 +200,7 @@ function handleSubmit(event, container, options) {
//
// Accepts these extra keys:
//
// container - Where to stick the response body.
// $(container).html(xhr.responseBody)
// container - String selector for where to stick the response body.
// push - Whether to pushState the URL. Defaults to true (of course).
// replace - Want to use replaceState instead? That's cool.
//
@ -217,11 +217,16 @@ function pjax(options) {
options.url = options.url()
}
var target = options.target
var hash = parseURL(options.url).hash
var context = options.context = findContainerFor(options.container)
var containerType = $.type(options.container)
if (containerType !== 'string') {
throw "expected string value for 'container' option; got " + containerType
}
var context = options.context = $(options.container)
if (!context.length) {
throw "the container selector '" + options.container + "' did not match anything"
}
// We want the browser to maintain two separate internal caches: one
// for pjax'd partial page loads and one for normal page loads.
@ -229,15 +234,14 @@ function pjax(options) {
// confuse the two.
if (!options.data) options.data = {}
if ($.isArray(options.data)) {
options.data = $.grep(options.data, function(obj) { return '_pjax' !== obj.name })
options.data.push({name: '_pjax', value: context.selector})
options.data.push({name: '_pjax', value: options.container})
} else {
options.data._pjax = context.selector
options.data._pjax = options.container
}
function fire(type, args, props) {
if (!props) props = {}
props.relatedTarget = target
props.relatedTarget = options.target
var event = $.Event(type, props)
context.trigger(event, args)
return !event.isDefaultPrevented()
@ -253,14 +257,7 @@ function pjax(options) {
}
xhr.setRequestHeader('X-PJAX', 'true')
xhr.setRequestHeader('X-PJAX-Container', context.selector)
if (settings.ieRedirectCompatibility) {
var ua = window.navigator.userAgent
if (ua.indexOf('MSIE ') > 0 || ua.indexOf('Trident/') > 0 || ua.indexOf('Edge/') > 0) {
xhr.setRequestHeader('X-Ie-Redirect-Compatibility', 'true')
}
}
xhr.setRequestHeader('X-PJAX-Container', options.container)
if (!fire('pjax:beforeSend', [xhr, settings]))
return false
@ -291,22 +288,15 @@ function pjax(options) {
options.error = function(xhr, textStatus, errorThrown) {
var container = extractContainer("", xhr, options)
// Check redirect status code
var redirect = (xhr.status >= 301 && xhr.status <= 303)
// Do not fire pjax::error in case of redirect
var allowed = redirect || fire('pjax:error', [xhr, textStatus, errorThrown, options])
if (redirect || options.type == 'GET' && textStatus !== 'abort' && allowed) {
if (options.replaceRedirect) {
locationReplace(container.url)
} else if (options.pushRedirect) {
window.history.pushState(null, "", container.url)
window.location.replace(container.url)
}
var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
if (options.type == 'GET' && textStatus !== 'abort' && allowed) {
locationReplace(container.url)
}
}
options.success = function(data, status, xhr) {
var previousState = pjax.state;
var previousState = pjax.state
// If $.pjax.defaults.version is a function, invoke it first.
// Otherwise it can be a static string.
@ -340,13 +330,12 @@ function pjax(options) {
id: options.id || uniqueId(),
url: container.url,
title: container.title,
container: context.selector,
container: options.container,
fragment: options.fragment,
timeout: options.timeout,
cache: options.cache
timeout: options.timeout
}
if (options.history && (options.push || options.replace)) {
if (options.push || options.replace) {
window.history.replaceState(pjax.state, container.title, container.url)
}
@ -375,9 +364,9 @@ function pjax(options) {
// http://www.w3.org/html/wg/drafts/html/master/forms.html
var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]
if (autofocusEl && document.activeElement !== autofocusEl) {
autofocusEl.focus();
autofocusEl.focus()
}
// removed @see headline doc
//executeScriptTags(container.scripts, context)
@ -405,10 +394,9 @@ function pjax(options) {
id: uniqueId(),
url: window.location.href,
title: document.title,
container: context.selector,
container: options.container,
fragment: options.fragment,
timeout: options.timeout,
cache: options.cache
timeout: options.timeout
}
window.history.replaceState(pjax.state, document.title)
}
@ -424,9 +412,9 @@ function pjax(options) {
var xhr = pjax.xhr = $.ajax(options)
if (xhr.readyState > 0) {
if (options.history && (options.push && !options.replace)) {
if (options.push && !options.replace) {
// Cache current container element before replacing it
cachePush(pjax.state.id, cloneContents(context))
cachePush(pjax.state.id, [options.container, cloneContents(context)])
window.history.pushState(null, "", options.requestUrl)
}
@ -459,7 +447,6 @@ function pjaxReload(container, options) {
//
// Returns nothing.
function locationReplace(url) {
if (!pjax.options.history) return;
window.history.replaceState(null, "", pjax.state.url)
window.location.replace(url)
}
@ -486,6 +473,7 @@ if ('state' in window.history) {
// You probably shouldn't use pjax on pages with other pushState
// stuff yet.
function onPjaxPopstate(event) {
// Hitting back or forward should override any pending PJAX request.
if (!initialPop) {
abortXHR(pjax.xhr)
@ -510,28 +498,18 @@ function onPjaxPopstate(event) {
direction = previousState.id < state.id ? 'forward' : 'back'
}
var cache = cacheMapping[state.id] || [];
var container = $(cache[0] || state.container);
var cache = cacheMapping[state.id] || []
var containerSelector = cache[0] || state.container
var container = $(containerSelector), contents = cache[1]
// HUMHUB PATCH, cached content was used even when cache is deactivated.
var contents = (state.cache) ? cache[1] : undefined;
if (container.length) {
var options = {
id: state.id,
url: state.url,
container: container,
push: false,
fragment: state.fragment,
timeout: state.timeout,
cache: state.cache,
scrollTo: false
}
if (previousState && options.cache) {
if (previousState) {
// Cache current container before replacement and inform the
// cache which direction the history shifted.
cachePop(direction, previousState.id, cloneContents(container))
cachePop(direction, previousState.id, [containerSelector, cloneContents(container)])
}
var popstateEvent = $.Event('pjax:popstate', {
@ -540,6 +518,16 @@ function onPjaxPopstate(event) {
})
container.trigger(popstateEvent)
var options = {
id: state.id,
url: state.url,
container: containerSelector,
push: false,
fragment: state.fragment,
timeout: state.timeout,
scrollTo: false
}
if (contents) {
container.trigger('pjax:start', [null, options])
@ -635,7 +623,7 @@ function cloneContents(container) {
cloned.find('script').each(function(){
if (!this.src) jQuery._data(this, 'globalEval', false)
})
return [container.selector, cloned.contents()]
return cloned.contents()
}
// Internal: Strip internal query params from parsed URL.
@ -685,44 +673,14 @@ function stripHash(location) {
//
// Returns options Object.
function optionsFor(container, options) {
// Both container and options
if ( container && options )
if (container && options) {
options = $.extend({}, options)
options.container = container
// First argument is options Object
else if ( $.isPlainObject(container) )
options = container
// Only container
else
options = {container: container}
// Find and validate container
if (options.container)
options.container = findContainerFor(options.container)
return options
}
// Internal: Find container element for a variety of inputs.
//
// Because we can't persist elements using the history API, we must be
// able to find a String selector that will consistently find the Element.
//
// container - A selector String, jQuery object, or DOM Element.
//
// Returns a jQuery object whose context is `document` and has a selector.
function findContainerFor(container) {
container = $(container)
if ( !container.length ) {
throw "no pjax container for " + container.selector
} else if ( container.selector !== '' && container.context === document ) {
return options
} else if ($.isPlainObject(container)) {
return container
} else if ( container.attr('id') ) {
return $('#' + container.attr('id'))
} else {
throw "cant get selector for pjax container!"
return {container: container}
}
}
@ -736,7 +694,7 @@ function findContainerFor(container) {
//
// Returns a jQuery object.
function findAll(elems, selector) {
return elems.filter(selector).add(elems.find(selector));
return elems.filter(selector).add(elems.find(selector))
}
function parseHTML(html) {
@ -811,8 +769,8 @@ function extractContainer(data, xhr, options) {
// Gather all script elements
/*
* Removed @see headline documentation.
*
* obj.scripts = findAll(obj.contents, 'script').remove()
*
* obj.scripts = findAll(obj.contents, 'script[src]').remove()
* obj.contents = obj.contents.not(obj.scripts)
*/
}
@ -829,44 +787,26 @@ function extractContainer(data, xhr, options) {
// globalEval.
//
// scripts - jQuery object of script Elements
// context - jQuery object whose context is `document` and has a selector
//
// Returns nothing.
function executeScriptTags(scripts, context) {
function executeScriptTags(scripts) {
if (!scripts) return
var existingScripts = $('script[src]')
var cb = function (next) {
scripts.each(function() {
var src = this.src
var matchedScripts = existingScripts.filter(function () {
var matchedScripts = existingScripts.filter(function() {
return this.src === src
})
if (matchedScripts.length) return
if (matchedScripts.length) {
next()
return
}
if (src) {
$.getScript(src).done(next).fail(next)
document.head.appendChild(this)
} else {
context.append(this)
next()
}
}
var i = 0;
var next = function () {
if (i >= scripts.length) {
return
}
var script = scripts[i]
i++
cb.call(script, next)
}
next()
var script = document.createElement('script')
var type = $(this).attr('type')
if (type) script.type = type
script.src = $(this).attr('src')
document.head.appendChild(script)
})
}
// Internal: History DOM caching class.
@ -883,9 +823,6 @@ var cacheBackStack = []
//
// Returns nothing.
function cachePush(id, value) {
if (!pjax.options.cache) {
return;
}
cacheMapping[id] = value
cacheBackStack.push(id)
@ -965,8 +902,6 @@ function enable() {
$.pjax.submit = handleSubmit
$.pjax.reload = pjaxReload
$.pjax.defaults = {
history: true,
cache: true,
timeout: 650,
push: true,
replace: false,
@ -974,11 +909,7 @@ function enable() {
dataType: 'html',
scrollTo: 0,
maxCacheLength: 20,
version: findVersion,
pushRedirect: false,
replaceRedirect: true,
skipOuterContainers: false,
ieRedirectCompatibility: true
version: findVersion
}
$(window).on('popstate.pjax', onPjaxPopstate)
}
@ -1009,8 +940,11 @@ function disable() {
// Add the state property to jQuery's event object so we can use it in
// $(window).bind('popstate')
if ( $.inArray('state', $.event.props) < 0 )
if ($.event.props && $.inArray('state', $.event.props) < 0) {
$.event.props.push('state')
} else if (!('state' in $.Event.prototype)) {
$.event.addProp('state')
}
// Is pjax supported by this browser?
$.support.pjax =
@ -1020,5 +954,4 @@ $.support.pjax =
$.support.pjax ? enable() : disable()
})(jQuery);
})(jQuery)