根据DOM结构排序包含对象的动态数组 [英] Sorting dynamic array which contains objects based on DOM structure

查看:86
本文介绍了根据DOM结构排序包含对象的动态数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于JSON数据更新的表。
表中的每一行都有一个复选框,它保存相应的JSON对象的值,这基本上是关于任何用户的信息。
在选择任何行,并保存以显示被添加到'div.container'的'div.parent'中的所选用户配置文件,我也将所选的JSON对象存储在数组'savedData' 。



现在,我有一些交换按钮,我可以用下一个或以前的'div.parent'交换每个'div.parent'。
所以,在交换时,DOM结构相应地改变。
但是,如何排序savedData数组,以便匹配交换顺序?例如,对于DOM中的第一个'div.parent',相应的对象应该在'savedData [0]'。同样,对于DOM中的第二个'div.parent',相应的对象应该在'savedData [1]'。



如何解决这个问题? p>

  function createTable(){$ .getJSON(https://api.randomuser ()(); data()(){var json = JSON.stringify()记录); $( '#数据表')附加($( '< TR>')。追加($( '< TD>'。)追加($( '<输入>'。)ATTR(类型','checkbox').addClass('selectRow').val(json)),$('< td>')。append($('< a> .picture.thumbnail).addClass('imgurl').attr('target','_blank').text(record.na me.first)),$(< TD>。)追加(record.dob))); })})。fail(function(error){console.log(********** AJAX ERROR:+ error);}); } var savedData = new Map; //按图片网址键入一开始就没有。函数saveData(){var errors = []; //添加选择映射$('input.selectRow:checked')。each(function(count){//获取存储为checkbox的值的JSON var obj = JSON.parse($(this).val ()); //看看这个URL是否已经被收集(这很容易使用Set)if(savedData.get(obj.picture.thumbnail)){errors.push(obj.name.first);} else {//附加它到地图:savedData.set(obj.picture.thumbnail,obj);}}); refreshDisplay(); if(errors.length){alert('以下内容已经被选中:\\\
'+ errors.join('\\\
')); }} function refreshDisplay(){$('。container')。html(''); saveData.forEach(function(obj){//重置容器,并附加收集的数据(使用jQuery进行追加)$('。container')。append($('< div>')addClass('parent' .append($('< label>')。addClass('dataLabel').text('Name:'),obj.name.first +''+ obj.name.last,$('< br& '),// name& pic $('< img>')之间的换行符addClass('myLink')。attr('src',obj.picture.thumbnail),$('< br> '',$('< label>')。addClass('dataLabel')。text('Date of birth:'),obj.dob,$('< br>'),$('< label> ;')。addClass('dataLabel')。text('Address:'),$('< br>'),obj.location.street,$('< br>'),obj.location.city +''+ obj.location.postcode,$('< br>'),obj.location.state,$('< br>'),$('< button>')addClass ')的.text(' 删除 '),$(' <按钮> ')addClass(' 顶部-b t(t)')text('Swap with top'),$('< button>')addClass('down-btn')。 })//清除复选框:$('。selectRow')。prop('checked',false); } function logSavedData(){//将Map转换为数组:var data = Array.from(savedData,function(pair){return pair [1];}); //转换为JSON并登录到控制台。你会把它//发布到一些URL,或将其保存到localStorage。 console.log(JSON.stringify(data,null,2)); } $(document).on('click','.removeMe',function(){var key = $('。myLink',$(this).parent())。attr('src'); //从保存的数据中删除此数据saveData.delete(key); //并重新显示refreshDisplay();}); / *在结果列表中交换显示的文章* / function resetEvents(){$(。top-btn,.down-btn)。unbind('click'); handleEvents(); $('。down(b)')。click(function(){var toMove1 = $(this).parents('。parent'); $(toMove1).insertAfter($(toMove1).next()); handleEvents ();}); $('。top-btn')。click(function(){var toMove1 = $(this).parents('。parent'); $(toMove1).insertBefore($(toMove1).prev()); handleEvents ();}); } / *禁用顶部&结果列表中第一个和最后一个文章的下拉按钮* / function handleEvents(){$(。top-btn,.down-btn)。prop(disabled,false).show(); $(。parent:first)。find(。top-btn)。prop(disabled,true).hide(); $(。parent:last)。find(。down-btn)。prop(disabled,true).hide(); } $(文件)。就绪(函数(){$( '#showExtForm-BTN')点击(函数(){$( '#extUser')切换();}); $( #extArticleForm) .submit(function(){addExtUser(); return false;});});

  table,th,td {border:1px solid #ddd;边界崩溃:崩溃padding:10px; } .parent {height:25%;宽度:90%;填充:1%;剩余左:1%;保证金:1%;边框:1px纯黑色; } .parent:nth-​​child(odd){background:skyblue; } .parent:nth-​​child(even){background:green; } label {float:left;宽度:80px; } input {width:130px; }  

 < button onclick =createTable()> ;创建表< / button> < table id =datatable> < TR><的第i;选择< /第><的第i;姓名< /第><的第i; DOB< /第>< / TR> < /表> < button onclick =saveData()>保存所选< / button> < br /> < div class =container>< / div> < button onclick =logSavedData()>获取保存的数据< / button>  

解决方案

如果您想保留特定的订单, Map 不合适。在这种情况下使用标准数组。那么这个优点就是这个数组正是你想以JSON导出的。缺点是,您需要迭代该数组以查看元素是否已被包含(例如, find )。



可以通过使用事件委托来简单地避免事件处理程序重新附加,就像您已经具有删除操作一样(使用 $(document).on 语法。



我建议不要直接在父div上执行交换,而是将它们应用于 savedData 数组,然后使用



查看下面的代码片段:



< pre class =snippet-code-js lang-js prettyprint-override> function createTable(){$ .getJSON(https://api.randomuser.me/?results=5,function (data){$('#datatable tr:has(td)')。remove(); data.results.forEach(function(record){ var json = JSON.stringify(record); $('#datatable')。append($('< tr>')。append($('< td> 'checkbox').addClass('selectRow').val(json)),$('< td>')。append($('< a>')。attr('href',record.picture。缩略图).addClass('imgurl').attr('target','_blank').text(record.name.first)),$('< td>')。append(record.dob))) })})。fail(function(error){console.log(********** AJAX ERROR:+ error);}); } var savedData = []; //对象为数组,所以要有一个order.function saveData(){var errors = []; //添加选择到数组$('input.selectRow:checked')。each(function(count){//获取存储为checkbox的值的JSON var obj = JSON.parse($(this).val ()); //看看这个URL是否已经被收集(这很容易使用Set)if(savedData.find(record => record.picture.thumbnail === obj.picture.thumbnail)){errors.push(obj .name.first);} else {//附加它savedData.push(obj);}}); refreshDisplay(); if(errors.length){alert('以下内容已经被选中:\\\
'+ errors.join('\\\
')); }} function refreshDisplay(){$('。container')。html(''); saveData.forEach(function(obj){//重置容器,并附加收集的数据(使用jQuery进行追加)$('。container')。append($('< div>')addClass('parent' .append($('< label>')。addClass('dataLabel').text('Name:'),obj.name.first +''+ obj.name.last,$('< br& '),// name& pic $('< img>')之间的换行符addClass('myLink')。attr('src',obj.picture.thumbnail),$('< br> '',$('< label>')。addClass('dataLabel')。text('Date of birth:'),obj.dob,$('< br>'),$('< label> ;')。addClass('dataLabel')。text('Address:'),$('< br>'),obj.location.street,$('< br>'),obj.location.city +''+ obj.location.postcode,$('< br>'),obj.location.state,$('< br>') $('< button>')。addClass('removeMe')。text('Delete'),$('< button>')addClass('top-btn' ),$('< button>')。addClass('down-btn')。text('Swap with down'))) })//清除复选框:$('。selectRow')。prop('checked',false); handleEvents();} function logSavedData(){//转换为JSON并记录到控制台。你会把它//发布到一些URL,或将其保存到localStorage。 console.log(JSON.stringify(savedData,null,2));} function getIndex(elem){return $(elem).parent('。parent')。index();} $(document)点击','.removeMe',function(){//从保存的Data savedData.splice(getIndex(this),1); //重新显示refreshDisplay();}); / *将所显示的文章结果列表* / $(document).on('click','.down-btn,function(){var index = getIndex(this); //在内存中交换saveData.splice(index,2,savedData [索引+ 1],savedData [index]); //并重新显示refreshDisplay();}); $(document).on('click',.top-btn,function(){var index = getIndex ); //在内存中交换saveData.splice(index-1,2,savedData [index],savedData [index-1]); //并重新显示refreshDisplay();}); / *禁用顶部&结果列表中第一个和最后一个文章的下拉按钮* / function handleEvents(){$(。top-btn,.down-btn)。prop(disabled,false).show(); $(。parent:first)。find(。top-btn)。prop(disabled,true).hide(); $(文件).ready(function(){$('#showExtForm -b()()()()()()()()() });

  table,th,td {border:1px固体#ddd边界崩溃:崩溃padding:10px;}。parent {height:25%;宽度:90%;填充:1%;剩余左:1%;保证金:1%; border:1px solid black;}。parent:nth-​​child(odd){background:skyblue;}。parent:nth-​​child(even){background:green;} label {float:left; width:80px;} input {width:130px;}  

  < script src =https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js>< / script>< button onclick =createTable()> ;创建表< / button>< table id =datatable> < tr>< th>选择< thth>< th> DOB< / th>< th>< / th>< / tr>< / table>< button onclick =saveData >保存所选的< / button>< br />< div class =container>< / div>< button onclick =logSavedData()>获取保存的数据< / button> / code> 


I've a table which gets updated based on JSON data. Each row in the table has a checkbox which holds the value of the corresponding JSON object, which is basically the information about any of the users. On selecting any of the rows, and saving to display the selected user profile in 'div.parent' which gets appended to 'div.container', I'm also storing the selected JSON object in an array 'savedData'.

Now, I've some swap buttons using which I can swap each of the 'div.parent' with the next or previous 'div.parent'. So, on swapping the, the DOM structure changes accordingly. But, how do I sort 'savedData' array, in order to match the swapping order? For e.g., for the first 'div.parent' in the DOM, the corresponding object should be at 'savedData[0]'. Likewise, for the 2nd 'div.parent' in the DOM, the corresponding object should be at 'savedData[1]'.

How do I fix this?

function createTable() {
			$.getJSON("https://api.randomuser.me/?results=5", function(data) {
				$('#datatable tr:has(td)').remove();
				data.results.forEach(function (record) {
					var json = JSON.stringify(record);
					$('#datatable').append(
						$('<tr>').append(
							$('<td>').append(
								$('<input>').attr('type', 'checkbox')
											.addClass('selectRow')
											.val(json)
							),
							$('<td>').append(
								$('<a>').attr('href', record.picture.thumbnail)
										.addClass('imgurl')
										.attr('target', '_blank')
										.text(record.name.first)
							),
							$('<td>').append(record.dob)
						)
					);
				})
			}).fail(function(error) {
				console.log("**********AJAX ERROR: " + error);
			});            
		}

		var savedData = new Map; // Keyed by image URL. Start with nothing.

		function saveData(){
			var errors = [];
			// Add selected to map
			$('input.selectRow:checked').each(function(count) {
				// Get the JSON that is stored as value for the checkbox
				var obj = JSON.parse($(this).val());
				// See if this URL was already collected (that's easy with Set)
				if (savedData.get(obj.picture.thumbnail)) {
					errors.push(obj.name.first);
				} else {
					// Append it to the Map:
					savedData.set(obj.picture.thumbnail, obj);
				}
			});
			refreshDisplay();
			if (errors.length) {
				alert('The following were already selected:\n' + errors.join('\n'));
			}
		}

		function refreshDisplay() {
			$('.container').html('');
			savedData.forEach(function (obj) {
				// Reset container, and append collected data (use jQuery for appending)
				$('.container').append(
					$('<div>').addClass('parent').append(
						$('<label>').addClass('dataLabel').text('Name: '),
						obj.name.first + ' ' + obj.name.last,
						$('<br>'), // line-break between name & pic
						$('<img>').addClass('myLink').attr('src', obj.picture.thumbnail), $('<br>'),
						$('<label>').addClass('dataLabel').text('Date of birth: '),
						obj.dob, $('<br>'),
						$('<label>').addClass('dataLabel').text('Address: '), $('<br>'),
						obj.location.street, $('<br>'),
						obj.location.city + ' ' + obj.location.postcode, $('<br>'),
						obj.location.state, $('<br>'),
						$('<button>').addClass('removeMe').text('Delete'),
						$('<button>').addClass('top-btn').text('Swap with top'),
						$('<button>').addClass('down-btn').text('Swap with down')
					)	
				);
				resetEvents();
			})
			// Clear checkboxes:
			$('.selectRow').prop('checked', false);
		}

		function logSavedData(){
			// Translate Map to array of values:
			var data = Array.from(savedData, function (pair) {
				return pair[1];
			});
			// Convert to JSON and log to console. You would instead post it
			// to some URL, or save it to localStorage.
			console.log(JSON.stringify(data, null, 2));
		}

		$(document).on('click', '.removeMe', function() {
			var key = $('.myLink', $(this).parent()).attr('src');
			// Delete this from the saved Data
			savedData.delete(key);
			// And redisplay
			refreshDisplay();
		});
		
			/* Swapping the displayed articles in the result list */
			function resetEvents() {

				$(".top-btn, .down-btn").unbind('click');

				handleEvents();
				
				$('.down-btn').click(function() {
					var toMove1 = $(this).parents('.parent');

					$(toMove1).insertAfter($(toMove1).next());

					handleEvents();
				});

				$('.top-btn').click(function() {
					var toMove1 = $(this).parents('.parent');
					
					$(toMove1).insertBefore($(toMove1).prev());
					handleEvents();
				});

			}
				
			/* Disable top & down buttons for the first and the last article respectively in the result list */
			function handleEvents() {
				$(".top-btn, .down-btn").prop("disabled", false).show();

				$(".parent:first").find(".top-btn").prop("disabled", true).hide();

				$(".parent:last").find(".down-btn").prop("disabled", true).hide();
			}
			
			$(document).ready(function(){
				$('#showExtForm-btn').click(function(){
					$('#extUser').toggle();
				});
				$("#extArticleForm").submit(function(){

                    addExtUser();
                    return false;
               });
			});

table, th, td {
			border: 1px solid #ddd;
			border-collapse: collapse;
			padding: 10px;
		}

		.parent {
			height: 25%;
			width: 90%;
			padding: 1%;
			margin-left: 1%;
			margin-top: 1%;
			border: 1px solid black;

		}

		.parent:nth-child(odd){
			background: skyblue;
		}

		.parent:nth-child(even){
			background: green;
		}
		
		label {
			float: left;
			width: 80px;
		}
		input {
			width: 130px;
		}

<button onclick="createTable()">Create Table</button>
		<table id="datatable">
			<tr><th>Select</th><th>Name</th><th>DOB</th></tr>
		</table>
		<button onclick="saveData()">Save Selected</button>
		<br />
		<div class="container"></div>
		<button onclick="logSavedData()">Get Saved Data</button>

解决方案

In the case you want to keep specific order a Map is less suitable. In that case use a standard array. The advantage is then also that this array is exactly what you want to export as JSON. The downside is that you need to iterate over that array to see whether an element is already included (with find for instance).

The event handler reattachment you do can be simply avoided by using event delegation, just like you already had it for the delete action (with $(document).on syntax.

I would suggest to not perform the swap on the parent divs directly, but to apply them to the savedData array, and then use the refreshDisplay function to display the result from that array.

See the snippet below:

function createTable() {
    $.getJSON("https://api.randomuser.me/?results=5", function(data) {
        $('#datatable tr:has(td)').remove();
        data.results.forEach(function (record) {
            var json = JSON.stringify(record);
            $('#datatable').append(
                $('<tr>').append(
                    $('<td>').append(
                        $('<input>').attr('type', 'checkbox')
                                    .addClass('selectRow')
                                    .val(json)
                    ),
                    $('<td>').append(
                        $('<a>').attr('href', record.picture.thumbnail)
                                .addClass('imgurl')
                                .attr('target', '_blank')
                                .text(record.name.first)
                    ),
                    $('<td>').append(record.dob)
                )
            );
        })
    }).fail(function(error) {
        console.log("**********AJAX ERROR: " + error);
    });            
}

var savedData = []; // The objects as array, so to have an order.

function saveData(){
    var errors = [];
    // Add selected to array
    $('input.selectRow:checked').each(function(count) {
        // Get the JSON that is stored as value for the checkbox
        var obj = JSON.parse($(this).val());
        // See if this URL was already collected (that's easy with Set)
        if (savedData.find(record => record.picture.thumbnail === obj.picture.thumbnail)) {
            errors.push(obj.name.first);
        } else {
            // Append it
            savedData.push(obj);
        }
    });
    refreshDisplay();
    if (errors.length) {
        alert('The following were already selected:\n' + errors.join('\n'));
    }
}

function refreshDisplay() {
    $('.container').html('');
    savedData.forEach(function (obj) {
        // Reset container, and append collected data (use jQuery for appending)
        $('.container').append(
            $('<div>').addClass('parent').append(
                $('<label>').addClass('dataLabel').text('Name: '),
                obj.name.first + ' ' + obj.name.last,
                $('<br>'), // line-break between name & pic
                $('<img>').addClass('myLink').attr('src', obj.picture.thumbnail), $('<br>'),
                $('<label>').addClass('dataLabel').text('Date of birth: '),
                obj.dob, $('<br>'),
                $('<label>').addClass('dataLabel').text('Address: '), $('<br>'),
                obj.location.street, $('<br>'),
                obj.location.city + ' ' + obj.location.postcode, $('<br>'),
                obj.location.state, $('<br>'),
                $('<button>').addClass('removeMe').text('Delete'),
                $('<button>').addClass('top-btn').text('Swap with top'),
                $('<button>').addClass('down-btn').text('Swap with down')
            )	
        );
    })
    // Clear checkboxes:
    $('.selectRow').prop('checked', false);
    handleEvents();
}

function logSavedData(){
    // Convert to JSON and log to console. You would instead post it
    // to some URL, or save it to localStorage.
    console.log(JSON.stringify(savedData, null, 2));
}

function getIndex(elem) {
    return $(elem).parent('.parent').index();
}

$(document).on('click', '.removeMe', function() {
    // Delete this from the saved Data
    savedData.splice(getIndex(this), 1);
    // And redisplay
    refreshDisplay();
});

/* Swapping the displayed articles in the result list */
$(document).on('click', ".down-btn", function() {
    var index = getIndex(this);
    // Swap in memory
    savedData.splice(index, 2, savedData[index+1], savedData[index]);
    // And redisplay
    refreshDisplay();
});

$(document).on('click', ".top-btn", function() {
    var index = getIndex(this);
    // Swap in memory
    savedData.splice(index-1, 2, savedData[index], savedData[index-1]);
    // And redisplay
    refreshDisplay();
});
    
/* Disable top & down buttons for the first and the last article respectively in the result list */
function handleEvents() {
    $(".top-btn, .down-btn").prop("disabled", false).show();
    $(".parent:first").find(".top-btn").prop("disabled", true).hide();
    $(".parent:last").find(".down-btn").prop("disabled", true).hide();
}

$(document).ready(function(){
    $('#showExtForm-btn').click(function(){
        $('#extUser').toggle();
    });
    $("#extArticleForm").submit(function(){
        addExtUser();
        return false;
   });
});

table, th, td {
    border: 1px solid #ddd;
    border-collapse: collapse;
    padding: 10px;
}

.parent {
    height: 25%;
    width: 90%;
    padding: 1%;
    margin-left: 1%;
    margin-top: 1%;
    border: 1px solid black;

}

.parent:nth-child(odd){
    background: skyblue;
}

.parent:nth-child(even){
    background: green;
}

label {
    float: left;
    width: 80px;
}
input {
    width: 130px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="createTable()">Create Table</button>
<table id="datatable">
    <tr><th>Select</th><th>Name</th><th>DOB</th></tr>
</table>
<button onclick="saveData()">Save Selected</button>
<br />
<div class="container"></div>
<button onclick="logSavedData()">Get Saved Data</button>

这篇关于根据DOM结构排序包含对象的动态数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆