Created
May 11, 2014 21:42
-
-
Save A-gambit/628f4362bb7e4c565799 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//green - збережені елемени | |
//red - видалені елменти | |
//blue - додані елменти | |
//orange - змінені елменти | |
var b, //before - перший фрагмент | |
a; //after - другий фрагмент | |
var bTag, //тегы before | |
aTag; //тегы after | |
var elem = [], //масив елементів з after, які збереглися у before | |
num=0, //кількість елементів у масиві elem | |
elemBefore = []; //масив елементів з before, які збереглися у after | |
numBefore=0; //кількість елементів у масиві elemBefore | |
cur=-1, //поточный номер збереженого елемента в before | |
mark = []; //масив маркерів на теги after | |
var objFirst = new Object(); //об'єкт, який зберігає нові елементи after | |
objFirst.type='added'; //ім'я об'єкту objFirst | |
objFirst.element=[]; //масив, який містить нові елементи у фрагменті after | |
var objSecond = new Object(); //об'єкт, який зберігає нові елементи before | |
objSecond.type='removed'; //ім'я об'єкту objSecond | |
objSecond.element=[]; //масив, який містить елементи before, яким не знайдено відповідність у after | |
var objThird = new Object(); //об'єкт, який зберігає елементи в яких потрібна заміна | |
objThird.type='changed'; //ім'я об'єкту objThird | |
objThird.beforeElement=[]; //масив елементів з after, які потребують заміни | |
objThird.afterElement=[]; //масив елементів з before, які потребують заміни | |
objThird.html=[]; //innerHTML after, які потребують заміни (або src(href) у випадку посилань) | |
//======функуція підготовки початкови станів тегів фрагментів, та значень глобальнх змінних============= | |
function prepear(){ | |
//перевірка на рівності фрагментів | |
if(b.innerText===a.innerText){ | |
b.style.color="green"; | |
a.style.color="green"; | |
} | |
else{ | |
b.style.color="red"; | |
a.style.color="blue"; | |
} | |
//маркування тегів фрагментів before | |
for(var i=0;i<bTag.length;i++){ | |
if(bTag[i].src!==undefined) | |
bTag[i].style.cssText="border: 4px solid red;"; | |
else | |
bTag[i].style.cssText="color: red;"; | |
} | |
//маркування тегів фрагментів after та підготовка масиву mark | |
for(var i=0;i<aTag.length;i++){ | |
if(aTag[i].src!==undefined) | |
aTag[i].style.cssText="border: 4px solid blue;"; | |
else | |
aTag[i].style.cssText="color: blue;"; | |
mark[i]=true; | |
} | |
} | |
//================ функція пошуку елементу (використовується для фраменту у after)======================= | |
function findElement(el){ | |
//значення елменту, який потрібно знайти | |
for(var i=0; i<elem.length;i++){ | |
if(elem[i]===el) | |
return false; | |
} | |
return true; | |
} | |
//================ функція первірки розташування збереженого елменту у after============================ | |
function position(el){ | |
//елемент, що шукається серед елментів after | |
for(var i=0;i<aTag.length;i++){ | |
if(aTag[i].tagName===el.tagName){ | |
if(aTag[i].src!==undefined){ | |
if(aTag[i].style.cssText!=="border: 4px solid green;" && el.src===aTag[i].src && mark[i]){ | |
mark[i]=false; | |
//перевірка чи поточний знайдений елемент має правильне розташування | |
if(i>cur){ | |
cur=i; | |
return true; | |
} | |
else | |
return false; | |
} | |
} | |
else{ | |
if(aTag[i].style.color!="green" && el.innerHTML===aTag[i].innerHTML && mark[i]){ | |
mark[i]=false; | |
//перевірка чи поточний знайдений елмент має правильне розташування | |
if(i>cur){ | |
cur=i; | |
return true; | |
} | |
else | |
return false; | |
} | |
} | |
} | |
} | |
} | |
//================функція превірки рівності посилань у елементах======================================= | |
function checkHref(beforeChilde, afterChilde, func){ | |
/*елемент з фрагменту before, елемент з фрагменту after, значення виклику функції | |
(значення пошуку однакових елементів/елементів, які потребують заміни, у фрагментах before та after)*/ | |
if(func){ | |
if(beforeChilde.href!==undefined && afterChilde.href!==undefined){ | |
if(beforeChilde.href===afterChilde.href){ | |
return true; | |
} | |
else | |
return false; | |
} | |
else{ | |
if(beforeChilde.href!==undefined || afterChilde.href!==undefined){ | |
return false; | |
} | |
else | |
return true; | |
} | |
} | |
else | |
return true; | |
} | |
//=================функція перевірки знаходження елементів, які потребують заміни===================== | |
function count(beforeChilde, afterChilde){ | |
//елемент з фрагменту before, елемент з фрагменту after | |
beforeChilde=beforeChilde.firstChild; | |
afterChilde=afterChilde.firstChild; | |
var beforeNumber=0,//кількість братів елементу у фрагменті before, які збережені у фрагменті after | |
afterNumber=0; //кількість братів елементу у фрагменті after, які збережені у фрагменті before | |
while(beforeChilde){ | |
if(beforeChilde.tagName!==undefined){ | |
if(beforeChilde.style.color==="green" || beforeChilde.style.cssText==="border: 4px solid green;"){ | |
beforeNumber++; | |
} | |
} | |
beforeChilde=beforeChilde.nextSibling; | |
} | |
while(afterChilde){ | |
if(afterChilde.tagName!==undefined){ | |
if(afterChilde.style.color==="green" || afterChilde.style.cssText==="border: 4px solid green;"){ | |
afterNumber++; | |
} | |
} | |
afterChilde=afterChilde.nextSibling; | |
} | |
//перевірка на рівність збережених братів | |
if(beforeNumber===afterNumber) | |
return true; | |
else | |
return false; | |
} | |
//=================функція перевірки батьківсьго збережених елементів================================== | |
function know(beforeChilde,afterChilde){ | |
//елемент з фрагменту before, елемент з фрагменту after | |
if(numBefore!==0){ | |
//перевірка умови існування одного батька у елементів | |
if(beforeChilde.parentNode===elemBefore[numBefore-1].parentNode){ | |
//перевірка умови існування одного батька | |
if(afterChilde.parentNode===elem[num-1].parentNode){ | |
return true; | |
} | |
else | |
return false; | |
} | |
else | |
return true; | |
} | |
else | |
return true; | |
} | |
/*====================функція знаходження подібних елментів before та after=============================== | |
===================================та елементів, яким потрібна заміна======================================*/ | |
function check(beforeNode, afterNode, func){ | |
/*елемент з фрагменту before, елемент з фрагменту after, значення виклику функції | |
(значення пошуку однакових елементів/елементів, які потребують заміни, у фрагментах before та after)*/ | |
var beforeChilde = beforeNode.firstChild,//задання елементу, як першого молодшого елементу beforeNode | |
afterChilde = afterNode; //задання елементу, який рівний afterNode | |
//поки існує елмент | |
while(beforeChilde){ | |
//перевірка на відповідність по всім елементам afterNode | |
for(var i=0; i<afterNode.childElementCount;i++){ | |
afterChilde=afterNode.children[i];//задати елемент як поточний елмент afterNode | |
//перевірка на однаковість типів елементів | |
if(beforeChilde.tagName===afterChilde.tagName){ | |
//перевірка на використання елемента | |
if(findElement(afterChilde)){ | |
//перевірка на наявність дітей у елементів | |
if(beforeChilde.childElementCount>0 && afterChilde.childElementCount>0){ | |
check(beforeChilde, afterChilde, func); | |
} | |
else{ | |
//перевірка на посилання | |
if(checkHref(beforeChilde,afterChilde,func)){ | |
//перевірка на тип елементу - зображення чи завантажений контент | |
if(beforeChilde.src===undefined){ | |
//перевірка innerHTML | |
if(func && beforeChilde.innerHTML===afterChilde.innerHTML && beforeChilde.style.color!=="green"){ | |
//перевірка послідовності розташування елемента за останнім збереженим фрагментом | |
if(position(afterChilde)){ | |
//перевірка послідовності розташування елемента за його батьківським елементом | |
if(know(beforeChilde,afterChilde)){ | |
//маркування елементів та додавання до відповідних масивів | |
beforeChilde.style.color="green"; | |
afterChilde.style.color="green"; | |
elem[num]=afterChilde; | |
elemBefore[numBefore]=beforeChilde; | |
numBefore++; | |
num++; | |
break; | |
} | |
} | |
} | |
//перевіка на маркування елемента у випадку пошуку елементів, яким потрібна заміна | |
if(!func && beforeChilde.style.color!=="green"){ | |
//перевірка правильності розташування елемента, який потребує заміни | |
if(count(beforeChilde.parentNode, afterChilde.parentNode)){ | |
//маркування елементів та додавання до відповідних масивів та об'єктів | |
beforeChilde.style.color="orange"; | |
afterChilde.style.color="orange"; | |
objThird.beforeElement[objThird.beforeElement.length]=beforeChilde; | |
objThird.afterElement[objThird.afterElement.length]=afterChilde; | |
objThird.html[objThird.html.length]=afterChilde.innerHTML; | |
elem[num]=afterChilde; | |
num++; | |
break; | |
} | |
} | |
} | |
else{ | |
if(func &&beforeChilde.src===afterChilde.src && beforeChilde.style.cssText!=="border: 4px solid green;"){ | |
if(position(afterChilde)){ | |
if(know(beforeChilde,afterChilde)){ | |
//маркування елементів та додавання до відповідних масивів | |
beforeChilde.style.cssText="border: 4px solid green;"; | |
afterChilde.style.cssText="border: 4px solid green;"; | |
elem[num]=afterChilde; | |
elemBefore[numBefore]=beforeChilde; | |
numBefore++; | |
num++; | |
break; | |
} | |
} | |
} | |
//перевіка на маркуванння елемента у випадку пошуку елементів, яким потрібна заміна | |
if(!func && beforeChilde.style.cssText!=="border: 4px solid green;"){ | |
//перевірка правильності розташування елемента, який потребує заміну | |
if(count(beforeChilde.parentNode, afterChilde.parentNode)){ | |
//маркування елементів та додання до відповідних масивів та об'єктів | |
beforeChilde.style.cssText="border: 4px solid orange;"; | |
afterChilde.style.cssText="border: 4px solid orange;"; | |
objThird.beforeElement[objThird.beforeElement.length]=beforeChilde; | |
objThird.afterElement[objThird.afterElement.length]=afterChilde; | |
objThird.html[objThird.html.length]=afterChilde.src; | |
elem[num]=afterChilde; | |
num++; | |
break; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
//перехід до наступного елементу | |
beforeChilde=beforeChilde.nextSibling; | |
} | |
} | |
/*функція, яка знаходить нові елементи у другому фрагменті та елементи, яким не було знайдено відповідності у другому фрагменті, тобто видалені елементи | |
також функція маркує батьківські блоки з збереженими елементами*/ | |
function element(node, task, name){ | |
/*фрагмент в якому шукаються зміни | |
значення роботи функції - пошуку змін чи маркування збережених елементів | |
тип пошуку - нових/видалених елементів*/ | |
var childe = node.firstChild; //елемент перший син node | |
while(childe){ | |
if (childe.tagName!==undefined){ | |
if(!task){ | |
//пошук доданих елементів | |
if(name===1){ | |
if(childe.style.color==="blue" || childe.style.cssText==="border: 4px solid blue;"){ | |
objFirst.element[objFirst.element.length]=childe; | |
} | |
} | |
//пошук видалених елементів | |
else if(name===2){ | |
if(childe.style.color==="red" || childe.style.cssText==="border: 4px solid red;"){ | |
objSecond.element[objSecond.element.length]=childe; | |
} | |
} | |
} | |
element(childe, task, name); | |
//перевірка на функцію маркерування | |
if(task){ | |
if(childe.parentNode!==a && childe.parentNode!==b){ | |
if(childe.style.color==="green" || childe.style.cssText==="border: 4px solid green;"){ | |
childe.parentNode.style.color="green"; | |
} | |
} | |
} | |
} | |
childe=childe.nextSibling; | |
} | |
} | |
//функція пошуку змінених елементів | |
function change(beforeNode, afterNode){ | |
//елемент х фрагменту before, елемент х фрагменту after | |
var beforeChilde = beforeNode.firstChild, //перший син beforeNode | |
afterChilde = afterNode; //елемент рівний afterNode | |
while(beforeChilde){ | |
if(beforeChilde.tagName!==undefined){ | |
if(beforeChilde.style.color==="green"){ | |
for(var i=0; i<afterNode.childElementCount;i++){ | |
afterChilde=afterNode.children[i];//елемент син afterNode | |
if(afterChilde.style.color==="green"){ | |
if(afterChilde.tagName===beforeChilde.tagName){ | |
if(beforeChilde.childElementCount>0 && afterChilde.childElementCount>0){ | |
//перевірка на неоднаковість innerHTML | |
if(afterChilde.innerHTML!==beforeChilde.innerHTML){ | |
objThird.beforeElement[objThird.beforeElement.length]=beforeChilde; | |
objThird.afterElement[objThird.afterElement.length]=afterChilde; | |
objThird.html[objThird.html.length]=afterChilde.innerHTML; | |
beforeChilde.style.color="orange"; | |
afterChilde.style.color="orange"; | |
change(beforeChilde,afterChilde); | |
break; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
beforeChilde=beforeChilde.nextSibling; | |
} | |
} | |
//головна функція diff() | |
function diff(){ | |
b=document.getElementById('before');//задання зміної для фрагменту before | |
a=document.getElementById('after');//задання зміної для фрагменту after | |
bTag = b.getElementsByTagName('*');//задання тегів фрагменту before | |
aTag = a.getElementsByTagName('*');//задання тегів фрагменту after | |
//підготовка початкових значень | |
prepear(); | |
//пошук збережених елементів у фрагментах before та after | |
check(b, a, true); | |
//пошук крайніх елементів, яким потрібна заміна before та after | |
check(b, a, false); | |
//додавання до об'єкту objFirst з типом added, нових елментів | |
element(a, true, 1); | |
//маркування елементів after, які містять подібні елементи з фрагментом before | |
element(a, false, 1); | |
//додавання до об'єкту objSecond з типом removed, видалених елементів | |
element(b, true, 2); | |
//маркування елементів before, які містять подібні елементи з фрагментом after | |
element(b, false, 2); | |
//знаходження пар елементів у фрагментах before і after, які потребують заміни, та запис їх у об'єкті objSecond з типом changed | |
change(b,a); | |
//виведення отриманих результатів у консоль | |
console.log(objFirst); | |
console.log(objSecond); | |
console.log(objThird); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment