/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2018.07.17
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
/**
* @constructor
*/
Banners = function() {
/**
* @type {!jQuery}
* @private
*/
this.root_ = jQuery('#page');
/**
* @type {!jQuery}
* @private
*/
this.banners_ = this.root_.find('#nav .banners');
/**
* @type {!jQuery}
* @private
*/
this.bannersSlides_ = this.banners_.find('.glide__slide');
/**
* @type {!jQuery}
* @private
*/
this.bannersList_ = this.root_.find('.banners_list');
/**
* @type {!jQuery}
* @private
*/
this.bannersInnerPage_ = this.root_.find('#main > .banners');
/**
* @type {!jQuery}
* @private
*/
this.bannersSlidesInnerPage_ = this.bannersInnerPage_.find('.glide__slide');
/**
* @type {!jQuery}
* @private
*/
this.bannersListInnerPage_ = this.bannersInnerPage_.find('.banners_list');
/**
* @type {number}
* @private
*/
this.widthTablet_ = 992; // px
this.init_();
this.initBanners_();
this.moveBanners_();
this.attachEvents_();
};
/**
* @private
*/
Banners.prototype.init_ = function() {
var that = this;
// Клонируем баннеры для показа вне слайдера
this.bannersSlides_.not('.clone').each(function() {
that.bannersList_.append(jQuery(this).clone());
});
// Клонируем баннеры для показа вне слайдера
this.bannersSlidesInnerPage_.not('.clone').each(function() {
that.bannersListInnerPage_.append(jQuery(this).clone());
});
};
/**
* @private
*/
Banners.prototype.moveBanners_ = function() {
var widthWindow = window.innerWidth;
if (widthWindow < this.widthTablet_) {
this.banners_.insertBefore('#content');
} else {
this.banners_.appendTo('#nav > .menu');
}
};
/**
* @private
*/
Banners.prototype.initBanners_ = function() {
var that = this;
jQuery(document).ready(function() {
if (that.root_.hasClass('wide') || window.innerWidth < that.widthTablet_) {
that.banners_.insertBefore('#content');
} else {
that.banners_.appendTo('#nav > .menu');
}
});
};
/**
* @private
*/
Banners.prototype.attachEvents_ = function() {
var that = this;
jQuery('.icon.toggler').on('click', function() {
if (that.root_.hasClass('wide')) {
that.banners_.appendTo('#nav > .menu');
} else {
that.banners_.insertBefore('#content');
}
});
jQuery(window).resize(function() {
that.moveBanners_();
});
};
jQuery(document).ready(function() {
new Banners();
});
/**
* @author Vlad Yakovlev (red.scorpix@gmail.com)
* @copyright Art.Lebedev Studio (http://www.artlebedev.ru)
* @version 0.3 alpha 16 (2010-12-10)
* @requires jQuery 1.4.2
*
* @changelog
* Version 0.3 alpha 16
* В svgCss исправлен баг.
* Добавлен Array.isArray
.
*
* @changelog
* Version 0.3 alpha 15
* Переделан jCommon.popupBlock
.
* Изменен jCommon.labelPlaceholder
.
* Добавлен jCommon.addZero
.
* В jCommon.webkitPlaceholder
добавлена функция unbind.
*
* @changelog
* Version 0.3 alpha 14
* Добавлен jCommon.generateId
.
*
* @changelog
* Version 0.3 alpha 13
* jCommon.popupBlock
обновился до версии 2.1.9.
*
* @changelog
* Version 0.3 alpha 12
* $c.eventDispatcher
обновился до версии 1.0.3.
*
* @changelog
* Version 0.3 alpha 11
* Добавились $c.rad2Deg
, $c.deg2Rad
, $c.generateId
.
*
* @changelog
* Version 0.3 alpha 10
* Тэгу html
добавляются классы, содержащие информацию о типе и версии браузера.
* jCommon.popupBlock
обновился до версии 2.1.8.
* jCommon.eventDispatcher
обновился до версии 1.0.2.
*
* @changelog
* Version 0.3 alpha 9
* Добавлен jCommon.bezierCoords
.
* Доработан jCommon.attrSuffix
. Написаны тесты.
* Доработан jCommon.betweenNumber
. Написаны тесты.
* В jCommon.popupWindow
убрано навешивание события на все элементы с классом popup
.
* jCommon.popupBlock
обновился до версии 2.1.6.
* Вместо метода dragDrop
добавлен jCommon.draggable
.
* jCommon.extend
теперь возвращает объект.
* Добавлены алиасы plus
и minus
в jCommon.keyCode
.
* Методы jCommon.shortcuts
возвращает сам объект теперь.
* Добавлен jCommon.supplant
.
*
* @changelog
* Version 0.3 alpha 8
* Оптимизирован jCommon.cookie
.
* Оптимизирован jCommon.popupWindow
.
* Добавлен jCommon.keyCode
.
* Изменен jCommon.shortcuts
. Инициализация ссылок по link
производится вне объекта.
* Изменен jCommon.fixIePng
. Добавлены дополнительные настройки.
* Добавлен jCommon.extend
.
* Добавлена возможность наследования классов.
* Добавлен jCommon.abstract
.
* Добавлен jCommon.loadImage
.
* jCommon.getSuffixClass
переименован в jCommon.attrSuffix
.
* jCommon.getXml
переименован в jCommon.xmlObject
.
* Добавлен jCommon.betweenNumber
.
* Добавлен jCommon.cleanToNumber
.
* Добавлен jCommon.findInArray
.
* Добавлен jCommon.formatNumber
.
* Добавлен jCommon.inject
.
* Добавлен jCommon.shuffleArray
.
* Добавлен jCommon.sortNum
.
* Добавлен jCommon.stripTags
.
* Добавлены методы массивов, которые появились в JavaScript 1.6 для тех браузеров, которые не поддерживают их (по крайней мере, IE lte 7): every
, filter
, forEach
, indexOf
, lastIndexOf
, map
, some
.
* Добавлены методы для работы с SVG-элементами.
* Добавлены jCommon.hex2Rgb
и jCommon.rgb2Hex
.
* Добавлен jCommon.random
.
* Добавлены методы в jQuery для драг-н-дропа: jQuery.drag
, jQuery.releaseDrag
, jQuery.undrag
.
*
* @changelog
* Version 0.2.3.3
* Добавлен параметр antialias
для VML-элементов.
*
* @changelog
* Version 0.2.3.2
* Исправлен баг в jCommon.webkitPlaceholder
.
* jCommon.eventDispatcher
теперь возвращает объект.
* Добавлена функция jCommon.getSuffixClass()
.
* Теперь можно обращаться к jCommon
через знак доллара — $c
.
*
* @changelog
* Version 0.2.3.1
* Исправлен баг в jCommon.measurer
.
* Добавлена функция jCommon.getXml
.
*
* @changelog
* Version 0.2.3
* jCommon.popup
переименован в jCommon.popupWindow
, исправлены ошибки, добавлены комментарии.
* jCommon.keyNavigation
переименован в jCommon.shortcuts
, добавлены комментарии.
* jCommon.popupBlock
дорос до версии 2.1.5.
* jCommon.labelPlaceholder
дорос до версии 0.1.2.
* Добавлен jCommon.eventDispatcher
версии 1.0.
*
* @changelog
* Version 0.2.2
* Добавлен jCommon.ns.ev
.
*
* @changelog
* Version 0.2.1
* Механизм фикса полупрозрачных png в IE6 перенесен в функцию jCommon.fixIePng
.
* Вместо переменной jCommon.isCanvas
теперь jCommon.support
, который имеет три свойства-флага: canvas
, svg
, vml
.
* Механизм создания плейсхолдеров, как в Webkit, перенесен в jCommon.webkitPlaceholder
. Можно добавлять вручную текстовые элементы формы.
* jCommon.utils
перенесен в jCommon.keyNavigation
и jCommon.poup
.
* Добавлен jCommon.ns
, который содержит неймспейсы svg
и xlink
.
* Добавлен jCommon.labelPlaceholder
.
* Добавлен jCommon.browser
.
* Добавлен jCommon.popupBlock
.
* Удален jCommon.object
.
* Исправление бага — теперь не добавляются новые html-элементы в jCommon.measurer
.
*/
(function() {
window.jCommon = window.$c = {
/**
* Кидает исключение.
* @param {String} [message]
*/
'abstract': function(message) {
throw('Abstract' + (message ? ': ' + message : ''));
},
abstraction: function(message) {
return function(){
throw new Error('Abstract' + (message ? ': ' + message : ''));
};
},
/**
* Возвращает суффикс по заданному префиксу у значения атрибута элемента.
* @param {String|Element|jQuery} el
* @param {String} prefix
* @param {String} [attrName = 'class']
* @return {String}
*
* @example
* $c.attrSuffix($(
), 'id_'); // 2
* $c.attrSuffix($(
), 'id_', 'id'); // 2
*/
attrSuffix: function(el, prefix, attrName) {
var
pattern = new RegExp('\\b(' + prefix + '\\w*)\\b'),
parts = pattern.exec($(el).attr(attrName || 'class'));
return parts && parts[1] ? parts[1].substr(prefix.length) : false;
},
/**
* Определяет, находится ли значение первого аргумента в диапазоне.
* @param {Number|String} source Проверяемое значение.
* @param {Number} a Первое значение диапазона.
* @param {Number} b Второе значение диапазона.
* @param {Boolean} [strict = false] Флаг строгого соответствия.
* @return {Boolean}
*
* @example
* $c.betweenNumber(101, 100, 200); // true
* $c.betweenNumber(101, 200, 100); // true
* $c.betweenNumber(100, 200, 100, true); // true
*/
betweenNumber: function(source, a, b, strict) {
var
min = Math.min(a, b),
max = Math.max(a, b),
value = source.valueOf();
return strict ? min <= value && value <= max : min < value && value < max;
},
getNumberInRange : function(source, a, b) {
var
min = Math.min(a, b),
max = Math.max(a, b),
value = source.valueOf();
return Math.max(min, Math.min(max, value));
},
/**
* @author John Resig (http://jquery.com/), Vlad Yakovlev (red.scorpix@gmail.com)
* @version 1.0
*/
browser: function() {
var userAgent = window.navigator.userAgent.toLowerCase();
return {
version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
webkit: /webkit/.test(userAgent),
opera: /opera/.test(userAgent),
msie: /msie/.test(userAgent) && !/opera/.test(userAgent),
mozilla: /mozilla/.test(userAgent ) && !/(compatible|webkit)/.test(userAgent),
safari: /safari/.test(userAgent) && !/chrome/.test(userAgent),
chrome: /chrome/.test(userAgent)
};
}(),
bezierCoords: function(parents, t) {
while (3 < parents.length) {
var childs = [];
for (var i = 0; i < parents.length - 2; i++) {
childs.push(parents[i] + (parents[i + 2] - parents[i]) * t);
}
parents = childs;
}
return parents;
},
/**
* Очищает строку от нечисловых символов, приводя ее к числу.
* @param {String} source
* @return {Number}
*/
cleanToNumber: function(source) {
var mayBeNumber = source.valueOf().replace(/[^\d\.]/g, '');
return '' === mayBeNumber || isNaN(mayBeNumber) ? NaN : new Number(mayBeNumber);
},
/**
* Проверяет, число ли в аргументе.
* @param {String} something
* @return {Boolean}
*/
isNumber : function(something) {
return typeof something === 'number' && isFinite(something);
},
/**
* Проверяет, определён ли аргумент.
* @param {String} something
* @return {Boolean}
*/
isDefined : function(something) {
return something !== undefined && something !== null;
},
eq: function(t1, t2) {
if (t1 === t2) {
return true;
}
if(!$.isArray(t1) || !$.isArray(t2)) {
return false;
}
if (t1.length != t2.length) {
return false;
}
var a = t1.sort(),
b = t2.sort();
for (var i = 0; t2[i]; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
},
/**
* Создает куки или возвращает значение.
*
* @example $c.cookie('the_cookie', 'the_value');
* @desc Задает куки для сессии.
*
* @example $c.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'site.com', secure: true });
* @desc Создает куки с опциями.
*
* @example $c.cookie('the_cookie', null);
* @desc Удаляет куки.
*
* @example $c.cookie('the_cookie');
* @desc Возвращает значение куки.
*
* @param {String} name Имя куки.
* @param {String} value Значение куки.
* @param {Object} options Объект опций куки.
* @option {Number|Date} expires Either an integer specifying the expiration date from now on in days or a Date object.
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
* If set to null or omitted, the cookie will be a session cookie and will not be retained
* when the the browser exits.
* @option {String} path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option {String} domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option {Boolean} secure If true, the secure attribute of the cookie will be set and the cookie transmission will
* require a secure protocol (like HTTPS).
*
* @return {mixed|jCommon} Значение куки или объект jCommon.
*
* @author Klaus Hartl (klaus.hartl@stilbuero.de), Vlad Yakovlev (red.scorpix@gmail.com)
* @version 1.0.1
* @date 2009-11-12
*/
cookie: function(name, value, options) {
if ('undefined' != typeof value) {
options = options || {};
if (null === value) {
value = '';
options.expires = -1;
}
// CAUTION: Needed to parenthesize options.path and options.domain in the following expressions,
// otherwise they evaluate to undefined in the packed version for some reason…
var
path = options.path ? '; path=' + options.path : '',
domain = options.domain ? '; domain=' + options.domain : '',
secure = options.secure ? '; secure' : '',
expires = '';
if (options.expires && ('number' == typeof options.expires || options.expires.toUTCString)) {
var date;
if ('number' == typeof options.expires) {
date = new Date();
date.setTime(date.getTime() + (options.expires * 86400000/*24 * 60 * 60 * 1000*/));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
window.document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
return this;
}
var cookieValue = null;
if (document.cookie && '' != document.cookie) {
$.each(document.cookie.split(';'), function() {
var cookie = $.trim(this);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
return false;
}
});
}
return cookieValue;
},
/**
* Дополняет строку нулями в начале.
* @param {Number} number Число, которое нужно дополнить.
* @param {Number} [fillNum = 2] Количество символов в результирующей строке.
* @return {String}
*/
addZero: function(number, fillNum) {
var
fillNum = fillNum || 2,
result = '' + number;
while (result.length < fillNum) {
result = '0' + result;
}
return result;
},
/**
* Позволяет расширять объекты.
* @param {Object} destination Объект, которому добавляются свойства.
* @param {Object} source Источник свойств.
* @param {Boolean} [replace = false] Заменять ли свойство, если оно уже присутствует в объекте.
* @return {Object} Объект со свойствами.
*/
extend: function(destination, source, replace) {
if (!('object' === typeof destination || $.isFunction(destination))) {
destination = {};
}
if (!('object' === typeof source || $.isFunction(source))) {
source = {};
}
for (var i in source) {
if (source.hasOwnProperty(i) && (replace || undefined === destination[i]) && undefined !== source[i]) {
destination[i] = source[i];
}
}
return destination;
},
/**
*
* @param {Array} source
* @param {mixed} searchStr
* @return {Array}
*/
findInArray: function(source, searchStr) {
var returnArray = false;
for (var i = 0; i < source.length; i++) {
if ('function' == typeof(searchStr)) {
if (searchStr.test(source[i])) {
if (!returnArray) {
returnArray = [];
}
returnArray.push(i);
}
} else {
if (source[i] === searchStr) {
if (!returnArray) {
returnArray = [];
}
returnArray.push(i);
}
}
}
return returnArray;
},
/**
* Фикс полупрозрачных PNG в IE6.
* @param {String|Element|Array[Element]|jQuery} el Элемент, у которого нужно сделать фикс.
* @param {Object} [options]
* @option {Boolean} [allIe = false] Флаг, для всех ли версий IE применять фильтр.
* @option {String} [scaleMode = 'crop'] Режим масштабирования.
* @option {String} [emptySrc] Путь к файлу прозрачного изображения.
* @option {Boolean} [notReplaceImg = false] Флаг «не заменять src изображения».
*
* @example
* .png {
* filter:expression($c.fixIePng(this));
* }
* @description Добавляем для всех элементов в IE 6 и старше принудительный фильтр.
*
* @example $c.fixIePng('img', true, 'scale');
* @description Добавляем для всех изображений во всех IE фильтр с режимом scale
.
*
* @version 1.1
* @date 2009-11-13
*/
fixIePng: function() {
var
reScaleMode = /iesizing_(\w+)/,
prefix = 'file:///',
/** Путь к прозрачному гифу. */
gifPath = prefix == location.href.substr(0, prefix.length) ? './i/0.gif' : '/f/1/global/i/0.gif';
/**
* Добавляет фильтр.
* @param {Element} el
* @param {Object} [options]
* @option {String} [scaleMode = 'crop'] Режим масштабирования.
* @option {String} [emptySrc] Путь к файлу прозрачного изображения.
* @option {Boolean} [notReplaceImg = false] Флаг «не заменять src изображения».
*/
function filter(el, options) {
var scaleMode = options.scaleMode || 'crop';
var emptySrc = options.emptySrc || gifPath;
var src;
if (('IMG' == el.tagName || ('INPUT' == el.tagName && 'image' == el.type)) && !options.notReplaceImg) {
if (/\.png$/.test(el.src)) {
src = el.src;
el.src = emptySrc;
}
} else {
src = el.currentStyle.backgroundImage.match(/url\("(.+\.png)"\)/i);
if (src) {
src = src[1];
el.runtimeStyle.backgroundImage = 'none';
}
}
var m = reScaleMode.exec(el.className);
if (m) {
scaleMode = m[1];
}
if (src) {
el.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "',sizingMethod='" + scaleMode + "')";
}
}
return function(el, options) {
if (!$c.browser.msie) return;
options = options || {};
if (options.allIe || 6 >= parseInt($c.browser.version)) {
$(el).each(function() {
filter(this, options);
});
}
};
}(),
/**
*
* @param {String|Number} source
* @param {String} [groupSeparator = ' ']
* @param {String} [fractionSeparator = ',']
* @return {String}
*/
formatNumber: function(source, groupSeparator, fractionSeparator) {
source = source.toString();
var
groupSeparator = groupSeparator || ' ',
fractionSeparator = fractionSeparator || ',',
/** @type {Number} */
fractionIndex = source.indexOf('.'),
/** @type {String} */
fraction = fractionIndex > -1 ? source.substring(fractionIndex + 1) : '',
/** @type {String} */
number = fractionIndex > -1 ? source.substring(0, fractionIndex) : source;
if (5 > number.length) {
return number + (fractionIndex > -1 ? fractionSeparator + fraction : '');
}
var result = '';
while (3 < number.length) {
result = number.substring(number.length - 3) + (result.length > 0 ? groupSeparator : '') + result;
number = number.substring(0, number.length - 3);
}
result = number + groupSeparator + result + (-1 < fractionIndex ? fractionSeparator + fraction : '');
return result;
},
/**
* Возвращает уникальный идентификатор.
* @return {String}
*/
generateId: function() {
var PREFIX = 'bltynbabrfnjh_';
var lastId = 0;
return function() {
lastId++;
return PREFIX + lastId;
};
}(),
/**
* Шаблонизирует текущую строку, впрыскивая в нужные места значения из oData.
* @example "height:{hey}px{semi}".inject({ hey: 100, semi: ";" }) -> "height:100px;".
* @param {String} s
* @param {Object} data
* @return {String}
*/
inject: function(s, data){
return s.replace(/{([^{}]*)}/g, function(match, itemKey) {
var itemData = data[itemKey];
return undefined !== itemData && ('string' === typeof itemData || 'number' === typeof itemData) ? new String(itemData) : match;
});
},
/**
* Загружает изображение.
* @param {String} src Путь к файлу изображения.
* @param {Function} [callback] Функция, вызываемая по окончании загрузки.
*/
loadImage: function(src, callback) {
var imgEl = new Image();
$(imgEl).load(callback || $.noop);
imgEl.src = src;
},
/**
* Попапы с открытием нового окна браузера.
*
* После загрузки документа автоматически создаются хэндлеры на создание попапов у элементов с классом popup
.
* @param {String|Array[Element]|Element|jQuery} el Элемент(ы) jQuery.
* @param {Object} options Свойства создаваемого окна.
*
* @example $c.popupWindow.add('.popup_els', { menubar: 'yes' });
*
* @version 0.1.3
* @date 2010-02-15
*/
popupWindow: function() {
/**
* Класс для создания попапов.
* @param {String|Array[Element]|Element|jQuery} el Элемент(ы) jQuery.
* @param {Object} options Свойства создаваемого окна.
*/
function popup(el, options) {
$(el).click(function() {
bind($(this).attr('href'), '', undefined === options ? {} : options);
return false;
});
/**
* Создает попап.
* @param {String} url Адрес, по которому откроется попап. Если указано изображение, то создается тело документа с изображением внутри.
* @param {String} name Тайтл окна.
* @param {Object} options Свойства окна.
*/
function bind(url, name, options) {
var popupDefaults = {
height: 600,
menubar: 'no',
resizeable: 'yes',
scrollbars: 'yes',
status: 'yes',
toolbar: 'no',
width: 540
};
var optionsPlane = [];
var empty = {};
$c.extend(options, popupDefaults);
options.left = Math.round((screen.availWidth - options.width) / 2);
options.top = Math.round((screen.availHeight - options.height) / 2);
$.each(options, function() {
optionsPlane.push(id + '=' + this);
});
/** @type {Window} */
var newWindow = window.open(url, '', optionsPlane.join(','));
if (url.match(/\.(gif|jpe?g|png)$/i)) {
newWindow.document.open();
newWindow.document.write('' + ('' != name ? '' + name + ' ' : '') + '' +
'' +
' ' + '
');
newWindow.document.close();
}
newWindow.focus();
}
}
return function(el, options) {
$(el).each(function() {
popup(this, options);
});
};
}(),
/**
* Возвращает случайное целое число.
* @param {Number} min Минимальное значение.
* @param {Number} max Максимальное значение.
* @requires {Number}
*/
random: function(min, max) {
min = parseInt(min);
max = parseInt(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
},
/**
* Перемешивает массив.
* @param {Array} source
*/
shuffleArray: function(source) {
for (var rnd, tmp, i = source.length; i; rnd = parseInt(Math.random() * i), tmp = source[--i], source[i] = source[rnd], source[rnd] = tmp);
},
/**
* Сортирует числовой массив.
* @param {Array} source
* @return {Array}
*/
sortNum: function(source) {
return source.sort(function (a, b) {
return a - b;
});
},
/**
* Удаляет тэги.
* @return {String} source
* @return {String}
*/
stripTags: function(source) {
return source.replace(/<\/?[^>]+>/gi, '');
},
/**
* supplant() does variable substitution on the string. It scans
* through the string looking for expressions enclosed in {} braces.
* If an expression is found, use it as a key on the object,
* and if the key has a string value or number value, it is
* substituted for the bracket expression and it repeats.
*/
supplant: function(str, o) {
return str.replace(/{([^{}]*)}/g,
function(a, b) {
var r = o[b];
return 'string' === typeof r || 'number' === typeof r ? r : a;
}
);
},
/**
* Проверка поддержки SVG, Canvas и VML.
* Возвращает объект с тремя свойствами-флагами: canvas
, svg
и vml
.
* Если VML поддерживается, то инициализируются неймспейсы.
*
* @version 1.0
*/
support: function() {
var result = {
canvas: false,
svg: document.createElementNS ? true : false,
vml: false
};
if ('undefined' == typeof(HTMLCanvasElement)) {
// В IE для VML надо добавить схему и стили.
if (!document.namespaces['v']) {
document.namespaces.add('v', 'urn:schemas-microsoft-com:vml');
document.namespaces.add('o', 'urn:schemas-microsoft-com:office:office');
var ss = document.createStyleSheet();
ss.cssText = 'v\\:arc,v\\:curve,v\\:extrusion,v\\:fill,v\\:formulas,v\\:group,v\\:handles,v\\:image,v\\:imagedata,v\\:line,v\\:oval,v\\:path,v\\:polyline,v\\:rect,v\\:roundrect,v\\:shadow,v\\:shape,v\\:shapetype,v\\:stroke,v\\:textbox,v\\:textpath,v\\:vmlframe{behavior:url(#default#VML);display:block;} o\\:callout, o\\:locks, o\\:skew {behavior:url(#default#VML);antialias:true;}';
}
result.vml = true;
} else {
result.canvas = true;
}
return result;
}(),
/**
* Возвращает XML из строки.
* @param {String} text XML в строке.
* @return {Element} XML в объекте.
*
* @version 1.0
* @date 2009-08-18
*
* @example
* $.ajax({
* dataType: 'text', // Обязательно, если хочешь получить XML
* success: function(data) {
* var xmlData = $c.xmlObject(data);
* xmlData = $('result', xmlData);
* }
* // Другие параметры
* });
*/
xmlObject: function(text) {
var xmlData = null;
try {
if (window.ActiveXObject) { // IE
xmlData = new ActiveXObject('Microsoft.XMLDOM');
xmlData.async = false;
xmlData.loadXML(text);
} else if (window.DOMParser) { // Все остальные
var xmlData = (new DOMParser()).parseFromString(text, 'text/xml');
}
if (!xmlData || !xmlData.documentElement || 'parsererror' == xmlData.documentElement.nodeName
|| xmlData.getElementsByTagName('parsererror').length) {
return false;
}
} catch (error) {
return false;
}
return xmlData;
}
};
$c.extend(Function, {
/**
* Реализует наследование классов.
* @param {Function} BaseClass Базовый класс, от которого наследуется текущий класс.
* @param {Object} overrides Перезаписываемые свойства.
*/
inheritFrom: function(BaseClass, overrides){
var Inheritance = function() {};
Inheritance.prototype = BaseClass.prototype;
this.prototype = new Inheritance();
this.prototype.constructor = this;
this.baseConstructor = BaseClass;
this.superClass = BaseClass.prototype;
if (overrides) {
for(var i in overrides) {
this.prototype[i] = overrides[i];
}
}
}
});
/**
* Навигация по ссылкам в тэгах link
.
*/
$(function() {
var navigationLinks = {
start: 'home',
prev: 'left',
up: 'up',
next: 'right',
down: 'down'
};
$('head link').each(function() {
var rel = $(this).attr('rel');
if (navigationLinks[rel]) {
$c.shortcuts.bind({
keyCode: $c.keyCode(navigationLinks[rel]),
ctrlCode: true
}, $(this).attr('href'));
}
});
});
/**
* Фикс кэширования картинок на странице в IE6.
*/
if ($c.browser.msie && 6 >= parseInt($c.browser.version)) {
try {
document.execCommand('BackgroundImageCache', false, true);
} catch(e) {}
}
$c.extend(Array, {
isArray: $.isArray
});
$c.extend(Array.prototype, {
every: function(fun /*, thisp*/) {
var len = this.length;
if ('function' != typeof fun) {
throw new TypeError('Not Function');
}
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this && !fun.call(thisp, this[i], i, this)) {
return false;
}
}
return true;
},
filter: function(fun /*, thisp*/) {
var len = this.length;
if ('function' != typeof fun) {
throw new TypeError('Not Function');
}
var res = new Array();
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) {
var val = this[i]; // in case fun mutates this
if (fun.call(thisp, val, i, this)) {
res.push(val);
}
}
}
return res;
},
forEach: function(fun /*, thisp*/) {
var len = this.length;
if ('function' != typeof fun) {
throw new TypeError('Not Function');
}
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) {
fun.call(thisp, this[i], i, this);
}
}
},
indexOf: function(elt /*, from*/) {
var len = this.length;
var from = Number(arguments[1]) || 0;
from = 0 > from ? Math.ceil(from) : Math.floor(from);
if (0 > from) {
from += len;
}
for (; from < len; from++) {
if (from in this && this[from] === elt) {
return from;
}
}
return -1;
},
lastIndexOf: function(elt /*, from*/) {
var len = this.length;
var from = Number(arguments[1]);
if (isNaN(from)) {
from = len - 1;
} else {
from = 0 > from ? Math.ceil(from) : Math.floor(from);
if (0 > from) {
from += len;
} else if (from >= len) {
from = len - 1;
}
}
for (; from > -1; from--) {
if (from in this && this[from] === elt) {
return from;
}
}
return -1;
},
map: function(fun /*, thisp*/) {
var len = this.length;
if ('function' != typeof fun) {
throw new TypeError('Not Function');
}
var res = new Array(len);
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) {
res[i] = fun.call(thisp, this[i], i, this);
}
}
return res;
},
some: function(fun /*, thisp*/) {
var len = this.length;
if ('function' != typeof fun) {
throw new TypeError('Not Function');
}
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this && fun.call(thisp, this[i], i, this)) {
return true;
}
}
return false;
}
});
(function() {
var classes = ['js'];
if ($c.browser.msie) {
classes.push('ie');
} else if ($c.browser.mozilla) {
classes.push('mozilla');
} else if ($c.browser.webkit) {
classes.push('webkit');
if ($c.browser.safari) {
classes.push('safari');
} else if ($c.browser.chrome) {
classes.push('chrome');
}
} else if ($c.browser.opera) {
classes.push('opera');
}
$(document.documentElement || document.body).attr('class', classes.join(' '));
})();
})();
/**
* Расширения
*/
/**
* Возвращает код клавиши по ее идентификатору.
* Регистр и пробелы не учитываются.
* Если идентификатор не известен, возвращает undefined
.
*
* @example $c.keyCode(1)
* @description Возвратит 49
*
* @example $c.keyCode('Caps Lock')
* @example $c.keyCode('CApsLock')
* @description Возвратит 20
*
* @param String|Number key Идентификатор клавиши.
* @return Number Код символа.
*
* @version 0.1.1
* @date 2009-12-08
*
* @changelog
* Version 0.1.1
* Добавлен код для Tab.
*/
$c.keyCode = function() {
var codes = {
alt: 18,
backspace: 8,
capslock: 20,
control: 17,
ctrl: 17,
'delete': 46,
del: 46,
down: 40,
end: 35,
enter: 13,
escape: 27,
home: 36,
insert: 45,
left: 37,
minus: 109,
pagedown: 34,
pageup: 33,
plus: 61,
right: 39,
shift: 16,
space: 32,
tab: 9,
up: 38
};
if (window.jCommon.browser.webkit) {
codes.plus = 187;
codes.minus = 189;
}
return function(key) {
return codes[key.toString().replace(' ', '').toLowerCase()];
};
}();
/**
* Объект для работы с клавиатурными сокращениями.
*
* @example $c.shortcuts.unbind($c.keyCode('Enter'));
* @description Удаляет действие при нажатии клавиши Enter.
*
* @example
* $c.shortcuts.bind($c.keyCode('Right'), function(evt) {
* alert(evt.keyCode);
* });
* или
* $c.shortcuts.bind('Right', function(evt) {
* alert(evt.keyCode);
* });
* @description Привязывает к «стрелка вправо» функцию.
*
* @example
* $c.shortcuts.bind('left right', function(evt) {
* alert(evt.keyCode);
* });
* @description Привязывает к «стрелка вправо» или «стрелка влево» функцию.
*
* @example
* $c.shortcuts.bind({
* keyCode: $c.keyCode('Right'),
* ctrlKey: true
* }, 'http://ya.ru');
* @description Привязывает к Ctrl + «стрелка вправо» переход на Яндекс.
*
* @example $c.shortcuts.unbindAll();
* @description Удаляет все действия.
*
* @version 1.1.1
* @date 2009-12-27
*/
$c.shortcuts = function() {
var
binded = {},
that = {};
$(document).keydown(dispatch);
function dispatch(evt) {
var links = binded;
for (var id in binded) {
if (binded[id].keyCode == evt.keyCode && binded[id].ctrlKey == evt.ctrlKey && binded[id].altKey == evt.altKey && binded[id].shiftKey == evt.shiftKey) {
if ('string' == typeof links[id].href && '' != binded[id].href) {
document.location = links[id].href;
return;
} else if ($.isFunction(binded[id].href)) {
return binded[id].href(evt);
}
}
}
}
/**
* Возвращает идентификатор с учетом спец. клавиш.
*/
function keyCodeId(keyCode) {
if ('number' == typeof keyCode) return keyCode.toString();
var parts = [ keyCode.keyCode.toString() ];
keyCode.ctrlCode && parts.push('ctrl');
keyCode.altCode && parts.push('alt');
keyCode.shiftCode && parts.push('shift');
return parts.join('_');
}
/**
* Привязывает к шорткату клавиатуры действие.
*
* @param {Number|String|Object} keyCode Код клавиши. Если число, то только код клавиши.
* Если объект, то код клавиши и спец. клавиши.
* @option {Number} [keyCode] Код клавиши.
* @option {Boolean} [ctrlKey] Нажат ли Ctrl
.
* @option {Boolean} [altKey] Нажат ли Alt
.
* @option {Boolean} [shiftKey] Нажат ли Shift
.
*
* @param {String|Function} href Если строка, то осуществлять переход по адресу, если функция, то выполнить функцию (первый параметр — объект Event).
*/
that.bind = function(keyCode, href) {
var
code,
options = {
href: '',
keyCode: '',
ctrlKey: false,
altKey: false,
shiftKey: false
};
if ('string' == typeof keyCode) {
$.each(keyCode.split(' '), function() {
$c.extend(options, {
href: href,
keyCode: $c.keyCode(this)
}, true);
binded[keyCodeId($c.keyCode(this))] = options;
});
} else if ('number' == typeof keyCode) {
$c.extend(options, {
href: href,
keyCode: keyCode
}, true);
binded[keyCodeId($c.keyCode(this))] = options;
} else {
binded[keyCodeId(keyCode)] = {
href: href,
keyCode: keyCode.keyCode,
ctrlKey: !!keyCode.ctrlCode,
altKey: !!keyCode.altCode,
shiftKey: !!keyCode.shiftCode
};
}
return that;
};
/**
* Удаляет действие для шортката.
* @param {Number|String|Object} keyCode Код клавиши. Если число, то только код клавиши.
* Если объект, то код клавиши и спец. клавиши.
* @option {Number} [keyCode] Код клавиши.
* @option {Boolean} [ctrlKey] Нажат ли Ctrl
.
* @option {Boolean} [altKey] Нажат ли Alt
.
* @option {Boolean} [shiftKey] Нажат ли Shift
.
*/
that.unbind = function(keyCode) {
if ('string' == typeof keyCode) {
$.each(keyCode.split(' '), function() {
delete binded[keyCodeId($c.keyCode(this))];
});
} else {
delete binded[keyCodeId(keyCode)];
}
return that;
};
/**
* Удаляет все шорткаты.
*/
that.unbindAll = function() {
binded = {};
return that;
};
return that;
}();
/**
* Отслеживает изменение размеров окна браузера и масштабирование текста.
* Отслеживание запускается только при добавлении первого хэндлера.
*
* @example
* function funcBind() { alert('yoop'); }
* $c.measurer.bind(funcBind);
* @description Теперь функция будет выполняться всякий раз, когда изменится размер окна браузера или размер текста.
* $c.measurer.unbind(funcBind);
* @description А теперь — нет.
*
* @version 1.0
*/
$c.measurer = function() {
var
callbacks = [],
interval = 500,
curHeight,
el,
isInit = false,
isDocReady = false;
$(function() {
isDocReady = true;
isInit && initBlock();
});
function initBlock() {
el = $('
').css({
height: '1em',
left: 0,
lineHeight: '1em',
margin: 0,
position: 'absolute',
padding: 0,
top: '-1em',
visibility: 'hidden',
width: '100%'
}).appendTo('body');
/**
* Периодически проверяем изменение размера текста.
*/
curHeight = el.height();
setInterval(function() {
var newHeight = el.height();
if (newHeight != curHeight) {
curHeight = newHeight;
callFuncs();
}
}, interval);
$(window).resize(callFuncs);
}
function callFuncs() {
for(var i = 0; i < callbacks.length; i++) {
callbacks[i]();
}
}
return {
/**
* Ручная инициализация события изменения размеров элементов на странице.
*/
resize: callFuncs,
/**
* Добавляет обработчик события.
* @param {Function} func Ссылка на функцию, которую нужно выполнить.
*/
bind: function(func) {
if (!el) {
isInit = true;
isDocReady && initBlock();
}
callbacks.push(func);
},
/**
* Удаляет обработчик события.
*/
unbind: function(func) {
for(var i = 0; i < callbacks.length; i++) {
if (callbacks[i] == func) {
callbacks.splice(i, 1);
}
}
}
};
}();
/**
* Эмулирует поведение , как в Webkit.
* @version 1.0
*/
$c.webkitPlaceholder = function() {
if ($c.browser.webkit) {
return {
bind: $.noop,
unbind: $.noop
};
}
var _classEmpty;
$(function() {
$('input[placeholder]').each(function () {
bind(this);
$(this).blur();
});
});
/**
* Добавляет функцию плейсхолдера у элемента(ов).
* @param {String|Array[Element]|Element|jQuery} els Поля ввода
* @param {String} [class_empty = 'empty'] Класс для пустого поля ввода
*/
function bind(els, classEmpty) {
els = $(els);
_classEmpty = ('string' === typeof classEmpty) ? classEmpty : 'empty';
els.filter(':input')
.bind('focus', onFocus)
.bind('blur', onBlur)
.each(function() {
if (!$(this).val().length) {
$(this).blur();
}
});
}
/**
* Удаляет функцию плейсхолдера у элемента(ов).
* @param {String|Array[Element]|Element|jQuery} els Поля ввода.
*/
function unbind(els) {
$(els).filter(':input')
.unbind('focus', onFocus)
.unbind('blur', onBlur);
}
/**
* @param {Event} evt
*/
function onFocus(evt) {
var el = $(this);
if (el.val() === el.attr('placeholder')) {
el.val('');
}
el.removeClass(_classEmpty);
}
/**
* @param {Event} evt
*/
function onBlur(evt) {
var el = $(this);
if (!el.val().length) {
el.val(el.attr('placeholder'));
el.addClass(_classEmpty);
}
}
return {
/**
* Вручную добавляет функцию плейсхолдера элементу.
* @param {String|Array[Element]|Element|jQuery} elem Поле ввода.
* @param {String} [class_empty] Класс для пустого поля ввода.
*/
bind: bind,
unbind: unbind
};
}();
/**
* Метки как плейсхолдеры.
*
* @author Sergey Chikuyonok (serge.che@gmail.com), Vlad Yakovlev (red.scorpix@gmail.com)
* @version 0.1.3
* @date 2010-08-31
*
* @changelog
* Version 0.1.3
* Изменен, чтобы не зависеть от объекта jQuery.data().
*
* @changelog
* Version 0.1.2
* Переименованы функции в bind
и unbind
.
*
* @changelog
* Version 0.1.1
* Теперь можно добавлять и удалять плейсхолдеры, но только после загрузки документа.
*/
$c.labelPlaceholder = function() {
/**
* Инициализирует поля формы, для которых есть заполнитель (placeholder).
*/
$(function() {
bind('label.placeholder');
});
function bind(labelEls) {
$(labelEls).each(function() {
var
labelEl = $(this),
fieldEl = $('#' + labelEl.attr('for'));
labelEl.bind('click', focusOnField);
// Событие change нужно для Сафари в случае, когда поле с автокомплитом.
// Заполнение поля значением происходит не сразу.
fieldEl
.bind('focus blur change', placeholderSwitcher)
.blur();
});
}
function unbind(labelEls) {
$(labelEls).each(function() {
var
labelEl = $(this),
fieldEl = $('#' + labelEl.attr('for'));
labelEl.unbind('click', focusOnField);
fieldEl.unbind('focus blur change', placeholderSwitcher);
});
}
/**
* Ставит фокус на поле, к которому привязана текущая подпись-заполнитель.
* @param {Event} evt
*/
function focusOnField(evt) {
var labelEl = $(this);
$('#' + labelEl.attr('for') + ':visible').focus();
evt.preventDefault();
}
/**
* Функция, отвечающая за переключение отображения заполнителя.
* Срабатывает автоматически при фокусе/блюре с элемента ввода.
* @param {Event} evt
*/
function placeholderSwitcher(evt) {
var
inputEl = $(this),
labelEl = $('label[for=' + inputEl.attr('id') + ']');
if (!$.trim(inputEl.val()) && 'blur' == evt.type) {
labelEl.show();
} else {
labelEl.hide();
}
}
return {
/**
* Добавляет обработчик.
* @param {String|Element|Array[Element]|jQuery} labelEls Элемент(ы) метки.
*/
bind: bind,
/**
* Удаляет обработчики у элементов.
* @param {String|Element|Array[Element]|jQuery} labelEls Элемент(ы) метки, у которого нужно удалить обработчик.
*/
unbind: unbind
};
}();
/**
* Попапы-блоки внутри окна браузера.
*
* @param {String|Element|jQuery} container Контейнер попапа.
* @param {Object} options Настройки:
* @option {String|Element|jQuery} faderEl Блок тени.
* @option {String|Element|Array[Element]|jQuery} linkEl Блоки для показа/скрытия попапа.
* @option {String|Element|Array[Element]|jQuery} closeEl Блоки для закрытия попапа.
* @option {Function} beforeShow Функция, выполняемая перед открытием.
* @option {Function} afterShow Функция, выполняемая после открытия.
* @option {Function} beforeHide Функция, выполняемая перед закрытием.
* @option {Function} afterHide Функция, выполняемая после закрытия.
* @option {Boolean|Function} show = true Флаг анимации показа попапа, своя функция (тогда afterShow
не выполняется) или без эффектов (false).
* @option {Boolean|Function} hide = false Флаг анимации скрытия попапа, своя функция (тогда afterHide
не выполняется) или без эффектов (false).
* @option {Boolean} escapeKey = true Закрывать ли попап при нажатии клавиши Esc.
* @option {Boolean} documentClick = true Закрывать ли попап при клике вне попапа.
*
* @return {Object} Функции:
*
* hide
* cancel
* show
* toggle
* unbind
*
*
* @author Stepan Reznikov [stepan.reznikov@gmail.com], Vladislav Yakovlev [red.scorpix@gmail.com]
* @version 2.1.10 (2010-09-09)
*
* @changelog
* Version 2.1.10
* Переделал, чтобы события не гасились.
*
* @changelog
* Version 2.1.9
* Изменил события.
*
* @changelog
* Version 2.1.8
* Добавлена опция documentClick
.
*
* @changelog
* Version 2.1.7
* Добавлен метод unbind
.
*
* @changelog
* Version 2.1.6
* Добавлены новые опции: show
, hide
, escapeKey
.
* Исправлена ошибка, когда закрывался попап при нажатии правой кнопки мыши.
*
* @changelog
* Version 2.1.5
* Исправлена ошибки, по которой были проблемы с множественным созданием попапов.
* Оптимизирован код.
* Обязательная опция блока вынесена в отдельный параметр container
.
*
* @changelog
* Version 2.1.4
* Оптимизирован код.
*
* @changelog
* Version 2.1.3
* Добавлены комментарии.
* Параметр showFunction
удален.
* Добавлены параметры beforeShow
, afterShow
, beforeHide
, afterHide
.
*
* @changelog
* Version 2.1
* Флаг keep
заменен на event.stopPropagation().
* Форма появляется и исчезает плавно (под IE появляется/исчезает мгновенно в виду проблем с filter
).
* Добавлен параметр showFunction
- функция, выполняемая после показа popup'а.
*/
$c.popupBlock = function(containerEl, options) {
containerEl = $(containerEl).first();
options = $.extend({
show: true,
hide: false,
escapeKey: true,
documentClick: true
}, options);
if (options.faderEl) {
options.faderEl = $(options.faderEl).first();
}
if (options.linkEl) {
options.linkEl = $(options.linkEl)
.bind('click', toggle);
}
if (options.closeEl) {
options.closeEl = $(options.closeEl)
.bind('click', hide);
}
var _doc = $(document);
function cancel(event) {
var code = event.keyCode ? event.keyCode : (event.which ? event.which : null);
if (27 === code) {
hide(event);
}
}
function hideWithCheck(event) {
var checkEls = $(event.target).parents().add(event.target);
if (checkEls.filter(containerEl).length && (
// Проверка на нажатие правой клавиши мыши.
//(3 === event.which) ||
// Проверка нажатия внутри попапа вне элементов закрытия попапа.
!(options.closeEl && checkEls.filter(options.closeEl).length)
)) {
return;
}
hide(event);
}
/**
* @param {Event} event
*/
function hide(event) {
if (options.documentClick) {
_doc.unbind('click', hideWithCheck);
}
if (options.escapeKey) {
_doc.unbind('keydown', cancel);
}
if (options.beforeHide) {
options.beforeHide(event);
}
if (options.faderEl) {
options.faderEl.addClass('hidden');
}
if (!options.hide || (true === options.hide && $c.browser.msie)) {
containerEl.addClass('hidden');
if (options.afterHide) {
options.afterHide(event);
}
} else if (true === options.hide) {
containerEl
.css('opacity', 1)
.animate({ opacity: 0 }, {
duration: 300,
complete: function() {
containerEl
.addClass('hidden')
.css('opacity', '');
if (options.afterHide) {
options.afterHide(event);
}
}
});
} else {
options.hide(event);
}
}
function show(event) {
if (options.documentClick) {
_doc.bind('click', hideWithCheck);
}
if (options.escapeKey) {
_doc.bind('keydown', cancel);
}
if (options.beforeShow) {
options.beforeShow(event);
}
if (options.faderEl) {
options.faderEl.removeClass('hidden');
}
if (!options.show || (true === options.show && $c.browser.msie)) {
containerEl.removeClass('hidden');
if (options.afterShow) {
options.afterShow(event);
}
} else if (true === options.show) {
containerEl
.css('opacity', 0)
.removeClass('hidden')
.animate({
opacity: 1
}, {
duration: 300,
complete: function() {
containerEl.css('opacity', '');
if (options.afterShow) {
options.afterShow(event);
}
}
});
} else {
options.show(event);
}
}
function toggle(event) {
return containerEl.hasClass('hidden') ? show(event) : hide(event);
}
function unbind() {
if (options.linkEl) {
options.linkEl.unbind('click', toggle);
}
if (options.closeEl) {
options.closeEl.unbind('click', toggle);
}
if (options.documentClick) {
_doc.unbind('click', hideWithCheck);
}
if (options.escapeKey) {
_doc.unbind('keydown', cancel);
}
}
return {
/**
* Вызывает событие скрытия попапа.
* @param {Event} [event]
*/
hide: hide,
/**
* Вызывает событие показа попапа.
* @param {Event} [event]
*/
show: show,
/**
* Вызывает событие переключения состояния попапа.
* @param {Event} [event]
*/
toggle: toggle,
/**
* Отписывает от событий.
*/
unbind: unbind
};
};
/**
* Диспетчер любых событий.
* @author Matthew Foster, Vlad Yakovlev (red.scorpix@gmail.com)
* @version 1.0.3
* @date 2010-05-11
*
* @changelog
* Version 1.0.3
* Добавлен метод one
.
*
* @changelog
* Version 1.0.2
* Исправлена ошибка при удалении подписчика (на самом деле не удалялся).
* Методы, кроме hasBinds
, возвращают объект-диспетчер.
* У метода unbind
аргументы стали не обязательными.
* Метод dispatch
переименован в trigger
.
* Метод hasBinds
переименован в bounddata
содержит startX, startY,
* а также moveX, moveY — перемещение с начала драг-н-дропа).
* @param {Function} stop Функция, вызываемая по окончании перемещения.
*
* @version 0.1.1
* @date 2010-02-16
*/
$c.draggable = function(el) {
el = $(el).first();
var
isDrag = false,
isBind = false,
startX,
startY,
lastX,
lastY,
that = {},
startFunc,
dropFunc,
endFunc;
bind();
function bind(start, drop, end) {
if (!el.length) return;
if (isBind) {
unbind();
}
isBind = true;
startFunc = start;
dropFunc = drop;
endFunc = end;
el.mousedown(startDnd);
}
function startDnd(evt) {
if (!(el.length && isBind && !isDrag)) {
return;
}
isDrag = true;
startX = parseInt(evt.pageX);
startY = parseInt(evt.pageY);
lastX = startX;
lastY = startY;
$(document).mousemove(dnd).mouseup(endDnd);
if (startFunc) {
return startFunc(evt);
}
}
function dnd(evt) {
if (!el.length) {
return;
}
var
pageX = parseInt(evt.pageX),
pageY = parseInt(evt.pageY),
stepX = pageX - lastX,
stepY = pageY - lastY;
lastX = pageX;
lastY = pageY;
if (dropFunc) {
return dropFunc(evt, {
startX: startX,
startY: startY,
moveX: pageX - startX,
moveY: pageY - startY,
stepX: stepX,
stepY: stepY
});
}
}
function endDnd(evt) {
if (!(el.length && isBind && isDrag)) {
return;
}
isDrag = false;
$(document).unbind('mousemove', dnd).unbind('mouseup', endDnd);
if (endFunc) {
return endFunc(evt, {
startX: startX,
startY: startY,
moveX: evt ? parseInt(evt.pageX) - startX : 0,
moveY: evt ? parseInt(evt.pageY) - startY : 0
});
}
}
/**
* Прекращает отслеживание драг-н-дропа.
*/
function unbind() {
if (!(el.length && isBind)) {
return;
}
endDnd();
startFunc = null;
dropFunc = null;
endFunc = null;
isBind = false;
el.unbind('mousedown', startDnd);
}
that.bind = function(start, drop, end) {
bind(start, drop, end);
return that;
};
that.unbind = function() {
unbind();
return that;
};
/**
* Принудительно завершает драг-н-дроп.
*/
that.release = function(evt) {
endDnd(evt);
return that;
};
that.start = function(evt) {
startDnd(evt);
return that;
};
return that;
};
/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2018.10.23
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
/**
* @constructor
*/
FixedSubmit = function() {
/**
* @type {!jQuery}
* @private
*/
this.body_ = jQuery('body');
/**
* @type {!jQuery}
* @private
*/
this.root_ = this.body_.find('form.fixed-submit');
if (!this.root_.length) {
return;
}
/**
* @type {!jQuery}
* @private
*/
this.formContainer_ = this.root_.find('.form-container');
/**
* @type {!jQuery}
* @private
*/
this.fixedExtra_ = this.root_.find('.extra');
/**
* @type {!jQuery}
* @private
*/
this.captcha_ = this.root_.find('.captcha');
/**
* @type {!jQuery}
* @private
*/
this.controls_ = this.root_.find('.controls');
/**
* @type {!jQuery}
* @private
*/
this.navToggler_ = this.root_.find('#nav .toggler');
this.init_();
this.setFixedBlockPosition_();
this.changeWidthFixedBlock_();
this.navTogglerAnimate_();
this.attachEvents_();
};
/**
* @private
*/
FixedSubmit.prototype.init_ = function() {
if (this.captcha_.find('.input-captcha.error').length) {
this.fixedExtra_.addClass('fixed show');
}
};
/**
* @private
*/
FixedSubmit.prototype.changeWidthFixedBlock_ = function() {
var padding = 30;
this.fixedExtra_.css('width', this.root_.width() + padding + 'px');
};
/**
* @private
*/
FixedSubmit.prototype.setFixedBlockPosition_ = function() {
var fixedContainerBottom =
this.formContainer_.offset().top + this.formContainer_.outerHeight();
var scrollPosition =
jQuery(window).scrollTop() +
jQuery(window).height() -
this.controls_.outerHeight();
(fixedContainerBottom <= scrollPosition) ?
this.controls_.removeClass('fixed') :
this.controls_.addClass('fixed');
};
/**
* @private
*/
FixedSubmit.prototype.navTogglerAnimate_ = function() {
var that = this;
this.navToggler_.bind('menuToggled', function() {
if (jQuery('#page').is('.wide')) {
that.controls_.animate({
left: '298px'
}, 200);
} else {
that.controls_.stop(true).animate({
left: '78px'
}, 200);
}
});
};
/**
* @private
*/
FixedSubmit.prototype.attachEvents_ = function() {
var that = this;
jQuery(window).scroll(function() {
that.changeWidthFixedBlock_();
that.setFixedBlockPosition_();
});
jQuery(window).resize(function() {
that.changeWidthFixedBlock_();
});
this.navToggler_.click(function() {
that.body_.trigger('menuToggled');
});
};
jQuery(document).ready(function() {
new FixedSubmit();
});
/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2018.04.10
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
// Копирование в буфер
window.Clipboard = (function(window, document, navigator) {
var textArea,
copy;
function isOS() {
return navigator.userAgent.match(/ipad|iphone/i);
}
function createTextArea(text) {
textArea = document.createElement('textArea');
textArea.value = text;
document.body.appendChild(textArea);
}
function selectText() {
var range,
selection;
if (isOS()) {
range = document.createRange();
range.selectNodeContents(textArea);
selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
textArea.setSelectionRange(0, 999999);
} else {
textArea.select();
}
}
function copyToClipboard() {
document.execCommand('copy');
document.body.removeChild(textArea);
}
copy = function(text) {
createTextArea(text);
selectText();
copyToClipboard();
};
return {
copy: copy
};
})(window, document, navigator);
jQuery(document).ready(function() {
jQuery('.clipboard_copy').click(function() {
Clipboard.copy(document.querySelector('.clipboard').innerText);
});
});
$(function() {
/* Blocks with hidden text */
var withHiddenText = $('.with_hidden_text');
withHiddenText.each(function() {
var that = $(this);
var link = $(this).find('.hidden_text_link');
var textContainer = $(this).find('.text');
var text = textContainer.text();
var textLength = text.length;
var SYMBOLS_LENGTH = 300;
if (textLength <= SYMBOLS_LENGTH) {
link.hide();
return;
}
var visibleText = text.slice(0, SYMBOLS_LENGTH);
var hiddenText = text.slice(SYMBOLS_LENGTH);
var newText = '' + visibleText + ' ' + '' + hiddenText + ' '
link.show();
textContainer.html(newText);
link.click(function() {
that.toggleClass('opened');
});
});
/* Blocks with hidden content */
var withHiddenContent = $('.with_hidden_content');
withHiddenContent.each(function() {
var that = $(this);
var link = $(this).find('.hidden_content_link');
var hiddenContent = $(this).find('.hidden_content');
link.click(function() {
that.toggleClass('opened');
});
});
/* Applicant fields addition*/
var counter = 0;
var addApplicantLink = $('.add_fields_link');
var additionalFields = $('#additional_fields');
var newFieldsContainer = $('#additional_fields_container');
function moreFields() {
counter++;
var newFields = additionalFields.clone();
var newFieldsId = newFields.attr('id');
newFields.show();
newFields.attr('id', newFieldsId + counter);
var newField = newFields.find('dd input');
var newFieldLabel = newFields.find('dl label');
// var newFieldTitleNum = newFields.find('.additional_fields_title .num');
for (var i=0;i 1) {
btnClose.css('display', 'inline-block');
} else {
btnClose.css('display', 'none');
}
}
moreFields();
addApplicantLink.click(moreFields);
newFieldsContainer.delegate('.additional_fields_close', 'click', function() {
var btnClose = newFieldsContainer.find('.additional_fields_close');
$(this).closest('.additional_fields').remove();
if (newFieldsContainer.children().length === 1) {
btnClose.css('display', 'none');
}
});
/* Drag & drop link hover */
var fileuploadContainer = $('.ajax__fileupload_selectFileContainer');
fileuploadContainer.find('input[type="file"]').hover(function() {
fileuploadContainer.addClass('hover');
}, function() {
fileuploadContainer.removeClass('hover');
});
$('.glide-carousel').glide({
type: 'carousel',
autoplay: false,
autoheight: true
});
});
/* Scrollable content */
$(function() {
var $zone = $('.switcher_content.scroll');
if ($zone.length){
$zone.each(function() {
var Scroll = {},
zone = $(this);
Scroll.prev = zone.find('.scroll_prev');
Scroll.next = zone.find('.scroll_next');
Scroll.scrollable = zone.find('.scrollable');
Scroll.width = Scroll.scrollable.width();
Scroll.realWidth = 0;
Scroll.scrollable.children().each(function(){
Scroll.realWidth += $(this).width();
});
Scroll.proportions = Scroll.realWidth / Scroll.width;
Scroll.currentScroll = 0;
bindScroll(Scroll)
});
function bindScroll(Scroll) {
Scroll.next.click(function() {
ScrollMove(Scroll, true)
});
Scroll.prev.click(function() {
ScrollMove(Scroll, false)
});
$(window).resize(function(){
Scroll.width = Scroll.scrollable.width();
Scroll.realWidth = Scroll.width * Scroll.proportions;
var translate = 'translate3d('+ (-Scroll.width*Scroll.currentScroll) + 'px, 0, 0)';
ScrollCross(Scroll,translate);
})
}
function ScrollMove(Scroll, dir) {
dir ? Scroll.currentScroll++ : Scroll.currentScroll--;
Scroll.Moveto = -Scroll.width*Scroll.currentScroll;
Math.abs(Scroll.Moveto) + Scroll.width > Scroll.realWidth ? Scroll.next.hide() : Scroll.next.show();
Scroll.currentScroll == 0 ? Scroll.prev.hide() : Scroll.prev.show();
var translate = 'translate3d('+ Scroll.Moveto + 'px, 0, 0)';
ScrollCross(Scroll,translate);
}
function ScrollCross(Scroll, translate){
Scroll.scrollable[0].style.transform = translate;
Scroll.scrollable[0].style.OTransform = translate;
Scroll.scrollable[0].style.msTransform = translate;
Scroll.scrollable[0].style.MozTransform = translate;
}
}
});
/* Animate showing content */
animation = function(wrap, elements, speed) {
var animTable = {};
animTable.wrap = wrap;
if (animTable.wrap.length) {
var columnsClass = 'visible',
speed = speed || 100,
floatSpeed = speed;
var animPossible = elements || ['gcolumns', 'tr'];
animTable.wrap.hasClass('slow') ? floatSpeed = 200 : floatSpeed = speed;
animate(elements);
function animate(elements) {
elements.each(function(row) {
var t = $(this);
setTimeout(function() {
t.addClass(columnsClass);
}, (row * floatSpeed));
})
}
}
};
$(function() {
var aspnetForm = $('#aspnetForm'),
prettyForm = $('.pretty_form'),
prettyFormPrev = prettyForm.prev('script'),
firstHeading = $('h2').first(),
switcherFoldable = $('.switcher.type2.foldable'),
switcherSimpleContainer = $('.switcher_simple_container'),
extraRight = $('.accent_block.extra.right');
if(!prettyFormPrev.size()) {
if(firstHeading.prev('script').size() ||
firstHeading.prev('span').size() ||
firstHeading.prev('input[type="hidden"]').size() ||
firstHeading.prev('.accent_block').first().size()) {
firstHeading.addClass('first');
}
} else {
firstHeading.addClass('after_pf');
}
switcherFoldable.parent().next('h2').addClass('after_foldable');
switcherFoldable.next('h2').addClass('after_foldable');
switcherFoldable.parents('.without_dash').find(switcherFoldable).addClass('inside_ul');
extraRight.nextUntil('h2', '.switcher.type2').addClass('switcher_near_extra');
var switchers={};
switchers.$All= $('.switcher.with_pseudo');
switchers.CONT= '.switcher_content_container';
switchers.TEXT= '.switcher_content';
switchers.$All.each(function() {
var t=$(this),
cont= t.next( switchers.CONT ).find( switchers.TEXT ) || $( switchers.CONT ).find( switchers.TEXT );
if(cont) new switcher(t.find('li .pseudo'), t.find('li'), cont);
});
switcherSimpleContainer.each(function() {
var switcherSimple =
jQuery(this).find(
'.switcher.type2.with_pseudo, .switcher.type3.with_pseudo, .switcher.type5'
);
var switcherSimpleContent = $(this).find('.switcher_simple_content');
var switcherSimpleItem = switcherSimple.find('li');
var switcherSimpleLink = switcherSimpleItem.find('.pseudo');
new switcher(switcherSimpleLink, switcherSimpleItem, switcherSimpleContent);
});
});
$(function() {
jQuery(window).on('load resize', function() {
var prettyForm = jQuery('#content .pretty_form:not(.vertical)');
var minWidthScreen = 580;
if (!prettyForm.length) {
return
}
prettyForm.toggleClass('vertical', jQuery(window).width() < minWidthScreen)
});
});
/**
* @author Alexander Samilyak (aleksam241@gmail.com)
* @date 16.03.11
* @time 13:30
* События:
* - before_open, перед показом попапа
* - after_open, после показа
* - before_close, перед скрытием
* - after_close, после скрытия
*/
commonPopup = function(jMain, jOpener, jExternalClickCatcher, mDuration) {
var
CLASS_CLOSE_BUTTON = "popup_close";
var
me;
var
jCloser = jMain.find("." + CLASS_CLOSE_BUTTON),
jRealExternalClickCatcher = $(jExternalClickCatcher || document);
var
oDispatcher = $({});
var
bHidden = !jMain.is(":visible"),
bAniInProgress = false;
publicInterface();
attachEvents();
function attachEvents() {
if (jOpener) {
jOpener.click(
function(evt){
me.toggle();
evt.stopPropagation();
evt.preventDefault();
return false;
}
);
}
jCloser.click(
function(){ me.close(); }
);
jRealExternalClickCatcher.click(onCatcherClick);
$(document).keyup(onKeyUp);
}
function onCatcherClick(evt) {
var bInsidePopup = jMain.is(evt.target) || jMain.has(evt.target).size();
if(!bInsidePopup && (evt.which === 1 || !evt.which)){
me.close();
}
}
function onKeyUp(evt) {
if(evt.keyCode === $c.keyCode("escape")){
me.close();
}
}
function publicInterface() {
me = {
getRoot : function() {
return jMain;
},
toggle : function(){
if (bHidden) {
me.open();
} else {
me.close();
}
},
open : function() {
if (!bHidden || bAniInProgress) {
return;
}
oDispatcher.trigger("before_open");
if (mDuration) {
bAniInProgress = true;
jMain.fadeIn(mDuration, "linear", function() {
bHidden = false;
bAniInProgress = false;
oDispatcher.trigger("after_open");
});
} else {
bHidden = false;
jMain.show();
oDispatcher.trigger("after_open");
}
},
close : function() {
if (bHidden || bAniInProgress) {
return;
}
oDispatcher.trigger("before_close");
if (mDuration) {
bAniInProgress = true;
jMain.fadeOut(mDuration, "linear", function() {
bHidden = true;
bAniInProgress = false;
oDispatcher.trigger("after_close");
});
} else {
bHidden = true;
jMain.hide();
oDispatcher.trigger("after_close");
}
},
isHidden : function() {
return bHidden;
},
bind : function(sEvent, fCall) {
oDispatcher.bind(sEvent, fCall);
return me;
},
unbind : function(sEvent, fCall) {
oDispatcher.unbind(sEvent, fCall);
return me;
},
destroy : function() {
jRealExternalClickCatcher.unbind("click", onCatcherClick);
$(document).unbind("click", onKeyUp);
me = null;
}
};
}
return me;
};
initPopup = function(params){
var t = this;
this.$wrap = params.wrap;
this.button = params.button;
this.href = params.withData || params.button;
this.size = params.size || '';
this.type = params.type || '';
this.Classes = {
close: 'popup_close'
};
this.speed = 250;
this.$fader = $('.fader');
this.$body = $('body');
this.$preloader = this.$wrap.next('.loader');
this.closeElement = ' ';
this.verticalScroll = $('#mCSB_1_dragger_vertical');
// if(this.type === 'gallery') new Gallery(1);
t.$wrap.mCustomScrollbar({
scrollInertia: 300,
enable:true,
mouseWheel: { preventDefault: true }
});
if(!t.$wrap.find('.'+this.Classes.close).length) t.$wrap.find('.mCustomScrollBox').before(t.closeElement);
this.Init = commonPopup(this.$wrap, this.button, null, "fast");
this.Init.bind("before_open", function() {
if (this.type !== 'gallery') {
t.getData(t.href.data('href'));
}
t.$fader.fadeIn(250);
t.$wrap.addClass(t.size);
t.$body.addClass('with-popup-opened');
});
this.Init.bind("after_open", function() {
if (t.type !== 'gallery') {
t.$wrap.mCustomScrollbar('update');
} else {
t.verticalScroll.addClass('hidden');
}
});
this.Init.bind("before_close", function () {
t.$fader.fadeOut(250);
});
this.Init.bind("after_close", function () {
if(t.type !== 'gallery') t.$wrap.find('.mCSB_container')[0].innerHTML = '';
t.$wrap.removeClass(t.size);
t.verticalScroll.removeClass('hidden');
t.$body.removeClass('with-popup-opened');
});
};
initPopup.prototype.getData = function(url) {
var t = this;
$.ajax({
url: url
})
.done(function( data ) {
if(t.type !== 'gallery') {
var contentselector = t.href.data('contentselector');
t.$wrap.find('.mCSB_container')[0].innerHTML =
(contentselector?$(data).find(contentselector).html():data);
}
t.$preloader.hide();
//if(t.type === 'gallery') new Gallery();
});
};
$(function(){
var $question = $('.question');
if (!$question.length) {
return;
}
//var $questionLink = $('.question > a');
var $linkInAnswer = $question.find('.answer a');
jQuery('.question').on('click', 'a.pseudo, a.title', function() {
var $questionLinkParent = $(this).parent();
var $answer = $questionLinkParent.children('.answer');
$answer.slideToggle('fast', function(){
$questionLinkParent.toggleClass('open');
if ($questionLinkParent.is('.open')) {
$(window).trigger('question_is_opened');
}
});
if ($questionLinkParent.is('.open')) {
$.cookie('question', null);
}
return false;
});
/* Expand all questions */
$('.questions_container').each(function(){
var container = $(this);
var expandAllLink = container.find('.faq_expand>a');
expandAllLink.on('click',function(){
$(this).parent().toggleClass('open');
if ($(this).parent().hasClass('open')) {
container.find('.question .answer').slideDown('fast', function(){
container.find('.question').addClass('open');
$(window).trigger('question_is_opened');
});
} else {
container.find('.question .answer').slideUp('fast', function(){
container.find('.question').removeClass('open');
});
}
return false;
});
});
/* Expand question with custom jquery event */
$question.on('cms-expand', function () {
if (!$(this).hasClass('open')) {
var $answer = $(this).children('.answer');
openQuestion($answer);
}
});
/* Save cookie of opened question */
$linkInAnswer.on('click', function() {
var $questionOpened = $(this).parents('.question');
var $answerOpened = $questionOpened.children('.answer');
var answerOpenedID = $answerOpened.attr('id');
$.cookie('question', answerOpenedID);
});
if ($.cookie('question') !== null) {
var cookieCurrent = $.cookie('question');
var $answerCurrent = $('.answer[id="' + cookieCurrent + '"]');
openQuestion($answerCurrent);
}
function openQuestion(answer) {
answer.slideDown('fast', function(){
answer.parent().addClass('open');
});
};
});
/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2018.05.25
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
/**
* @constructor
*/
LeftMenu = function() {
/**
* @type {!jQuery}
* @private
*/
this.page_ = jQuery('#page');
/**
* @type {!jQuery}
* @private
*/
this.menu_ = this.page_.find('#nav .menu');
/**
* @type {!jQuery}
* @private
*/
this.toggler_ = this.menu_.find('.toggler');
/**
* @type {!jQuery}
* @private
*/
this.main_ = this.page_.find('#main');
/**
* @type {boolean}
* @private
*/
this.inProgress_ = false;
this.attachEvents_();
};
/**
* @const
*/
LeftMenu.MARGIN_FOR_HIDDEN_MENU = -240; // px
/**
* @const
*/
LeftMenu.MARGIN_FOR_VISIBLE_MENU = 0; // px
/**
* @const
*/
LeftMenu.CONTENT_HOLDER_MARGIN_WHEN_MENU_IS_HIDDEN = 40; // px
/**
* @const
*/
LeftMenu.CONTENT_HOLDER_MARGIN_WHEN_MENU_IS_VISIBLE = 280; // px
/**
* @const
*/
LeftMenu.CLASS_PAGE_WITH_HIDDEN_MENU = 'wide';
/**
* @const
*/
LeftMenu.COOKIE_NAME = 'isLeftMenuHidden';
/**
* @const
*/
LeftMenu.COOKIE_LIFETIME = 365; // days;
/**
* @private
*/
LeftMenu.prototype.toggleLayout_ = function() {
this.inProgress_ = true;
!this.page_.hasClass(LeftMenu.CLASS_PAGE_WITH_HIDDEN_MENU) ? this.hideMenu_() : this.showMenu_();
};
/**
* @private
*/
LeftMenu.prototype.hideMenu_ = function() {
this.toggler_.queue([this.menuRollOut_(), this.onFinish_()]);
};
/**
* @private
*/
LeftMenu.prototype.showMenu_ = function() {
this.toggler_.queue([this.menuRollIn_(), this.onFinish_()]);
};
/**
* @private
*/
LeftMenu.prototype.menuRollOut_ = function() {
var that = this;
this.menu_.animate({'margin-left': LeftMenu.MARGIN_FOR_HIDDEN_MENU}, 'fast',
function() {
that.page_.addClass(LeftMenu.CLASS_PAGE_WITH_HIDDEN_MENU);
}
);
this.main_.animate({'margin-left': LeftMenu.CONTENT_HOLDER_MARGIN_WHEN_MENU_IS_HIDDEN}, 'fast');
};
/**
* @private
*/
LeftMenu.prototype.menuRollIn_ = function() {
var that = this;
this.menu_.animate({'margin-left': LeftMenu.MARGIN_FOR_VISIBLE_MENU}, 'fast',
function() {
that.page_.removeClass(LeftMenu.CLASS_PAGE_WITH_HIDDEN_MENU);
}
);
this.main_.animate({'margin-left': LeftMenu.CONTENT_HOLDER_MARGIN_WHEN_MENU_IS_VISIBLE}, 'fast');
};
/**
* @private
*/
LeftMenu.prototype.onFinish_ = function() {
this.inProgress_ = false;
};
/**
* @private
*/
LeftMenu.prototype.refreshCookie_ = function() {
if (!this.page_.hasClass(LeftMenu.CLASS_PAGE_WITH_HIDDEN_MENU)) {
jQuery.cookie(
LeftMenu.COOKIE_NAME, 'true',
{expires: LeftMenu.COOKIE_LIFETIME, path: '/'}
);
} else {
jQuery.removeCookie(LeftMenu.COOKIE_NAME, { path: '/' });
}
};
LeftMenu.prototype.checkCookie_ = function() {
if (jQuery.cookie(LeftMenu.COOKIE_NAME)) {
this.page_.addClass(LeftMenu.CLASS_PAGE_WITH_HIDDEN_MENU);
} else {
this.page_.removeClass(LeftMenu.CLASS_PAGE_WITH_HIDDEN_MENU);
}
};
/**
* @private
*/
LeftMenu.prototype.attachEvents_ = function() {
var that = this;
if (!this.menu_.length) {
return;
}
this.checkCookie_();
this.toggler_.on('click', function() {
if (that.inProgress_) {
return;
}
that.toggleLayout_();
that.refreshCookie_();
});
};
jQuery(document).ready(function() {
new LeftMenu();
});
/**
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2019.05.06
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
/**
* @constructor
*/
ScrollPane = function() {
/**
* @type {!jQuery}
* @private
*/
this.root_ = jQuery('#page');
/**
* @type {!jQuery}
* @private
*/
this.scrollPane_ = this.root_.find('.scroll-pane');
/**
* @type {!jQuery}
* @private
*/
this.question_ = this.root_.find('.question');
/**
* @type {!jQuery}
* @private
*/
this.navToggler_ = this.root_.find('#nav .toggler');
this.init_();
this.attachEvents_();
};
/**
* @private
*/
ScrollPane.prototype.init_ = function() {
this.scrollPane_.each(
function() {
jQuery(this).jScrollPane({
showArrows: jQuery(this).is('.arrow')
}
);
var api = jQuery(this).data('jsp');
var throttleTimeout;
jQuery(window).on('resize click-question click-nav', function(event) {
if (!throttleTimeout) {
var time = 50;
if (event.type === 'click-nav') {
time = 200;
}
throttleTimeout = setTimeout(
function() {
api.reinitialise();
throttleTimeout = null;
},
time
);
}
});
}
)
};
/**
* @private
*/
ScrollPane.prototype.attachEvents_ = function() {
var that = this;
that.question_.on('click', 'a.pseudo, a.title', function() {
that.question_.trigger('click-question');
});
that.navToggler_.on('click', function() {
that.navToggler_.trigger('click-nav');
});
};
jQuery(document).ready(function() {
new ScrollPane();
});
/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2018.04.10
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
/**
* @constructor
*/
Search = function() {
/**
* @type {!jQuery}
* @private
*/
this.burger_ = jQuery('.whole_site_opener .burger');
/**
* @type {!jQuery}
* @private
*/
this.searchInput_ = null;
/**
* @type {!jQuery}
* @private
*/
this.searchSubmit_ = jQuery('.search-field').find('*[type="submit"]');
this.init_();
this.getSearchInput_();
this.attachEvents_();
};
/**
* @private
*/
Search.prototype.init_ = function() {
this.searchSubmit_.prop('disabled', true);
};
/**
* @private
*/
Search.prototype.checkInput_ = function(searchInput) {
for (var i = 0; i < searchInput.length; i++) {
var search = jQuery(searchInput[i]);
var searchButton = search.next('*[type="submit"]');
if (!search.val().length || search.val() === search.attr('placeholder')) {
searchButton.removeClass('disabled').prop('disabled', true);
} else {
if (searchButton.hasClass('disabled')) {
return;
}
searchButton.addClass('disabled').prop('disabled', false);
}
}
};
/**
* @private
*/
Search.prototype.getSearchInput_ = function() {
var that = this;
this.searchInput_ = jQuery('.search-field').find('input[type="text"]');
that.checkInput_(this.searchInput_);
this.searchInput_.on('input propertychange keypress load', function(e) {
var searchButton = jQuery(e.currentTarget).next('*[type="submit"]');
if (e.keyCode === 13 && !searchButton.hasClass('disabled')) {
e.preventDefault();
}
that.checkInput_(jQuery(e.currentTarget));
});
};
/**
* @private
*/
Search.prototype.attachEvents_ = function() {
var that = this;
this.burger_.on('click', function() {
setTimeout(function() { // Ожидание подгрузки строки поиска в меню.
that.getSearchInput_();
}, 500);
});
};
jQuery(document).ready(function() {
new Search();
});
/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2018.04.19
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
/**
* @constructor
*/
Video = function() {
/**
* @type {!jQuery}
* @private
*/
this.root_ = jQuery('#content');
/**
* @type {!jQuery}
* @private
*/
this.videoContainer_ = this.root_.find('.video-container');
/**
* @type {!number}
* @private
*/
this.videoWidth_ = 650; //px
this.checkVideoWidth_();
this.attachEvents_();
};
/**
* @private
*/
Video.prototype.checkVideoWidth_ = function() {
for (var i = 0; i < this.videoContainer_.length; i++) {
if (this.videoContainer_.eq(i).width() < this.videoWidth_) {
this.videoContainer_.eq(i).addClass('narrow');
} else {
this.videoContainer_.eq(i).removeClass('narrow');
}
}
};
/**
* @private
*/
Video.prototype.attachEvents_ = function() {
var that = this;
jQuery(window).resize(function() {
that.checkVideoWidth_();
});
};
jQuery(document).ready(function() {
new Video();
});
/**
* @author Alexander Samilyak (aleksam241@gmail.com)
* @date 7/11/11
* @time 1:58 PM
*/
(function () {
function wholeSite() {
var
jMain = $('.whole_site'),
jOpener = $('.whole_site_opener .burger'),
jClose = $('.whole_site .popup_close, .whole_site .burger'),
fullMenu = true;
init();
initPopup();
initFirstLevelSwitcher();
changeFirstLevelSwitcher();
jQuery(window).resize(function() {
changeFirstLevelSwitcher();
});
function init() {
jMain.appendTo("#page");
jOpener.on('click', function () {
$('body').addClass('menu-opened');
});
jClose.on('click', function () {
$('body').removeClass('menu-opened');
});
}
function initPopup() {
var popup = commonPopup(jMain, jOpener, null, "fast");
var mapContainer = jMain.find(".whole_site_map_container");
if (mapContainer.length > 0) {
popup.bind("before_open", function () {
mapContainer.triggerHandler("get_whole_site_map", function () {
initFirstLevelSwitcher();
popup.unbind("before_open");
});
});
}
}
function changeFirstLevelSwitcher() {
var item = jQuery('.whole_site .first_level_switcher li.selected, .whole_site .first_level_switcher li.selected a');
var href = item.find('a').attr('href');
item.on('click', function () {
if (jQuery(document).width() > 768 && fullMenu === false) {
fullMenu = true;
return false;
} else if (jQuery(document).width() <= 768 && fullMenu === true) {
window.location.href = href;
fullMenu = false;
}
});
}
function initFirstLevelSwitcher() {
var mapContainer = $('.whole_site_map_container');
mapContainer.bind('get_whole_site_map', function() {
mapContainer.html('Загружается...
');
jQuery.ajax({
dataType: 'json',
url: jQuery('.whole_site_map_container').data('config')['url'],
error: function () {
mapContainer.html('Не удалось загрузить карту сайта. Попробуйте ещё раз.');
},
success: function(data) {
var mainMenu = [];
var titleSubMenu = [];
jQuery.each(data.children, function (key, val) {
var pseudo = '';
var directlink = '';
if (data.children[key].children.length) {
pseudo = ' class="pseudo"';
} else {
directlink = ' directlink';
}
mainMenu.push('' + val.title + ' ');
var middle = false;
var mainSubMenu_col1 = [];
var mainSubMenu_col2 = [];
var mainSubMenu = mainSubMenu_col1;
jQuery.each(data.children[key].children, function (subKey, subVal) {
var mainSubSubMenu = [];
jQuery.each(data.children[key].children[subKey].children, function (subSubKey, subSubVal) {
mainSubSubMenu.push('' +
'' +
' ');
});
if (!middle && subKey > (val.children.length / 2)) {
middle = true;
mainSubMenu = mainSubMenu_col2
}
mainSubMenu.push('' +
'' + mainSubSubMenu.join('') + ' ' +
' ');
});
titleSubMenu.push('' +
'
' + mainSubMenu_col1.join('') + ' ' +
'
' + mainSubMenu_col2.join('') + ' ' +
'
');
});
var parseMainMenu = '' + mainMenu.join('') + ' ' + titleSubMenu.join('');
jQuery('.whole_site_map_container').html(parseMainMenu);
//copy links
$('.whole_site_extra').html($('.header__extra-inner').html());
$('.quick_menu:not(.cms_main_menu)').each(function () {
var $first_level = $('.first_level_switcher ul');
$first_level.append('
');
$(this).find('li').each(function () {
$(this).addClass('directlink');
$first_level.append($(this).clone());
});
});
//set current branch
var ancestors = jQuery('.whole_site_map_container').data('config')['catalogPath'];
if (ancestors.length > 0) {
var topCatalogId = ancestors[ancestors.length - 1];
$('.whole_site_map_container .for_branch_' + topCatalogId).addClass('selected');
$('.whole_site_map_container .branch_' + topCatalogId).addClass('selected');
}
for (var i = 0; i < ancestors.length - 1; ++i) {
var id = ancestors[i];
$('.whole_site_map_container li[data-catalogid=' + id + ']').addClass('selected');
}
if (ancestors.length > 0) {
var catalogId = ancestors[0];
$('.whole_site_map_container *[data-catalogid=' + catalogId + '] > .link').remove();
$('.whole_site_map_container *[data-catalogid!=' + catalogId + '] > .current').remove();
}
var contents = jMain.find(".front");
if (contents.length) {
var sw = switcher(
jMain.find(".first_level_switcher .pseudo1"),
jMain.find(".first_level_switcher li"),
contents,
true
);
sw.bind(function () {
var jItem = jMain.find(".first_level_switcher li.selected");
if (jItem.length === 0) {
return;
}
var itemName = parseItemName(jItem);
var jDetails = jMain.find("." + itemName);
if (jDetails.is(":hidden") || jDetails.find(".navigation li").length === 0) {
var href = jItem.find("a").attr("href");
window.location.href = href;
}
});
function parseItemName(jItem) {
var aMatch = jItem[0].className.match(/for_(\w+)/);
if (aMatch) {
return aMatch[1];
} else {
return null;
}
}
}
}
});
});
}
}
$(wholeSite);
})();
/**
* @author Roma Kosovichev (roma@roma.so)
* @date 09.12.15
* @time 13:40
*/
$(function() {
var _popup = {};
_popup.$wrap = $('.popup_complaint');
_popup.$PersonButton = $('.persons').find('.gcolumns, .item');
if (_popup.$PersonButton.length) {
_popup.$PersonButton.each(function() {
new initPopup({
wrap: _popup.$wrap,
size: 'wide',
button: $(this)
})
});
}
});
/**
* @author Alexander Samilyak (aleksam241@gmail.com)
* @date 18.03.11
* @time 13:31
*/
switcher = function (jLinks, jLinkHolders, jContents, jSelectedItem) {
var
CLASS_SELECTED = "selected",
//inherit from animation.js:
CLASS_VISIBLE = "visible",
CLASS_ANIMATION = "animate";
var me;
var oDispatcher = $({});
var
aItems = [],
pItems = ['.gcolumns', 'tr'],
oPrevSelectedItem,
oSelectedItem;
publicInterface();
init();
function init() {
initItems();
}
function initItems() {
var
jLinkRoots = jLinkHolders || jLinks,
jLinkRootsExceptLinkForAll = jLinkRoots.filter(":not(.for_all)"),
oInitialSelectedItem;
jLinkRoots.each(
function (i) {
var
jLinkRoot = $(this),
jLink,
jContent;
if (jLinks.eq(i).size()) {
jLink = jLinks.eq(i);
} else {
jLink = jLinkRoot;
}
if (jContents) {
var sLinkName = parseItemName(jLinkRoot);
if (sLinkName === "all") {
jContent = jContents;
} else if (sLinkName) {
jContent = jContents.filter("." + sLinkName);
} else {
jContent = jContents.eq(
jLinkRootsExceptLinkForAll.index(jLinkRoot)
);
}
} else {
jContent = null;
}
var oItem = item(jLinkRoot, jLink, jContent, i);
aItems.push(oItem);
if (jLinkRoot.hasClass(CLASS_SELECTED)) {
oInitialSelectedItem = oItem;
}
oItem.deselect();
}
);
selectItem(oInitialSelectedItem || aItems[0], true);
}
function selectItem(oItem, bInitial) {
if ((!oItem || oItem === oSelectedItem) && !jSelectedItem) {
return;
}
if (oSelectedItem) {
oPrevSelectedItem = oSelectedItem;
oSelectedItem.deselect();
}
oItem.select();
oSelectedItem = oItem;
if (!bInitial) {
oDispatcher.trigger(
"change",
me.getIndex(), me.getPrevIndex()
);
}
}
function parseItemName(jItem) {
var aMatch = jItem[0].className.match(/for_(\w+)/);
if (aMatch) {
return aMatch[1];
} else {
return null;
}
}
function getItemByIndex(iIndex) {
return $.grep(aItems, function (oItem) {
return iIndex === oItem.getIndex();
})[0];
}
function item(jItemRoot, jLink, jContent, iIndex) {
var me;
packageInterface();
init();
function init() {
attachEvents();
}
function attachEvents() {
jLink.click(
function (evt) {
selectItem(me, false);
evt.stopPropagation();
evt.preventDefault();
return false;
}
);
}
function packageInterface() {
me = {
getIndex: function () {
return iIndex;
},
showItems: function (show) {
for (var i = 0; i < pItems.length; i++) {
if (pItems.length) {
show ? new animation(jContent, jContent.find(pItems[i])) : jContent.find(pItems[i]).removeClass(CLASS_VISIBLE)
}
}
},
select: function () {
jItemRoot.addClass(CLASS_SELECTED);
if (jContent) {
jContent.show();
}
if (jContent.hasClass(CLASS_ANIMATION)) {
me.showItems(true);
}
},
deselect: function () {
jItemRoot.removeClass(CLASS_SELECTED);
if (jContent) {
jContent.hide();
}
if (jContent.hasClass(CLASS_ANIMATION)) {
me.showItems(false);
}
}
};
}
return me;
}
function publicInterface() {
me = {
getIndex: function () {
return (
oSelectedItem ?
oSelectedItem.getIndex() :
null
);
},
setIndex: function (iIndex) {
selectItem(
getItemByIndex(iIndex),
false
);
return me;
},
getPrevIndex: function () {
return (
oPrevSelectedItem ?
oPrevSelectedItem.getIndex() :
null
);
},
bind: function (fCall) {
oDispatcher.bind("change", fCall);
return me;
},
unbind: function (fCall) {
oDispatcher.unbind("change", fCall);
return me;
}
};
}
return me;
};
/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2017.12.11
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
*/
/**
* @constructor
*/
Switcher = function() {
this.root_ = jQuery('.switcher.foldable.type2');
this.switcher_ = this.root_.find('.foldable_switcher');
this.defaultSwitcherHeight = 2.7; // em
this.faqLinks_ = jQuery('.faq_expand a, .question a');
this.init_();
this.attachEvents_();
this.itemsChange_();
};
/**
* @private
*/
Switcher.prototype.init_ = function() {
var that = this;
that.root_.css('height', that.defaultSwitcherHeight + 'em');
};
/**
* @private
*/
Switcher.prototype.itemsChange_ = function() {
var that = this;
that.root_.each(function(key) {
// Новые облака списков файлов
var switcherLine = that.root_.eq(key).find('.switcher-line');
var switcherAllItems = switcherLine.find('.switcher-item');
if (switcherAllItems.length) {
var selectedLine = false;
for (var a = 0; a < switcherLine.length; a++) {
var switcherLineItems = switcherLine.eq(a).find('.switcher-item');
for (var b = 0; b < switcherLineItems.length; b++) {
if (switcherLineItems.eq(b).hasClass('selected')) {
selectedLine = true;
that.itemsHidden_(switcherLine.eq(a));
}
}
}
if (!selectedLine) {
selectedLine = false;
that.itemsHidden_(switcherLine.first());
setTimeout(function() {
that.itemsHidden_(switcherLine.first());
}, 0);
}
if (switcherLine.length == 1) {
var switcherItemsFirst = switcherAllItems.first().position().top;
var switcherItemsLast = switcherAllItems.last().position().top;
switcherLine.parents('.switcher').addClass('padding_right_redefine');
if (switcherItemsFirst == switcherItemsLast) {
switcherLine.parents('.switcher').addClass('padding_right_redefine');
} else {
switcherLine.parents('.switcher').removeClass('padding_right_redefine');
}
}
} else {
// Старые облака списков файлов
that.oldSwitcher_(that.root_.eq(key));
}
});
};
/**
* @private
*/
Switcher.prototype.oldSwitcher_ = function(root) {
var that = this;
// Старые облака списков файлов
var switcherAllItems = root.find('li');
if (switcherAllItems.length) {
var switcherItemsFirst = switcherAllItems.first().position().top;
var switcherItemsLast = switcherAllItems.last().position().top;
root.addClass('padding_right_redefine');
if (switcherItemsFirst == switcherItemsLast) {
root.addClass('padding_right_redefine');
} else {
root.removeClass('padding_right_redefine');
}
}
};
/**
* @private
*/
Switcher.prototype.itemsHidden_ = function(switcherLine) {
var that = this;
switcherLine.addClass('switcher-line-selected');
for (var i = 0; i < switcherLine.children().length; i++) {
var switcherItemsFirst = switcherLine.children(':first').position().top;
if (switcherLine.children().eq(i).position().top !== switcherItemsFirst) {
switcherLine.children().eq(i).addClass('hidden');
} else {
switcherLine.children().eq(i).removeClass('hidden');
}
}
};
/**
* @private
*/
Switcher.prototype.attachEvents_ = function() {
var that = this;
jQuery(window).resize(function() {
that.itemsChange_();
});
that.switcher_.on('click', function() {
var currentSwitcher = jQuery(this).parent();
if (currentSwitcher.hasClass('open')) {
currentSwitcher.removeClass('open');
currentSwitcher.css('height', that.defaultSwitcherHeight + 'em');
} else {
currentSwitcher.addClass('open');
currentSwitcher.removeAttr('style');
}
});
jQuery('.answer *').on('cms-expand', function() {
setTimeout(function() {
that.itemsChange_();
}, 0);
});
that.faqLinks_.on('click cms-expand', function() {
setTimeout(function() {
that.itemsChange_();
}, 0);
});
};
jQuery(document).ready(function() {
new Switcher();
});
$(function(){
$('table.data, table.CBRTBL').each(function(){
var prev_tr_td = [];
$(this).find('tr').each(function(){
var prev_td = [];
for(var i = prev_tr_td.length - 1; i >= 0 ; i--)
prev_tr_td[i].span--;
$(this).find('td').each(function(){
var $td = $(this), rowspan = $td.attr('rowspan');
$td.data('linked_td', $.merge([], prev_td));
for(var i = prev_td.length - 1; i >= 0 ; i--)
prev_td[i].data('linked_td').push($td);
for(var i = prev_tr_td.length - 1; i >= 0 ; i--)
if(prev_tr_td[i].span > 0){
$td.data('linked_td').push(prev_tr_td[i].$td);
prev_tr_td[i].$td.data('linked_td').push($td);
}
if(!rowspan){
rowspan = 1;
}
if(rowspan > 1){
prev_tr_td.push({span: rowspan, $td: $td});
}
prev_td.push($td);
$td.mouseover(function(){
var linked_td = $(this).addClass('hover').data('linked_td');
if(linked_td){
for(var i = linked_td.length - 1; i >= 0 ; i--)
linked_td[i].addClass('hover');
}
});
$td.mouseout(function(){
var linked_td = $(this).removeClass('hover').data('linked_td');
if(linked_td){
for(var i = linked_td.length - 1; i >= 0 ; i--)
linked_td[i].removeClass('hover');
}
});
});
});
});
});
/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2019.07.11
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
/**
* @constructor
*/
ToggleText = function() {
/**
* @type {!jQuery}
* @private
*/
this.toggleControl_ = jQuery('.toggle-control');
this.attachEvents_();
};
/**
* @private
*/
ToggleText.prototype.attachEvents_ = function() {
var that = this;
this.toggleControl_.find('.pseudo').on('click', function(event) {
jQuery(event.currentTarget).closest('.toggle-text').toggleClass('show');
});
};
jQuery(document).ready(function() {
new ToggleText();
});
$(function(){
var bubbleContainer = $('.has_bubble'),
bubble = bubbleContainer.find('.bubble');
bubbleContainer.hover(function(){
$(this).addClass('show');
}, function() {
$(this).removeClass('show');
});
});
/**
* @author Malashenko Alyona (malashenko@design.ru)
* @date 14/03/17
* @time 1:58 PM
*/
$(function() {
var $body = $('body');
var $versionSwitcher = $('.version-switcher');
var $versionSwitcherLink = $('.version-switcher__link');
$versionSwitcherLink.click(function(event) {
$body.toggleClass('vision-impaired');
$versionSwitcher.toggleClass('active');
$(window).trigger('version_changed');
if ($.cookie('vision_impaired') == 'true') {
$.cookie('vision_impaired', 'false', { path: '/' });
} else {
$.cookie('vision_impaired', 'true', { path: '/' });
}
event.preventDefault();
});
if ($.cookie('vision_impaired') && $.cookie('vision_impaired') == 'true') {
$body.addClass('vision-impaired');
$versionSwitcher.addClass('active');
} else {
$body.removeClass('vision-impaired');
$versionSwitcher.removeClass('active');
}
});
/*
@author Oleg Krasnov (krasnov@artlebedev.ru)
@created 2019.10.17
@copyright Art. Lebedev Studio (http://www.artlebedev.ru/)
This source code follows Formatting section of Google Javascript Style Guide
https://google.github.io/styleguide/jsguide.html#formatting
*/
/**
* @constructor
*/
CookieWarning = function() {
/**
* @type {!jQuery}
* @private
*/
this.root_ = jQuery('#page');
/**
* @type {!jQuery}
* @private
*/
this.cookieWarning_ = this.root_.find('.cookie-warning');
/**
* @type {!jQuery}
* @private
*/
this.cookieWarningButton_ = this.cookieWarning_.find('button');
/**
* @type {!string}
* @private
*/
this.cookieWarningTitle_ = 'cbr-cookie-warning';
this.initCookieWarning_();
this.attachEvents_();
};
/**
* @private
*/
CookieWarning.prototype.initCookieWarning_ = function() {
var that = this;
if (jQuery.cookie(that.cookieWarningTitle_) === undefined) {
setTimeout(function() {
that.cookieWarning_.addClass('show');
}, 2000);
} else {
this.cookieWarning_.removeClass('show');
}
};
/**
* @private
*/
CookieWarning.prototype.attachEvents_ = function() {
var that = this;
this.cookieWarningButton_.on('click', function() {
jQuery.cookie(that.cookieWarningTitle_, true, {'expires': 3650, 'path': '/'});
that.initCookieWarning_();
});
};
jQuery(document).ready(function() {
new CookieWarning();
});