diff dom

by lid0

HTML

<!-- Sample of diff where existing elements got changes -->
<div class="container">
<div id="a" class='view'>
 <p>hellob</p>
 <p>aaa</p>
 <h1>this is sparta</h1>
 <p>what is going on</p>
 <p>bbbb</p>
</div>

<div id="b" class='view'>
 <p>hellob</p>
 <p>aaa</p>
 <h1>this is sparta2</h1>
 <p>what is going on</p>
 <p>bbabb</p>
</div>
    
</div>


<div class="container">
<div id="aa" class='view'>
 <p>hellob</p>
 <p>aaa</p>
 <h1>this is sparta</h1>
 <p>what is going on</p>
 <p>bbbb</p>
</div>

<div id="bb" class='view'>
 <p>aaa</p>
 <p>hellob</p>
 <p>aaa</p>
 <h1>this is sparta</h1>
 <h1>this is not sparta</h1>
 <p>what is going on</p>
 <p>ccccc</p>
 <p>bbbb</p>
 <p>ccccc</p>
 <p>ddddddd</p>
</div>    
</div>

<!-- Sample of diff with new lines
<div id="a">
 <p>hellob</p>
 <p>aaa</p>
 <h1>this is sparta</h1>
 <p>what is going on</p>
 <p>bbbb</p>
</div>

<div id="b">
 <p>aaa</p>
 <p>hellob</p>
 <p>aaa</p>
 <h1>this is sparta</h1>
 <h1>this is not sparta</h1>
 <p>what is going on</p>
 <p>ccccc</p>
 <p>bbbb</p>
 <p>ccccc</p>
</div>
-->

CSS

.view{
    border:1px solid #cfcfcf;
    display:inline-block;
    padding:5px;
    vertical-align:top;
}
.container{
    border-bottom:2px dashed black;
    margin-bottom:15px;
    display:block;
    clear:both;
}

.diff {
    border:1px dashed green;    
    background:#D8FFC5;
}

JavaScript

/**
 A prototype code to detect difference between two similar DOM containers.
 This is usful for an editor with a live preview, and the detection of the 
 element that was changes to bring it into view.
 
 Ideally the diff should be performed with a small increment of changes between.
 view A and view B
 
**/
a1 = $("#a");
b1 = $("#b");

a2 = $("#aa");
b2 = $("#bb");

function inner_diff(a,b){
    console.log("inner_diff", a, b);
    if (a.html() === b.html()){
        return true;
    } else{
        return false;
    }
}

console.log("equal by innerHTML:", inner_diff(a1,b1)? "yes" : "no");
    
function find_diff(a,b){
    var same_root_children = (a.length === b.length);
    console.log( a.length, b.length );
    var ai = 0, bi =0;
    
    while( (ai < a.length || bi < b.length) && (ai<a.length) && (bi<b.length) ){
        if ($(a[ai]).html() == $(b[bi]).html()){        
            console.log("match at", ai, bi);
        } else {
            console.log("diff at", ai, bi, $(b[bi]).html() );
            $(b[bi]).addClass("diff");
            if (same_root_children) {
                //if we have the same number of children
                //the change is on a specific line
                //once we detect the different line
                // we increment bot ai and bi pointers.
                
                //in this case we can also perform a deeper
                //diff if there are multiple childrens,
                //to identify the sub element it occured at.
            } else{
                ai--; //prevent increment 
            }
        }
        
        //detect new lines, when view b has more "lines" at the end
        if (ai==a.length-1 && bi < b.length){
            while(bi < b.length-1){ //mark the rest of the element as "new"
                bi++;                
                $(b[bi]).addClass("diff");
                console.log("possible more new lines", ai,bi,b[bi]);

            }
        }
        
        ai++;
       ...