开发者

How to increase performance of this js script (function calls exponentially increasing)?

Any general tips how to increase a longish js code like this? It works great but sometimes it gets a little sluggish and all the drag/drop and ajax features slow down.

I know this code is a little longer so I am not looking for specific suggestions. Just your first thoughts after taking a quick glance at this code.

EDIT:

I have found a pretty scary thing. The calls to dragDrop() are exponentially increasing in the $('.folderListOnclick').click event. After each click dragDrop() is called 1 time, 2 times, 4 times, 8 times. That's what's slowing it down.

But I don't understand why it is happening.

<script type="text/javascript">
    //<!--
$(document).ready(function() {

    function in_array (needle, haystack, argStrict) {
        var key = '', strict = !!argStrict; 
        if (strict) {
            for (key in haystack) {
                if (haystack[key] === needle) {
                    return true;            }
            }
        } else {
            for (key in haystack) {
                if (haystack[key] == needle) {
                    return true;
                }
            }
        }
         return false;
    }

    var openedFolders = new Array();

    var start = 0;
    var stop = 0;
    $('.drag').each(function() {
        var draggables = $(this).parents('table').find('.drag');
        var $next = draggables.filter(':gt(' + draggables.index(this) + ')').first();
        var width = $(this).css('width');
        var nextWidth = $next.css('width');
        if (nextWidth > width /*&& 30 == parseInt(width)*/) {
            $(this).removeClass('ordinaryFolderClosed');
            $(this).removeClass('ordinaryFolderOpened');
            if (in_array($(this).attr('rel'), openedFolders)) {
                $(this).addClass('ordinaryFolderOpened');
            } else {
                $(this).addClass('ordinaryFolderClosed');
            }               
        }
        if (in_array($(this).attr('rel'), openedFolders)) {
            start = 1;
        }
        if (1 == start && stop < 2) {               
            if (30 == parseInt(width)) {
                stop++;
            }
        } else {
            start = 0;
            stop = 0;
            if (parseInt(width) > 30) {
                $(this).parent().parent().hide();
            }
        }
    });

    function dragDrop()
    {       
        $('.folders .trow1').hover(
            function () {
                if ($(this).css('backgroundColor') != 'rgb(52, 108, 182)' && $(this).css('backgroundColor') != '#346cb6') {
                    $(this).css('background', "#C2E3EF");
                }
            },
            function () {
                if ($(this).css('backgroundColor') != 'rgb(52, 108, 182)' && $(this).css('backgroundColor') != '#346cb6') {
                    $(this).css('background', 'transparent');   
                }
            }
        );

        $('.drag').click(function() {

            if ($(this).hasClass('noclick')) {
                $(this).removeClass('noclick');
            } else {

                var draggables = $(this).parents('table').find('.drag');
                var $next = draggables.filter(':gt(' + draggables.index(this) + ')').first();
                var width = $(this).css('width');
                var nextWidth = $next.css('width');
                if (nextWidth > width /*&& 30 == parseInt(width)*/) {
                    var isVisible = $next.is(':visible');
                    if (isVisible) {
                        $(this).removeClass('ordinaryFolderClosed');
                        $(this).removeClass('ordinaryFolderOpened');
                        $(this).addClass('ordinaryFolderClosed');
                    } else {
                        $(this).removeClass('ordinaryFolderClosed');
                        $(this).removeClass('ordinaryFolderOpened');
                        $(this).addClass('ordinaryFolderOpened');
                    }
                    clickedId = $(this).attr('rel');
                    clickedId = clickedId.split(',');
                    clickedType = clickedId[1];
                    clickedId = clickedId[0];
//                  $.ajax({
//                      type:    'POST',
//                      url:     'body/obsah/mediaManager/setOpenedFolder.php',
//                      data:    'id='+clickedId+'&type='+clickedType,
//                      success: function(msg){
//                          //alert(msg);
//                      }
//                  });
                    var start = 0;
                    var stop = 0;
                    var i = 0;
                    // close folder
                    if (isVisible) {
                        $('.drag').each(function() {
                            if (0 == start) {
                                iteratedId = $(this).attr('rel');
                                iteratedId = iteratedId.split(',');
                                iteratedId = iteratedId[0];
                                if (iteratedId == clickedId) {
                                    start = 1;
                                }
                            }
                            if (1 == start && stop < 2) {
                                if ($(this).css('width') > width) {
                                    $(this).parent().parent().hide();
                                    if ($(this).hasClass('ordinaryFolderClosed') || $(this).hasClass('ordinaryFolderOpened')) {
                                        $(this).removeClass('ordinaryFolderClosed');
                                        $(this).removeClass('ordinaryFolderOpened');
                                        $(this).addClass('ordinaryFolderClosed');
                                    }
                                } else {
                                    stop++;
                                }
                            }
                            i++;
                        }); 
                    }
                    // open folder
                    else {
                        $('.drag').each(function() {
                            if (0 == start) {
                                iteratedId = $(this).attr('rel');
                                iteratedId = iteratedId.split(',');
                                iteratedId = iteratedId[0];
                                if (iteratedId == clickedId) {
                                    start = 1;
                                }
                            }
                            if (1 == start && stop < 2) {
                                if (parseInt($(this).css('width')) == parseInt(width)+5) {
                                    $(this).parent().parent().show();                   
                                }

                                if (parseInt($(this).css('width')) == parseInt(width)) {
                                    stop++;
                                }
                            }
                            i++;
                        });
                    }
                }

            }
        });

        var dragId = 0;
开发者_如何学Python        var dragType = 0;
        var dropId = 0;
        var dropType = 0;
        var isFile = false; 

        $('.drag').draggable({ 
            revert: true,
            cursorAt: {top: 0, left: 0},
            drag: function() {
                if ($(this).attr('rel') !== undefined) {
                    dragId = $(this).attr('rel');
                    dragId = dragId.split(',');
                    dragType = dragId[1];
                    dragId = dragId[0];
                }
                isFile = false;
            },
            start: function(event, ui) {
                 $(this).addClass('noclick');
            }
        });

        $('.drag2').draggable({
            revert: true,
            cursorAt: {top: 0, left: 0},
            drag: function() {
                if ($(this).attr('rel') !== undefined) {
                    dragId = $(this).attr('rel');
                    dragId = dragId.split(',');
                    dragType = dragId[1];
                    dragId = dragId[0];
                }
                isFile = true;
            }
        });     

        $('.drop').droppable({
            tolerance: 'pointer',
            drop: function() {
                if ($(this).attr('rel') !== undefined) {
                    dropId = $(this).attr('rel');
                    dropId = dropId.split(',');
                    dropType = dropId[1];
                    dropId = dropId[0];
                    if (dropId != dragId) {
                        if (false == isFile) {
                            $.ajax({
                                type:    'POST',
                                url:     'body/obsah/mediaManager/folder_move.php',
                                data:    'nid='+dragId+'&pid='+dropId+'&ft='+dropType,
                                success: function(msg){
                                    ajaxElementCall('left1', 'body/obsah/mediaManager/folder_list.php?type=1', 'right1', 'body/obsah/mediaManager/file_list.php?type=1&browse=0&assignType=0&CKEditorFuncNum=0&idFolder=0');
                                    dragDrop();
                                }
                            });
                        } else if (true == isFile) {
                            $.ajax({
                                type:    'POST',
                                url:     'body/obsah/mediaManager/file_move.php',
                                data:    'fid='+dragId+'&did='+dropId+'&ft='+dropType,
                                success: function(msg){
                                    ajaxElementCall('right1', 'body/obsah/mediaManager/file_list.php?type=1&browse=0&assignType=0&CKEditorFuncNum=0&idFolder=0&reloadTree=0');
                                    dragDrop();
                                }
                            });
                        }
                    }
                }           
            }
        });

    }

    dragDrop();

    $('.folderListOnclick').click(function() {
        var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0&reloadTree=0';
        ajaxElementCall('right1', 'body/obsah/mediaManager/file_list.php?type=1&'+append);
        dragDrop();
        $('.trow1').css('background', 'transparent');
        $('.trow1').css('color', '#3e4245');
        $(this).parent().css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
        $(this).parent().css('color', 'white');
    });

    $('.folderEditOnclick').click(function() {
        var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0';
        showModal('modal_div', 'Editácia adresára'); 
        ajaxElementCall('modal_div', 'body/obsah/mediaManager/folder_edit.php?kam=edit1&'+append);
    });

    $('.folderDeleteOnclick').click(function() {
        var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0';
        showModal('modal_div', 'Vymazanie adresára'); 
        ajaxElementCall('modal_div', 'body/obsah/mediaManager/folder_delete.php?kam=del1&'+append);
    });

    $('.addNewFolder').click(function() {
        showModal('modal_div', 'Nový adresár');
        var id = '0';
        $('.folders .trow1').each(function() {
            if ($(this).css('backgroundColor') == 'rgb(52, 108, 182)' || $(this).css('backgroundColor') == '#346cb6') {
                id = $(this).attr('rel');
                id = id.split(',');
                id = id[0];
            }
        });
        ajaxElementCall('modal_div', '/body/obsah/mediaManager/folder_add.php?type=1&kam=new1&idFolder='+id+'&browse=0&assignType=0&CKEditorFuncNum=0');
    });

});    //-->

</script>


Well you have not posted any of your HTML markup, and you have not posted the details of what the "ajaxElementCall" function does. Therefore it's hard to say exactly how you should fix the problem. It is true however that on every "drop" event, you end up calling the "dragDrop()" setup function again. You say that "ajaxElementCall" reloads some portion of the page, but your "dragDrop()" code always installs new event handlers on all ".drag" and ".drop" elements on the page. If "ajaxElementCall" only updates part of the page, then all the unchanged ".drag" and ".drop" elements will get additional event handlers piled on.

When you call .click() or .hover() for some selector, jQuery adds the event handler you supply to the set of handlers already registered. Thus, because you register new event handlers every time "dragDrop()" is called, you'll get more and more piled up. When an event happens, all of those handlers will be run.

Probably what you need to do is change "dragDrop()" so that you can tell it to only operate on a particular fraction of the page. Either that, or else when it runs it should "mark" each element it affects and then check for that mark before applying new event handlers. That way it will only affect newly-loaded code. (It would be more efficient to narrow down the search, however; the expression $('.drag') may have to look through every DOM element on the page, so it would be preferable to use something more precise anyway.)


For one, all the $(this) should be changed to use a variable.

var me = $(this); 

me.XXX

$(this) is a method call and its unnessesary to call it over and over again on the same object.

This needs to be done on a per block basis as this will be differet objects in every block ;)


Lookup operations like $(this) are pretty expensive. You'd better store and address object references instead; it helped me a lot in similar circumstances.


It won't make it that much faster, but this will speed it up a few milliseconds: You should reuse a jquery instance instead of generating a new one (this costs some time).

Example: instead of

$(this).parent().css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
$(this).parent().css('color', 'white');

use

var this_parent = $(this).parent();
this_parent.css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
this_parent.css('color', 'white');


One thing that can significantly optimize the above code is replacing the in_array function and the openedFolders array a JS object that functions as a dictionary and is much more efficient. Decleration:

openedFolders={};

Add a new folder to the opened folders object:

openedFolders[folderName]=valueRelatedToTheFolderIfYouHaveOneOrWhatEver; // :)

Search for an opened folder:

if(openedFolders.hasOwnProperty(folderName)){/*folderName is open*/}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜