Как я могу устранить / консолидировать эти функции setTimeout? - PullRequest
0 голосов
/ 16 сентября 2011

В связанном вопросе я спросил, как отфильтровать и автоматически выбрать данную строку в jqGrid.В настоящее время у меня есть решение для этого:

$(function () {
   $('.relatedrecipe').click(function () {
      // store off the value of the related recipe I want to switch to
      var recipe = $(this).data('recipename');
      // clear any filters on the grid
      setTimeout(function () {
         $("#recipegrid")[0].clearToolbar();
      }, 50);
      // set the recipe filter to the related recipe name and trigger the filtering
      setTimeout(function () {
         $('#gs_RecipeName').val(recipe);
         $('#recipegrid')[0].triggerToolbar();
      }, 200);
      // auto-select the first row
      setTimeout(function () {
         var firstRowID = $('#recipegrid').jqGrid('getDataIds')[0];
         $('#recipegrid').setSelection(firstRowId, true);      
      }, 500);
   });
}

Что мне не нравится в этом решении (я делаю так, как будто оно предоставило мне решениеЭто то, что я, по сути, ставлю в очередь кучу функций, которые будут выполняться в будущем, на 50 мс, 200 мс и 500 мс.Это выглядит как потенциально проблематичное решение, основанное на правильной настройке времени, поэтому мне оно не очень нравится.

Я рассмотрел вложение этих функций одна в другую, по 50 мсек для каждой.Что-то вроде:

$(function () {
   $('.relatedrecipe').click(function () {
      // store off the value of the related recipe I want to switch to
      var recipe = $(this).data('recipename');
      // clear any filters on the grid
      setTimeout(function () {
         $("#recipegrid")[0].clearToolbar();
         // set the recipe filter to the related recipe name and trigger the filtering
         setTimeout(function () {
            $('#gs_RecipeName').val(recipe);
            $('#recipegrid')[0].triggerToolbar();
            // auto-select the first row
            setTimeout(function () {
               var firstRowID = $('#recipegrid').jqGrid('getDataIds')[0];
               $('#recipegrid').setSelection(firstRowId, true);      
            }, 50);
         }, 50);
      }, 50);
   });
}

Это лучше?Я изменил свой код, чтобы сделать это таким образом, и он, кажется, тоже работает, но есть ли лучший способ сделать это?

Шаги должны быть выполнены в этом порядке, но я считаю, что должно пройти некоторое время, чтобы закончить каждый из первых двух разделов, прежде чем приступить к третьему.Есть мысли по этому поводу?

Ответы [ 3 ]

1 голос
/ 16 сентября 2011

Как насчет этого?

var exec_stack = [];
exec_stack.push(function() { 
    // do stuff 1
});
exec_stack.push(function() { 
    // do stuff 2
});
exec_stack.push(function() { 
    // do stuff 3
});

function run_stack(delay) {
    if (exec_stack.length > 0) {
        exec_stack.pop()();
        setTimeout(function() { run_stack(delay) }, delay);
    }
}
run_stack(50);

http://jsfiddle.net/SJmcG/

Естественно, ваши функции не должны быть анонимными:

function foo() {
    //do stuff
}
exec_stack.push(foo);
0 голосов
/ 16 сентября 2011

Я бы предложил переписать ваш обработчик click следующим образом:

$('.relatedrecipe').click(function () {
    // store off the value of the related recipe I want to switch to
    var recipe = $(this).data('recipename'),
        grid = $grid[0];

    // clear any filters on the grid WITHOUT reloading
    grid.clearToolbar(false);

    // set the recipe filter to the related recipe name
    $('#gs_RecipeName').val(recipe).trigger('change');

   // trigger the filtering
   grid.triggerToolbar();
});

Может случиться так, что в приведенном выше коде вызов .trigger('change') не нужен, и вы можете удалить его. Просто проверьте это.

Код, который выбирает первую строку сетки, которую я бы поместил внутри обработчика событий loadComplete. Функция обратного вызова loadComplete будет вызываться после того, как сетка будет заполнена данными.

loadComplete: function () {
    var $grid = $(this),
        $firstRowWithData = $grid.find("tr.jqgrow:first");

    if ($firstRowWithData.length > 0) {
        // if at least one row with data filled in the grid
        $grid.jqGrid ('setSelection', $firstRowWithData[0].id, true);
    }
}

Использование getDataIds означает, что jqGrid будет проходить через все строки сетки и заполнять массив идентификаторами. Тогда вы получите только первый элемент из массива.

Другой, еще более эффективный способ получения идентификатора первой строки с данными будет в вашем случае просто

loadComplete: function () {
    var $firstRowWithData = this.rows;

    if (this.rows.length > 1) {
        // if at least one row with data filled in the grid
         $(this).jqGrid ('setSelection', this.rows[1].id, true);
    }
}

В последней версии кода я использовал тот факт, что this, если DOM-элемент <table>, который строит сетку. Таким образом, this.rows представляет массив <tr> элементов (строк сетки). Первый элемент this.rows[0] - это фиктивная строка, которая имеет height: 0px и будет использоваться для определения ширины столбцов. Вторая строка (если есть) this.rows[1] - первая строка с данными. Это id это rowid. Вы можете прочитать ответ для получения дополнительной информации.

0 голосов
/ 16 сентября 2011

Мой окончательный ответ будет зависеть от ответа , почему вещи должны происходить в таком порядке.

Похоже, что у панели инструментов много ворот: в таком случае неплохо было бы настроить панель инструментов, чтобы либо (а) обеспечить некоторые обратные вызовы, либо (б) запустить некоторые пользовательские события, с которыми вы можете связать .

Как вы и предполагаете, полагаться на синхронизацию - довольно плохая идея, особенно если вы хотите, чтобы во всех браузерах и при загрузке браузера было одинаковое поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...