зеркало из https://github.com/mozilla/bedrock.git
Bug 906943 - Show the translation bar at the top of the page if it's localized into visitor's language
This commit is contained in:
Родитель
ebbe5d57bf
Коммит
b80d456614
|
@ -64,7 +64,7 @@
|
|||
|
||||
{% block site_header %}
|
||||
<header id="masthead">
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla">{{ _('Mozilla') }}</a>
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="{{ settings.TABZILLA_INFOBAR_OPTIONS }}">{{ _('Mozilla') }}</a>
|
||||
{% block site_header_nav %}
|
||||
<span class="toggle" role="button" aria-controls="nav-main-menu" tabindex="0">{{_('Menu')}}</span>
|
||||
<nav id="nav-main" role="navigation">
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
|
||||
{% block site_header %}
|
||||
<header id="masthead">
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla">{{ _('Mozilla') }}</a>
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="{{ settings.TABZILLA_INFOBAR_OPTIONS }}">{{ _('Mozilla') }}</a>
|
||||
|
||||
{% block site_header_nav %}
|
||||
<nav id="nav-main" role="navigation">
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<header id="masthead">
|
||||
<div class="wrapper stuck">
|
||||
<div class="inner">
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla">Mozilla</a>
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="{{ settings.TABZILLA_INFOBAR_OPTIONS }}">{{ _('Mozilla') }}</a>
|
||||
|
||||
{% block site_header_logo %}
|
||||
<h2 id="ffos-main-logo"><a href="#masthead" class="nav"><img src="{{ MEDIA_URL }}img/firefox/os/logo/firefox-os.png" alt="Firefox OS"></a></h2>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
{% block site_header %}
|
||||
<header id="masthead">
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla">{{ _('Mozilla') }}</a>
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="{{ settings.TABZILLA_INFOBAR_OPTIONS }}">{{ _('Mozilla') }}</a>
|
||||
{% block site_header_nav %}
|
||||
<span class="toggle" role="button" aria-controls="nav-main-menu" tabindex="0">{{_('Menu')}}</span>
|
||||
<nav id="nav-main" role="navigation">
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
{% block site_header %}
|
||||
<header id="masthead">
|
||||
<a href="//www.mozilla.org/" id="tabzilla">{{ _('Mozilla') }}</a>
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="{{ settings.TABZILLA_INFOBAR_OPTIONS }}">{{ _('Mozilla') }}</a>
|
||||
|
||||
{% block site_header_nav %}{% endblock %}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
{% block site_header %}
|
||||
<header id="masthead">
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla">Mozilla</a>
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="{{ settings.TABZILLA_INFOBAR_OPTIONS }}">{{ _('Mozilla') }}</a>
|
||||
|
||||
{% block site_header_nav %}{% endblock %}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
{% block site_header %}
|
||||
<header id="masthead">
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla">{{ _('Mozilla') }}</a>
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="{{ settings.TABZILLA_INFOBAR_OPTIONS }}">{{ _('Mozilla') }}</a>
|
||||
{% block site_header_nav %}{% endblock %}
|
||||
</header>
|
||||
{% endblock %}
|
||||
|
|
|
@ -643,6 +643,8 @@ DOMAIN_METHODS = {
|
|||
'tower.extract_tower_template'),
|
||||
('%s/**/templates/**.js' % PROJECT_MODULE,
|
||||
'tower.extract_tower_template'),
|
||||
('%s/**/templates/**.jsonp' % PROJECT_MODULE,
|
||||
'tower.extract_tower_template'),
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -885,3 +887,5 @@ DONATE_LOCALE_LINK = {
|
|||
|
||||
# Mapbox token for spaces and communities pages
|
||||
MAPBOX_TOKEN = 'examples.map-9ijuk24y'
|
||||
|
||||
TABZILLA_INFOBAR_OPTIONS = 'translation'
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
{% block content %}
|
||||
<div id="content">
|
||||
<header id="masthead">
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla">{{ _('Mozilla') }}</a>
|
||||
<a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="{{ settings.TABZILLA_INFOBAR_OPTIONS }}">{{ _('Mozilla') }}</a>
|
||||
</header>
|
||||
|
||||
{% block sidebar %}
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
<code><link href="//mozorg.cdn.mozilla.net/media/css/tabzilla-min.css" rel="stylesheet" /></code></li>
|
||||
<li>Include the tabzilla.js file in your template (preferably in the footer) <br />
|
||||
<code><script src="//mozorg.cdn.mozilla.net/tabzilla/tabzilla.js"></script></code></li>
|
||||
<li>If you'd like to have the Translation Bar extension, include <a href="https://support.google.com/webmasters/answer/189077">alternate URLs</a> in the <code><head></code> element and add the <code>data-infobar</code> attribute to the tab link, with the <code>translation</code> option <br />
|
||||
<code><a href="{{ url('mozorg.home') }}" id="tabzilla" data-infobar="translation">{{ _('Mozilla') }}</a></code></li>
|
||||
</ol>
|
||||
<p>See the <a href="http://bedrock.readthedocs.org/en/latest/tabzilla.html">Tabzilla documentation</a> for full instructions and notes on localization.</p>
|
||||
</section>
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
* @author Michael Gauthier <mike@silverorange.com>
|
||||
* @author Steven Garrity <steven@silverorange.com>
|
||||
* @author Isac Lagerblad <icaaaq@gmail.com>
|
||||
* @author Kohei Yoshino <kohei.yoshino@gmail.com>
|
||||
*/
|
||||
|
||||
var Tabzilla = (function (Tabzilla) {
|
||||
|
@ -240,6 +241,180 @@ var Tabzilla = (function (Tabzilla) {
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
var Infobar = function (id, name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.disabled = false;
|
||||
this.prefName = 'tabzilla.infobar.' + id + '.disabled';
|
||||
|
||||
// Read the preference
|
||||
try {
|
||||
if (sessionStorage.getItem(this.prefName) === 'true') {
|
||||
this.disabled = true;
|
||||
}
|
||||
} catch (ex) {}
|
||||
|
||||
// If there is already another infobar, don't show this
|
||||
if ($('#tabzilla-infobar').length) {
|
||||
this.disabled = true;
|
||||
}
|
||||
};
|
||||
Infobar.prototype.show = function (str) {
|
||||
// A infobar can be disabled by pref.
|
||||
// And check the existence of another infobar again
|
||||
if (this.disabled || $('#tabzilla-infobar').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var bar = self.element = $(
|
||||
'<div id="tabzilla-infobar" class="' + self.id + '" role="dialog"><div>'
|
||||
+ '<p>' + str.message + '</p><ul>'
|
||||
+ '<li><a href="#" class="btn-accept" role="button">' + str.accept + '</a></li>'
|
||||
+ '<li><a href="#" class="btn-cancel" role="button">' + str.cancel + '</a></li>'
|
||||
+ '</ul></div></div>').prependTo(panel);
|
||||
|
||||
bar.find('.btn-accept').click(function (event) {
|
||||
event.preventDefault();
|
||||
self.trackEvent(self.onaccept.trackAction || 'accept',
|
||||
self.onaccept.trackLabel,
|
||||
self.onaccept.callback);
|
||||
self.hide();
|
||||
});
|
||||
|
||||
bar.find('.btn-cancel').click(function (event) {
|
||||
event.preventDefault();
|
||||
self.trackEvent(self.oncancel.trackAction || 'cancel',
|
||||
self.oncancel.trackLabel,
|
||||
self.oncancel.callback);
|
||||
self.hide();
|
||||
try {
|
||||
sessionStorage.setItem(self.prefName, 'true');
|
||||
} catch (ex) {}
|
||||
});
|
||||
|
||||
panel.trigger('infobar-showing');
|
||||
self.trackEvent(self.onshow.trackAction || 'show',
|
||||
self.onshow.trackLabel,
|
||||
self.onshow.callback);
|
||||
|
||||
if (opened) {
|
||||
bar.css('height', 0)
|
||||
.animate({'height': bar.find('div').outerHeight()}, 200,
|
||||
function () { panel.trigger('infobar-shown'); });
|
||||
} else {
|
||||
panel.animate({'height': bar.height()}, 200,
|
||||
function () { panel.trigger('infobar-shown'); });
|
||||
}
|
||||
|
||||
return bar;
|
||||
};
|
||||
Infobar.prototype.hide = function () {
|
||||
var self = this;
|
||||
var target = (opened) ? self.element : panel;
|
||||
|
||||
panel.trigger('infobar-hiding');
|
||||
|
||||
target.animate({'height': 0}, 200, function () {
|
||||
self.element.remove();
|
||||
panel.trigger('infobar-hidden');
|
||||
});
|
||||
};
|
||||
Infobar.prototype.trackEvent = function (action, label, callback) {
|
||||
if (typeof(_gaq) !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Track events with Google Analytics
|
||||
window._gaq.push(['_trackEvent',
|
||||
'Tabzilla - ' + this.name, action, label]);
|
||||
|
||||
if (callback) {
|
||||
var timer = null;
|
||||
var _callback = function () {
|
||||
clearTimeout(timer);
|
||||
callback();
|
||||
};
|
||||
timer = setTimeout(_callback, 500);
|
||||
window._gaq.push(_callback);
|
||||
}
|
||||
};
|
||||
Infobar.prototype.onshow = {};
|
||||
Infobar.prototype.onaccept = {};
|
||||
Infobar.prototype.oncancel = {};
|
||||
var setupTransbar = function () {
|
||||
var transbar = new Infobar('transbar', 'Translation Bar');
|
||||
if (transbar.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Compare the user's language and the page's language
|
||||
var userLang = navigator.language || navigator.browserLanguage;
|
||||
var pageLang = document.documentElement.lang;
|
||||
if (!userLang || !pageLang ||
|
||||
userLang.toLowerCase() === pageLang.toLowerCase()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize the user language in the form of ab or ab-CD
|
||||
userLang = userLang.replace(/^(\w+)(?:-(\w+))?$/, function (m, p1, p2) {
|
||||
return p1.toLowerCase() + ((p2) ? '-' + p2.toUpperCase() : '');
|
||||
});
|
||||
|
||||
// Check the availability of the translated page for the user.
|
||||
// Use an alternate URL in <head> or a language option in <form>
|
||||
var langLink = $(['link[hreflang="' + userLang + '"]',
|
||||
// The user language can be ab-CD while the page language is ab
|
||||
// (Example: fr-FR vs fr, ja-JP vs ja)
|
||||
'link[hreflang="' + userLang.split('-')[0] + '"]'].join(','));
|
||||
var langOption = $(['#language [value="' + userLang + '"]',
|
||||
// Languages in the language switcher are uncapitalized on some
|
||||
// sites (AMO, Firefox Flicks)
|
||||
'#language [value="' + userLang.toLowerCase() + '"]',
|
||||
// The user language can be ab-CD while the page language is ab
|
||||
// (Example: fr-FR vs fr, ja-JP vs ja)
|
||||
'#language [value="' + userLang.split('-')[0] + '"]',
|
||||
// Sometimes the value of a language switcher option is the path of
|
||||
// a localized page on some sites (MDN)
|
||||
'#language [value^="/' + userLang + '/"]'].join(','));
|
||||
if (!langLink.length && !langOption.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize the user language again, based on the language of the site
|
||||
userLang = (langLink.length) ? langLink.attr('hreflang')
|
||||
: langOption.val();
|
||||
|
||||
// The language label: English (US) -> English
|
||||
var langLabel = (langLink.length) ? langLink.attr('title')
|
||||
: langOption.text();
|
||||
langLabel = langLabel.match(/^(.+?)(\s\(.+\))?$/)[1];
|
||||
|
||||
// Log the language of the current page
|
||||
transbar.onshow.trackLabel = transbar.oncancel.trackLabel = userLang;
|
||||
transbar.oncancel.trackAction = 'hide';
|
||||
|
||||
// If the user selects Yes, show the translated page
|
||||
transbar.onaccept = {
|
||||
trackAction: 'change',
|
||||
trackLabel: userLang,
|
||||
callback: function () {
|
||||
if (langLink.length) {
|
||||
location.href = langLink.attr('href');
|
||||
} else {
|
||||
langOption.attr('selected', 'selected').get(0).form.submit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch the localized strings and show the Translation Bar
|
||||
$.ajax({ url: '{{ settings.CDN_BASE_URL }}/' + userLang + '/tabzilla/transbar.jsonp',
|
||||
cache: false, crossDomain: true, dataType: 'jsonp',
|
||||
jsonpCallback: "_", success: function (str) {
|
||||
str.message = str.message.replace('%s', langLabel);
|
||||
transbar.show(str).attr('lang', userLang);
|
||||
}});
|
||||
};
|
||||
var setupGATracking = function () {
|
||||
// track tabzilla links in GA
|
||||
$('#tabzilla-contents').on('click', 'a', function (e) {
|
||||
|
@ -356,6 +531,17 @@ var Tabzilla = (function (Tabzilla) {
|
|||
}
|
||||
});
|
||||
|
||||
// Information Bars in order of priority
|
||||
var infobars = {
|
||||
translation: setupTransbar
|
||||
};
|
||||
$.each((tab.data('infobar') || '').split(' '), function (index, value) {
|
||||
var setup = infobars[value];
|
||||
if (setup) {
|
||||
setup.call();
|
||||
}
|
||||
});
|
||||
|
||||
setupGATracking();
|
||||
|
||||
// Careers teaser in error console.
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{% set_lang_files "tabzilla/tabzilla" %}
|
||||
_({
|
||||
{# L10n: %s will be replaced with a language name like English. You can instead hardcode your language name in the string if you want. -#}
|
||||
"message": "{{ _('Would you like to see this page in %s?')|js_escape }}",
|
||||
{# L10n: Your translation can just say Yes -#}
|
||||
"accept": "{{ _('Yes, please!')|js_escape }}",
|
||||
{# L10n: Your translation can just say No -#}
|
||||
"cancel": "{{ _('No, thanks.')|js_escape }}"
|
||||
})
|
|
@ -9,4 +9,5 @@ import views
|
|||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^tabzilla\.js$', views.tabzilla_js, name='tabzilla'),
|
||||
url(r'^transbar\.jsonp$', views.transbar_jsonp, name='transbar'),
|
||||
)
|
||||
|
|
|
@ -10,10 +10,8 @@ from lib import l10n_utils
|
|||
from bedrock.mozorg.decorators import cache_control_expires
|
||||
|
||||
|
||||
@cache_control_expires(12)
|
||||
def tabzilla_js(request):
|
||||
resp = l10n_utils.render(request, 'tabzilla/tabzilla.js',
|
||||
content_type='text/javascript')
|
||||
def _resp(request, path, ctype):
|
||||
resp = l10n_utils.render(request, path, content_type=ctype)
|
||||
|
||||
is_enabled = not settings.TEMPLATE_DEBUG and settings.CDN_BASE_URL
|
||||
if is_enabled and isinstance(resp, HttpResponseRedirect):
|
||||
|
@ -23,3 +21,15 @@ def tabzilla_js(request):
|
|||
cdn_base = protocol + settings.CDN_BASE_URL
|
||||
resp['location'] = cdn_base + resp['location']
|
||||
return resp
|
||||
|
||||
|
||||
@cache_control_expires(12)
|
||||
def tabzilla_js(request):
|
||||
return _resp(request, 'tabzilla/tabzilla.js', 'text/javascript')
|
||||
|
||||
|
||||
@cache_control_expires(12)
|
||||
def transbar_jsonp(request):
|
||||
resp = _resp(request, 'tabzilla/transbar.jsonp', 'application/javascript')
|
||||
resp['Access-Control-Allow-Origin'] = '*'
|
||||
return resp
|
||||
|
|
|
@ -57,3 +57,26 @@ As the universal tab does inject HTML/CSS into the DOM, some there are some requ
|
|||
Any background image or absolutely positioned element attached to the ``body`` element would not move with the rest of the contents when the tab slides open. Instead, any such background or element should be attached to anoter HTML element in the page (a wrapper div, for example). Note that this issue does not apply to solid background colors, or backgrounds that do not vary vertically (solid vertical stripes, for example).
|
||||
|
||||
If jQuery is already included on the page, it will be used by Tabzilla. If jQuery is not already on the page, it will automatically be included after the page has loaded.
|
||||
|
||||
|
||||
Translation Bar
|
||||
---------------
|
||||
|
||||
Tabzilla has an opt-in extension called *Translation Bar* that automatically offers a link to a localized page, if available, based on the user's locale. It is intended to improve international user experience.
|
||||
|
||||
Adding the Translation Bar extension to Tabzilla requires:
|
||||
|
||||
1. Include `alternate URLs <https://support.google.com/webmasters/answer/189077>`_ in the ``<head>`` element. For example::
|
||||
|
||||
<link rel="alternate" hreflang="en-US" href="http://www.mozilla.org/en-US/firefox/new/" title="English (US)">
|
||||
<link rel="alternate" hreflang="fr" href="http://www.mozilla.org/fr/firefox/new/" title="Français">
|
||||
|
||||
The Translation Bar alternatively detects available translations by looking for a language switcher like below, but implementation of alternate URLs is recommended also from the SEO perspective::
|
||||
|
||||
<select id="language"><option value="en-US">English (US)</option></select>
|
||||
|
||||
2. Add the ``data-infobar`` attribute to the tab link, with the ``translation`` option::
|
||||
|
||||
<a href="https://www.mozilla.org/" id="tabzilla" data-infobar="translation">mozilla</a>
|
||||
|
||||
.. note:: Though the Translation Bar is currently implemented as an extension of Tabzilla, it might be moved to a standalone language utility in the future.
|
||||
|
|
|
@ -312,6 +312,36 @@
|
|||
#tabzilla-panel #tabzilla-nav ul li#tabzilla-search input::-webkit-input-placeholder { color: #ddd; }
|
||||
#tabzilla-panel #tabzilla-nav ul li#tabzilla-search input:-moz-placeholder { color: #ddd; }
|
||||
|
||||
#tabzilla-infobar {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
width: 940px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
|
||||
div {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
p {
|
||||
display: inline;
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline;
|
||||
margin: 0 10px 0 0;
|
||||
white-space: nowrap;
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Firefox Flicks Promo
|
||||
|
||||
#tabzilla-promo .snippet {
|
||||
|
@ -486,6 +516,10 @@ html[lang='de'] #tabzilla-promo .snippet#tabzilla-promo-donate-201312 a {
|
|||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
#tabzilla-infobar {
|
||||
position: static;
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 719px) {
|
||||
|
@ -604,4 +638,12 @@ html[lang='de'] #tabzilla-promo .snippet#tabzilla-promo-donate-201312 a {
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#tabzilla-infobar {
|
||||
position: static;
|
||||
width: auto;
|
||||
|
||||
div {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -314,14 +314,30 @@
|
|||
// toggle sticky masthead when tabzilla is opened/closed
|
||||
$tabzilla.on('click', function () {
|
||||
var $tab = $('#tabzilla-panel');
|
||||
|
||||
$('#masthead .wrapper').toggleClass('stuck');
|
||||
var $wrapper = $('#masthead .wrapper');
|
||||
|
||||
//if we're on mobile then masthead position is relative
|
||||
if ($w.width() < 760) { return; }
|
||||
|
||||
if ($tab.hasClass('open')) {
|
||||
$tab.css('height', 0);
|
||||
$wrapper.addClass('stuck');
|
||||
} else {
|
||||
$wrapper.removeClass('stuck');
|
||||
}
|
||||
});
|
||||
|
||||
// Support for an information bar of Tabzilla
|
||||
$(document).on('infobar-showing', '#tabzilla-panel', function () {
|
||||
var $wrapper = $('#masthead .wrapper');
|
||||
if ($wrapper.hasClass('scroll')) {
|
||||
$(this).stop(true); // Do not show the bar when scrolled down
|
||||
} else {
|
||||
$wrapper.removeClass('stuck');
|
||||
}
|
||||
}).on('infobar-hidden', '#tabzilla-panel', function () {
|
||||
if (!$(this).hasClass('open')) {
|
||||
$('#masthead .wrapper').addClass('stuck');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -340,14 +356,14 @@
|
|||
if (direction === 'down') {
|
||||
// if tabzilla is open then close if we start to scroll
|
||||
if ($tab.hasClass('open')) {
|
||||
$tab.css('height', 0);
|
||||
$tabzilla.trigger('click');
|
||||
}
|
||||
$tabzilla.fadeOut('fast');
|
||||
$btn.fadeIn();
|
||||
$wrapper.animate({backgroundColor: '#fff'}, 'fast');
|
||||
$current.promise().done(function () {
|
||||
$wrapper.addClass('scroll');
|
||||
$tab.css('height', 0);
|
||||
$wrapper.addClass('scroll stuck');
|
||||
});
|
||||
$('#masthead ul li a').animate({color: '#0096DD'}, 'fast');
|
||||
|
||||
|
@ -359,6 +375,13 @@
|
|||
$wrapper.removeClass('scroll');
|
||||
});
|
||||
$('#masthead ul li a').animate({color: '##484848'}, 'fast');
|
||||
// Support for an information bar of Tabzilla
|
||||
var $infobar = $('#tabzilla-infobar').css('height', 'auto');
|
||||
if ($infobar.length) {
|
||||
$tab.animate({'height': $infobar.height()}, 200, function () {
|
||||
$(this).trigger('infobar-shown');
|
||||
}).trigger('infobar-showing');
|
||||
}
|
||||
}
|
||||
}, { offset: -1 });
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче