Подскажите как быть в данной ситуации
Ситуация следующая, у меня сайт работает на основе 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(['']); один раз нормально загружаются, а потом просто повторно снова грузятся и все когда по страницам ходишь - извиняюсь если не внятно объяснил, как можно исключить дублирование скриптов? Или как решить проблемы с тем что при переходе по страницам скрипты как встроенные, так и внешние которые были на странице отказываются работать? |
Ну дак вроде очевидно.
Запоминайте имена скриптов в массиве, которые уже загружены или ещё находятся в процессе загрузки, и если добавленный в загрузку скрипт уже присутствует в массиве, то не грузите его. После того как страница по ajax загружена, кидайте глобально событие pageload, пусть ваши скрипты слушают это события, и выполняют необходимый функционал. К примеру обычный скрипт слайд шоу в ответ на событие pageload, может подцепить это слайд шоу ко всем вновь найденным DOM элементам с классом .slideshow |
Кину сюда то что писал человеку на почту:
$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 помоему чересчур замороченно
попробывал покороче и попроще сделать. проверено хром, опера, 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"); }); |
Цитата:
|
ну и плюс ко всему такой код читать тяжело:
... 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 не факт что проявится это баг, хотя я и не проверял. |
спасибо что глянул.
Там был ряд костылей, но я их уже выпилил :) чем посоветуешь заменить '\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(); } })(); |
ну вот уменьшил свой код, столько же строк стало что и у тебя, безо всяких таймеров, хаков с багами и прочей неприятной ерунды)))
|
Цитата:
|
ты свой скрипт переписал.
Жулик :D |
Часовой пояс GMT +3, время: 21:32. |