Здравствуйте, я разрабатываю свой собственный маршрутизатор API в Javascript. Он выполняет маршрутизацию на основе #FregmentIdentifiers (document.location.hash).
API завершен, но я все еще работаю над событием backbuttom. Всякий раз, когда нажата кнопка, и хэш изменился, и его видели раньше, старый контент будет восстановлен.
Знаете ли вы, как сохранить и восстановить весь контент?
Моя проблема здесь в том, что если я сохраню и восстановлю document.body.innerHTML, будет восстановлена только разметка, но не события, например, например. гуглмапс перестает работать.
Я пытался клонировать document.body или document.documentElement, но javascript либо сказал мне, что в поле нет установщика, либо что мой клон недопустим.
EDIT:
Чтобы после всего понять, над чем я работаю, я решил опубликовать свой текущий код.
Вопрос направлен на части, отмеченные комментарием // TODO.
function Router(){
var that = this;
var router = this;
var executionObservers = [];
that.routes = [];
this.registerRoute = function(route){
that.routes.push(route);
};
var history = null;
this.init = function(){
var i;
var identifier = document.location.hash;
history = new History();
history.start();
if(identifier.length > 0){
identifier = identifier.substring(1,identifier.length);
for(i = 0; i< that.routes.length; i++){
var route = that.routes[i];
if(route.contains(identifier)){
route.getAction(identifier)(route.getParams(identifier));
return true;
}
}
}
return false;
};
this.executed = function (identifier){
var i;
for(i=0; i<executionObservers.length; i++){
executionObservers[i](identifier);
}
document.location.hash = identifier;
};
this.addExecutionObserver = function(observer){
executionObservers.push(observer);
};
function History(){
var history = [];
var timeout = 200;
var lastAddedHash = null;
var loop = function(callback){
var hash = window.location.hash;
window.setTimeout(
function(){
if(window.location.hash!=hash){
hash = window.location.hash;
callback(hash);
}
loop(callback);
},
timeout
);
};
this.add = function(hash){
lastAddedHash = hash;
window.setTimeout(addCallback(hash), timeout);
};
addCallback = function(hash){
return function(){
var i;
var found = false;
for(i =0; i< history.length&&!found; i++){
if(history[i][1] == hash){
found = true;
//TODO create backup
//history[i][0] =
}
}
if(!found){history.push(new Array(document.documentElement.cloneNode(true),hash));}
}
}
this.setTimeout = function(micoseconds){
timeout = microseconds;
};
started = false;
this.start = function(){
if(!started){
started = true;
loop(function(hash){
var i;
if(lastAddedHash!=null&&hash!=lastAddedHash){
for(i =0; i<history.length; i++){
if(history[i][1] == hash){
//TODO restore from backup
document.location.reload();
}
}
}
});
}
};
router.addExecutionObserver(this.add);
}
}
Router.instance = null;
Router.getInstance = function(){
if(Router.instance === null ){
Router.instance = new Router();
}
return Router.instance;
};
/**
* @param getParams = function(identifier)
* @param getIdentifier = function(params)
* @param contains = function(identifier)
*/
function Route(action, getParams, getIdentifier, contains){
var that = this;
var router = Router.getInstance();
this.contains = contains;
this.getParams = getParams;
this.getAction = function(){
return action;
}
this.reExecute = function(identifier){
action(getParams(identifier));
};
this.execute = function(params){
action(params);
this.executed(params);
}
this.executed = function(params){
router.executed('#' + getIdentifier(params));
};
this.register = function(){
router.registerRoute(this);
};
}
function PrefixedRouterConfig(prefix,paramRegexes){
this.contains = function(identifier){
var regex = "^" + prefix;
for(var i=0;i<paramRegexes.length;i++){
regex+="_"+paramRegexes[i];
}
regex +="$";
var match = identifier.match(regex);
return match != null && (typeof match) == 'object' && (match[0] == identifier);
};
this.getIdentifier = function(params){
ret = prefix;
for(var i=0;i<params.length;i++){
ret+="_"+params[i];
}
return ret;
};
this.getParams = function(identifier){
var regex = "^" + prefix;
for(var i=0;i<paramRegexes.length;i++){
regex+="_("+paramRegexes[i]+")";
}
regex +="$";
var matches = identifier.match(regex);
var ret = [];
for(var i=1;i<matches.length;i++){
ret.push(matches[i]);
}
return ret;
};
}
Пример использования моего API может выглядеть следующим образом:
config = new PrefixedRouterConfig('show_map',new Array("\\d+", "-?\\d+(?:\\.\\d+)?", "-?\\d+(?:\\.\\d+)?"));
var ROUTE_SHOW_MAP = new Route(
function(params){
var zoom = params[0];
var lat = params[1];
var lng = params[2];
MyGmapInterface.preparePage(-1);
addTabSelectedCallback(MyGmapInterface.tabLoaded);
addTabClosedCallback(MyGmapInterface.tabClosed);
MyGmapInterface.tabsLoaded = true;
MyGmapInterface.myMap = new MyMap(lat,lng,zoom,MyGmapInterface.getMapContainer(),MyGmapInterface.notCompatible);
MyGmapInterface.addNewCamMarkers(MyGmapInterface.loadCams());
MyGmapInterface.initListeners();
tabSelected(TAB_LEFT);
},
config.getParams,
config.getIdentifier,
config.contains
);
ROUTE_SHOW_MAP.register();
После того, как все файлы Javascript включены (которые могут регистрировать маршруты), я вызываю Router.getInstance (). Init ();
Когда я делаю где-нибудь ajax-запрос (вручную), для которого существует маршрут, я вызываю ROUTE_NAME.executed (), чтобы установить идентификатор фрагмента и зарегистрировать его в истории.
Кроме того, у меня есть наблюдатель, который обновляет некоторые ссылки, которые используются для прямых переводов, всякий раз, когда хеш местоположения изменяется с помощью execute ()