1(function () { 2 'use strict'; 3 4 var ru = location.pathname === '/ru' || location.pathname.startsWith('/ru/'); 5 6 function normalizedLetter(value) { 7 return String(value || '') 8 .trim() 9 .charAt(0) 10 .normalize('NFD') 11 .replace(/[\u0300-\u036f]/g, '') 12 .toLocaleUpperCase(ru ? 'ru-RU' : 'en-US'); 13 } 14 15 function closeExpanded(record) { 16 record.querySelectorAll('.t585__trigger-button[aria-expanded="true"]').forEach(function (button) { 17 button.click(); 18 }); 19 } 20 21 function splitComposerName(value) { 22 var parts = String(value || '').split(','); 23 return { 24 surname: (parts.shift() || '').trim(), 25 givenName: parts.join(',').trim() 26 }; 27 } 28 29 function composerInitials(value) { 30 return String(value || '') 31 .trim() 32 .split(/\s+/) 33 .filter(Boolean) 34 .map(function (part) { 35 return part.split('-').map(function (namePart) { 36 return namePart ? Array.from(namePart)[0].toLocaleUpperCase(ru ? 'ru-RU' : 'en-US') + '.' : ''; 37 }).join('-'); 38 }) 39 .join(' '); 40 } 41 42 function structureEntry(accordion, title) { 43 var titleNode = accordion.querySelector('.t585__title'); 44 var textWrapper = accordion.querySelector('.t585__textwrapper'); 45 var text = accordion.querySelector('.t585__text'); 46 var name = splitComposerName(title); 47 48 if (titleNode) { 49 titleNode.textContent = ''; 50 51 var surname = document.createElement('span'); 52 surname.className = 'ln-repertoire-composer__surname'; 53 surname.textContent = name.surname + (name.givenName ? ' ' + composerInitials(name.givenName) : ''); 54 titleNode.appendChild(surname); 55 } 56 57 if (textWrapper && text && !textWrapper.querySelector('.ln-repertoire-programme__label')) { 58 var label = document.createElement('div'); 59 label.className = 'ln-repertoire-programme__label'; 60 label.textContent = ru ? 'ÐÐ ÐÐÐ ÐÐÐÐ' : 'PROGRAMME'; 61 textWrapper.insertBefore(label, text); 62 } 63 } 64 65 function removeCategorySwitch() { 66 document.querySelectorAll('.r[data-record-type="1363"]').forEach(function (record) { 67 var text = record.textContent || ''; 68 var isEnglishSwitch = /orchestral/i.test(text) && /operas/i.test(text); 69 var isRussianSwitch = /оÑкеÑÑÑов/i.test(text) && /опеÑн/i.test(text); 70 if (isEnglishSwitch || isRussianSwitch) record.remove(); 71 }); 72 } 73 74 function removeContactBlock() { 75 ['rec1919870581', 'rec1919870961', 'rec1919872111', 'rec1919957721'].forEach(function (id) { 76 document.getElementById(id)?.remove(); 77 }); 78 document.querySelectorAll('.ln-contact').forEach(function (section) { 79 section.remove(); 80 }); 81 } 82 83 function accordionTitle(accordion) { 84 return accordion.querySelector('.t585__title')?.textContent.trim() || ''; 85 } 86 87 function findAccordion(record, composer) { 88 return Array.from(record.querySelectorAll('.t585__accordion')).find(function (accordion) { 89 return accordionTitle(accordion) === composer; 90 }); 91 } 92 93 function setAccordionWorks(accordion, works) { 94 var list = accordion.querySelector('.t585__text ul'); 95 if (!list) return; 96 list.textContent = ''; 97 works.forEach(function (work) { 98 var item = document.createElement('li'); 99 item.dataset.list = 'bullet'; 100 item.textContent = work; 101 list.appendChild(item); 102 }); 103 } 104 105 function bindLocalAccordion(accordion) { 106 var button = accordion.querySelector('.t585__trigger-button'); 107 var header = accordion.querySelector('.t585__header'); 108 var content = accordion.querySelector('.t585__content'); 109 if (!button || !header || !content) return; 110 button.addEventListener('click', function () { 111 var expanded = button.getAttribute('aria-expanded') === 'true'; 112 button.setAttribute('aria-expanded', String(!expanded)); 113 header.classList.toggle('t585__opened', !expanded); 114 content.hidden = expanded; 115 content.style.display = expanded ? 'none' : 'block'; 116 content.style.maxHeight = expanded ? '' : content.scrollHeight + 'px'; 117 }); 118 } 119 120 function buildColumn(template, composer, works, uid) { 121 var column = template.closest('.t-col').cloneNode(true); 122 var accordion = column.querySelector('.t585__accordion'); 123 var title = accordion.querySelector('.t585__title'); 124 var button = accordion.querySelector('.t585__trigger-button'); 125 var content = accordion.querySelector('.t585__content'); 126 var text = accordion.querySelector('.t585__text'); 127 128 title.textContent = composer; 129 title.setAttribute('field', 'ln_title_' + uid); 130 text.setAttribute('field', 'ln_descr_' + uid); 131 button.setAttribute('aria-controls', uid); 132 button.setAttribute('aria-expanded', 'false'); 133 content.id = uid; 134 content.hidden = true; 135 content.style.display = 'none'; 136 setAccordionWorks(accordion, works || []); 137 bindLocalAccordion(accordion); 138 return column; 139 } 140 141 function addAccordion(record, section, update, updateIndex) { 142 var before = update.insertBefore ? findAccordion(record, update.insertBefore) : null; 143 var template = before || record.querySelector('.t585__accordion'); 144 if (!template) return null; 145 146 var uid = 'ln-repertoire-' + (ru ? 'ru' : 'en') + '-' + section + '-' + updateIndex; 147 var column = buildColumn(template, update.composer, update.works, uid); 148 149 var beforeColumn = before?.closest('.t-col'); 150 record.querySelector('.t-container').insertBefore(column, beforeColumn || null); 151 return column.querySelector('.t585__accordion'); 152 } 153 154 function applyRepertoireUpdates(record, section) { 155 var dataNode = document.getElementById('ln-repertoire-updates'); 156 if (!dataNode) return; 157 158 var updates; 159 try { 160 updates = (JSON.parse(dataNode.textContent)[ru ? 'ru' : 'en'] || []).filter(function (update) { 161 return (update.section || 'orchestral') === section; 162 }); 163 } catch (error) { 164 return; 165 } 166
167 updates.forEach(function (update, updateIndex) { 168 var accordion = findAccordion(record, update.composer) 169 || (update.works ? addAccordion(record, section, update, updateIndex) : null); 170 if (!accordion) return; 171 172 var works = Array.from(accordion.querySelectorAll('.t585__text li')).map(function (item) { 173 return item.textContent.trim(); 174 }); 175 176 Object.entries(update.replace || {}).forEach(function (entry) { 177 var index = works.indexOf(entry[0]); 178 if (index < 0) return; 179 var replacement = Array.isArray(entry[1]) ? entry[1] : [entry[1]]; 180 works.splice.apply(works, [index, 1].concat(replacement)); 181 }); 182 183 Object.entries(update.appendAfter || {}).forEach(function (entry) { 184 var index = works.indexOf(entry[0]); 185 var additions = Array.isArray(entry[1]) ? entry[1] : [entry[1]]; 186 additions.forEach(function (work, offset) { 187 if (!works.includes(work)) works.splice(index < 0 ? works.length : index + 1 + offset, 0, work); 188 }); 189 }); 190 191 (update.append || []).forEach(function (work) { 192 if (!works.includes(work)) works.push(work); 193 }); 194 setAccordionWorks(accordion, works); 195 }); 196 } 197 198 // Раздел «ÐалеÑÑ» в зеÑкале ТилÑÐ´Ñ Ð¾ÑÑÑÑÑÑвÑеÑ: на ÑайÑе еÑÑÑ ÑолÑко 199 // оÑкеÑÑÑовÑй и опеÑнÑй блоки. ÐоÑÑÐ¾Ð¼Ñ ÑÑеÑий блок ÑобиÑаеÑÑÑ Ð¸Ð· копии 200 // опеÑного â Ñак он полÑÑÐ°ÐµÑ ÑÑ Ð¶Ðµ вÑÑÑÑкÑ, Ñе же бÑейкпоинÑÑ Ð¸ ÑÐ¾Ñ Ð¶Ðµ 201 // заголовок-зеÑоблок, а не пÑиблизиÑелÑное повÑоÑение ÑÑками. 202 function cloneTildaRecord(source, newRecordId) { 203 var oldRecordId = source.id.replace('rec', ''); 204 var clone = source.cloneNode(true); 205 206 (function rewrite(node) { 207 Array.from(node.attributes || []).forEach(function (attribute) { 208 if (attribute.value.includes(oldRecordId)) { 209 node.setAttribute(attribute.name, attribute.value.split(oldRecordId).join(newRecordId)); 210 } 211 }); 212 if (node.tagName === 'STYLE') { 213 node.textContent = node.textContent.split(oldRecordId).join(newRecordId); 214 } 215 Array.from(node.children).forEach(rewrite); 216 }(clone)); 217 218 // ÐнÑÑÑенние иденÑиÑикаÑоÑÑ Ð·ÐµÑоблока (molecule-â¦) в Ð½Ð¾Ð¼ÐµÑ Ð·Ð°Ð¿Ð¸Ñи не Ð²Ñ Ð¾Ð´ÑÑ, 219 // поÑÑÐ¾Ð¼Ñ Ð² копии они повÑоÑилиÑÑ Ð±Ñ. ÐеÑеименовÑваем Ð¸Ñ Ð²Ð¼ÐµÑÑе Ñо ÑÑÑлками 220 // на Ð½Ð¸Ñ Ð² ÑÑилÑÑ Ð±Ð»Ð¾ÐºÐ°. 221 var styles = Array.from(clone.querySelectorAll('style')); 222 clone.querySelectorAll('[id]').forEach(function (node) { 223 if (!document.getElementById(node.id)) return; 224 var renamed = node.id + '-' + newRecordId; 225 styles.forEach(function (style) { 226 style.textContent = style.textContent.split('#' + node.id).join('#' + renamed); 227 }); 228 node.id = renamed; 229 }); 230 231 // СкÑипÑÑ Ð¢Ð¸Ð»ÑÐ´Ñ Ð² копии не вÑполнÑÑÑÑ, а зеÑоблок иниÑиализиÑÑем вÑÑÑнÑÑ. 232 clone.querySelectorAll('script').forEach(function (script) { script.remove(); }); 233 return clone; 234 } 235 236 var lastRecordId = 1900000000; 237 238 function nextRecordId() { 239 do { lastRecordId += 1; } while (document.getElementById('rec' + lastRecordId)); 240 return String(lastRecordId); 241 } 242 243 function initZeroBlock(recordId) { 244 if (typeof window.t_onFuncLoad !== 'function') return; 245 window.t_onFuncLoad('t396_initialScale', function () { window.t396_initialScale(recordId); }); 246 window.t_onFuncLoad('t396_init', function () { window.t396_init(recordId); }); 247 } 248 249 function createBalletsSection(operasRecord) { 250 var dataNode = document.getElementById('ln-repertoire-updates'); 251 if (!dataNode || !operasRecord) return null; 252 253 var section; 254 try { 255 section = (JSON.parse(dataNode.textContent).ballets || {})[ru ? 'ru' : 'en']; 256 } catch (error) { 257 return null; 258 } 259 if (!section || !Array.isArray(section.entries) || !section.entries.length) return null; 260 261 var operasHeading = operasRecord.previousElementSibling; 262 var template = operasRecord.querySelector('.t585__accordion'); 263 if (!template || !operasHeading || operasHeading.dataset.recordType !== '396') return null; 264 265 var headingId = nextRecordId(); 266 var heading = cloneTildaRecord(operasHeading, headingId); 267 var headingTitle = Array.from(heading.querySelectorAll('.tn-atom')).find(function (atom) { 268 return atom.textContent.trim(); 269 }); 270 if (headingTitle) headingTitle.textContent = section.heading; 271 272 var record = cloneTildaRecord(operasRecord, nextRecordId()); 273 delete record.dataset.localRepertoire; 274 var container = record.querySelector('.t-container'); 275 container.textContent = '';
276 section.entries.forEach(function (entry, index) { 277 var uid = 'ln-repertoire-ballet-' + (ru ? 'ru' : 'en') + '-' + index; 278 container.appendChild(buildColumn(template, entry.composer, entry.works, uid)); 279 }); 280 281 operasRecord.parentNode.insertBefore(heading, operasRecord.nextSibling); 282 heading.parentNode.insertBefore(record, heading.nextSibling); 283 initZeroBlock(headingId); 284 return record; 285 } 286 287 function createDownloadSection(record) { 288 var section = document.createElement('section'); 289 section.className = 'ln-repertoire-download-section'; 290 section.innerHTML = '<div class="ln-repertoire-download-section__inner">' 291 + '<a class="ln-repertoire-filter__download" href="/downloads/liubov-nosova-repertoire-' 292 + (ru ? 'ru' : 'en') + '.pdf" download>' 293 + '<span>' + (ru ? 'СÐÐЧÐТЬ ÐÐÐÐЫРРÐÐÐРТУÐÐ (PDF)' : 'DOWNLOAD FULL REPERTOIRE (PDF)') + '</span>' 294 + '<span class="ln-repertoire-filter__download-icon" aria-hidden="true">' 295 + '<span class="ln-repertoire-filter__download-icon-arrow"></span></span>' 296 + '</a></div>'; 297 298 var categoryHeading = record.previousElementSibling; 299 record.parentNode.insertBefore(section, categoryHeading || record); 300 } 301 302 function enhance(record, recordIndex) { 303 if (record.dataset.localRepertoire === 'ready') return; 304 305 var entries = Array.from(record.querySelectorAll('.t585__accordion')).map(function (accordion) { 306 var title = accordion.querySelector('.t585__title')?.textContent.trim() || ''; 307 structureEntry(accordion, title); 308 return { 309 item: accordion.closest('.t-col'), 310 letter: normalizedLetter(title) 311 }; 312 }).filter(function (entry) { 313 return entry.item && entry.letter; 314 }); 315 if (!entries.length) return; 316 317 var letters = Array.from(new Set(entries.map(function (entry) { return entry.letter; }))); 318 var filter = document.createElement('section'); 319 filter.className = 'ln-repertoire-filter'; 320 filter.setAttribute('aria-label', ru ? 'ФилÑÑÑ ÐºÐ¾Ð¼Ð¿Ð¾Ð·Ð¸ÑоÑов по алÑавиÑÑ' : 'Filter composers by letter'); 321 filter.innerHTML = '<div class="ln-repertoire-filter__inner">' 322 + '<div class="ln-repertoire-filter__alphabet" role="group"></div>' 323 + '</div>'; 324 325 var alphabet = filter.querySelector('.ln-repertoire-filter__alphabet'); 326 alphabet.innerHTML = letters.map(function (letter) { 327 return '<button class="ln-repertoire-filter__button" type="button" data-letter="' 328 + letter + '" aria-pressed="false">' + letter + '</button>'; 329 }).join(''); 330 331 record.insertBefore(filter, record.firstChild); 332 record.classList.add('ln-repertoire-record'); 333 record.dataset.localRepertoire = 'ready'; 334 335 if (recordIndex === 0) createDownloadSection(record); 336 337 entries.forEach(function (entry) { 338 entry.item.dataset.repertoireLetter = entry.letter; 339 }); 340 341 function select(letter) { 342 closeExpanded(record); 343 alphabet.querySelectorAll('button').forEach(function (button) { 344 button.setAttribute('aria-pressed', String(button.dataset.letter === letter)); 345 }); 346 entries.forEach(function (entry) { 347 entry.item.classList.toggle('ln-repertoire-record__hidden', entry.letter !== letter); 348 }); 349 } 350 351 alphabet.addEventListener('click', function (event) { 352 var button = event.target.closest('[data-letter]'); 353 if (!button) return; 354 select(button.dataset.letter); 355 }); 356 357 filter.id = 'ln-repertoire-filter-' + recordIndex; 358 select(letters[0]); 359 } 360 361 function init() { 362 removeCategorySwitch(); 363 removeContactBlock(); 364 var records = Array.from(document.querySelectorAll('.r[data-record-type="585"]')); 365 // ÐÐ¾Ð¿Ð¸Ñ Ð´Ð»Ñ Â«ÐалеÑов» Ñнимаем до пÑавок и оÑоÑÐ¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑного блока, 366 // ÑÑÐ¾Ð±Ñ Ð² Ð½ÐµÑ Ð½Ðµ попали ни ÑилÑÑÑ Ð¿Ð¾ алÑавиÑÑ, ни ÑÑжие аккоÑдеонÑ. 367 var ballets = createBalletsSection(records[1]); 368 369 records.forEach(function (record, recordIndex) { 370 applyRepertoireUpdates(record, recordIndex === 0 ? 'orchestral' : 'operas'); 371 enhance(record, recordIndex); 372 }); 373 374 if (ballets) enhance(ballets, records.length); 375 } 376 377 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); 378 else init(); 379}());
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.