ajax search results: a cvan/gkobes collabo (bug 684342)
This commit is contained in:
Родитель
a9564b1c04
Коммит
e07256c6e6
|
@ -1,4 +1,4 @@
|
|||
<div id="sorter" class="c">
|
||||
<div id="sorter" class="c pjax-trigger">
|
||||
<h3>{{ _('Sort by:') }}</h3>
|
||||
<ul>
|
||||
{% for item in sort_opts %}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% if pager.paginator.num_pages > 1 %}
|
||||
<nav class="paginator c">
|
||||
<nav class="paginator c pjax-trigger">
|
||||
<p class="num">
|
||||
{# L10n: This is a page range (e.g., Page 1 of 50). #}
|
||||
{% trans current_pg=pager.number,
|
||||
|
@ -16,10 +16,10 @@
|
|||
{% if not pager.has_previous() %}class="disabled"{% endif %}>
|
||||
◂◂</a>
|
||||
<a href="{{ pager.url|urlparams(page=pager.previous_page_number()) }}"
|
||||
class="button{% if not pager.has_previous() %} disabled{% endif %}">
|
||||
class="button prev{% if not pager.has_previous() %} disabled{% endif %}">
|
||||
◂ {{ _('Previous') }}</a>
|
||||
<a href="{{ pager.url|urlparams(page=pager.next_page_number()) }}"
|
||||
class="button{% if not pager.has_next() %} disabled{% endif %}">
|
||||
class="button next{% if not pager.has_next() %} disabled{% endif %}">
|
||||
{{ _('Next') }} ▸</a>
|
||||
<a href="{{ pager.url|urlparams(page=pager.paginator.num_pages) }}"
|
||||
title="{{ _('Jump to last page') }}"
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
{% extends "impala/base.html" %}
|
||||
{% extends "base_ajax.html" if is_pjax else "impala/base.html" %}
|
||||
|
||||
{% block bodyclass %}
|
||||
{{ 'pjax' if waffle.switch('ajax-search') }} {{ super() }}
|
||||
{% endblock %}
|
||||
|
||||
{% block search_form %}
|
||||
{% with skip_autofill=True %}
|
||||
|
@ -47,9 +51,12 @@
|
|||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
<section id="search-facets" class="secondary" role="complementary">
|
||||
{% if is_pjax %}
|
||||
{% include "search/results_inner.html" %}
|
||||
{% else %}
|
||||
<section id="search-facets" class="secondary" role="complementary">
|
||||
<h2>{{ _('Filter Results') }}</h2>
|
||||
<ul class="facets island">
|
||||
<ul class="facets island pjax-trigger">
|
||||
{{ facet(_('Category'), categories) }}
|
||||
<li class="facet">
|
||||
<h3>{{ _('Works with') }}</h3>
|
||||
|
@ -63,26 +70,15 @@
|
|||
{{ facet(_('Tag'), tags) }}
|
||||
</ul>
|
||||
<p>{{ _('{0} matching results')|f(pager.paginator.count|numberfmt) }}</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="primary" role="main">
|
||||
|
||||
<div class="listing results island hero c">
|
||||
<section class="primary" role="main">
|
||||
<h1>{{ heading }}</h1>
|
||||
{{ impala_addon_listing_header(
|
||||
request.get_full_path()|urlparams(page=None),
|
||||
sort_opts, query.sort, extra_sort_opts) }}
|
||||
{% if pager.object_list %}
|
||||
<div class="items">
|
||||
{{ impala_addon_listing_items(pager.object_list, field=query.sort,
|
||||
src='search') }}
|
||||
<div class="listing results island hero c">
|
||||
<div id="pjax-results">
|
||||
{% include "search/results_inner.html" %}
|
||||
</div>
|
||||
{{ pager|impala_paginator }}
|
||||
{% else %}
|
||||
{% include 'search/no_results.html' %}
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{{ impala_addon_listing_header(request.get_full_path()|urlparams(page=None),
|
||||
sort_opts, query.sort, extra_sort_opts) }}
|
||||
{% if pager.object_list %}
|
||||
<div class="items">
|
||||
{{ impala_addon_listing_items(pager.object_list, field=query.sort,
|
||||
src='search') }}
|
||||
</div>
|
||||
{{ pager|impala_paginator }}
|
||||
{% else %}
|
||||
{% include 'search/no_results.html' %}
|
||||
{% endif %}
|
|
@ -104,9 +104,10 @@ class TestESSearch(amo.tests.ESTestCase):
|
|||
def setUpClass(cls):
|
||||
super(TestESSearch, cls).setUpClass()
|
||||
cls.setUpIndex()
|
||||
cls.search_views = ('search.search', 'apps.search')
|
||||
|
||||
@amo.tests.mobile_test
|
||||
def test_mobile_get(self):
|
||||
def test_mobile_results(self):
|
||||
r = self.client.get(reverse('search.search'))
|
||||
eq_(r.status_code, 200)
|
||||
self.assertTemplateUsed(r, 'search/mobile/results.html')
|
||||
|
@ -116,6 +117,40 @@ class TestESSearch(amo.tests.ESTestCase):
|
|||
r = self.client.get(base + '?sort=averagerating')
|
||||
self.assertRedirects(r, base + '?sort=rating', status_code=301)
|
||||
|
||||
def test_results(self):
|
||||
# These context variables should exist for normal requests.
|
||||
expected_context_vars = {
|
||||
'search.search': ('categories', 'platforms', 'versions', 'tags'),
|
||||
'apps.search': ('categories', 'tags'),
|
||||
}
|
||||
|
||||
for view in self.search_views:
|
||||
r = self.client.get(reverse(view))
|
||||
eq_(r.status_code, 200)
|
||||
eq_(r.context['is_pjax'], None)
|
||||
|
||||
for var in expected_context_vars[view]:
|
||||
assert var in r.context, (
|
||||
'%r missing context var in view %r' % (var, view))
|
||||
|
||||
doc = pq(r.content)
|
||||
eq_(doc('html').length, 1)
|
||||
eq_(doc('#pjax-results').length, 1)
|
||||
eq_(doc('#search-facets .facets.pjax-trigger').length, 1)
|
||||
eq_(doc('#sorter.pjax-trigger').length, 1)
|
||||
|
||||
def test_pjax_results(self):
|
||||
for view in self.search_views:
|
||||
r = self.client.get(reverse(view), HTTP_X_PJAX=True)
|
||||
eq_(r.status_code, 200)
|
||||
eq_(r.context['is_pjax'], True)
|
||||
|
||||
doc = pq(r.content)
|
||||
eq_(doc('html').length, 0)
|
||||
eq_(doc('#pjax-results').length, 0)
|
||||
eq_(doc('#search-facets .facets.pjax-trigger').length, 0)
|
||||
eq_(doc('#sorter.pjax-trigger').length, 1)
|
||||
|
||||
def assert_ajax_query(self, params, addons=[]):
|
||||
r = self.client.get(reverse('search.ajax') + '?' + params)
|
||||
eq_(r.status_code, 200)
|
||||
|
@ -172,7 +207,6 @@ class TestESSearch(amo.tests.ESTestCase):
|
|||
addon.update(type=amo.ADDON_PERSONA)
|
||||
Persona.objects.create(persona_id=4, addon_id=4)
|
||||
self.assert_ajax_query('q=4', [addon])
|
||||
self.assert_ajax_query('q=4&exclude_personas=true', [])
|
||||
|
||||
def test_ajax_search_char_limit(self):
|
||||
self.assert_ajax_query('q=ad', [])
|
||||
|
|
|
@ -418,14 +418,18 @@ def app_search(request, template=None):
|
|||
facets = pager.object_list.facets
|
||||
|
||||
ctx = {
|
||||
'is_pjax': request.META.get('HTTP_X_PJAX'),
|
||||
'pager': pager,
|
||||
'query': query,
|
||||
'form': form,
|
||||
'sorting': sort_sidebar(request, query, form),
|
||||
'sort_opts': form.fields['sort'].choices,
|
||||
}
|
||||
if not ctx['is_pjax']:
|
||||
ctx.update({
|
||||
'categories': category_sidebar(request, query, facets),
|
||||
'tags': tag_sidebar(request, query, facets),
|
||||
}
|
||||
})
|
||||
return jingo.render(request, template, ctx)
|
||||
|
||||
|
||||
|
@ -500,20 +504,24 @@ def search(request, tag_name=None, template=None):
|
|||
qs = qs.order_by('-weekly_downloads')
|
||||
|
||||
pager = amo.utils.paginate(request, qs)
|
||||
facets = pager.object_list.facets
|
||||
|
||||
ctx = {
|
||||
'is_pjax': request.META.get('HTTP_X_PJAX'),
|
||||
'pager': pager,
|
||||
'query': query,
|
||||
'form': form,
|
||||
'sort_opts': sort,
|
||||
'extra_sort_opts': extra_sort,
|
||||
'sorting': sort_sidebar(request, query, form),
|
||||
}
|
||||
if not ctx['is_pjax']:
|
||||
facets = pager.object_list.facets
|
||||
ctx.update({
|
||||
'categories': category_sidebar(request, query, facets),
|
||||
'platforms': platform_sidebar(request, query, facets),
|
||||
'versions': version_sidebar(request, query, facets),
|
||||
'tags': tag_sidebar(request, query, facets),
|
||||
}
|
||||
})
|
||||
return jingo.render(request, template, ctx)
|
||||
|
||||
|
||||
|
|
|
@ -123,5 +123,49 @@
|
|||
li ul {
|
||||
padding: 0 12px 0 0;
|
||||
}
|
||||
.facets .facet {
|
||||
&:after {
|
||||
right: auto;
|
||||
left: 5px;
|
||||
}
|
||||
&.active:after {
|
||||
-moz-transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.results {
|
||||
position: relative;
|
||||
&.loading {
|
||||
.updating {
|
||||
background: rgba(255,255,255, 0.8)
|
||||
url(../../img/impala/loading-big.gif)
|
||||
50% 50px no-repeat;
|
||||
border: 1px solid #ddd;
|
||||
.box-shadow(0 -2px 0 rgba(200, 200, 200, 0.3) inset,
|
||||
0 0 1px rgba(0, 0, 0, 0.1));
|
||||
.border-box;
|
||||
.border-radius(5px);
|
||||
color: @medium-gray;
|
||||
font: bold 20px @head-sans;
|
||||
margin-left: -250px / 2;
|
||||
position: absolute;
|
||||
top: 45px;
|
||||
left: 50%;
|
||||
padding: 15px 15px 45px;
|
||||
text-align: center;
|
||||
z-index: 100;
|
||||
width: 250px;
|
||||
&.tall {
|
||||
top: 200px;
|
||||
}
|
||||
}
|
||||
.items {
|
||||
opacity: .2;
|
||||
}
|
||||
}
|
||||
#sorter {
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 11 KiB |
|
@ -13,3 +13,9 @@ function populateErrors(context, o) {
|
|||
$row.append($list.append($(format('<li>{0}</li>', v))));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function fieldFocused(e) {
|
||||
var tags = /input|keygen|meter|option|output|progress|select|textarea/i;
|
||||
return tags.test(e.target.nodeName);
|
||||
}
|
||||
|
|
|
@ -5,16 +5,7 @@ $(function() {
|
|||
$p.popup($a, {width: 300, pointTo: $a});
|
||||
});
|
||||
|
||||
// Mark incompatible add-ons on listing pages unless marked with ignore.
|
||||
$('.listing .item.addon').each(function() {
|
||||
var $this = $(this);
|
||||
if ($this.find('.acr-override').length) {
|
||||
$this.addClass('acr');
|
||||
} else if (!$this.hasClass('ignore-compatibility') &&
|
||||
$this.find('.concealed').length == $this.find('.button').length) {
|
||||
$this.addClass('incompatible');
|
||||
}
|
||||
});
|
||||
initListingCompat();
|
||||
|
||||
$('.theme-grid .hovercard.theme').each(function() {
|
||||
var $this = $(this);
|
||||
|
@ -38,3 +29,18 @@ $(function() {
|
|||
$('.item.static').removeClass('static');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function initListingCompat(domContext) {
|
||||
domContext = domContext || document.body;
|
||||
// Mark incompatible add-ons on listing pages unless marked with ignore.
|
||||
$('.listing .item.addon', domContext).each(function() {
|
||||
var $this = $(this);
|
||||
if ($this.find('.acr-override').length) {
|
||||
$this.addClass('acr');
|
||||
} else if (!$this.hasClass('ignore-compatibility') &&
|
||||
$this.find('.concealed').length == $this.find('.button').length) {
|
||||
$this.addClass('incompatible');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,13 +1,91 @@
|
|||
$(function() {
|
||||
$('#search-facets').delegate('li.facet', 'click', function() {
|
||||
$('#search-facets').delegate('li.facet', 'click', function(e) {
|
||||
var $this = $(this);
|
||||
if ($this.hasClass('active')) {
|
||||
var $tgt = $(e.target);
|
||||
if ($tgt.is('a')) {
|
||||
$tgt.closest('.facet').find('.selected').removeClass('selected');
|
||||
$tgt.closest('li').addClass('selected');
|
||||
return;
|
||||
}
|
||||
$this.removeClass('active');
|
||||
} else {
|
||||
$this.closest('ul').find('.active').removeClass('active');
|
||||
$this.addClass('active');
|
||||
}
|
||||
}).delegate('li.facet a', 'click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
if ($('body').hasClass('pjax') && $.support.pjax) {
|
||||
initSearchPjax('#pjax-results');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function initSearchPjax(container) {
|
||||
var $container = $(container);
|
||||
|
||||
function pjaxOpen(url) {
|
||||
var urlBase = location.pathname + location.search;
|
||||
if (!!url && url != '#' && url != urlBase) {
|
||||
$.pjax({'url': url, 'container': container});
|
||||
}
|
||||
}
|
||||
|
||||
function hijackLink() {
|
||||
pjaxOpen($(this).attr('href'));
|
||||
}
|
||||
|
||||
function loading() {
|
||||
var $this = $(this),
|
||||
$wrapper = $this.closest('.results'),
|
||||
msg = gettext('Updating results…'),
|
||||
cls = 'updating';
|
||||
$wrapper.addClass('loading');
|
||||
|
||||
// The loading indicator is absolutely positioned atop the
|
||||
// search results, so we do this to ensure a max-margin of sorts.
|
||||
if ($this.outerHeight() > 300) {
|
||||
cls += ' tall';
|
||||
}
|
||||
|
||||
// Insert the loading indicator.
|
||||
$('<div>', {'class': cls, 'html': msg}).insertBefore($this);
|
||||
}
|
||||
|
||||
function finished() {
|
||||
var $this = $(this),
|
||||
$wrapper = $this.closest('.results');
|
||||
|
||||
// Initialize install buttons and compatibility checking.
|
||||
$.when($this.find('.install:not(.triggered)').installButton()).done(function() {
|
||||
$this.find('.install').addClass('triggered');
|
||||
initListingCompat();
|
||||
});
|
||||
|
||||
// Remove the loading indicator.
|
||||
$wrapper.removeClass('loading').find('.updating').remove();
|
||||
|
||||
// Scroll up.
|
||||
$('html').animate({scrollTop: 0}, 200);
|
||||
}
|
||||
|
||||
function turnPages(e) {
|
||||
if (fieldFocused(e)) {
|
||||
return;
|
||||
}
|
||||
if (e.which == $.ui.keyCode.LEFT || e.which == $.ui.keyCode.RIGHT) {
|
||||
e.preventDefault();
|
||||
var sel;
|
||||
if (e.which == $.ui.keyCode.LEFT) {
|
||||
sel = '.paginator .prev:not(.disabled)';
|
||||
} else {
|
||||
sel = '.paginator .next:not(.disabled)';
|
||||
}
|
||||
pjaxOpen($container.find(sel).attr('href'));
|
||||
}
|
||||
}
|
||||
|
||||
$('.pjax-trigger a').live('click', _pd(hijackLink));
|
||||
$container.bind('start.pjax', loading).bind('end.pjax', finished);
|
||||
$(document).keyup(_.throttle(turnPages, 300));
|
||||
}
|
||||
|
|
|
@ -163,8 +163,7 @@ $.fn.searchSuggestions = function(results) {
|
|||
});
|
||||
|
||||
$(document).keyup(function(e) {
|
||||
if (/input|keygen|meter|option|output|progress|select|textarea/i.test(e.target.nodeName) ||
|
||||
e.target.type === 'text') {
|
||||
if (fieldFocused(e)) {
|
||||
return;
|
||||
}
|
||||
if (e.which == 16 || e.which == 83) {
|
||||
|
|
|
@ -25,15 +25,15 @@
|
|||
// Returns the jQuery object
|
||||
$.fn.pjax = function( container, options ) {
|
||||
if ( options )
|
||||
options.container = container
|
||||
options.container = container;
|
||||
else
|
||||
options = $.isPlainObject(container) ? container : {container:container}
|
||||
options = $.isPlainObject(container) ? container : {container:container};
|
||||
|
||||
// We can't persist $objects using the history API so we must use
|
||||
// a String selector. Bail if we got anything else.
|
||||
if ( options.container && typeof options.container !== 'string' ) {
|
||||
throw "pjax container must be a string selector!"
|
||||
return false
|
||||
throw "pjax container must be a string selector!";
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.live('click', function(event){
|
||||
|
@ -42,18 +42,18 @@ $.fn.pjax = function( container, options ) {
|
|||
if ( event.which > 1 || event.metaKey ||
|
||||
// the href was only a hash:
|
||||
this.href.replace(this.hash || '', '') == window.location)
|
||||
return true
|
||||
return true;
|
||||
|
||||
var defaults = {
|
||||
url: this.href,
|
||||
container: $(this).attr('data-pjax'),
|
||||
clickedElement: $(this),
|
||||
fragment: null
|
||||
}
|
||||
};
|
||||
|
||||
$.pjax($.extend({}, defaults, options))
|
||||
$.pjax($.extend({}, defaults, options));
|
||||
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -79,100 +79,100 @@ $.fn.pjax = function( container, options ) {
|
|||
// Returns whatever $.ajax returns.
|
||||
var pjax = $.pjax = function( options ) {
|
||||
var $container = $(options.container),
|
||||
success = options.success || $.noop
|
||||
success = options.success || $.noop;
|
||||
|
||||
// We don't want to let anyone override our success handler.
|
||||
delete options.success
|
||||
delete options.success;
|
||||
|
||||
// We can't persist $objects using the history API so we must use
|
||||
// a String selector. Bail if we got anything else.
|
||||
if ( typeof options.container !== 'string' )
|
||||
throw "pjax container must be a string selector!"
|
||||
throw "pjax container must be a string selector!";
|
||||
|
||||
options = $.extend(true, {}, pjax.defaults, options)
|
||||
|
||||
if ( $.isFunction(options.url) ) {
|
||||
options.url = options.url()
|
||||
options.url = options.url();
|
||||
}
|
||||
|
||||
options.context = $container
|
||||
options.context = $container;
|
||||
|
||||
options.success = function(data){
|
||||
if ( options.fragment ) {
|
||||
// If they specified a fragment, look for it in the response
|
||||
// and pull it out.
|
||||
var $fragment = $(data).find(options.fragment)
|
||||
var $fragment = $(data).find(options.fragment);
|
||||
if ( $fragment.length )
|
||||
data = $fragment.children()
|
||||
data = $fragment.children();
|
||||
else
|
||||
return window.location = options.url
|
||||
return window.location = options.url;
|
||||
} else {
|
||||
// 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
|
||||
return window.location = options.url;
|
||||
}
|
||||
|
||||
// Make it happen.
|
||||
this.html(data)
|
||||
this.html(data);
|
||||
|
||||
// If there's a <title> tag in the response, use it as
|
||||
// the page's title.
|
||||
var oldTitle = document.title,
|
||||
title = $.trim( this.find('title').remove().text() )
|
||||
if ( title ) document.title = title
|
||||
title = $.trim( this.find('title').remove().text() );
|
||||
if ( title ) document.title = title;
|
||||
|
||||
var state = {
|
||||
pjax: options.container,
|
||||
fragment: options.fragment,
|
||||
timeout: options.timeout
|
||||
}
|
||||
};
|
||||
|
||||
// If there are extra params, save the complete URL in the state object
|
||||
var query = $.param(options.data)
|
||||
var query = $.param(options.data);
|
||||
if ( query != "_pjax=true" )
|
||||
state.url = options.url + (/\?/.test(options.url) ? "&" : "?") + query
|
||||
state.url = options.url + (/\?/.test(options.url) ? "&" : "?") + query;
|
||||
|
||||
if ( options.replace ) {
|
||||
window.history.replaceState(state, document.title, options.url)
|
||||
window.history.replaceState(state, document.title, options.url);
|
||||
} else if ( options.push ) {
|
||||
// this extra replaceState before first push ensures good back
|
||||
// button behavior
|
||||
if ( !pjax.active ) {
|
||||
window.history.replaceState($.extend({}, state, {url:null}), oldTitle)
|
||||
pjax.active = true
|
||||
window.history.replaceState($.extend({}, state, {url:null}), oldTitle);
|
||||
pjax.active = true;
|
||||
}
|
||||
|
||||
window.history.pushState(state, document.title, options.url)
|
||||
window.history.pushState(state, document.title, options.url);
|
||||
}
|
||||
|
||||
// Google Analytics support
|
||||
if ( (options.replace || options.push) && window._gaq )
|
||||
_gaq.push(['_trackPageview'])
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
// If the URL has a hash in it, make sure the browser
|
||||
// knows to navigate to the hash.
|
||||
var hash = window.location.hash.toString()
|
||||
var hash = window.location.hash.toString();
|
||||
if ( hash !== '' ) {
|
||||
window.location.href = hash
|
||||
window.location.href = hash;
|
||||
}
|
||||
|
||||
// Invoke their success handler if they gave us one.
|
||||
success.apply(this, arguments)
|
||||
success.apply(this, arguments);
|
||||
}
|
||||
|
||||
// Cancel the current request if we're already pjaxing
|
||||
var xhr = pjax.xhr
|
||||
var xhr = pjax.xhr;
|
||||
if ( xhr && xhr.readyState < 4) {
|
||||
xhr.onreadystatechange = $.noop
|
||||
xhr.abort()
|
||||
xhr.onreadystatechange = $.noop;
|
||||
xhr.abort();
|
||||
}
|
||||
|
||||
pjax.options = options
|
||||
pjax.xhr = $.ajax(options)
|
||||
$(document).trigger('pjax', [pjax.xhr, options])
|
||||
pjax.options = options;
|
||||
pjax.xhr = $.ajax(options);
|
||||
$(document).trigger('pjax', [pjax.xhr, options]);
|
||||
|
||||
return pjax.xhr
|
||||
return pjax.xhr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,22 +187,22 @@ pjax.defaults = {
|
|||
type: 'GET',
|
||||
dataType: 'html',
|
||||
beforeSend: function(xhr){
|
||||
this.trigger('start.pjax', [xhr, pjax.options])
|
||||
xhr.setRequestHeader('X-PJAX', 'true')
|
||||
this.trigger('start.pjax', [xhr, pjax.options]);
|
||||
xhr.setRequestHeader('X-PJAX', 'true');
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown){
|
||||
if ( textStatus !== 'abort' )
|
||||
window.location = pjax.options.url
|
||||
window.location = pjax.options.url;
|
||||
},
|
||||
complete: function(xhr){
|
||||
this.trigger('end.pjax', [xhr, pjax.options])
|
||||
this.trigger('end.pjax', [xhr, pjax.options]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Used to detect initial (useless) popstate.
|
||||
// If history.state exists, assume browser isn't going to fire initial popstate.
|
||||
var popped = ('state' in window.history), initialURL = location.href
|
||||
var popped = ('state' in window.history), initialURL = location.href;
|
||||
|
||||
|
||||
// popstate handler takes care of the back and forward buttons
|
||||
|
@ -211,14 +211,14 @@ var popped = ('state' in window.history), initialURL = location.href
|
|||
// stuff yet.
|
||||
$(window).bind('popstate', function(event){
|
||||
// Ignore inital popstate that some browsers fire on page load
|
||||
var initialPop = !popped && location.href == initialURL
|
||||
popped = true
|
||||
if ( initialPop ) return
|
||||
var initialPop = !popped && location.href == initialURL;
|
||||
popped = true;
|
||||
if ( initialPop ) return;
|
||||
|
||||
var state = event.state
|
||||
var state = event.state;
|
||||
|
||||
if ( state && state.pjax ) {
|
||||
var container = state.pjax
|
||||
var container = state.pjax;
|
||||
if ( $(container+'').length )
|
||||
$.pjax({
|
||||
url: state.url || location.href,
|
||||
|
@ -226,9 +226,9 @@ $(window).bind('popstate', function(event){
|
|||
container: container,
|
||||
push: false,
|
||||
timeout: state.timeout
|
||||
})
|
||||
});
|
||||
else
|
||||
window.location = location.href
|
||||
window.location = location.href;
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -236,22 +236,22 @@ $(window).bind('popstate', function(event){
|
|||
// Add the state property to jQuery's event object so we can use it in
|
||||
// $(window).bind('popstate')
|
||||
if ( $.inArray('state', $.event.props) < 0 )
|
||||
$.event.props.push('state')
|
||||
$.event.props.push('state');
|
||||
|
||||
|
||||
// Is pjax supported by this browser?
|
||||
$.support.pjax =
|
||||
window.history && window.history.pushState && window.history.replaceState
|
||||
// pushState isn't reliable on iOS yet.
|
||||
&& !navigator.userAgent.match(/(iPod|iPhone|iPad|WebApps\/.+CFNetwork)/)
|
||||
&& !navigator.userAgent.match(/(iPod|iPhone|iPad|WebApps\/.+CFNetwork)/);
|
||||
|
||||
|
||||
// Fall back to normalcy for older browsers.
|
||||
if ( !$.support.pjax ) {
|
||||
$.pjax = function( options ) {
|
||||
window.location = $.isFunction(options.url) ? options.url() : options.url
|
||||
}
|
||||
$.fn.pjax = function() { return this }
|
||||
};
|
||||
$.fn.pjax = function() { return this };
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
|
|
|
@ -138,7 +138,9 @@ var installButton = function() {
|
|||
}
|
||||
};
|
||||
|
||||
var addWarning = function(msg, type) { $this.parent().append(format(type || notavail, [msg])); };
|
||||
var addWarning = function(msg, type) {
|
||||
$this.parent().append(format(type || notavail, [msg]));
|
||||
};
|
||||
|
||||
// Change the button text to "Add to Firefox".
|
||||
var addToApp = function() {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
INSERT INTO waffle_switch (name, active) VALUES ('ajax-search', 0);
|
|
@ -590,6 +590,7 @@ MINIFY_BUNDLES = {
|
|||
'js/lib/jquery.cookie.js',
|
||||
'js/zamboni/storage.js',
|
||||
'js/zamboni/buttons.js',
|
||||
'js/lib/jquery.pjax.js',
|
||||
|
||||
# jQuery UI
|
||||
'js/lib/jquery-ui/jquery.ui.core.js',
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{% block content %}{% endblock %}
|
Загрузка…
Ссылка в новой задаче