Book design is the art of incorporating the content, style, format, design, and sequence of the various components of a book into a coherent whole. In the words of Jan Tschichold, "methods and rules upon which it is impossible to improve, have been developed over centuries. To produce perfect books, these rules have to be brought back to life and applied."
Front matter, or preliminaries, is the first section of a book and is usually the smallest section in terms of the number of pages. Each page is counted, but no folio or page number is expressed or printed, on either display pages or blank pages.

<!--Основная карта-->
<div id='map-main' class="map-main"></div>

<!--Карты по секторам-->
<div id='map-sector-a'  class="map-sector-a"></div>
<div id='map-sector-b'  class="map-sector-b"></div>
<div id='map-sector-c'  class="map-sector-c"></div>
<div id='map-sector-d'  class="map-sector-d"></div>
<div id='map-sector-e'  class="map-sector-e"></div>
<div id='map-sector-f'  class="map-sector-f"></div>
<div id='map-sector-g'  class="map-sector-g"></div>
<div id='map-sector-h'  class="map-sector-h"></div>
<div id='map-sector-j'  class="map-sector-j"></div>
<div id='map-sector-k'  class="map-sector-k"></div>
<div id='map-sector-l'  class="map-sector-l"></div>


<!--Форма-->
<a href="#popup:parkform" class="popuplink"></a>
<a href="#popup:alertform" class="popupalert"></a>

<script>

// Загрузка основной карты
$.get('https://310401.selcdn.ru/MIXED/SVG/main_map.svg', function(data) {  let svg =  $(data).find('svg')[0];  $('#map-main').html(svg);});

// Загрузка A - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_a.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-a').html(svg); });
// Загрузка B - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_b.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-b').html(svg); });
// Загрузка C - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_c.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-c').html(svg); });
// Загрузка D - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_d.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-d').html(svg); });
// Загрузка E - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_e.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-e').html(svg); });
// Загрузка F - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_f.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-f').html(svg); });
// Загрузка G - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_g.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-g').html(svg); });
// Загрузка H - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_h.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-h').html(svg); });
// Загрузка J - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_j.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-j').html(svg); });
// Загрузка К - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_k.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-k').html(svg); });
// Загрузка L - карты
$.get('https://310401.selcdn.ru/MIXED/SVG/sector_l.svg', function(data) {  let svg =  $(data).find('svg')[0]; $('#map-sector-l').html(svg); });


// При нажатии на сектор основной карты
$(document).on('click', 'g[id^="main_map_"]', function(){
    $('#map-main').hide(500);//Скрываем основную карту
    
    let letter = $(this).attr('id');
    letter = letter.split('_')[2];
    letter = letter.toLowerCase();

    $('#map-sector-'+letter).show(500);//Показываем нужную карту
    $('.uc-back').show(0);//Показываем кнопку назад
});

// При нажатии на кнопку назад
$(document).on('click', '.uc-back .back-btn', function(){
    $('div[id^="map-sector-"]').hide(500); //Скрываем все карты
    $('#map-main').show(500); //Показываем основную карту
    $('.uc-back').hide(0); //Скрываем кнопку назад
});


$( document ).ready(function() {

$('.uc-park-form .t702__text-wrapper').append('<div class="place-wrapper t-text"></div>');
$('.uc-park-form .t-submit:first').attr('type', 'button');
$('.call-btn').addClass('parked-already');

let placeLimit = 10;

//Сбор всех выбранных парковочных места
function collectParkPlace(){
    let places = '';
    let placesBox = '';
    
    $('.place-wrapper').html('');
    
    $('.parked').each(function(){
        let parent = $(this);

        let parkplace = parent.find('[id^="place_"]').attr('id');
        let color = parent.find('[id^="place_"]').attr('fill');

        parkplace = parkplace.split('_')[1];

        parkplace = parkplace.toUpperCase(); 
        places += parkplace+'; ';
        
        placesBox +=`
            <div class="place-box" data-key-box="${parkplace}" style="background:${color}" ><span>${parkplace}</span> <div class="park-close-icon"></div></div>
        `;
        
    });
    
    $('input[name="park-place"]').val('Место: '+places);
    $('.place-wrapper').append(placesBox);
    //$('.popuplink')[0].click();
    
};

// При выборе парковочного места
$(document).on('click', 'g[id^="sector_"]>g , #sector_c', function(){
    let chsPlace = $('.parked').length;
        let parent = $(this);
        
        let parkplace = parent.find('[id^="place_"]').attr('id');
        
        parkplace = parkplace.split('_')[1];
        parkplace = parkplace.toUpperCase();
    
        if( parent.attr('class') == 'parked' ){
            parent.removeAttr('class');
            collectParkPlace();
        }else{
            if(chsPlace<placeLimit){
                parent.attr('class','parked');  
                collectParkPlace();
            }else{
                $('.t390__descr').html('Не больше 10-ти мест в одном заказе');
                $('.popupalert')[0].click();
            };    

        };
        
        if( $('.parked').length>0 ){
            $('.call-btn').removeClass('parked-already');
        }else{
            $('.call-btn').addClass('parked-already');
        };
});

// При удалении парковочного места из формы  
$(document).on('click', '.park-close-icon', function(){
    //Получаем код парковки из описания соседа
    let parkCode = $(this).prev('span').html().toLowerCase();
    //Ищем этот элемент на картах
    
    $('#place_'+parkCode).closest('g').removeAttr('class');
    $('#place_'+parkCode.toUpperCase()).closest('g').removeAttr('class');
    
    
    collectParkPlace();
});

let dataIDList = {};
let dataParkList = {};
let dataIDListParked = [];
let pushData = false;
let goClick = true;  

//Список литер от всех таблиц AT
let dataKeyTable = ['A', 'B1', 'B2', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L'];


//Полчучаем данные из AirTable
function getAirTableLikes(){
        dataIDListParked = [];
        let count = 1;
        $.each( dataKeyTable , function(imm, nmm){

            (function(){
                let url = "https://api.airtable.com/v0/appiYBYvEdbv4FANX/Park_"+nmm;
                let xhr = new XMLHttpRequest(); xhr.open("GET", url);
                xhr.setRequestHeader("Authorization", "Bearer keykltFv8keJC1QS1");
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        let data = JSON.parse(xhr.responseText);
                        
                        for (let i = 0; i < data.records.length; i++) {
                            dataIDList[data.records[i].fields.ParkName] = data.records[i].id;
                            dataParkList[data.records[i].id] = data.records[i].fields.ParkName;
                            let parkName = data.records[i].fields.ParkName;
                            let parked = data.records[i].fields.Parked;

                            if(parked!=undefined){

                                dataIDListParked.push(data.records[i].id);
                                $('#place_'+parkName.toLowerCase()).closest('g').attr('class','parked-already');
                                $('#place_'+parkName).closest('g').attr('class','parked-already');
                            };
                        };
                        
                        //Если нажали кнопку отправки и собрали данные из всех таблиц AirTable
                        if(pushData &&  count==(dataKeyTable.length) ) {
                            pushData = false;
                            //Запускаем обновление данных в AirTable
                            updateAirTableLikes();
                        };
                        count++;
                        
 
                   }};
                xhr.send();
            })(); 
            
            
        });
     
};

//Обновляем данные в AirTable
function updateAirTableLikes(){
    let idList = {};
    let finData = '';
    let codeArr = [];
    
    //Собираем все выбранные пользователем места
    $('.place-box').each(function(){
        let code = $(this).find('span').text(); //Вынимаем номер места из бокса
        
        let lt = code.replace(/[0-9]/g, ''); //Удаляем цифры и получаем только букву
        let num = code.replace(/[^0-9\.]/g, '');//Удаляем буквы  и получаем только цифру
    
        //Проверка для сектора B
        if(lt=='B'){
            lt = 'B1';
            if(num>60) lt = 'B2';
        };

        codeArr.push(lt); //Помещаем букву в массив
        idList[code] =  dataIDList[code];
        
    });
    
    
    
    //Формируем массив только из букв секторов выбранных мест
    let uniquecodeArr = [];
    $.each(codeArr, function(i, el){
        if($.inArray(el, uniquecodeArr) === -1) uniquecodeArr.push(el);
    });
    
    
    
    let fPartData = `{  "records": [`;
    let lPartData = `]}`;
    
    let matchCodes = '';
    let match = false;
    
    let sendObj = {};
    
    
    
    //Делаем перебор по буквам выбранных секторов
    $.each(uniquecodeArr, function(key, value){
        
        let mPartData = '';
        //Делаем перебор по ID выбранных мест на всех секторах
        $.each(idList, function(let, rec){
            //Извлекаем букву сектора
            let letter = let.replace(/[0-9]/g, '');
            let num = let.replace(/[^0-9\.]/g, '');//Удаляем буквы  и получаем только цифру
    
            //Проверка для сектора B
            if(letter=='B'){
                letter = 'B1';
                if(num>60) letter = 'B2';
            };
            
            //Если буква текущего места совпадает с секторам, что сейчас  на рассмотрении
            
            
            if(value==letter){
                //Формируем среднюю часть данных для данного сектора
                mPartData += `{
                    "id": "${rec}",
                    "fields": {
                    "Parked": true
                    }
                },`;
            };

            //Проверяем, не заняли ли места, пока пользователь формирует заказ
            $.each(dataIDListParked , function(ind, vl) { 
                if(rec==vl) {
                    match = true;
                    //Формируем список занятых мест
                    matchCodes += dataParkList[vl]+'; '; 
                };
            });    
        });
        //Формируем данные для отправки по секторам
        sendObj[value] = fPartData + mPartData.slice(0,-1) + lPartData; ;
    
    });
;
    
    //Если какое-то из мест уже заняли
    if(match){
        //Выводим сообщение об ошибке со списком этих мест
        $('.uc-alertform .t390__descr').html('Эти места уже заняли: '+matchCodes);
        $('.popupalert')[0].click();
        
        //Удаляем из формы занятые места
        setTimeout(function(){
            matchCodes = matchCodes.replace(/\s+/g, '');
            matchCodes = matchCodes.slice(0,-1);
            matchCodes = matchCodes.split(';')
            
            $.each(matchCodes, function(key, value){
                $('.place-box[data-key-box="'+value+'"]').remove();
            });
     
        }, 1000);
  
    }else{          
                    
        //Если всё свободно, то запускаем цикл обновления данных            
        if(goClick){
            goClick=false;
            //Меняем тип кнопки на форме и запускаем штатную отправку данных            
            $('.uc-park-form .t-submit:first').attr('type', 'submit');
            $('.uc-park-form .t-submit').click();
            $('.uc-park-form .t-submit:first').attr('type', 'button');


            setTimeout(function(){
                //Если заполнено всё верно и форма ушла без ошибок
                if ( $('.uc-park-form .t-form').hasClass("js-send-form-success")){

                    //Отправляем только выбранные сектора
                    let count = 1;
                    $.each(sendObj, function(key, value){
                        let url2 =  "https://api.airtable.com/v0/appiYBYvEdbv4FANX/Park_"+key;
                        let xhr2 = new XMLHttpRequest(); xhr2.open("PATCH", url2);
                        xhr2.setRequestHeader("Accept", "application/json");
                        xhr2.setRequestHeader("Authorization", "Bearer keykltFv8keJC1QS1");
                        xhr2.setRequestHeader("Content-Type", "application/json");
                        xhr2.onreadystatechange = function () {
                        if (xhr2.readyState === 4) { 
                    
                            //Если завершили всю отправку данных в АТ
                            if(count == uniquecodeArr.length){
                                console.log('Reload');
                                //Перезагружаем страничку
                                window.setTimeout('location.reload()', 1000);     
                            };
                            count++;
                        }};
                    xhr2.send(value);
                    });
           
                //Если заполнено с ошибками
                }else{
                    setTimeout(function(){
                        goClick=true;  //Разрешаем повторную отправку формы
                        console.log('error:form empty');
                        }, 500);    
                };
      
            }, 1000);
                            
                            
        };
          
    };

};

setTimeout(function () {
    getAirTableLikes();
}, 500); 


//Отправка данных по событию
$('.uc-park-form .t-submit').click(function(){
    if(goClick){
        pushData = true;
        getAirTableLikes();
    };
});

$(document).on("keydown", ".t-form", function(event) {return event.key != "Enter";});

});
</script>


<style>

.back-btn{
    cursor: pointer;
}

g[id^="main_map_"] {transition: all 0.1s ease-in-out;cursor: pointer;}
g[id^="main_map_"]:hover {
    filter: drop-shadow(2px 4px 6px black);
}


g[id^="sector_"]>g,
g[id^="sector_"]>#place_C1{
    transition: all 0.1s ease-in-out;
    cursor: pointer;
}



g[id^="sector_"]>g:hover,
g[id^="sector_"]:hover>#place_C1{
    -webkit-filter: drop-shadow(0px 1px 1px black);
    -moz-filter: drop-shadow(0px 1px 1px black);
    filter: drop-shadow(0px 1px 1px black);
}

g.parked rect,
g.parked #place_C1
{
    fill: #FFEB3B;
}

g[id^="sector_"]>g:hover rect,
g[id^="sector_"]:hover>#place_C1{
    fill: #FFEB3B;
}



.place-wrapper {
    display: flex;
    flex-wrap: wrap;
    margin-top: 30px;
    margin-bottom: 30px;
}

.place-box {
    padding: 12px 10px;
    box-sizing: border-box;
    border: 1px solid #ababab;
    border-radius: 5px;
    min-width: 100px;
    margin-right: 10px;
    margin-bottom: 10px;
    position: relative;
}

.park-close-icon {
    width: 20px;
    height: 20px;
    background-image: url(https://static.tildacdn.com/tild3161-3336-4333-a133-356163366262/Group_6.svg);
    background-size: contain;
    position: absolute;
    top: -5px;
    right: -5px;
    z-index: 99;
    cursor: pointer;
}


div[id^="map-sector-"],
.uc-back {
  display: none;
}

.parked-already{
    opacity: 0.2;
    pointer-events: none;
}



div#map-main svg{
    width: 100%;
    height: 600px;
    min-width: 800px;
}


div[id^="map-sector-"] svg {
    height: 600px;
    width: 100%;
    overflow: visible;
    min-width: 800px;
}

div#map-main , div[id^="map-sector-"] {
    padding: 40px;
    overflow-x: auto;
}

</style>

Made on
Tilda