【问题标题】:removeChild sometimes removes entire span and sometimes doesn'tremoveChild 有时会删除整个跨度,有时不会
【发布时间】:2012-10-04 23:04:16
【问题描述】:

我正在开发一个适用于 iOS 的富文本编辑器,其中大部分都可以工作,但遇到了无穷无尽的问题,以确保当用户开始输入时光标在视口中可见。

我想出了一个新颖的方法:在光标位置插入一个跨度,滚动到该跨度,然后将其删除。 (如果跨度在屏幕上,我还没有只滚动。)这是我写的:

document.addEventListener('keypress', function(e) {            
   jumpToID();
}, false);

function jumpToID() {
  var id = "jumphere2374657";
  var text = "<span id='" + id + "'>&nbsp;</span>"
  document.execCommand('insertHTML', false, text);
  var element = document.getElementById(id);
  element.scrollIntoView();
  element.parentNode.removeChild(element);
}

在某些情况下,这工作得很好,在某些情况下,它会在每次按键之间留下一个不间断的空间,只删除 标记。有任何想法吗?如果有人有建议,我愿意接受更好的方法。让光标出现有多难让我有点震惊,但是 JS 对我来说是新的。

编辑

这是有效的代码:

var viewportHeight = 0;

function setViewportHeight(vph) {
  viewportHeight = vph;
  if(viewportHeight == 0 && vph != 0)
    viewportHeight = window.innerHeight;
}

function getViewportHeight() {
  if(viewportHeight == 0)
    return window.innerHeight;
  return viewportHeight;
}

function makeCursorVisible() {
  var sel = document.getSelection();                  // change the selection
  var ran = sel.getRangeAt(0);                        // into a range
  var rec = ran.getClientRects()[0];                  // that we can get coordinates from
  if (rec == null) {
    // Can't get coords at start of blank line, so we
    // insert a char at the cursor, get the coords of that,
    // then delete it again. Happens too fast to see.
    ran.insertNode( document.createTextNode(".") );
    rec = ran.getClientRects()[0];  // try again now that there's text
    ran.deleteContents();
  }
  var top = rec.top;               // Y coord of selection top edge
  var bottom  = rec.bottom;        // Y coord of selection bottom edge
  var vph = getViewportHeight();
  if (top < 0)      // if selection top edge is above viewport top,
    window.scrollBy(0, top);  // scroll up by enough to make the selection top visible
  if (bottom >= vph)   // if selection bottom edge is below viewport bottom,
    window.scrollBy(0, bottom-vph + 1); // scroll down by enough to make the selection bottom visible
}

viewportHeight 比 Web 应用所需的复杂。对于移动应用,我们需要考虑键盘,因此提供一种手动设置 viewportHeight 以及从 window.innerHeight 自动设置的方法。

【问题讨论】:

  • 不使用removeChild.execCommand('undo', .. 做了什么?
  • 感谢您的回复。我试过了。它也不起作用。
  • 我在这里看到了一些东西。在 contentEditable 上,它会在每一行周围创建一个
    标签,因此会发生这种情况:
    Line 1

    /div>
    Line 2
    如果我强制第 1 行
    第 2 行并在那里编辑,它不会这样做,但如果我在 div 中输入它会这样做。

标签: javascript ios uiwebview removechild


【解决方案1】:

我不知道这是否适用于 iOS,但如果光标的位置意味着此时有一个选择..

function moveToSelection(){
    var sel = document.getSelection(), // change the selection
        ran = sel.getRangeAt(0),       // into a range
        rec = ran.getClientRects()[0], // that we can get co-ordinates from
        dy  = rec.top;                 // distance to move down/up
    window.scrollBy( 0, dy );          // actual move

    // console.log( sel, ran, rec, y );   // help debug
}

moveToSelection();

相关链接

  1. getSelection
  2. getRangeAt
  3. getClientRects
  4. scrollBy

【讨论】:

  • 看起来很接近。但是,如果我在换行符之后直接键入一个键,我会收到一个未定义的错误。这意味着光标位于 '

    ' 内,如果没有文本,我假设无法形成矩形。有什么建议如何针对该实例进行调整?此外,如果您有任何想法如何在光标已经在视口中时不滚动,我也会很感激。目前,即使光标已经在视口内,它也会自动转到顶部。感谢您抽出宝贵时间!
  • 为了不滚动,检查dy是否小于视口的高度。至于未定义,在这种情况下找出范围的值,为它添加检查并忽略该情况或执行不同的操作(例如滚动到最后一个&lt;br&gt;
  • 谢谢@shhac!我们让它工作了。稍后我会发布最终代码,因为我们需要先清理一些东西。
  • 嗯,这确实有效,但我不太明白 rec.top 如何代表 dy?
  • @KevinLee developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly/top 底部的支持表并不反映上述代码的支持,因为 mdn 页面特定于原型树的一部分,不一定匹配,但是有交叉实现
猜你喜欢
相关资源
最近更新 更多
热门标签