代码之家  ›  专栏  ›  技术社区  ›  Hao Wu

如何知道输入框中文本的哪一部分发生了更改?

  •  1
  • Hao Wu  · 技术社区  · 7 年前

    我有一个输入框,我希望我能检测到用户修改的细节。

    例如:

    • deletedTextCount = 0, deletePosition = -1, insertPosition = 0, insertedText = 'A'

    • 当框中有“ABCD”时,用户将插入符号放在“C”之后,然后单击backspace:

      deletedTextCount = 1, deletePosition = 2, insertPosition = -1, insertedText = ''

    • deletedTextCount = 2, deletePosition = 1, insertPosition = 1, insertedText = 'FOO'

    输入事件是否有属性可以提供这些,或者我必须以某种方式计算它们?

    $('#input').on('input', onChange);
    
    let before = '';
    
    function onChange(target){
      const { value: after } = target.currentTarget;
      
      console.log(`before: ${before}, after: ${after}`);
      
      let insertedText = '';
      let insertPosition = -1;
      
      let deletedTextCount = 0;
      let deletePosition = -1;
      
      before = after;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <input id="input" type="text" />
    2 回复  |  直到 7 年前
        1
  •  0
  •   dotconnor    7 年前

    编辑 好的,当从输入的中间开始工作时,这不起作用,但是我建议使用一个字符串差异库,比如 jsdiff 以获取非常详细的更改列表。


    此函数将计算更改、添加或删除的内容。

    $('#input').on('input', onChange);
    
    let before = '';
    
    function onChange(target){
      const { value: after } = target.currentTarget;
      // Length of change, negative if removed
      const lengthChange = after.length - before.length;
      let changed;
      // If added some, get the new stuff
      if (lengthChange > 0) {
        changed = after.slice(after.length - lengthChange);
      // Other wise get the old stuff
      } else {
        changed = "-" + before.slice(before.length + lengthChange);
      }
      console.log(`before: ${before}, change: ${changed}, after: ${after}`);
      before = after;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <input id="input" type="text" />
        2
  •  0
  •   Hao Wu    7 年前

    $('#input').on('input', onChange);
    
    let before = '';
    
    function onChange(target){
        const { selectionStart: start, value: after } = target.currentTarget;
        
        // calculate the different starting points from both direction
        let p1 = 0, p2 = 0;
        // calclate the end point first
        for(; p2 < after.length - start; p2++){
            if(before[before.length - 1 - p2] === undefined || before[before.length - 1 - p2] !== after[after.length - 1 - p2]){
                break;
            }
        }
        // calclate start point
        for(; p1 < after.length - p2 - (after.length > before.length ? 1 : 0); p1++){
            if(before[p1] !== after[p1] || p1 + p2 >= before.length){
                break;
            }
        }
        
        let insertedText = '';
        let insertPosition = -1;
        
        let deletedTextCount = 0;
        let deletePosition = -1;
        
        // has delete
        if(p1 + p2 < before.length){
            deletedTextCount = before.length - (p1 + p2);
            deletePosition = p1;
        }
    
        // has add
        if(p1 + p2 < after.length){
            insertedText = after.substr(p1, after.length - (p1 + p2));
            insertPosition = p1;
        }
        
        console.log(`deletePosition: ${deletePosition}, deletedTextCount: ${deletedTextCount}, insertPosition: ${insertPosition}, insertedText: "${insertedText}"`);
        
        before = after;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <input id="input" type="text" />