$(function() { //Global functions //Ссылка стандартного формата на книгу и главу AZ.bibLink = ( args = { 'url':false, // создать абсолютный веб-адрес 'text':'', // строка в формате "книга.глава:стихи" либо объект {book, chapter} 'langs':false, // включать в ссылку языки: bool либо string-обозначение языков 'short':false // без '?' и всего что перед ним } )=>{ let text = args.text, langs = ''; if(args.text && args.text.book){ text = args.text.book + (args.text.chapter ? '.' + args.text.chapter : '' ); } if(args.langs === true) langs = AZ.cookie_langs; else if(args.langs) langs = args.langs; let prefix = args.short ? '' : ( args.url ? location.origin + '/' + AZ.root_path + '/?' : '' ); return prefix + text + ( langs ? '&' + langs : '' ); }; //Ссылка специального формата (без query-параметров) AZ.externalBookLink = (slug)=>{ return AZ.path['external_link_book'].replace(':slug', slug); } AZ.setSelectedVerses = (arr)=>{ AZ.selected_verses = arr; } AZ.getSelectedVersesFromContent = ()=>{ AZ.selected_verses = []; AZ.selected_verse_nodes = $('.verse.selected'); AZ.selected_verse_nodes.each(function (i, element) { const text = $.trim(element.dataset['verse']); if (!AZ.selected_verses.includes(text)) { AZ.selected_verses.push(text); } }); return AZ.selected_verses; } AZ.parseVerse = (v)=>{ let pts = v.split('.'); let chapAndVerse = pts[1].split(':'); return { 'book':pts[0], 'chapter':parseInt(chapAndVerse[0]), 'verse':parseInt(chapAndVerse[1]) }; } //Формирует адрес стандартного формата исходя из выбранных стихов AZ.versesToText = (selection , params = { 'url' : false, // абсолютный адрес 'book_slug' : true, // включать слаг книги (или только цифровую часть) 'short' : false // без '?' и всего, что перед ним } )=>{ let url = params.url; let book_slug = params.book_slug; let short = params.short; let selected_verses_data = []; if(!selection) selection = $('.verse.selected:not(.verse-chapter-title)'); selection.each((i,item)=>{ selected_verses_data.push(AZ.parseVerse(item.dataset['verse'])); }); let text = book_slug ? AZ.book_slug + '.' : ''; let prev = null; let diap_mode = false; let current_chapter = null; let finish_diap = end => { if (diap_mode) { text += '-'; let end_chapter = prev['chapter']; if (current_chapter !== end_chapter) { // text += end_chapter + ':'; } text += prev['verse']; diap_mode = false; } } let gen_verse_number = (el) => { let chap = el['chapter']; return ((chap === current_chapter) ? '' : (chap + ':')) + el['verse']; } selected_verses_data.forEach(el => { if (!prev) { text += gen_verse_number(el); current_chapter = el['chapter']; } else if (el['chapter'] === prev['chapter'] && el['verse'] === prev['verse'] + 1) { diap_mode = true; } else { finish_diap(); text += ',' + gen_verse_number(el); current_chapter = el['chapter']; } prev = el; }); finish_diap(); return AZ.bibLink({url, text, short}); } AZ.findTopVerse = ()=>{ let topOffset = $('.header').height(), topEl = false, verses = $('.verse[data-verse]:not(.verse-chapter-title)'); verses.each((i,el)=>{ if(topEl) return false; let top = el.getBoundingClientRect().top; if(top > topOffset){ topEl = el; } }); if(!topEl) topEl = verses.first(); return topEl; } AZ.validateLogin = async function( doAlert = true, onSuccess = null, onFail = null ){ if(AZ.logged_in) return true; const myRequest = new Request(AZ.path['app_login_ajax']); await fetch(myRequest) .then((response) => { return response.json(); }) .then((json) => { AZ.logged_in = json.success == true; }); if(AZ.logged_in){ if(onSuccess) onSuccess(); return true; }else{ if( doAlert ) $('#please_register_popup').addClass('active'); if(onFail) onFail(); return false; } } AZ.ajax = (route, data, onOk, onFail, onAny)=>{ $.ajax({ url: AZ.path[route], method: 'post', cache: false, data: data, }).done(function (res) { if (res.success !== undefined) { if (res.success) { if(onOk) onOk(res); } else { if(onFail) onFail(res); else AZ.alert(res.message); } }else{ if(onFail) onFail(res); else AZ.alert('Возникла ошибка, сообщите об этом нам'); } if(onAny) onAny(res); }); }; AZ.getBookAbbr = selected => { let parentTable = selected.closest('.tbl-content'), selectedLang = selected.attr('data-lang'), colHeader = parentTable.find('#column_header_' + selectedLang); if(!colHeader.length) colHeader = $('#column_header_' + selectedLang); let abbr = colHeader.attr('data-abbreviation'); AZ.book_abbr = (abbr && abbr!=='') ? abbr : parentTable.attr('data-book-abbreviation'); }; // Bookmark $('.rb-nav .btn-bookmark').on('click', async function (e) { let $this = $(this); if ($this.attr('data-disabled') === 'true' || !(await AZ.validateLogin())) { return; } let verse = null, chapter = null; let $firstVerse = $(AZ.findTopVerse()); if ($firstVerse.length) { verse = $firstVerse.attr('data-verse'); chapter = $firstVerse.attr('data-chapter'); } let data = $.extend(getBookData(), { 'hex-codes': AZ.hex_codes, 'verse': verse, chapter, }); AZ.ajax('user_add_bookmark', data, (res)=>AZ.notify(res.message ?? 'Закладка добавлена')); }); // Создание и редактирование Избранного let addFavPopup = $('#add_fav_popup'), favData = {}; // item должен быть существующим объектом класса favorite по шаблону из favorite_addon.twig // kind - вид 'chapter'|'verses'|'interp' // target - информация по сохраняемому объекту, формируется в спецфункции в зависимости от вида // link - ссылка на объект // label - Выводимый в окне редактирования и в списках ЛК текст // опционально: // onSuccess(), onFail() let updateMode = false; let resetFavVars = ()=>{ favData = {}; }; // Главная функция создания/редактирования блока favorite updateFavorite = async function (params = {}){ if(!(await AZ.validateLogin())) return; let $item = $(params.item).closest('.favorite'); let $pop = $('#add_fav_popup'); $('.tag-container .tag', $pop).remove(); let favLink = AZ.path['user_favorites'] + "?kind[]=" + params.kind; let title = (($item && $item.length && $item.is('.has-fav')) ? "Редактировать" : "Добавить в" ) + " избранное"; let color = lsGet('fav_color') ?? 0 ; let tags = []; let comment = ''; let target = {}; // получаем параметры редактируемого объекта if($item.length){ color = $item.attr('data-color') || $item.find('[data-color]').attr('data-color') || 0; $('.tag', $item).each((i,el)=>{ AZ.insertTag($('.tag-container', $pop), el.dataset['tag'], true); }); comment = $.trim($item.find('.comment').text()); } //Сохраним данные для дальнейшей обработки при отправке на сервер и после неё favData = params; //Заполним и отобразим форму редактора $('.title', $pop).html(title); $('.text', $pop).html(params.label); // заполняется отдельно в спец-функциях $('.color-swatch', $pop).removeClass('active icon-check'); $('.color-swatch[data-id="'+ color +'"]', $pop).addClass('active icon-check'); $('.add-fav-comment', $pop).val(comment); $('.btn-personal').attr('href', favLink); $pop.addClass('active'); AZ.popup_on_close['add_fav_popup'] = ()=>{ // отмена отправки, очищаем выделение, удаляем временное избранное //$('.tmp-fav').remove(); if(AZ.resetSelection) AZ.resetSelection(); if(params.onFail) params.onFail(); }; }; //Специальные функции для разного вида избранного, формируют уникальный ключ и параметры, передают их updateFavorite() AZ.updateFavorite = {}; // Добавить в избранное главу AZ.updateFavorite['chapter'] = ($item)=>{ resetFavVars(); let chapterNumber = $item[0].dataset['chapter'], label = $item[0].dataset['label'] ?? AZ.book_title+", глава "+chapterNumber; updateFavorite({ 'item':$item, 'kind':'chapter', 'target':{ 'bookSlug':AZ.book_slug, chapterNumber, label, }, label, 'link': '?'+AZ.bibLink( { 'text':{'book':AZ.book_slug, 'chapter':chapterNumber } } ), }); } let getVersesByFav = (fav)=>{ return $('.verse[data-fav-id='+fav.attr('data-id')+']'); }, getFavByVerse = (verse)=>{ return $('.favorite[data-id="' + verse.attr('data-fav-id') + '"]'); }; // Добавить выделенные стихи в избранное AZ.updateFavorite['verses'] = (fav)=>{ resetFavVars(); let selected = null; let newFav = false; if(fav){ //favorite задан selected = getVersesByFav(fav); }else{ // пробуем найти favorite по выбранным стихам selected = $('.verse.selected'); if(selected.is('[data-fav-id]')){ fav = getFavByVerse(selected); if(fav && fav.length) selected = getVersesByFav(fav); } } if(!selected.length){ AZ.alert('Ничего не выбрано'); return; } //Для days и, возможно, других проблемных мест - берём данные о книге из родительской tbl-content if(!AZ.book_slug || AZ.book_slug == ''){ AZ.book_slug = selected.closest('.tbl-content').attr('data-book-slug'); } if(!AZ.book_abbr || AZ.book_abbr == '') AZ.getBookAbbr(selected); if(!fav || !fav.length){ //блока избранного нет -- создадим fav = $($('#favorite_template').html()); fav.addClass('tmp-fav'); fav.attr('data-color', lsGet('fav_color') ?? 0); //выставляем последний использованный цвет newFav = true; } // Если не задано сокращённое название книги, ищем его внутри, либо снаружи (атрибут .tbl-content data-book-abbreviation) label = ( AZ.book_abbr ?? fav.find('[data-book-abbr]').attr('data-book-abbr')) + AZ.versesToText(selected, {'url':false, 'book_slug':false}); let target = {}; target.verses=[]; selected.each((i,el)=>{ target.verses.push(el.dataset['verse']); //формируется массив стихов }); target.lang = selected[0].dataset['lang']; target.label = label; if(AZ.resetSelection) AZ.resetSelection(); updateFavorite({ 'item':fav, 'kind':'verses', target, label, 'link': '?'+AZ.versesToText(selected, {'url':false, 'book_slug':true, 'short':true}), 'onSuccess': res=>{ //обновить связанные стихи и добавить избранное selected.attr('data-fav-id', fav.attr('data-id')).attr('data-fav-color', fav.attr('data-color')); if(newFav) selected.eq(0).prepend(fav); }, }); }; // Добавить толкование в избранное AZ.updateFavorite['interp'] = (item)=>{ resetFavVars(); let interpId = item[0].dataset['interp'], label = item[0].dataset['label']; link = item[0].dataset['link']; updateFavorite({ item, 'kind':'interp', 'target':{ interpId, label }, label, link, }); }; //Унивесальное добавление в зависимости от вида (для ЛК) AZ.updateFavoriteByItem = item => { updateMode = true; AZ.updateFavorite[item.attr('data-kind')](item); } //Удаление из избранного AZ.removeFavorite = (item, onYes, onNo, force = false)=>{ item = $(item); if(!item.length) item = favData.item; let doRemove = ()=>{ let data = { 'favorite': item.attr('data-id'), }; AZ.ajax( 'user_delete_favorite', data, function(res){ let rel_verses = $('.verse[data-fav-id="'+item.attr('data-id')+'"]').removeAttr('data-fav-id').removeAttr('data-fav-color'); resetFavorite(item); if(onYes) onYes(); }, onNo, onNo ); }; if(AZ.options['confirm_fav_remove'] && !force) AZ.confirm('Удалить из избранного?', doRemove, ''); else doRemove(); }; //Обнуление блока favorite после удаления function resetFavorite(item){ if(item.parents('.verse').length) item.remove(); else{ item.removeAttr('data-color').removeAttr('data-id').removeClass('has-fav').addClass('no-fav'); item.find('.tag-container, .comment').empty(); } } //перключатель цветов $('.popup .color-swatch').on('click', function (e) { let $this = $(this); $('.popup .color-swatch').removeClass('active icon-check'); $this.addClass('active icon-check'); }) //Создание тэгов let inputTag = e=>{ let $tagInput = $('#add_fav_tag_input'); if ($tagInput.val().length !== 0) { insertTag('#add_fav_tag_container', $.trim($tagInput.val()), true); } $tagInput.val(''); }; $('#add_fav_tag_btn').on('click', inputTag); $('#add_fav_tag_input').on('input change', function (e){ //$('#add_fav_tag_btn').toggleClass('active', !!this.value); if(this.value.includes(' ')){ inputTag(); } }); $('#add_fav_tag_input').on('keydown', function(e){ if( event.key == "Backspace" && this.value==""){ //backspace $('#add_fav_tag_container .tag').last().remove(); }else if(event.key == "Enter"){ //enter inputTag(); } }); //Добавление тэгов из списка $('#add_fav_user_tag_container .tag').on( 'click', function (e) { insertTag('#add_fav_tag_container', $(this).attr('data-tag'), true); }); //Отправка избранного на сервер после редактирования и обновление текущего блока favorite $('#add_fav_save').on( 'click', function (e) { let $this = $(this); if ($this.attr('data-disabled') === 'true') { return; } //считывание данных из формы let color = $('#add_fav_colors .active').attr('data-id'); inputTag();//на случай если человек ввёл тэг в поле и не нажал "плюс" let tags = []; $('#add_fav_tag_container .tag').each(function (i, element) { tags.push(element.dataset['tag']); }); let content = $('#fav_content').val() ?? null; //подготовка данных к отправке //при обновлении существующего избранного достаточно ссылки и обязательных параметров let data = updateMode ? { tags: tags, color: color, content: content, link: favData.item.attr('data-link') ?? favData.link, } : { tags: tags, color: color, content: content, book: favData.book ?? AZ.book_slug ?? favData.item.attr('data-book'), link: favData.link, kind: favData.kind, target: favData.target, }; //перенос из favData в data /*for(thing of ['kind']){ if(favData[thing]) data[thing] = favData[thing]; }*/ //Сохраним данные для обновления DOM после успешной отправки favData = $.extend(favData, data); //отправка $this.addClass('disabled'); AZ.ajax('user_add_favorite', data, afterAddFavorite, null, ()=>{ $this.removeClass('disabled'); updateMode = false; } ); }); // Обновление DOM после успешной отправки function afterAddFavorite(res){ console.log('afterAddFavorite', res, favData); AZ.notify('Сохранено'); let item = favData.item.addClass('has-fav').removeClass('no-fav tmp-fav'); if(res.id) item.attr('data-id', res.id); item.attr('data-color', favData.color); //обновим тэги в блоке favorite let tagCont = item.find('.tag-container'); tagCont.empty(); for(let tag of favData.tags){ AZ.insertTag(tagCont, tag, false); }; item.find('.comment').html(favData.content); //after -- можно повесить функцию обновления связанных элементов if(favData.onSuccess) favData.onSuccess(res); } //Универсальное добавление тэга в контейнер function insertTag(container, tag = null, withRemove = false) { let $tagContainer = $(container); let tags = []; $tagContainer.find('.tag').each(function (i, element) { tags.push(String($(element).attr('data-tag'))); }) if (tag !== null && tag !== 0) { tags.push(String(tag)); } tags = tags.filter((v, i, a) => a.indexOf(v) === i); if (tags.length !== 0) { let html = ''; tags.forEach(function (element, i) { html += '' + element + ''; }) $tagContainer.html(html); if($tagContainer.is('.tag-scroller')){ $tagContainer.animate({'scrollLeft':9999}, 300); } } } AZ.insertTag = insertTag; function getBookData(){ return { 'book':AZ.book_slug, 'title':AZ.book_title, 'abbr':AZ.book_abbr, }; } //Назначение кликов в интерфейсе книги // Добавить в избранное выделенные стихи $('.selection-menu .add-fav').on('click', ()=>AZ.updateFavorite['verses']()); // Chapter Note AZ.body.on('click', '.chapter-title .fav-edit, .title-container .fav-edit' , function (e) { AZ.updateFavorite['chapter']($(this).closest('.favorite')); }); // редактировать избранные стихи $(AZ.body).on('click', '.verse .fav-edit', function(){ AZ.updateFavorite['verses']($(this).closest('.favorite')); }); // добавит/редактировать избранное толкование $(AZ.body).on('click', '.interpretation .fav-edit', function(){ AZ.updateFavorite['interp']($(this).closest('.favorite')); }); // удалить избранное $(AZ.body).on('click', '.fav-remove', function(){ AZ.removeFavorite($(this).closest('.favorite')); }); });

Org.robodk.app.sharex Vybor-imeni-rebenka Samoobolshhenie Hola-fake-gps-guia-on-pc Speedway-challenge-2023-on-pc