HTML5, draggable и contentEditable не работают вместе
Когда атрибут draggable
включен в родительском элементе (<li>
), я не могу заставить contenteditable
работать с его дочерним элементом (<a>
).
В центре внимания находится дочерний элемент (<a>
), но я вообще не могу его редактировать.
Пожалуйста, проверьте этот образец
http://jsfiddle.net/pavank/4rdpV/11/
EDIT: я могу редактировать контент, если отключить draggable
на <li>
Ответы
Ответ 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
});