/* @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(''); 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('
  • ' + '' + '
  • '); }); titleSubMenu.push('

    ' + val.title + '

    ' + '
    ' + '
    ' + '
    '); }); 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(); });