I have problem while calling jquery functions it generates double output while when we do highlight questions and crossout on html content sometimes highlight and crossout also not working with selecting using Ctrl+A or select all.

highlight and crossout values i am storing to database so, we can remain next time in questions.

I am trying and just needs to works it well.

Click Here For Output

HTML CODE:

<style>
.highlight{background:yellow;}
.crossout{text-decoration: line-through;}
</style> <input type="button" onClick="return false;" id="btn_highlight" unselectable="on" value="highlight" class="unselectable" alt="highlight" width="36" height="38"> <input type="button" onClick="return false;" id="btn_crossout" unselectable="on" value="crossout" class="unselectable" alt="crossout" width="36" height="38" /> <input name="highlight" id="highlight" type="text" value=""/> <input name="crossout" id="crossout" type="text" value=""/> <div class="highlight_area"> <div id="high" class="question_area"> <div class="question_stem"> <p>A 47-year-old male with chronic kidney disease and peptic ulcer disease presents to the emergency room with chest pain. The patient states the pain increases with breathing and radiates to his back but improves with leaning forward. He states that he recently had a viral upper respiratory infection that left him with a cough for the past 3 weeks. An echocardiogram is ordered which appears normal. EKG shows diffuse ST segment elevations with PR depression. What is the most appropriate treatment at this time?</p> </div> <br> </div> <div class="input radio"><input type="radio" name="data[Answer][answer]" id="answer11" value="1"><label for="answer11">A.  NSAID only</label></div> <div class="input radio"><input type="radio" name="data[Answer][answer]" id="answer22" value="2"><label for="answer22">B.  Colchicine only</label></div> <div class="input radio"><input type="radio" name="data[Answer][answer]" id="answer33" value="3"><label for="answer33">C.  NSAIDS and colchicine</label></div> <div class="input radio"><input type="radio" name="data[Answer][answer]" id="answer44" value="4"><label for="answer44">D.  Corticosteroids</label></div> <div class="input radio"><input type="radio" name="data[Answer][answer]" id="answer55" value="5"><label for="answer55">E.  Dialysis</label></div> <input type="hidden" name="data[Answer][correct]" value="2" id="AnswerCorrect"> </div>

JQUERY CODE:

$(document).on('click', '#btn_highlight', function() {
    select('#highlight');
    apply('highlight');
});
$(document).on('click', '#btn_crossout', function() {
    select('#crossout');
    apply('crossout');
});
function select(id) {
    function append(id, begin, end) {
        // console.log('Add: ' + begin + ' to ' + end);
        var highlights = $(id).val().trim().split(',');
        var start = -1;
        var done = -1;
        var duplicate = -1;
        var inside = -1;
        var out = [];
        var previous = 99999999;
        var on = false;
        for (x in highlights) {
            var mark = highlights[x];
            if (!mark) continue;
            // console.log('Check: ' + mark + ' Start: ' + start + ' End: ' + done);
            if (duplicate == mark) {
                // console.log('Repeated mark');
                out.push(mark);
            }
            if (done >= 0) {
                out.push(mark);
                continue;
            } else if (start < 0) {
                if (end < mark) {
                    // console.log('Prepend new');
                    out.push(begin);
                    out.push(end);
                    out.push(mark);
                    start = mark;
                    done = end;
                } else if (end == mark || begin < mark) {
                    if (!on && end <= mark) {
                        // console.log('Prepend consecutive');
                        out.push(begin);
                        out.push(end);
                        out.push(mark);
                        done = mark;
                    } else if (on) {
                        // console.log('Start inside');
                        inside = begin
                    } else {
                        // console.log('Start new');
                        out.push(begin);
                    }
                    start = begin;
                } else if (begin == mark) {
                    // console.log('Start overlapped');
                    duplicate = mark;
                    start = mark;
                } else {
                    // console.log('Skip one');
                    out.push(mark);
                }
            }
            if (done < 0 && start >= 0) {
                if (end == mark) {
                    if (inside >= 0) {
                        // console.log('End overlapped from inside');
                        out.push(inside);
                        on = !on;
                    } else if (duplicate < 0) {
                        // console.log('End overlapped from outside');
                        out.push(end);
                    }
                    done = mark;
                } else if (end > previous && end < mark) {
                    if (!on || duplicate >= 0) {
                        // console.log('End new');
                        out.push(end);
                    }
                    out.push(mark);
                    done = mark;
                }
            }
            on = !on;
            // console.log(out);
            previous = mark;
        }
        if (done < 0) {
            if (duplicate >= 0 && begin == mark) {
                out.push(begin);
                out.push(begin);
                out.push(end);
            } else {
                if (start < 0) {
                    out.push(begin);
                } else if (duplicate >= 0) {
                    // console.log('End from duplicate');
                    out.push(duplicate);
                }
                out.push(end);
            }
        }
        $(id).val(out.toString().trim(','));
        // console.log(id + ': ' + $(id).val());
        if (out.length % 2 != 0) {
            console.log('Error!');
        }
    }
    var temp = '#temp';
    function getIndex(elem, offset) {
        var parent = $(elem).parents('.highlight_area');
        elem.nodeValue = temp + elem.nodeValue;
        var text = parent.text();
        var add = text.indexOf(temp);
        offset = offset + add;
        elem.nodeValue = elem.nodeValue.substr(temp.length);
        return offset;
    }
    function getIndex2(elem, offset) {
        var parent = elem.parents('.highlight_area');
        elem.text(temp + elem.text());
        var text = parent.text();
        var add = text.indexOf(temp);
        offset = offset + add;
        elem.text(elem.text().substr(temp.length));
        return offset;
    }
    function getElem(node) {
        if (node.is('.highlight,.crossout')) {
            node = node.parent();
        }
        return node;
    }
    var highlight = window.getSelection();
    // console.log(highlight);
    var base = highlight.focusNode;
    var anchor = highlight.anchorNode;
    var baseOffset = highlight.focusOffset;
    var anchorOffset = highlight.anchorOffset;
    if (!highlight.rangeCount || !$(base).parents('.highlight_area').length || !$(anchor).parents('.highlight_area').length) {
        // console.log(highlight.rangeCount + ' ; ' + $(base).parents('.highlight_area').length + ' ; ' + $(anchor).parents('.highlight_area').length);
        return;
    }
    baseOffset = getIndex(base, baseOffset);
    anchorOffset = getIndex(anchor, anchorOffset);
    var stem = $('.highlight_area');
    var baseIndex = getElem($(base.parentElement)).index();
    var anchorIndex = getElem($(anchor.parentElement)).index();
    var start = Math.min(baseOffset, anchorOffset);
    var end = Math.max(baseOffset, anchorOffset);
    // console.log('Offset: ' + start + ' to ' + end);
    // console.log('Indexes: ' + baseIndex + ' v ' + anchorIndex);
    if (baseIndex == anchorIndex) {
        append(id, start, end);
    } else {
        var children = stem.find(':not(.highlight,.crossout)');
        var startIndex = Math.min(baseIndex, anchorIndex);
        var endIndex = Math.max(baseIndex, anchorIndex);
        var child = $(children[startIndex]);
        var text = child.text();
        var textStart = getIndex2(child, text.length);
        append(id, start, textStart);
        for (var i = startIndex + 1; i < endIndex; i++) {
            child = $(children[i]);
            text = child.text();
            if (!text.trim().length) continue;
            append(id, textStart, textStart + text.length);
            textStart = textStart + text.length;
        }
        var child = $(children[endIndex]);
        var textStart = getIndex2(child, 0);
        append(id, textStart, end);
    }
}
function apply() {
    var highlights = $('#highlight').val().split(',');
    var crossouts = $('#crossout').val().split(',');
    var marks = {};
    for (x in highlights) {
        if (typeof marks[highlights[x]] != 'undefined') {
            // 2 consecutive highlights
            marks[highlights[x]] = 4;
        } else {
            marks[highlights[x]] = 1;
        }
    }
    for (x in crossouts) {
        if (typeof marks[crossouts[x]] == 'undefined') {
            marks[crossouts[x]] = 2;
        } else {
            if (marks[crossouts[x]] == 4) {
                // 2 highlights and a crossout
                marks[crossouts[x]] = 6;
            } else if (marks[crossouts[x]] == 2) {
                // 2 consecutive crossouts
                marks[crossouts[x]] = 5;
            } else if (marks[crossouts[x]] == 6) {
                // 2 consecutive highlights and crossouts
                marks[crossouts[x]] = 7;
            } else if (marks[crossouts[x]] == 3) {
                // 2 consecutive crossouts and highlight
                marks[crossouts[x]] = 8;
            } else {
                // highlight and crossout
                marks[crossouts[x]] = 3;
            }
        }
    }
    var stem = $('.highlight_area');
    var children = stem.find(':not(.highlight,.crossout)');
    var childIndex = 0;
    var child = $(children[childIndex]);
    var text = child.text().replace(/(<([^>]+)>)/ig, "");
    var high = false;
    var cross = false;
    var previousMark = 0;
    var passedChars = 0;
    var mode = 0;
    var string = '';
    var nextEdge = 0;
    stem.empty();
    child.empty();
    var first = true;
    var maxLoop = 10;
    for (x in marks) {
        if (x == '') continue;
        // console.log('Mark: ' + x);
        nextEdge = 1 * passedChars + 1 * text.length;
        // console.log('Next edge: ' + nextEdge);
        var loopCount = 0;
        while (x > nextEdge && loopCount++ < maxLoop) {
            string = text.substr(previousMark - passedChars);
            stem.append(child.append(string));
            passedChars = 1 * passedChars + 1 * text.length;
            previousMark = passedChars;
            // move on to next
            childIndex = childIndex + 1;
            child = $(children[childIndex]);
            text = child.text();
            child.empty();
            nextEdge = 1 * text.length + 1 * passedChars;
            // console.log('Next edge : ' + nextEdge);
        }
        // console.log('Select: ' + previousMark + ' to ' + x);
        string = text.substr(previousMark - passedChars, x - previousMark);
        // console.log(string);
        var type = '';
        if (high) {
            type = type + ' highlight';
        }
        if (cross) {
            type = type + ' crossout';
        }
        if (type) {
            var span = $('<span></span>').addClass(type);
            span.text(string);
            child.append(span);
        } else {
            child.append(string);
        }
        previousMark = x;
        if (marks[x] == 1) {
            high = !high;
        } else if (marks[x] == 2) {
            cross = !cross;
        } else if (marks[x] == 3) {
            high = !high;
            cross = !cross;
        } else if (marks[x] == 4) {
            high = true;
        } else if (marks[x] == 5) {
            cross = true;
        } else if (marks[x] == 6) {
            high = true;
            cross = !cross;
        } else if (marks[x] == 7) {
            high = true;
            cross = true;
        } else if (marks[x] == 8) {
            high = !high;
            cross = true;
        }
    }
    string = text.substr(previousMark - passedChars);
    stem.append(child.append(string));
    childIndex = childIndex + 1;
    while (childIndex < children.length) {
        child = $(children[childIndex]);
        child.find('.highlight,.crossout').each(function(i, e) {
            child.html(child.html().replace($(e).outerHtml(), $(e).text()));
        });
        stem.append(child);
        childIndex = childIndex + 1;
    }
}
apply();