Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 08.01.2013, 21:45
Новичок на форуме
Отправить личное сообщение для Saffoniy Посмотреть профиль Найти все сообщения от Saffoniy
 
Регистрация: 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(['']); один раз нормально загружаются, а потом просто повторно снова грузятся и все когда по страницам ходишь - извиняюсь если не внятно объяснил, как можно исключить дублирование скриптов? Или как решить проблемы с тем что при переходе по страницам скрипты как встроенные, так и внешние которые были на странице отказываются работать?
Ответить с цитированием
  #2 (permalink)  
Старый 08.01.2013, 23:24
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 04.02.2011
Сообщений: 1,815

Ну дак вроде очевидно.
Запоминайте имена скриптов в массиве, которые уже загружены или ещё находятся в процессе загрузки, и если добавленный в загрузку скрипт уже присутствует в массиве, то не грузите его.

После того как страница по ajax загружена, кидайте глобально событие pageload, пусть ваши скрипты слушают это события, и выполняют необходимый функционал. К примеру обычный скрипт слайд шоу в ответ на событие pageload, может подцепить это слайд шоу ко всем вновь найденным DOM элементам с классом .slideshow
__________________
Лучше калымить в гандурасе чем гандурасить на колыме

Последний раз редактировалось DjDiablo, 09.01.2013 в 01:25.
Ответить с цитированием
  #3 (permalink)  
Старый 09.01.2013, 18:24
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 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(){
    // тут ваш код, который будет автоматически выполнен
    // после загрузки или в уже загруженном скрипте.
});
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine

Последний раз редактировалось devote, 10.01.2013 в 00:33.
Ответить с цитированием
  #4 (permalink)  
Старый 09.01.2013, 21:56
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 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.
Ответить с цитированием
  #5 (permalink)  
Старый 10.01.2013, 00:02
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от DjDiablo
devote помоему чересчур замороченно
ну я не старался, написал за 10 минут, главное работает. А оптимизация дело второе... Плюс ты не учел запуск скриптов, что уже загружены. Я специально ввел для этого instances
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #6 (permalink)  
Старый 10.01.2013, 00:16
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 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 не факт что проявится это баг, хотя я и не проверял.
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #7 (permalink)  
Старый 10.01.2013, 00:33
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 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.
Ответить с цитированием
  #8 (permalink)  
Старый 10.01.2013, 00:34
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

ну вот уменьшил свой код, столько же строк стало что и у тебя, безо всяких таймеров, хаков с багами и прочей неприятной ерунды)))
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #9 (permalink)  
Старый 10.01.2013, 00:35
что-то знаю
Отправить личное сообщение для devote Посмотреть профиль Найти все сообщения от devote
 
Регистрация: 24.05.2009
Сообщений: 5,176

Сообщение от DjDiablo
последняя версия,
всё ковырять больше небуду,надоело
как скажешь, но ты все же забыл про instances
__________________
хм Russians say завтра but завтра doesn't mean "tomorrow" it just means "not today."
HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
QSA CSS3 Selector Engine
Ответить с цитированием
  #10 (permalink)  
Старый 10.01.2013, 01:37
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 04.02.2011
Сообщений: 1,815

ты свой скрипт переписал.
Жулик
__________________
Лучше калымить в гандурасе чем гандурасить на колыме

Последний раз редактировалось DjDiablo, 10.01.2013 в 02:06.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подскажите как отобразить текст. potkin Общие вопросы Javascript 17 26.10.2017 15:09
Не правильно работает прокрутка, подскажите как сделать правильно? denfer12 Общие вопросы Javascript 0 09.05.2012 00:34
подскажите, как сделать индикатор «до начала загрузки страницы»? SergAG Элементы интерфейса 7 31.05.2011 19:53
Подскажите как убрать часть текста при нажатии на кномпу или гиперссылку. potkin Общие вопросы Javascript 6 10.10.2008 07:55
Подскажите как при помощи JS hta в трею свернуть kimboo Общие вопросы Javascript 4 11.07.2008 16:00