JavaScript "contenteditable" - Получение/настройка позиции Caret
Я прочитал несколько сообщений о размещении каретки, но никто, кажется, не ответил на мою конкретную проблему.
- У меня есть 2 divs (div1 и div2)
- div1= uneditable div
- div2= contenteditable div
- оба divs содержат точное содержимое
- когда пользователь нажимает div1, он скрывается, а div2 отображается в точном месте, и пользователь может редактировать
Проблема: я хочу, чтобы каретка отображалась в точном месте на div2 как div1
Итак, мне нужно как-то ПРОЧИТАТЬ место, где пользователь нажимает на div1, а затем, когда div2 появляется, поместите курсор/каретку в том же месте, поэтому getCaretLocation (in_div_id) и setCaretLocation (in_div_id).
Как это сделать?
Спасибо -
Ответы
Ответ 1
Короткий ответ: вы не можете
Длинный ответ. Проблема, с которой вы столкнетесь, заключается в том, что вы сможете получить координаты (x, y) для события click на div1, но любая реализация позиции каретки при необходимости вы знаете положение каретки в содержимом (которое представляет собой число символов, предшествующих карете).
Чтобы преобразовать координаты (x, y) в позицию символа, вам действительно нужно знать, сколько символов было раньше (т.е. слева на текущей строке и выше, если текст - ltr).
Если вы используете шрифт с фиксированной шириной, вы можете упростить проблему: сопоставление координаты (x, y) с координатой (строка, столбец) в сетке символов.
Однако вы по-прежнему сталкиваетесь с проблемой незнания того, как текст завернут. Например:
------------------
|Lorem ipsum |
|dolor sit amet |
|consectetur |
|adipiscing elit |
------------------
Если пользователь нажимает на d в долоре, вы знаете, что этот символ является первым на 2-й строке, но, не зная алгоритма обертывания, вы не знаете, что это 13-й персонаж в "Lorem ipsum dolor сидеть...". И нет никакой гарантии, что такой алгоритм обертки идентичен между браузерами и платформой.
Теперь, что мне интересно, почему вы в первую очередь используете 2 разных синхронизированных div
? Не было бы проще использовать только один div и установить его содержимое для редактирования, когда пользователь нажимает (или наводит)?
Ответ 2
Вы можете вставить крошечный элемент span в карете, получить его положение и удалить его. Для библиотеки кросс-браузера и библиотеки выбора см. rangy.
Ответ 3
вы можете, в основном, вам нужно установить временный контент, редактируемый на вашем первом div, чтобы поймать каретку pos
$('div1').hover(function()
{ $(this).attr('contenteditable','true');
},function()
{ $(this).removeAttr('contenteditable');
}).mouseup(function()
{ var t = $(this);
// get caret position and remove content editable
var caret = t.getCaret();
t.removeAttr('contenteditable');
// do your div switch stuff
...
// and apply saved caret position
$('div2').setCaret(caret);
});
теперь просто нужен метод get/set caret:)
edit > вот моя собственная, (живая демонстрация)
getSelection:function($e)
{ if(undefined === window.getSelection) return false;
var range = window.getSelection().getRangeAt(0);
function getTreeOffset($root,$node)
{ if($node.parents($root).length === 0) return false; // is node child of root ?
var tree = [], treesize = 0;
while(1)
{ if($node.is($root)) break;
var index, $parent = $node.parent();
index = $parent.contents().index($node);
if(index !== -1) { tree[treesize++] = index; } $node = $parent;
}; return tree.reverse();
}
var start = getTreeOffset($e,$(range.startContainer));
var end = getTreeOffset($e,$(range.endContainer));
if(start & end === false) return false;
return {start:start,end:end,startOffset:range.startOffset,endOffset:range.endOffset};
}, setSelection:function($e,s,win)
{ $e.focus(); if(s === false) return; var sel = win.getSelection(); sel.removeAllRanges();
function getNode($e,s)
{ var node = $e;
for( var n=0;n<s.length;n++ )
{ var index = s[n]; if(index < 0) break;
node = node.contents(':eq('+index+')');
} return node.get(0);
}
var start = getNode($e,s.start), end = getNode($e,s.end), range = win.document.createRange();
range.setStart(start,s.startOffset); range.setEnd(end,s.endOffset); sel.addRange(range);
}
Ответ 4
Похоже, вы пытаетесь сделать встроенное редактирование... посмотрели ли вы на jeditable плагин?
Ответ 5
Когда вы нажимаете на элемент, создается объект Selection с нулевой длиной (получить его из element.getSelection(), где элемент является рассматриваемым div). FocusOffset этого объекта сообщит вам, что вы нажали, например, 74-й символ в этом div (это то, что сказал Адриен, было невозможно в другом ответе).
Ответ 6
Прочитайте позицию каретки в тексте, а затем установите положение каретки в окне редактирования.