简体   繁体   English

HTML5,draggable和contentEditable不能一起工作

[英]HTML5,draggable and contentEditable not working together

When a draggable attribute is enabled on a parent element( <li> ) I cant make contenteditable work on its child element ( <a> ). 当在父元素( <li> )上启用了draggable属性时,我无法对其子元素( <a> )进行contenteditable工作。

The focus goes on to child element ( <a> ),but I cant edit it at all. 重点是子元素( <a> ),但我根本无法编辑它。

Please check this sample 请检查此样本

http://jsfiddle.net/pavank/4rdpV/11/ http://jsfiddle.net/pavank/4rdpV/11/

EDIT: I can edit content when I disable draggable on <li> 编辑:当我在<li>上禁用draggable时,我可以编辑内容

I came across the same problem today, and found a solution [using jQuery] 我今天遇到了同样的问题,并找到了一个解决方案[使用jQuery]

$('body').delegate('[contenteditable=true]','focus',function(){
    $(this).parents('[draggable=true]')
            .attr('data-draggableDisabled',1)
            .removeAttr('draggable');
    $(this).blur(function(){
        $(this).parents('[data-draggableDisabled="1"]')
                .attr('draggable','true')
                .removeAttr('data-draggableDisabled');
    });
});

$('body') can be replaced by anything more specific. $('body')可以被更具体的东西取代。

If new contenteditable elements are not added in the runtime, one can use bind instead of delegate . 如果未在运行时添加新的contenteditable元素,则可以使用bind而不是delegate

It makes sense that the draggable and contenteditable properties would collide. 有意义的是, draggabledraggable contenteditable属性会发生碰撞。 contenteditable elements, like any text field, will focus on mousedown (not click). 与任何文本字段一样, contenteditable元素将专注于mousedown(而不是单击)。 draggable elements operate based on mousemove, but so does selecting text in a contenteditable element, so how would the browser determine whether you are trying to drag the element or select text? draggable元素基于mousemove进行操作,但在contenteditable元素中选择文本也是如此,那么浏览器将如何确定您是在尝试拖动元素还是选择文本? Since the properties can't coexist on the same element, it appears that you need a javascript solution. 由于属性不能在同一元素上共存,因此您需要一个javascript解决方案。

Try adding these two attributes to your anchor tag: 尝试将这两个属性添加到锚标记:

onfocus="this.parentNode.draggable = false;"
onblur="this.parentNode.draggable = true;"

That works for me if I add it to the <a> tags in your jsFiddle. 如果我将它添加到你的jsFiddle中的<a>标签,这对我有用。 You could also use jQuery if it's more complicated than getting the parentNode. 如果它比获取parentNode更复杂,你也可以使用jQuery。

Note: This is a workaround since I believe the inability for these two functionalities to work together resides in the HTML spec itself (ie the not working together thing is intentional since the browser can't determine whether you want to focus or drag on the mousedown event) 注意:这是一种解决方法,因为我认为这两个功能无法协同工作存在于HTML规范本身(即,由于浏览器无法确定您是否要关注或拖动mousedown,因此无法合作的事情是故意的事件)


I noticed you explicitly set 'no libraries', so I will provide a raw javascript/HTML5 answer 我注意到你明确设置'没有库',所以我将提供一个原始的javascript / HTML5答案

http://jsfiddle.net/4rdpV/26/ http://jsfiddle.net/4rdpV/26/

This was my crack at it. 这是我对它的破解。

First of all, it might be better to include the data in one single localStorage item, rather than scatter it. 首先,最好将数据包含在一个localStorage项中,而不是将其分散。

 storage={ '1.text':'test 1', '2.text':'test 2' } if(localStorage['test']){ storage=JSON.parse(localStorage['test']) } 

this creates that ability, using JSON to convert between object and string. 这创建了这种能力,使用JSON在对象和字符串之间进行转换。 Objects can indeed be nested 对象确实可以嵌套

I also added (edit) links next to the items, when clicked, these links will transform the items into input elements, so you can edit the text. 我还添加了(edit)项目旁边的链接,单击这些链接时,这些链接会将项目转换为input元素,因此您可以编辑文本。 After hitting enter, it transforms it back and saves the data. 点击进入后,它会将其转换回来并保存数据。 At the same time, the list items remain draggable. 同时,列表项仍然可以拖动。

After saving, hit F12 in chrome, find the console, and look in the localStorage object, you will see all the data was saved in localStorage['test'] as an Object using JSON.stringify() 保存后,在chrome中点击F12,找到控制台,然后查看localStorage对象,您将看到所有数据都使用JSON.stringify()作为Object保存在localStorage['test']

I tried my best to design this to be scaleable, and I think I succeeded well enough; 我尽力将它设计成可扩展的,我认为我成功了; you just need to replace the HTML with a container and use a javascript for loop to write out several items, using the iterator of your choice to fill the parameter for edit() . 你只需要用容器替换HTML并使用javascript for循环来写出几个项目,使用你选择的迭代器来填充edit()的参数。 For example: 例如:

Say you changed storage to hold "paradigms" of lists, and you have one called "shopping list". 假设您更改了存储以保存列表的“范例”,并且您有一个名为“购物清单”的存储。 And say the storage object looks something like this: 并说存储对象看起来像这样:

for(i in storage['shopping list']){
    _item = storage['shopping list'][i];
    container.innerHTML+='<li draggable=true><a id="item'+i+'">'+_item+'</a><a href="#" onclick="edit('+i+')"> (edit)</a></li>'
}

This could render that list out: 这可能会导致列出:

 for(i in storage['shopping list']){ _item = storage['shopping list'][i]; container.innerHTML+='<li draggable=true><a id="item'+i+'">'+_item+'</a><a href="#" onclick="edit('+i+')"> (edit)</a></li>' } 

Of course, if you were to edit the structure of the storage object, you would need to edit the functions as well. 当然,如果要编辑存储对象的结构,则还需要编辑这些函数。

The output would look something like this: 输出看起来像这样:

 Milk (edit) Eggs (edit) Bread (edit) 

Don't worry about the input elements if that worries you; 如果您担心,请不要担心输入元素; CSS can easily fix it to look like it didn't just change. CSS可以很容易地修复它看起来不仅仅是改变。

If you don't want the (edit) links to be visible, for example, you can do this in CSS: 例如,如果您不希望(edit)链接可见,则可以在CSS中执行此操作:

 a[href="#"]{ display:none; } li[draggable="true"]:hover a[href="#"]{ display:inline; } 

Now the edit links will only appear when you hover the mouse over the list item, like this version: 现在只有将鼠标悬停在列表项上时才会显示编辑链接,如此版本:

http://jsfiddle.net/4rdpV/27/ http://jsfiddle.net/4rdpV/27/


I hope this answer helped. 我希望这个答案有所帮助。

Using html5sortable and newer JQuery events (delegate is deprecated, answer 3 years after initial question), bug still affects Chrome 37. Contenteditable spans and html5sortable seem to play nice in other browsers. 使用html5sortable和更新的JQuery事件(委托已被弃用,在初始问题后3年回答),bug仍然影响Chrome 37. Contenteditable spans和html5sortable似乎在其他浏览器中表现不错。 I know this is only partially relevant, just keeping documentation on changes I've noticed. 我知道这只是部分相关,只是记录我注意到的变化。

$(document).on('focus', 'li span[contenteditable]', function() {
    $(this).parent().parent().sortable('destroy'); // removes sortable from the whole parent UL
});

$(document).on('blur', 'li span[contenteditable]', function() {
    $(this).parent().parent().sortable({ connectWith: '.sortable' }); // re-adds sortable to the parent UL
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM