08.01.2013, 21:45
|
Новичок на форуме
|
|
Регистрация: 08.01.2013
Сообщений: 1
|
|
Подскажите как быть в данной ситуации
Ситуация следующая, у меня сайт работает на основе ajax, history api
http://history.spb-piksel.ru/ вот этого движка, страницы грузятся у меня асинхронно, после чего js скрипты которые находились на странице отказываются работать, как быть?
-------------------------------
И еще, я использую на сайте асинхронную загрузку js скриптов
$Load = function (c, d) {
for (var b = c.length, e = b, f = function () {
if (!(this.readyState
&& this.readyState !== "complete"
&& this.readyState !== "loaded")) {
this.onload = this.onreadystatechange = null;
--e || d()
}
}, g = document.getElementsByTagName("head")[0], i = function (h) {
var a = document.createElement("script");
a.async = true;
a.src = h;
a.onload = a.onreadystatechange = f;
g.appendChild(a)
}; b;) i(c[--b])
};
Так это работает
$Load(['/js/script.js'], function () {alert('script loaded');});
При использовании такого способа асинхронной загрузки js скриптов, скрипты на странице дублируются при каждом переходе на страницу, то есть скрипты которые указаны в $Load(['']); один раз нормально загружаются, а потом просто повторно снова грузятся и все когда по страницам ходишь - извиняюсь если не внятно объяснил, как можно исключить дублирование скриптов? Или как решить проблемы с тем что при переходе по страницам скрипты как встроенные, так и внешние которые были на странице отказываются работать?
|
|
08.01.2013, 23:24
|
Профессор
|
|
Регистрация: 04.02.2011
Сообщений: 1,815
|
|
Ну дак вроде очевидно.
Запоминайте имена скриптов в массиве, которые уже загружены или ещё находятся в процессе загрузки, и если добавленный в загрузку скрипт уже присутствует в массиве, то не грузите его.
После того как страница по ajax загружена, кидайте глобально событие pageload, пусть ваши скрипты слушают это события, и выполняют необходимый функционал. К примеру обычный скрипт слайд шоу в ответ на событие pageload, может подцепить это слайд шоу ко всем вновь найденным DOM элементам с классом .slideshow
__________________
Лучше калымить в гандурасе чем гандурасить на колыме
Последний раз редактировалось DjDiablo, 09.01.2013 в 01:25.
|
|
09.01.2013, 18:24
|
что-то знаю
|
|
Регистрация: 24.05.2009
Сообщений: 5,176
|
|
Кину сюда то что писал человеку на почту:
$Load = (function() {
// в этой переменной будем хранить ссылки на скрипты которые уже загружали
var loadedScripts = {};
function loadAsync(src, callback) {
if (src in loadedScripts) {
callback(loadedScripts[src] || src);
} else {
var script = document.createElement('script');
script.type = 'text/javascript';
if ("onload" in script || !("readyState" in script)) {
script.onload = function() {
callback(src);
}
} else {
script.onreadystatechange = function() {
if (this.readyState == "loaded" ||
this.readyState == "complete") {
callback(src);
}
}
}
script.src = src;
document.documentElement.firstChild.appendChild(script);
}
}
function loader(scripts, onload) {
scripts = typeof scripts === "string" ? [scripts] : scripts;
var
asyncCallback,
length = loader.instances.length;
if (scripts.length === 0) {
return onload && onload.call(this);
}
loadAsync(scripts.shift(), asyncCallback = function(src) {
if (typeof src === "function") {
src();
} else if (loader.instances.length > length) {
loadedScripts[src] = loader.instances[ length++ ];
loadedScripts[src]();
} else {
loadedScripts[src] = null;
}
if (scripts.length === 0) {
onload && onload.call(this);
} else {
loadAsync(scripts.shift(), asyncCallback);
}
});
}
loader.instances = [];
return loader;
})();
Использовать примерно так:
$Load(['script1.js', 'script2.js'], function() {
// loaded
});
// ну или вместо массива строка:
$Load('script1.js', function() {
// loaded
});
Далее в каждом скрипте который загружаете аяксом, код который нужно снова выполнить, обернуть вот так:
$Load.instances.push(function(){
// тут ваш код, который будет автоматически выполнен
// после загрузки или в уже загруженном скрипте.
});
Последний раз редактировалось devote, 10.01.2013 в 00:33.
|
|
09.01.2013, 21:56
|
Профессор
|
|
Регистрация: 04.02.2011
Сообщений: 1,815
|
|
devote помоему чересчур замороченно
попробывал покороче и попроще сделать.
проверено хром, опера, ie.
код
$Load = (function() {
var loadedScripts = {},//только загруженные скрипты
allscript={};//все скрипты
//хелпер для установки обработчиков событий
function event(el,event,fn) {
if (el.readyState=="complete") return fn();
var count= (event=="readystatechange") ? 2:1;
if ( el.addEventListener) el.addEventListener (event, fn ,false)
else el.attachEvent("on"+event, function(){ count--; if (count==0) fn() } );
}
//грузит скрипт и вешает событие load
function loadAsync(src, callback) {
setTimeout(function(){
if (! (src in allscript) ) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.documentElement.firstChild.appendChild(script);
allscript[src]=script;
}
event( allscript[src], '\v'!='v'?'load':"readystatechange",function(){
callback(src,script)
})
},1)
}
//возвращаем функцию
return function (scripts, onload) {
var scripts = typeof scripts === "string" ? [scripts] : scripts,
count=scripts.length;
for( var i = 0; i < scripts.length; i++ ) {
if (scripts[i] in loadedScripts ) count--;
else loadAsync( scripts[i], function(src,script){
loadedScripts[src]=script;
count--;
if ( count==0) onload();
});
}
if (count==0) onload();
}
})();
использование
$Load(["test.js","test2.js","test.js","test.js"],function(){
alert("result");
});
__________________
Лучше калымить в гандурасе чем гандурасить на колыме
Последний раз редактировалось DjDiablo, 09.01.2013 в 23:49.
|
|
10.01.2013, 00:02
|
что-то знаю
|
|
Регистрация: 24.05.2009
Сообщений: 5,176
|
|
Сообщение от DjDiablo
|
devote помоему чересчур замороченно
|
ну я не старался, написал за 10 минут, главное работает. А оптимизация дело второе... Плюс ты не учел запуск скриптов, что уже загружены. Я специально ввел для этого instances
|
|
10.01.2013, 00:16
|
что-то знаю
|
|
Регистрация: 24.05.2009
Сообщений: 5,176
|
|
ну и плюс ко всему такой код читать тяжело:
...
function event(el,event,fn) {
if (el.readyState=="complete") return fn();
var count= (event=="readystatechange") ? 2:1;
if ( el.addEventListener) el.addEventListener (event, fn ,false)
else el.attachEvent("on"+event, function(){ count--; if (count==0) fn() } );
}
...
А если его привести в читаемый вид, то не многим меньше он станет:
$Load = (function() {
var loadedScripts = {},//только загруженные скрипты
allscript={};//все скрипты
//хелпер для установки обработчиков событий
function event(el, event, fn) {
if (el.readyState == "complete") {
return fn();
}
var count = (event == "readystatechange") ? 2 : 1;
if (el.addEventListener) {
el.addEventListener(event, fn ,false);
} else {
el.attachEvent("on" + event, function(){
count--;
if (count == 0) {
fn();
}
});
}
}
//грузит скрипт и вешает событие load
function loadAsync(src, callback) {
setTimeout(function() {
if (!(src in allscript)) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.documentElement.firstChild.appendChild(script);
allscript[src] = script;
}
event(allscript[src], '\v' != 'v' ? 'load' : "readystatechange", function() {
callback(src, script);
});
}, 1);
}
//возвращаем функцию
return function (scripts, onload) {
var scripts = typeof scripts === "string" ? [scripts] : scripts,
count = scripts.length;
for(var i = 0; i < scripts.length; i++) {
if (scripts[i] in loadedScripts) {
count--;
} else {
loadAsync(scripts[i], function(src, script){
loadedScripts[src] = script;
count--;
if (count == 0) {
onload();
}
});
}
}
if (count == 0) {
onload();
}
}
})();
Плюс таймеры это излишек,
плюс проверка: (event == "readystatechange") ? 2 : 1;
совсем не правильно, ибо гарантии нет что отработает именно два раза
плюс условие '\v' != 'v'
это вообще из разряда идиотизма, ибо код написанный с использованием багов браузера, может привести к неожиданным последствиям. Такое нужно использовать только в крайней необходимости. Ибо при эмуляции того же ИЕ8 в ИЕ9 не факт что проявится это баг, хотя я и не проверял.
|
|
10.01.2013, 00:33
|
Профессор
|
|
Регистрация: 04.02.2011
Сообщений: 1,815
|
|
спасибо что глянул.
Там был ряд костылей, но я их уже выпилил
чем посоветуешь заменить '\v'!='v' может if (el.attachEvent) попробывать.
посмотри кстатии самый короткий способ определить ie
последняя версия,
всё ковырять больше небуду,надоело
$Load = (function() {
var loadedScripts = {},//только загруженные скрипты
allscript={};//все скрипты
//хелпер для установки обработчиков событий
function event(el,fn) {
if ( '\v'!='v') el.addEventListener ("load", fn ,false)
else el.attachEvent("onreadystatechange", function(){
if (el.readyState=="complete" || el.readyState=="loaded") fn()
});
}
//грузит скрипт и вешает событие load
function loadAsync(src, callback) {
if (! (src in allscript) ) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.documentElement.firstChild.appendChild(script);
allscript[src]=script;
}
event( allscript[src], function(){
loadedScripts[src]=allscript[src];
callback(src)
})
}
//возвращаем функцию
return function (scripts, onload) {
var scripts = typeof scripts === "string" ? [scripts] : scripts,
count=scripts.length;
for( var i = 0; i < scripts.length; i++ ) {
if (scripts[i] in loadedScripts ) count--;
else loadAsync( scripts[i], function(src){
count--;
if ( count==0) onload();
});
}
if (count==0) onload();
}
})();
__________________
Лучше калымить в гандурасе чем гандурасить на колыме
Последний раз редактировалось DjDiablo, 10.01.2013 в 00:50.
|
|
10.01.2013, 00:34
|
что-то знаю
|
|
Регистрация: 24.05.2009
Сообщений: 5,176
|
|
ну вот уменьшил свой код, столько же строк стало что и у тебя, безо всяких таймеров, хаков с багами и прочей неприятной ерунды)))
|
|
10.01.2013, 00:35
|
что-то знаю
|
|
Регистрация: 24.05.2009
Сообщений: 5,176
|
|
Сообщение от DjDiablo
|
последняя версия,
всё ковырять больше небуду,надоело
|
как скажешь, но ты все же забыл про instances
|
|
10.01.2013, 01:37
|
Профессор
|
|
Регистрация: 04.02.2011
Сообщений: 1,815
|
|
ты свой скрипт переписал.
Жулик
__________________
Лучше калымить в гандурасе чем гандурасить на колыме
Последний раз редактировалось DjDiablo, 10.01.2013 в 02:06.
|
|
|
|