2010-11-18 2 views
5

Общий шаблон в пользовательских интерфейсах на основе AJAX заключается в том, что когда пользователь выполняет действие, он мгновенно отображается в пользовательском интерфейсе, но помечается как незавершенный до получения ответа AJAX прибытия, подтверждающего, что все в порядке. Так, например, добавление события в Календарь Google работает. И когда есть ошибка, это временное изменение пользовательского интерфейса отменяется.jQuery AJAX «undo helper»

Теперь, когда такое обращение вручную не слишком креативно, я подозреваю, что в jQuery есть некоторая «команда отмены», которая позволяет сохранить состояние элементов пользовательского интерфейса, а затем восстановить его - тип стека атрибутов или что-то еще как это. Это даже не должно иметь никакого отношения к AJAX.

Есть ли что-нибудь подобное?

ответ

7

В таких ситуациях я всегда находил, что государственные машины - это путь. Создайте свою страницу/JavaScript, чтобы в любой момент времени вы могли указать набор входов, и вы всегда будете получать одинаковый результат на всей странице. Самое приятное в этом подходе - вы не знаете , как вы попали туда, где находитесь в своей программе, вам просто нужно знать, какие данные привели к текущему состоянию.

В вашем случае, вы можете создать базовый объект, описывающий ваше состояние:

var state = { user: 'Tomasz', ajaxSent: false, otherState: 123 }; 

function updateFromState(state){ 
    // Set all dependent UI visibilities, etc. based on state object 
} 

Тогда, прежде чем делать какие-либо изменения, нажмите текущее состояние на массив так, если это необходимо вы можете вернуться:

var stateList = []; 
stateList.push({ user: 'Tomasz', ajaxSent: false, otherState: 123 }); 

// Do something that changes your state 
var newState = {user: 'Tomasz', ajaxSent: true, otherState: 123 }; 
updateFromState(newState); 

// Now, if you need to revert 
var previousState = stateList.pop(); 
updateFromState(previousState); 

Недостатком этого подхода является то, что вы фактически не «уничтожаете» любые побочные эффекты, которые вы могли бы вызвать. Если, например, вы сделали сообщение AJAX, которое изменило данные на сервере, вам нужно было бы понять, как «отменить» эту запись AJAX. Это выходит за рамки простого изменения локального состояния страницы. Но, если вам не нужно отменять побочные эффекты на стороне сервера, но просто иметь возможность точно отражать правильное состояние страницы, это может сработать для вас.

Вот что я бы, вероятно, использовать, чтобы начать работу, если я делал что-то вроде этого:

var StateHelper = function(){ 
    var stateList = []; 
    var callbacks = []; 

    this.onChange = function(callback){ 
     callbacks.push(callback); 
    }; 

    this.set = function(opts){ 
     stateList.push(opts); 
     apply(opts); 
    }; 

    this.undo = function(){ 
     if(stateList.length <= 1){ 
      return; // nothing to undo 
     } 

     // To undo, we go back 2, since top of stack is current 
     stateList.pop(); 
     var last = stateList[stateList.length - 1]; 
     apply(last); 
    }; 

    var apply = function(opts){ 
     var length = callbacks.length; 
     for(var i = 0; i < length; i++){ 
      callbacks[i](opts); 
     } 
    }; 
}; 

Тогда, если моя страница выглядит следующим образом:

<div id='title' style='text-decoration: underline;'>some title</div> 
<div id='state1' class='clickable'>click to set state2 (title = 'second')</div> 
<div id='state2' class='clickable'>click to set state3 (title = 'third')</div> 
<br/> 
<div id='undo' class='clickable'>undo</div> 

я мог бы использовать выше StateHelper как это (обратите внимание, я использовал прикосновение JQuery):

// A function that should be called when state changes 
var updateTitle = function(opts){ 
    // Update the pages title based on state 
    console.log('title updating'); 
    $('#title').text(opts.title); 
}; 

var myState = new StateHelper(); 
myState.onChange(updateTitle); // hook the state change event 

// some example states 
var state2 = { title: 'second' }; 
var state3 = { title: 'third' }; 

// Just some click handlers 
$(document).ready(function(){ 
    $('#state1').click(function(){ 
     myState.set(state2); 
    }); 

    $('#state2').click(function(){ 
     myState.set(state3); 
    }); 

    $('#undo').click(function(){ 
     myState.undo(); 
    }); 

    // Set initial state 
    myState.set({title: 'some title'}); 
}); 

Для живого примера, см: http://jsfiddle.net/belorion/Hywtc/

+0

+1 за очень хороший Ответ. Я чувствовал, что мне не хватает такого простого решения. И на самом деле я в основном обеспокоен отменой изменений DOM после неудачного запроса AJAX, поэтому никаких изменений на стороне сервера не требуется. –

+0

@ Tomasz обновлен с кодом – Matt

+0

Я еще не обволакиваю все это, но это похоже на решение моей проблемы, поэтому я принимаю ваш ответ сейчас. Благодаря! –