- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试创建一个列表,可以通过拖动其中的项目来重新排序。
当我第一次拖动元素时 dragstart.trigger="drag($event)"
调用 drag(e)
.在 drag(e)
我设置拖动元素的数据。
拖放元素时 drop.trigger="drop($event)"
调用 drop(e)
.在 drop(e)
我得到拖动的元素并将其从列表/父元素中删除 <ul>
.之后,我将拖动的元素插入到放置的位置。
问题是一旦元素被拖动。我无法将它再次拖动到不同的目标,因为 dragstart.trigger="drag($event)"
没有调用 drag(e)
.
如何调用 dragstart.trigger="drag($event)"
?
<ul id="columns" drop.trigger="drop($event)" dragover.trigger="allowDrop($event)">
<li id="item1" class="column" draggable="true" dragstart.trigger="drag($event)" dragend.trigger="dragend($event)"><header>A</header></li>
<li id="item2" class="column" draggable="true" dragstart.trigger="drag($event)" dragend.trigger="dragend($event)"><header>B</header></li>
<li id="item3" class="column" draggable="true" dragstart.trigger="drag($event)" dragend.trigger="dragend($event)"><header>C</header></li>
<li id="item4" class="column" draggable="true" dragstart.trigger="drag($event)" dragend.trigger="dragend($event)"><header>D</header></li>
<li id="item5" class="column" draggable="true" dragstart.trigger="drag($event)" dragend.trigger="dragend($event)"><header>E</header></li>
</ul>
JS :
drag(e) {
console.log('handleDragStart');
// Target element is the source node.
this.dragSrcEl = e.currentTarget;
console.log('dragSrcEl :', this.dragSrcEl);
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', e.currentTarget.outerHTML);
e.currentTarget.classList.add('dragElem');
return true;
}
allowDrop(e) {
console.log('handleDragover');
e.preventDefault();
}
dragend() {
console.log('handleDragEnd');
}
drop(e) {
console.log('handleDrop');
if (e.stopPropagation) {
e.stopPropagation();
}
// Don't do anything if dropping the same column we're dragging.
if (this.dragSrcEl != e.srcElement) {
e.currentTarget.removeChild(this.dragSrcEl);
let dropHTML = e.dataTransfer.getData('text/html');
e.srcElement.parentNode.insertAdjacentHTML('beforebegin',dropHTML)
}
e.currentTarget.classList.remove('over');
return false;
}
最佳答案
dragstart
在重新排序元素后没有被调用的原因是因为您并不是真正地重新排序它们。您实际上是在删除拖动的元素,然后插入它的新副本。
这个新副本不由 aurelia 的组合引擎处理,因此不会编译,因此 html 中的任何特定于 aurelia 的表达式都不会执行任何操作。 .trigger
此时只是一个死标签。
拖放是一种特殊的野兽,以自然方式实现从来都不是特别简单,尤其是当这些元素附加了各种自定义框架行为时。
这里有 3 个选项:
不要使用 aurelia 的 trigger
,而是在首次创建它们时和创建新副本时都使用 el.addEventListener
。
每当您删除一个元素时,使用 aurelia 的 ViewEngine
重新编译(部分) View ,以便处理 .trigger
,在后台,无论如何,确实只是 el.addEventListener
使用 repeat.for
将其转换为自定义元素,并让 Aurelia 处理 html 方面的事情。
现在选项 1 肯定是让它工作的最快方法,选项 2 会稍微更健壮和更棘手,但两者都非常 hacky。
我强烈主张使用框架而不是绕过它,因为从长远来看,事情会更容易维护,而且随着项目的发展,您可以更轻松地添加额外的奇特行为。
它看起来可能比你现在做的要复杂得多,但是通过使用更多的框架来处理低级的东西,你将拥有“活的”可拖动元素和一个你可以做很多事情的功能齐全的 Aurelia更多的东西。
所以这只是您可能如何处理选项 3 的一个示例:
在 app.js 中,将您的列变成一个 javascript 对象列表:
items = [
{ text: "A", id: "item1" },
{ text: "B", id: "item2" },
{ text: "C", id: "item3" },
{ text: "D", id: "item4" },
{ text: "E", id: "item5" }
];
在 app.html 中,将这些项目传递给 columns
自定义元素(为了使 html 与您的示例相似,我将使用 as-element
)
<template>
<require from="./resources/elements/columns"></require>
<ul as-element="columns" items.bind="items"></ul>
</template>
在 resources/elements/columns.js 中,针对单个项目 View 模型而不是针对 html 元素进行操作:
import { customElement, children, bindable } from "aurelia-templating";
@customElement("columns")
export class Columns {
// keeps a list of the viewmodels of the direct "li" children
@children("li") children;
// the columns
@bindable() items;
// the currently dragged column
dragColumn;
// the customEvent we dispatch from the child "column" element
handleColDragStart(e) {
// the viewmodel we passed into the customEvent
this.dragColumn = e.detail.column;
}
allowDrop(e) {
console.log("handleDragover");
e.preventDefault();
}
drop(e) {
console.log("handleDrop");
if (e.stopPropagation) {
e.stopPropagation();
}
// source drag index
let dragIdx = this.children.indexOf(this.dragColumn);
// if we can't resolve to a sibling (e.g. dropped on or outside the list),
// naively drop it at index 0 instead
let dropIdx = 0;
// try to find the drop target
let dropTarget = e.srcElement;
while (dropTarget !== document.body) {
let dropTargetVm = dropTarget.au && dropTarget.au.controller && dropTarget.au.controller.viewModel;
if (dropTargetVm) {
dropIdx = this.children.indexOf(dropTargetVm);
break;
} else {
dropTarget = dropTarget.parentElement;
}
}
if (dragIdx !== dropIdx) {
// only modify the order in the array of javascript objects;
// the repeat.for will re-order the html for us
this.items.splice(dropIdx, 0, this.items.splice(dragIdx, 1)[0]);
}
return false;
}
}
在 resources/elements/columns.html 中,只监听我们从 column
元素发送的 customEvent,除此之外只处理 drop
:
<template id="columns" drop.trigger="drop($event)" dragover.trigger="allowDrop($event)">
<require from="./column"></require>
<li as-element="column" repeat.for="col of items" column.bind="col" coldragstart.trigger="handleColDragStart($event)">
</li>
</template>
在 resource/elements/column.js 中处理 dragstart
和 dragend
事件,然后派发一个带有对 viewModel 的引用的 customEvent(因此您不必过多地处理 html):
import { customElement, bindable } from "aurelia-templating";
import { inject } from "aurelia-dependency-injection";
@customElement("column")
@inject(Element)
export class Column {
el;
constructor(el) {
this.el = el;
}
@bindable() column;
dragstart(e) {
this.el.dispatchEvent(
new CustomEvent("coldragstart", {
bubbles: true,
detail: {
column: this
}
})
);
return true;
}
}
最后,在 resources/elements/column.html 中监听 dragstart
事件:
<template draggable="true" dragstart.trigger="dragstart($event)">
<header>${column.text}</header>
</template>
这个解决方案的部分对你来说可能看起来有点奇怪,我仍然认为有点老套的部分是我们尝试通过 el.au.controller.viewModel
获取 ViewModel >.
这是您“只需要知道”的事情。自定义元素/html 行为始终有一个 au
属性,其中包含对具有 Controller 、 View 等的行为实例的引用。
当直接针对 html 工作时,这基本上是“掌握”aurelia 的最简单(有时也是唯一)方法。对于拖放之类的事情,我认为没有任何方法可以避免这种情况,因为不幸的是没有原生的 aurelia 支持它。
关于javascript - 重新排序元素后未调用 Dragstart,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49335385/
chrome 抛出错误:无法调用未定义的方法“setData”,我发现 e 不等于 window.event(它没有 propert dataTransfer);两者有很大的不同 我发现两者在点击事件
dragstart 事件未在 Chrome 浏览器上触发...我想在鼠标拖动事件上将状态设置为 true。所以我将 document.addeventlistener('dragstart', thi
我正在尝试创建一个列表,可以通过拖动其中的项目来重新排序。 当我第一次拖动元素时 dragstart.trigger="drag($event)"调用 drag(e) .在 drag(e)我设置拖动元
下面是我的代码: var
我想知道如何在 Dragstart 事件中首先存储和检索元素的坐标(offest)。 我正在使用interact.js,但这是一个普遍问题...... 到目前为止,我编写了这个函数,因为我想我必须使用
我正在开发“Windows 应用商店”应用程序。我希望能够拖动一个按钮来在网格单元格中设置一个值。这是按钮的声明: 下面是事件处理程序的代码: private void dragSt
所以我添加了sortablejs给我的blazor应用程序,它的工作原理 - 第一次拖放。 首先,这是发生了什么: Blazor 组件代码: @foreach (var m in manuf
我正在尝试使用 d3 制作一个可拖动的圆圈,但会保留原始圆圈的副本。这是圆圈: g.selectAll('circle') .data([{ cx: 90, cy: 80,
我试图在拖动开始后将光标更改为“移动”。我尝试将 dropEffect 属性设置为 move 但这不起作用。 https://developer.mozilla.org/en-US/docs/Web/
我有一个 super 简单的 hammer.js 示例,它适用于“tap”事件,但不适用于“dragstart”。我似乎无法弄清楚为什么。 HIT ME - var element = documen
我正在处理以下格式的 html: div1 div2 当我将鼠标放在第一个 div 上时,鼠标悬停事件的目标是该 div,但是当我拖动该 div 时,目标成为整个标签。有没有办法将拖动目标
我想在页面上实现一些可拖动的元素,这些元素不应该破坏页面上当前获得焦点的控件。这就是我的尝试: $('input').focus(); $('div').on('mousedown', functio
我目前正在尝试加快我的移动设备网络应用程序的速度,但现在我陷入了最重要的部分——缓存。如何在用户开始拖动之前缓存整个图层并在拖动 Action 停止时将其恢复为可用的 Kinetic.Nodes? 目
从 MDN 文档我可以读到: Drag - Fired when an element or text selection is being dragged. Dragstart - Fired wh
我想让一个 img 元素不可选择且不可拖动,因为我将它用作窗口大小调整控件(单击并拖动周围的 div 可调整窗口大小)。 它工作得很好,如下所示: noSelect[x].ondragstart =
我正在尝试触发 Slider Thumb.DragStarted使用 MVVMLight 的事件 EventToCommand但它不起作用。同样的事情对于 Slider Event ValueChan
当尝试在我的 ResponsiveGridLayout 中拖动或调整任何面板的大小时,我收到以下错误: not mounted on DragStart!这是我的 GridLayout: handl
我尝试阻止浏览器默认图像在dragstart中拖动,但不知何故它也禁用了drag和dragend事件。无论如何,我可以禁用浏览器默认图像拖动,但它仍然会运行拖动和拖动结束事件? 或者唯一的选择是使用背
我正在尝试实现拖放来更改文章调度系统中的日期。我希望用户能够将一篇文章条目从一个日期拖到另一个日期,然后时间表应该自动更新。这是我的代码: $(function () { $
我想根据拖动 slider 的程度来更改视频位置。所以我想使用 DragStarted 和 DragCompleted 事件。但它显示“本地属性‘Dragstarted’只能应用于从‘Thumb’派生
我是一名优秀的程序员,十分优秀!