Как создать вложенный объект JSON, который отражает вложенную форму HTML? - PullRequest
0 голосов
/ 19 июня 2020

У меня есть форма с HTML, похожая на эту (обратите внимание, что она организована по вкладкам, необязательным наборам полей и элементам полей):

  • div.tab1
    • div.fieldset3
      • div.container308
      • div.container314
      • div.fieldset4
        • div.container309
        • div.container310
  • div.tab2
    • div.fieldset1
      • div.container311
      • div .fieldset2
        • div.container313
        • div.container312
  • div.tab3
    • div.container315
    • div.container316

Каждый div является контейнером для одного или нескольких элементов input, но для этого вопроса Я сосредотачиваюсь на контейнерах.

Я пытаюсь написать функцию JavaScript, которая будет "обходить" указанный элемент HTML и создавать объект JSON в этом формате (обратите внимание на вложение, которое формируется на основе вкладки, наборы полей и элементы ввода формы e):

   {
        "content": 
        [        
            {
                "type": "tab",
                "id": "left-defaults1",
                "order": 1,
                "content": 
                [
                    {
                        "id": "fieldset-3",
                        "order": 1,
                        "type": "fieldset",
                        "content": [
                            {
                                "id": "container308",
                                "order": 1,
                                "type": "field"
                            },
                            {
                                "id": "container314",
                                "order": 1,
                                "type": "field"
                            },        
                            {
                                "id": "fieldset-4",
                                "order": 1,
                                "type": "fieldset",
                                "content": [
                                    {
                                        "id": "container309",
                                        "order": 1,
                                        "type": "field"
                                    },
                                    {
                                        "id": "container310",
                                        "order": 1,
                                        "type": "field"
                                    }
                                ]
                            }
                        ]
                    },
                ]
            },        
            {
                "type": "tab",
                "id": "left-defaults2",
                "order": 2,
                "content": 
                [
                    {
                        "id": "fieldset-1",
                        "order": 1,
                        "type": "fieldset",
                        "content": [
                            {
                                "id": "container311",
                                "order": 1,
                                "type": "field"
                            },
                            {
                                "id": "fieldset-2",
                                "order": 1,
                                "type": "fieldset",
                                "content": [            
                                    {
                                        "id": "container313",
                                        "order": 1,
                                        "type": "field"
                                    },
                                    {
                                        "id": "container312",
                                        "order": 1,
                                        "type": "field"
                                    }
                                ]
                            }
                        ]
                    }
                ]
            },        
            {
                "type": "tab",
                "id": "left-defaults3",
                "order": 3,
                "content": 
                [
                    {
                        "id": "container315",
                        "order": 1,
                        "type": "field"
                    },
                    {
                        "id": "container316",
                        "order": 1,
                        "type": "field"
                    }
                ]
            }
        ]
    }

У меня возникли проблемы с прохождением второго «уровня». Я могу идентифицировать HTML элементы, которые нужно «пройти», и могу установить sh уровень «вкладки» в JSON объект. Я также могу поместить в него sh следующий уровень набора полей или элементов поля. Но помимо этого я сбиваюсь с пути; Я не знаю, как найти данный родительский слой третьего слоя (или четвертого слоя, или пятого, и т. Д. c) внутри объекта JSON.

Этот JavaScript является ядром этого попытка:

var createNestedJSON = function(){
    //establish JSON object
    var tab_order = 0,
        form_content_nested_and_ordered = {'content': []},
        element_ii_object = {};

    //so we can retrieve them in the order they exist in the page, class as "JSONMe" all the things we are going to want to represent in form_content_nested_and_ordered
    $('#fmWkflw').find('.tab-option-container').addClass('JSONMe').find('li').addClass('JSONMe');

    $('.JSONMe').each(function(element_index){
        var $this = $(this).data('JSON_id', element_index);
        console.log('tag:'+ this.tagName +', id:'+ this.id +', parentId: '+ $this.parent().prop('id') +', className: '+ this.className);

        if( this.tagName === 'UL' ){
            //this is a tab; add it
            form_content_nested_and_ordered["content"].push( {'type': 'tab', 'id': this.id, 'order': ++tab_order, 'content' : []} );
            console.log('added tab');
        }
        else {
            element_ii_object = {
                    'id': this.id,
                    'order': 1,
                    'type': 'field'
                };

            if( $this.hasClass('fieldset') ) {
                //this is a fieldset, so it has type "fieldset" and a "content" array
                element_ii_object.type = 'fieldset';
                element_ii_object.content = [];
            }

            console.log(element_ii_object);

            form_content_nested_and_ordered.content[ tab_order-1 ]['content'].push( element_ii_object );

            console.log('added '+ element_ii_object.type);
        };
    });

    /*
    form_content_nested_and_ordered["content"][getIndexIfObjWithOwnAttr(form_content_nested_and_ordered["content"], 'id', 2)]['content'].push( {'type': 'field', 'id': 14, 'order': 12} );
    form_content_nested_and_ordered["content"][getIndexIfObjWithOwnAttr(form_content_nested_and_ordered["content"], 'id', 1)]['content'].push( {'type': 'field', 'id': 23, 'order': 7} );
    form_content_nested_and_ordered["content"][getIndexIfObjWithOwnAttr(form_content_nested_and_ordered["content"], 'id', 1)]['content'].push( {'type': 'field', 'id': 24, 'order': 8} );
    */

    //tear down
    $('#fmWkflw').find('.JSONMe').data('JSON_id', 0).removeClass('.JSONMe');

    return form_content_nested_and_ordered;
};

Я попытался переключить передачи на использовать serializeArray() с reduce(), но взлетел, как свинцовый шар .

1 Ответ

1 голос
/ 19 июня 2020

Здравствуйте, насколько я понял, вам нужно делать там рекурсию, так как вы не знаете ее уровни, поэтому вот пример, sh это вам поможет.

Рекурсивное отображение Дерево

function copyTree(originalTree){
    return originalTree.map((elem, index) => ({
      id: 'div.'+elem.id,
      content: !elem.content ? [] : this.copyTree(elem.content),
    }));
  }

РЕДАКТИРОВАТЬ: Я неправильно понял, что вы хотели, вот что-то похожее на то, что вы ожидаете получить i wi sh, это может вам помочь.
Некоторые объяснение кода: я использую querySelectorAll, потому что он возвращает NodeList, с которым вы можете выполнять итерацию, причина [... arr] в том, что

он будет создавать массив из объекта, если объект является повторяемым. для дополнительных примеров go фильтр или карта NodeList

После этого я создаю функцию, которая будет вызывать рекурсивно, чтобы sh содержимое совпадений больше нет.

var getIndexIfObjWithOwnAttr = function(array, attr, value) {
    for(var i = 0; i < array.length; i++) {
        if(array[i].hasOwnProperty(attr) && array[i][attr] === value) {
            return i;
        }
    }
    return -1;
};

var createNestedJSON = function(){
	//establish JSON object
	var tab_order = 0,
		form_content_nested_and_ordered = {'content': []},
		element_ii_object = {};
	
	//so we can retrieve them in the order they exist in the page, class as "JSONMe" all the things we are going to want to represent in form_content_nested_and_ordered
	$('#fmWkflw').find('.tab-option-container').addClass('JSONMe').find('li').addClass('JSONMe')
	var htmltest = document.querySelectorAll('.JSONMe')

	form_content_nested_and_ordered = function (arr){
		return [...arr].map((elem, index) => ({
			type: elem.localName,
			id: elem.id,
			content: elem.children && elem.children.length>0 && (elem.localName ==='li' || elem.localName ==='ul' || elem.localName ==='fieldset') ? form_content_nested_and_ordered(elem.children) : [],
		  }));
	}
	//console.log(form_content_nested_and_ordered(htmltest))
	var filtered = form_content_nested_and_ordered(htmltest).filter((x)=>{
		return x.type == 'ul'
	})
	
	return filtered;
};

$('#formSubmit').click(function(){
	$('#resulting_JSON')[0].innerHTML = JSON.stringify(createNestedJSON());
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...