Подтвердить что ты не робот

HTML5, draggable и contentEditable не работают вместе

Когда атрибут draggable включен в родительском элементе (<li>), я не могу заставить contenteditable работать с его дочерним элементом (<a>).

В центре внимания находится дочерний элемент (<a>), но я вообще не могу его редактировать.

Пожалуйста, проверьте этот образец

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

EDIT: я могу редактировать контент, если отключить draggable на <li>

4b9b3361

Ответ 1

Сегодня я столкнулся с той же проблемой и нашел решение [using 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') можно заменить чем-то более конкретным.

Если новые элементы contenteditable не добавляются во время выполнения, можно использовать bind вместо delegate.

Ответ 2

Имеет смысл, что свойства draggable и contenteditable будут сталкиваться. Элементы contenteditable, как и любое текстовое поле, будут фокусироваться на mousedown (не нажимать). Элементы draggable работают на основе mousemove, но также выбор текста в контентном элементе, поэтому как браузер определит, пытаетесь ли вы перетащить элемент или выбрать текст? Поскольку свойства не могут сосуществовать на одном и том же элементе, кажется, что вам нужно решение javascript.

Попробуйте добавить эти два атрибута в свой якорный тег:

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

Это работает для меня, если я добавлю его в теги <a> в jsFiddle. Вы также можете использовать jQuery, если он более сложный, чем получение parentNode.

Ответ 3

Примечание. Это временное решение, так как я считаю, что невозможность совместной работы этих двух функциональных возможностей находится в самой спецификации HTML (т.е. не работая вместе, это намеренно, поскольку браузер не может определить, хотите ли вы фокус или перетащить на событие mousedown)


Я заметил, что вы явно задали "нет библиотек", поэтому я предоставил необработанный ответ javascript/HTML5

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

Это была моя трещина.

Прежде всего, лучше включить данные в один элемент localStorage, а не разбросать его.

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

это создает эту способность, используя JSON для преобразования между объектом и строкой. Объекты действительно могут быть вложенными

Я также добавил ссылки (edit) рядом с элементами, при нажатии эти ссылки преобразуют элементы в элементы input, поэтому вы можете редактировать текст. После входа в систему он преобразует его обратно и сохраняет данные. В то же время элементы списка остаются перетаскиваемыми.

После сохранения нажмите F12 в chrome, найдите консоль и посмотрите в объекте localStorage, вы увидите, что все данные были сохранены в localStorage['test'] в качестве объекта с использованием JSON.stringify()

Я изо всех сил старался сделать это масштабируемым, и я думаю, что я преуспел достаточно хорошо; вам просто нужно заменить HTML контейнером и использовать цикл javascript for, чтобы выписать несколько элементов, используя итератор по вашему выбору, чтобы заполнить параметр для edit(). Например:

Скажите, что вы сменили хранилище, чтобы провести "парадигмы" списков, и вы назвали "список покупок". И скажем, что объект хранения выглядит примерно так:

{
    "shopping list":{
         1:"Milk",
         2:"Eggs",
         3:"Bread"
    }
}

Это может отобразить этот список:

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>'
}

Конечно, если вы должны были отредактировать структуру объекта хранения, вам также нужно будет отредактировать функции.

Результат будет выглядеть примерно так:

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

Не беспокойтесь о входных элементах, если это вас беспокоит; CSS может легко исправить это, чтобы выглядеть так, как будто это не просто изменилось.

Если вы не хотите, чтобы ссылки (edit) были видимыми, например, вы можете сделать это в CSS:

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

Теперь ссылки редактирования появятся только при наведении указателя мыши на элемент списка, например, на эту версию:

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


Надеюсь, этот ответ помог.

Ответ 4

Использование html5sortable и новых событий JQuery (делегат устарел, ответьте через 3 года после первоначального вопроса), ошибка все еще затрагивает Chrome 37. Contenteditable spans и html5sortable, похоже, играют хорошо в других браузерах. Я знаю, что это лишь частично актуально, просто сохраняя документацию об изменениях, которые я заметил.

$(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
});