복붙노트

[JQUERY] HTML에서 선택 후 다양한 개체의 변화를 지속

JQUERY

HTML에서 선택 후 다양한 개체의 변화를 지속

해결법


  1. 1.각 선택의 경우, 문자 오프셋 선택한 범위를 직렬화 할 수와 같은 것을 사용하여 다시로드에 다시 역 직렬화 :

    각 선택의 경우, 문자 오프셋 선택한 범위를 직렬화 할 수와 같은 것을 사용하여 다시로드에 다시 역 직렬화 :

    데모 : http://jsfiddle.net/WeWy7/3/

    암호:

    var saveSelection, restoreSelection;
    
    if (window.getSelection && document.createRange) {
        saveSelection = function(containerEl) {
            var range = window.getSelection().getRangeAt(0);
            var preSelectionRange = range.cloneRange();
            preSelectionRange.selectNodeContents(containerEl);
            preSelectionRange.setEnd(range.startContainer, range.startOffset);
            var start = preSelectionRange.toString().length;
    
            return {
                start: start,
                end: start + range.toString().length
            };
        };
    
        restoreSelection = function(containerEl, savedSel) {
            var charIndex = 0, range = document.createRange();
            range.setStart(containerEl, 0);
            range.collapse(true);
            var nodeStack = [containerEl], node, foundStart = false, stop = false;
    
            while (!stop && (node = nodeStack.pop())) {
                if (node.nodeType == 3) {
                    var nextCharIndex = charIndex + node.length;
                    if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
                        range.setStart(node, savedSel.start - charIndex);
                        foundStart = true;
                    }
                    if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
                        range.setEnd(node, savedSel.end - charIndex);
                        stop = true;
                    }
                    charIndex = nextCharIndex;
                } else {
                    var i = node.childNodes.length;
                    while (i--) {
                        nodeStack.push(node.childNodes[i]);
                    }
                }
            }
    
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        }
    } else if (document.selection) {
        saveSelection = function(containerEl) {
            var selectedTextRange = document.selection.createRange();
            var preSelectionTextRange = document.body.createTextRange();
            preSelectionTextRange.moveToElementText(containerEl);
            preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
            var start = preSelectionTextRange.text.length;
    
            return {
                start: start,
                end: start + selectedTextRange.text.length
            }
        };
    
        restoreSelection = function(containerEl, savedSel) {
            var textRange = document.body.createTextRange();
            textRange.moveToElementText(containerEl);
            textRange.collapse(true);
            textRange.moveEnd("character", savedSel.end);
            textRange.moveStart("character", savedSel.start);
            textRange.select();
        };
    }
    

  2. 2.커서가 새 단락의 시작 부분에있는 경우 문자 오프셋을 사용하면 작동하지 않습니다. 접근 방식은 아래의 DOM 노드를 산책하고 오프셋을 향한 모든 노드를 계산합니다. 또한 핸들을 시작하고 있는지 선택의 정확한 위치를 기억하고 있는지 확인하기 위해 개별적으로 끝납니다. 저는 여기에 주요 프로젝트에 사용 (끝 기능 참조) 것을 업데이트 된 버전은 다음과 같습니다

    커서가 새 단락의 시작 부분에있는 경우 문자 오프셋을 사용하면 작동하지 않습니다. 접근 방식은 아래의 DOM 노드를 산책하고 오프셋을 향한 모든 노드를 계산합니다. 또한 핸들을 시작하고 있는지 선택의 정확한 위치를 기억하고 있는지 확인하기 위해 개별적으로 끝납니다. 저는 여기에 주요 프로젝트에 사용 (끝 기능 참조) 것을 업데이트 된 버전은 다음과 같습니다

    /*
     Gets the offset of a node within another node. Text nodes are
     counted a n where n is the length. Entering (or passing) an
     element is one offset. Exiting is 0.
     */
    var getNodeOffset = function(start, dest) {
      var offset = 0;
    
      var node = start;
      var stack = [];
    
      while (true) {
        if (node === dest) {
          return offset;
        }
    
        // Go into children
        if (node.firstChild) {
          // Going into first one doesn't count
          if (node !== start)
            offset += 1;
          stack.push(node);
          node = node.firstChild;
        }
        // If can go to next sibling
        else if (stack.length > 0 && node.nextSibling) {
          // If text, count length (plus 1)
          if (node.nodeType === 3)
            offset += node.nodeValue.length + 1;
          else
            offset += 1;
    
          node = node.nextSibling;
        }
        else {
          // If text, count length
          if (node.nodeType === 3)
            offset += node.nodeValue.length + 1;
          else
            offset += 1;
    
          // No children or siblings, move up stack
          while (true) {
            if (stack.length <= 1)
              return offset;
    
            var next = stack.pop();
    
            // Go to sibling
            if (next.nextSibling) {
              node = next.nextSibling;
              break;
            }
          }
        }
      }
    };
    
    // Calculate the total offsets of a node
    var calculateNodeOffset = function(node) {
      var offset = 0;
    
      // If text, count length
      if (node.nodeType === 3)
        offset += node.nodeValue.length + 1;
      else
        offset += 1;
    
      if (node.childNodes) {
        for (var i=0;i<node.childNodes.length;i++) {
          offset += calculateNodeOffset(node.childNodes[i]);
        }
      }
    
      return offset;
    };
    
    // Determine total offset length from returned offset from ranges
    var totalOffsets = function(parentNode, offset) {
      if (parentNode.nodeType == 3)
        return offset;
    
      if (parentNode.nodeType == 1) {
        var total = 0;
        // Get child nodes
        for (var i=0;i<offset;i++) {
          total += calculateNodeOffset(parentNode.childNodes[i]);
        }
        return total;
      }
    
      return 0;
    };
    
    var getNodeAndOffsetAt = function(start, offset) {
      var node = start;
      var stack = [];
    
      while (true) {
        // If arrived
        if (offset <= 0)
          return { node: node, offset: 0 };
    
        // If will be within current text node
        if (node.nodeType == 3 && (offset <= node.nodeValue.length))
          return { node: node, offset: Math.min(offset, node.nodeValue.length) };
    
        // Go into children (first one doesn't count)
        if (node.firstChild) {
          if (node !== start)
            offset -= 1;
          stack.push(node);
          node = node.firstChild;
        }
        // If can go to next sibling
        else if (stack.length > 0 && node.nextSibling) {
          // If text, count length
          if (node.nodeType === 3)
            offset -= node.nodeValue.length + 1;
          else
            offset -= 1;
    
          node = node.nextSibling;
        }
        else {
          // No children or siblings, move up stack
          while (true) {
            if (stack.length <= 1) {
              // No more options, use current node
              if (node.nodeType == 3)
                return { node: node, offset: Math.min(offset, node.nodeValue.length) };
              else
                return { node: node, offset: 0 };
            }
    
            var next = stack.pop();
    
            // Go to sibling
            if (next.nextSibling) {
              // If text, count length
              if (node.nodeType === 3)
                offset -= node.nodeValue.length + 1;
              else
                offset -= 1;
    
              node = next.nextSibling;
              break;
            }
          }
        }
      }
    };
    
    exports.save = function(containerEl) {
      // Get range
      var selection = window.getSelection();
      if (selection.rangeCount > 0) {
        var range = selection.getRangeAt(0);
        return {
          start: getNodeOffset(containerEl, range.startContainer) + totalOffsets(range.startContainer, range.startOffset),
          end: getNodeOffset(containerEl, range.endContainer) + totalOffsets(range.endContainer, range.endOffset)
        };
      }
      else
        return null;
    };
    
    exports.restore = function(containerEl, savedSel) {
      if (!savedSel)
        return;
    
      var range = document.createRange();
    
      var startNodeOffset, endNodeOffset;
      startNodeOffset = getNodeAndOffsetAt(containerEl, savedSel.start);
      endNodeOffset = getNodeAndOffsetAt(containerEl, savedSel.end);
    
      range.setStart(startNodeOffset.node, startNodeOffset.offset);
      range.setEnd(endNodeOffset.node, endNodeOffset.offset);
    
      var sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
    };
    

    이것은 단지 (적어도 IE 9 이상) 최신 브라우저에서 작동합니다.


  3. 3.컨텍스트에 대한 자세한 내용을 모른 채, 정확한 대답을하기 어렵다,하지만 네, 그것은 가능할 것이다, 그러나 대부분의 경우 매우 복잡 할 것이다. 쓰임새에 따라 갈 수있는 몇 가지 방법이 있습니다.

    컨텍스트에 대한 자세한 내용을 모른 채, 정확한 대답을하기 어렵다,하지만 네, 그것은 가능할 것이다, 그러나 대부분의 경우 매우 복잡 할 것이다. 쓰임새에 따라 갈 수있는 몇 가지 방법이 있습니다.

    쿠키 또는 로컬 저장

    요소가 어떻게 수정했는지 당신은 클라이언트 측 저장 (쿠키, 로컬 스토리지 또는 이와 유사한 것) 등에 대한 정보 저장의 일종을 사용할 수 있습니다. 페이지가 다시로드 될 때마다 해당 스토리지를 읽고 변경 사항을 적용합니다. 어떻게 이러한 변화가 어떻게 만들어 지는지에 따라 달라집니다 구현하고, 난 두려워 하나의 SO-대답 커버에 광범위한 to0 될 것입니다.

    서버 측 저장소

    당신은 그들이 (구성되어 있지만) 뭔가의 모양을 변경할 때마다 각 사용자가 (당신이 인증의 형태가) 누구인지 알고있는 경우 서버 및 데이터베이스에 해당 변경 사항 저장 아약스 요청을합니다. 이후의 모든 페이지로드에, 당신은 다음, 사용 요청을하고 무엇을 확인해야 그들이 어떤 변경 한 있는지 확인하기 위해 데이터베이스에 조회를 수행하고 경우에 따라 적용 할 수 있습니다.

    모두 클라이언트 - 서버 측 스토리지 솔루션에 대한 일반적인 그들은 내가 믿는 구현하기가 매우 광범위 할 것입니다.

    브라우저 플러그인

    이동하는 또 다른 방법은 사용자가 웹 페이지를 렌더링하는 방식을 사용자 정의 할 수 있습니다 파이어 폭스 Greasemonkey와 같은 플러그인을 활용하는 것입니다. 이러한 사용자 지정은 페이지가로드에 걸쳐 지속 될 것입니다.

  4. from https://stackoverflow.com/questions/13949059/persisting-the-changes-of-range-objects-after-selection-in-html by cc-by-sa and MIT license