Search code examples
htmljquerydom-traversal

Comparing Original Array of Dom Elements with Sort Array of Dom Elements and check if they are different


I have a structure of dynamic DOM elements that I'm continuously evaluating with a for loop and a setInterval. While in that interval I sort the array and then change the dom with a JQuery Sort function in order to order my DOM structure on the fly.

The thing is I only want to change the DOM if the sort function is actually changing the order of elements (usually this happens when a new DOM element comes into the structure dynamically), if the sort function runs again over an already sortered array I don't want to do anything with the dom.

I have found A LOT of ways to compare if Arrays are equal but my case is special since i don't really care about the arrays elements / content but I really need to check if those elements are not in the same order so i can change the dom.

    setInterval(function () {       
    //Incoming Chat Structure Variables
    var $incomingChatsTable, $incomingChatsRows, $incomingChatTags
    $incomingChatsTable= $("div[__jx__id*='incoming_list__list_content_container']")
    $incomingChatsRowsContainer=$("div[__jx__id='___$_194__visitor_list__incoming_list__list__content']")
    $incomingChatsRows = $("div[class*='renderers_Incoming']")
    $incomingChatTags = $( "div[__jx__id*='incoming_list__list__content'] div[class*='renderers_Incoming'] .visitorlist_tags .jx_ui_html_span:last-child .tag").toArray()        
    $popupTrigger = $("div[jx\\:list\\:rowid]") 
    //Assigning Priorities Function
    function assignPriority(arrayParent) {
        for ( var i=0; i <= arrayParent.length; i++) {
            var actualRow = $(arrayParent[i])
            var minutesInQueue = $(actualRow).find('.time_cell').text().substr(0,2)
            var priorityVal = parseInt(minutesInQueue)
            var actualRowTags = $( actualRow ).find('.tag').toArray()
            $(actualRow).addClass('priorityRow')               
            for (var k=0; k <= actualRowTags.length; k++) {
                let normalHolderTag = $(actualRowTags[k]).text().toLowerCase()
                if (normalHolderTag === 'vip') {
                    priorityVal += 30
                    $(actualRow).attr('data-priority', priorityVal)                    
                } else if ( normalHolderTag === 'rg' ) {
                    priorityVal += 20
                    $(actualRow).attr('data-priority', priorityVal)
                } else if ( normalHolderTag === 'accountclosure' ) {
                    priorityVal += 10
                    $(actualRow).attr('data-priority', priorityVal)                    
                } else {
                    $(actualRow).attr('data-priority', priorityVal)   
                } 
                //$(actualRow).find('.numbers_cell').text(priorityVal)
            }
        }     
    }   
    //Sorting Incoming Chats By Priority
    function orderByPriority(container) {
        myArray = container.find('.priorityRow')
        var changed = false
        myArray.sort(function(a,b){
            contentA = parseInt( $(a).data('priority') )
            contentB = parseInt( $(b).data('priority') )
            if ( (contentB - contentA) * ( myArray.indexOf(b) - myArray.indexOf(a) ) > 0 ){
                changed = true
            }                     
            return (contentB - contentA)                             
        })
        if(changed) {
            $(sortedArray).prependTo( container )
        } else{
            console.log('No need To Sort')
        }
    }
    setInterval(function () {
        assignPriority( $incomingChatsRows )
        orderByPriority( $incomingChatsRowsContainer )
    }, 500)
}, 1000) 

UPDATE:

myArray is now a global variable, I have added an IF statement evaluating the sort function result and multiplying that result by the a, b indexes. If that's greater than 0 then i change the value of my "changed" variable to "true" BUT I'm getting a "myArray.indexOf is not a function" error.


Solution

  • You can add a line of code in your orderByPriority sort function which sets a variable to true only if it actually changes something:

    function orderByPriority(container) {
            var myArray = container.find('.priorityRow')
            var changed = false
            myArray.sort(function(a,b){
                contentA = parseInt( $(a).data('priority') )
                contentB = parseInt( $(b).data('priority') )
                if((contentB - contentA)*(myArray.index(b)-myArray.index(a))>0){ 
                //check if these have the same sign, i.e. something has changed
                changed = true;
                }
                return (contentB - contentA)                              
            })
            if(changed){}//do something to modify DOM
        }
    

    The sort function has three possible outputs which will determine whether the two inputs need to be sorted:

    • Greater than 0: sort a to an index greater than b
    • Less than 0: sort b to an index greater than a
    • Equal to 0: don't change the order

    The possible conditions which will result in a change being made are therefore:

    • Output greater than 0 and the index of a is currently less than the index of b
    • Output less than 0 and the index of a is currently greater than the index of b

    We can represent the difference between the two indexes as index(b)-index(a). If the index of a is currently less than the index of b, this value will be positive. Otherwise, the value will be negative.
    We can thus see that the above conditions are really saying:

    • if output and index(b)-index(a) have the same sign, something needs to be changed.

    We can check if they have the same sign by multiplying them by eachother and testing if the result is greater than 0. This means that something has changed, so inside the if condition we set changed to true