diff --git a/static/js/jquery.pjax.modified.js b/static/js/jquery.pjax.modified.js index d8ce0067d4..b9ac511cfe 100644 --- a/static/js/jquery.pjax.modified.js +++ b/static/js/jquery.pjax.modified.js @@ -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)