JQuery UI sortable placeholder с строками Bootstrap

Я пытаюсь сделать перетаскиваемый набор панелей, используя jQuery UI и Bootstrap rows/panels. У меня есть что-то, что в основном работает, моя проблема в том, что заполнитель не имеет правильного размера при перетаскивании панели. Это размер всей строки, а не размер элемента.

$('.row').sortable({
	connectWith: ".panel",
	handle: ".panel-heading",
	placeholder: "panel-placeholder"
});

$('.panel').on('mousedown', function(){
	$(this).css( 'cursor', 'move' );
}).on('mouseup', function(){
	$(this).css( 'cursor', 'auto' );
});;
.panel-placeholder {
	border: 1px dotted black;
	margin: 1em 1em 1em 1em;
	height: 50px;
}
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'; return false;" rel="stylesheet"/>
<link href="#" onclick="location.href='https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css'; return false;" rel="stylesheet"/>
<div class="container-fluid">
	<div class="row">
		<div class="col-md-3">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
		<div class="col-md-4">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
		<div class="col-md-8">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
	</div>
</div>

Ответ 1

Решение OpherV работает. Здесь, однако, упрощенная версия, которая все еще работает и пытается удержать разделение проблем, оставив CSS в CSS-коде. Я попытался сохранить взаимоблокировки/маржирование на самом js-коде.

Идея такая же, я получаю width и height непосредственно из .panel, и я копирую как все классы в div col-. Но поля и paddings устанавливаются с помощью CSS для соответствия Bootstrap Default.

Вы можете найти его в фрагменте ниже или здесь, на jsfiddle. https://jsfiddle.net/zdfb3e0p/16/

$('.row').sortable({
     connectWith: ".panel",
     handle: ".panel-heading",
     placeholder: "panel-placeholder",
     start: function(e, ui){
         ui.placeholder.width(ui.item.find('.panel').width());
         ui.placeholder.height(ui.item.find('.panel').height());
         ui.placeholder.addClass(ui.item.attr("class"));
     }
});

$('.panel').on('mousedown', function(){
  $(this).css( 'cursor', 'move' );
}).on('mouseup', function(){
  $(this).css( 'cursor', 'auto' );
});;
.panel-placeholder {
  border: 1px dotted black;
  border-radius: 4px;
  margin: 0 15px 20px 15px;
  padding: 0;
  height: 50px;
}
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<div class="container-fluid">
	<div class="row">
		<div class="col-md-3">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
		<div class="col-md-4">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
		<div class="col-md-8">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
	</div>
</div>

Ответ 2

Если вы хотите, чтобы ваш заполнитель имел точные размеры элемента, вы можете использовать событие Sortable start, как описано в API, для вычисления и воздействия на тот же стиль, что и перетаскивание.

После того как у вас есть ссылка как элемента-заполнителя, так и элемента управления из события, вы можете просто скопировать каждый соответствующий атрибут CSS.

Кроме того, чтобы поддерживать позиционирование в сетке в качестве исходного элемента, вам нужно будет обязательно присвоить класс col из исходного элемента. Я также объяснил некоторые причуды, например, тот факт, что по умолчанию заполнитель jQuery присваивается встроенным маркером и что пунктирная граница также занимает некоторое пространство.

$('.row').sortable({
    connectWith: ".panel",
    handle: ".panel-heading",
    placeholder: "panel-placeholder",
    start: function(event, ui){
        var classes = ui.item.attr('class').split(/\s+/);
        for(var x=0; x<classes.length;x++){   
            if (classes[x].indexOf("col")>-1){
            ui.placeholder.addClass(classes[x]);
           }
         }

        ui.placeholder.css({      
          width: ui.item.innerWidth() - 30 + 1, //account for margin and border
          height: ui.item.innerHeight() - 15 + 1, //account for margin and border    
          padding: ui.item.css("padding"), //use original padding
          marginTop: 0 //dispose of the jQuery margin
        });       

    }
  }
});

Здесь рабочий пример скрипта

Я проверил это во всех режимах реагирования.

введите описание изображения здесь

Ответ 3

Система Bootstrap Grid имеет отступы по умолчанию 30px (15 пикселей на сторону). Поскольку вы привязываете сортировку к .row, вам нужно учитывать это. Изменение значения margin на .panel-placeholder до 15px приведет к тому, что он упадет в соответствии с сеткой сетки Bootstrap.

$('.row').sortable({
	connectWith: ".panel",
	handle: ".panel-heading",
	placeholder: "panel-placeholder"
});

$('.panel').on('mousedown', function(){
	$(this).css( 'cursor', 'move' );
}).on('mouseup', function(){
	$(this).css( 'cursor', 'auto' );
});;
.panel-placeholder {
	border: 1px dotted black;
	margin: 15px;
	height: 50px;
}
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'; return false;" rel="stylesheet"/>
<link href="#" onclick="location.href='https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css'; return false;" rel="stylesheet"/>
<div class="container-fluid">
	<div class="row">
		<div class="col-md-3">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
		<div class="col-md-4">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
		<div class="col-md-3">
			<div class="panel panel-primary">
				<div class="panel-heading">
					<h3 class="panel-title">Panel title</h3>
				</div>
				<div class="panel-body">
					Panel content
				</div>
			</div>
		</div>
	</div>
</div>