各ループのデータバインディング用にカスタマイズされたソート可能なjQueryアコーディオンがあります。ここで、アコーディオンからアイテムを「駐車場」にドロップしたいと考えています。
出発点として、jQuery UI の「ショッピング カート」を使用しました。
これは私のコードです:
まず、HTML アコーディオン ループ:
<div id="accordion" data-bind="jqAccordion: { },template: { name: tasktemplate', foreach: Tasks, afterAdd: function(elem){$(elem).trigger('valueChanged');} }" class="group accordion ui-widget ui-helper-clearfix" ></div>
<!-------------------- template: begins --------------------->
<script type="text/html" task-template" >
<div data-bind="attr: {'id': 'Task' + TaskId}, click: $root.SelectedTask" class="group ui-widget-content ui-corner-tr" >
<div class="accordion-header ui-widget-header">
<table class="myAccordionHeaderTable" >
<tbody>
<tr>
<td class="left-upper" ><label for="TaskSequenceNo">Seq:</label> <span data-bind="text: TaskSequenceNo"></span>
</td>
<td class="center" rowspan="2" >
<h3><input name="TaskName" data-bind="value: TaskName" /></h3>
</td>
<td class="right-upper" colspan="2">Due: <span data-bind="text: DueDate"></span>
</td>
</tr>
<tr>
<td class="left-bottom">Id: <span data-bind="text: TaskId" ></span></td>
<td class="right-bottom" title="Number of employees attached to task">T: <span data-bind="text: TaskEmployees"></span></td>
</tr>
</tbody>
</table>
</div>
<div class="accordion-content">
<label for="Description" >Description:</label><textarea name="Description" data-bind="value: Description" class="description"></textarea>
</div>
</div>
</script>
<!-------------------- template: ends ----------------------->
そして「駐車場」:
<div id="parking" class="ui-widget-content ui-state-default">
<h2 class="ui-widget-header">Parking</h2>
<div class="ui-widget-content">
<div>
<span class="placeholder">Park tasks here</span>
</div>
</div>
</div>
アコーディオンのデータ バインディングは次のようになります (興味深い部分は、下部にある "$(element).draggable(...)" です)。
ko.bindingHandlers.jqAccordion = {
init: function (element, valueAccessor) {
var options = valueAccessor();
$(element).accordion(options);
$(element).bind("valueChanged", function () {
ko.bindingHandlers.jqAccordion.update(element, valueAccessor);
});
},
update: function (element, valueAccessor) {
var options = valueAccessor();
$(element).accordion("destroy").accordion({
header: ".accordion-header",
collapsible: true,
navigation: true,
heightStyle: "content",
active: false
})
.sortable({
axis: "x, y",
handle: ".accordion-header",
placeholder: "ui-state-highlight",
start: function (event, ui) {
//change bool to true
sorting = true;
//find what tab is open, false if none
active = $(this).accordion("option", "active");
//possibly change animation here (to make the animation instant if you like)
$(element).accordion("option", "animate", {
easing: 'swing',
duration: 0
});
//close tab
$(element).accordion({
active: false
});
},
over: function (event, ui) {
$(element).accordion({
active: false
});
},
stop: function (event, ui) {
//1st: Handle the visible impression during sorting...
// IE doesn't register the blur when sorting so trigger focusout handlers to remove .ui-state-focus
ui.item.children("h3").triggerHandler("focusout");
//possibly change animation here; { } is default value
$(element).accordion("option", "animate", {});
//open previously active panel - set active to 'false' to maintain closed.
active = false;
$(element).accordion("option", "active", active);
//change bool to false
sorting = false;
//alert("element=" + element);
//2nd: Create sequence listing of items for later saving
var items = [];
var itemSeqNos = [];
ui.item.siblings().andSelf().each(function () {
//compare data('index') and the real index
if ($(this).data('index') != $(this).index()) {
items.push(this.id);
itemSeqNos.push(this.id.replace("Task", "")); // Remove prefix ("Task") to build SequenceNo-array... NB!! Could this record been built only with items involved and not whole list to reduce traffic ????
}
});
ui.item.parent().trigger('stop');
//Collect data from the accordion to set selected and set new sequence no.
var context = ko.contextFor(this);
//add a child to the appropriate parent, calling a method off of the main view model (context.$root)
context.$root.isAccordionSorted(itemSeqNos); // THIS WORKS!!!
}
})
.on({
click: function () {
$("#debug").text("-on Click: ");
setTimeout(function () {
$("#debug").text("------");
}, 1000);
},
stop: function () {
$("#debug").text("-on Stop");
$(this).siblings().andSelf().each(function (i) {
$(this).data('index', i);
});
}
})
.trigger('stop');
$(element).draggable({
handle: "div.accordion-header",
axis: "x, y",
cancel: "invalid",
cursor: "move",
appendTo: "body",
helper: "clone"
});
}
};
最後に、「駐車場」のドロップ可能なコード:
<script>
$(function() {
$("#parking div").droppable({
activeClass: "ui-state-default",
hoverclass: "ui-state-hover",
accept: ":not(.ui-sortable-helper)",
drop: function(event, ui){
$(this).find(".placeholder").remove();
$("<div></div>").text( ui-draggable.text() ).appendTo(this);
}
}).sortable({
items:"span:not(.placeholder)",
sort: function(){
// gets addde unintentionally by droppable interacting with sortable
// using connectWithSortable fixed this, but doesn\t allow customizee active/hoverClass options
$(this).removeClass("ui-state-default");
}
});
});
</script>
基本的に私が欲しいのは: 1.アコーディオンからアイテムをドラッグドロップできるようにする " 2.アイテムを「パーキングスポット」にドロップする 3.アコーディオンヘッダーのDueDateとTaskEmployeesを非表示にしますが、TaskNameは非表示にします。
次のステップ: 4. アイテムをパーキングからドラッグ アンド ドロップして戻します。