ATS - движок для сайта на javascript =)

Discussion in 'PHP' started by Дикс, 12 Jun 2008.

  1. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    писал из спортивного интереса, но очень хочу найти и исправить все косяки, чтобы можно было использовать, поэтому выкладываю чтобы потестили.

    онлайн-версия здесь: http://litprom.890m.com/ast/

    сорцы здесь: http://up.giga.su/738058803/ (6.35 кб)

    Назначение:
    создание в максимально сжатые сроки статичного сайта с удобной поддержкой и расширением.
    Альтернатива серверным модульным движкам, SSI, dreamweaver templates.

    Суть проекта:
    На страницу цепляется основной скрипт.
    Появляется возможность создавать простые ссылки, которые заполняют контент страницы содержимым файлов, лежащих на сервере в текстовом формате.
     
    #1 Дикс, 12 Jun 2008
    Last edited: 12 Jun 2008
    4 people like this.
  2. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    я вот че думаю - можно сделать кэширование текстов - сохраняя их в переменные, а затем проверяя их наличие.
    как вы считаете - стоит?
     
  3. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    Попробуй это использовать
    http://forum.antichat.ru/thread72316.html
     
  4. astrologer

    astrologer Elder - Старейшина

    Joined:
    30 Aug 2007
    Messages:
    837
    Likes Received:
    267
    Reputations:
    59
    1. В функции «ajax» логика получения экземпляра XMLHttpRequest воспроизводится каждый раз.
    2. В переменной contentDiv можно сохранить готовую ссылку на объект ( который <div id="corpse" /> ) вместо строки "corpse".
    3. Имеет смысл навешивать обработчики событий в js коде, а не в html.
    4. Чтобы свести к минимуму вероятность перезаписи переменных, можно создать объект, например, «AST» и хранить их там:
      Code:
      var AST =
      {
        folder: 'pages/',
        ext: 'txt',
        load: function(){ /* код */ }
      };
    5. corpse
    По-моему, нет.
     
    1 person likes this.
  5. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    1, 2 - сделал

    не совсем понял.
    если у меня будет меню из одних спанов, без онклика и вызова функции,
    как я тогда укажу - какой пункт меню, какую страницу открывает?

    4 - буду учиться работать с массивами и тоже реализую

    5 - ясно. может попробую вот эти способы:
    http://forum.antichat.ru/thread72316.html

    а ты можешь привести доводы, почему кешировать не стоит?

    ПС я знаю что corpse - 'труп'.
    это мой маленький кулинарный изыск :)
     
  6. astrologer

    astrologer Elder - Старейшина

    Joined:
    30 Aug 2007
    Messages:
    837
    Likes Received:
    267
    Reputations:
    59
    Потому, что браузер кэширует страницы самостоятельно, в том числе те, которые получены "Ajax'ом". Воспроизводить эту логику на JS - задача нетривиальная, если подойти к задаче серьёзно.

    lazy-реализация первого пункта. Несколько объёмно:
    Code:
    function XHR()
    {
      var ms =
      [
        'Microsoft.XMLHTTP',
        'MSXML2.XMLHTTP',
        'MSXML2.XMLHTTP.3.0',
        'MSXML2.XMLHTTP.4.0',
        'MSXML2.XMLHTTP.5.0'
      ], i = ms.length, nop = function(){};
      
      if(window.XMLHttpRequest)
      {
        return (XHR = function()
        {
          return new XMLHttpRequest();
        })();
      }
      else if(window.ActiveXObject)
      {
        while(i--)
        {
          try
          {
            return (XHR = function()
            {
              return new ActiveXObject(ms[i]);
            })();
          } catch(e) {}
        }
      }
      
      return (XHR = function(){
        return {
          open: nop,
          send: function()
          {
            this.onreadystatechange();
          },
          readyState: 4,
          onreadystatechange: nop,
          responseText: 'XMLHttpRequest instantiation error'
        };
      })();
    };
    Меню обычно делается как список ссылок. Обработчик навешивается на родительский элемент. При щелчке на ссылке, если не работает js - происходит простой переход по ссылке. Если работает - js отменяет переход и подгружает данные. Техника довольно распространённая, называется event delegation.
    Вот пример, не затрагивающий уже существующую разметку:
    Code:
    function init()
    {
      /* ... */
      
      var m = document.getElementById('menu'),
      s = m.getElementsByTagName('span'),
          
      m.addEventListener('click', function(e)
      {
        var name = '';
        switch(e.target || e.srcElement)
        {
          case s[0]:
            name = 'home';
            break;
          case s[1]:
            name = 'installation';
            break;
          case s[2]:
            name = 'contacts';
            break;
          case s[3]:
            name = 'license';
            break;
          default: return true;
        }
        
        loadPage(name);
        (e.preventDefault || function(){ e.returnValue = false; })();
        return false;
      }, false);
    };
    Можно вместо конструкции switch использовать объект-хеш, в качестве ключей - текст пунктов меню.
    P.S. для IE - attachEvent вместо addEventListener.
     
    1 person likes this.
  7. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    почти со всем справился, но вот этот код не отменяет перехода по ссылке ни в одном браузере:

    просто e.preventDefault () хорошо отменяет переход в ФФ и опере, а в ИЕ6 не работает.
    как в ИЕ убить переход?
    я повесил обработчик на теги A.
     
  8. astrologer

    astrologer Elder - Старейшина

    Joined:
    30 Aug 2007
    Messages:
    837
    Likes Received:
    267
    Reputations:
    59
    Это я перемудрил :)
    Code:
    if(e.preventDefault)
    {
      e.preventDefault();
    }
    else
    {
      e.returnValue = false;
    }
    return false;
     
  9. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    http://up.giga.su/713746505/
    вот сорцы
    ИЕ на этот код ваще не реагирует
     
  10. astrologer

    astrologer Elder - Старейшина

    Joined:
    30 Aug 2007
    Messages:
    837
    Likes Received:
    267
    Reputations:
    59
    В IE события, вопреки стандарту, называются не 'click' или 'keyup', а 'onclick', 'onkeyup' и т.д.
    В результате:
    Code:
    attachEvent('onclick', function(e){/*...*/});
    Также [ Element ].attachEvent принимает только два параметра. Третий - булево значение - игнорируется.
    Далее.
    Функция attachEvent переписывает нативную в IE функцию window.attachEvent. Это не плохо, но нежелательно.

    Code:
    try           {window.xmlHttp=new XMLHttpRequest();}
      catch (e){ try{window.xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");}
      catch (e){ try{window.xmlHttp=new ActiveXObject("MSXML2.XMLHTTP");}
      catch (e){ try{window.xmlHttp=new ActiveXObject("MSXML2.XMLHTTP.3.0");}
      catch (e){ try{window.xmlHttp=new ActiveXObject("MSXML2.XMLHTTP.4.0");}
      catch (e){ try{window.xmlHttp=new ActiveXObject("MSXML2.XMLHTTP.5.0");}
      catch (e){return false;}}}}}}
    Ааааа!
     
    #10 astrologer, 21 Jun 2008
    Last edited: 21 Jun 2008
    1 person likes this.
  11. [Raz0r]

    [Raz0r] Elder - Старейшина

    Joined:
    25 Feb 2007
    Messages:
    425
    Likes Received:
    484
    Reputations:
    295
    Как вариант для attachEvent и addEventListener:
    Code:
    <a id=aid href=#>Click me!</a>
    <script>
    Array.prototype.append = function(obj, nodup) {
    	if(!(nodup && this.contains(obj))) {
    		this[this.length] = obj;
    	}
    }
    
    EventRouter = function(el, eventType) {
    	this.lsnrs = new Array();
    	this.el = el;
    	el.eventRouter = this;
    	el[eventType] = EventRouter.callback;
    }
    
    EventRouter.prototype.addListener = function(lsnr) {
    	this.lsnrs.append(lsnr);
    }
    
    EventRouter.prototype.notify = function(e) {
    	var lsnrs = this.lsnrs;
    	for(var i=0; i < lsnrs.length; i++) {
    		var lsnr=lsnrs[i];
    		lsnr.call(this, e);
    	}
    }
    
    EventRouter.callback = function(event) {
    	var e = event || window.event;
    	var router = this.eventRouter;
    	router.notify(e);
    }
    var aid = document.getElementById("aid");
    var ev = new EventRouter(aid, "onclick");
    ev.addListener(function(){alert("Click!");});
    </script>
     
  12. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    astrologer
    событие исправил на onclick, спасибо
    третий параметр уже убрал
    аттачевент уже переименовал

    ща имеем такой код:

    PHP:
    PHP:
    if ((navigator.userAgent.indexOf('MSIE') != -1)
     && (
    navigator.userAgent.indexOf('Win') != -1))
        
    AST.menuId.attachEvent('onclick'addEvent);
    else
        
    AST.menuId.addEventListener('click', function(e){addEvent(e)}, false);
    PHP:
    function addEvent(e){
    alert('ХУЙ');
     
    AST.trgt = (e.target || e.srcElement);

        for(
    i=0iAST.links.lengthi++)
            if(
    AST.trgt == AST.links[i])
                 
    loadPage(AST.links[i].valueOf());

    if(
    e.preventDefault)
      
    e.preventDefault();

    e.returnValue false;

    return  
    false;
    }
    он отлично работает в опере, фф, сафари (для винды), но не работает в ие! орёт матерное слово и перебрасывает прямиком на блокнот

    может проблема в том, что всё вынесено в отдельный скрипт?

    ПС
    че? )))
     
    1 person likes this.
  13. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    вот снова залил сорцы (6 кб)
    http://up.giga.su/643686467/

    я там создал функцию тест.
    она по сути дублирует функцию loadPage.

    вот что она должна делать:
    - создать пустой див (ок)
    - очистить контейнер, куда будет помещаться контент новой страницы (ок)
    - аяксом подгрузить новый контент
    - приаттачить его к контейнеру

    если закоментить вызов моей самописной аякс-функции - то ссылки как и должно быть - не совершают перехода.
    они чистят страницу, создают див, и отменяют переход по ссылке.

    теперь осталось получить новые данные.

    если раскомментировать строку - то ИЕ просто перейдёт по ссылке на текстовый файл. т.е. функция перестаёт работать.

    Тем не менее в функции init() есть строки загружающие страницу по умолчанию.
    они также используют loadPage(), ajax(), но у них всё работает нормально.
    если поставить алерты - то видно, что аякс получает тело страницы.

    в случае же с тест-функцией, которую я прилепил в качестве обработчика исключительно для ИЕ - аякс ниче не возвращает и до отмены перехода по ссылке видно вообще дело не доходит..

    добьём эту шнягу! чуток осталось :)

    я вот тут ещё писал:
    http://forum.ixbt.com/topic.cgi?id=26:38394
    но там не особо почерпнул пока
     
  14. astrologer

    astrologer Elder - Старейшина

    Joined:
    30 Aug 2007
    Messages:
    837
    Likes Received:
    267
    Reputations:
    59
    Для начала:
    Code:
    function(msg){ alert(msg) } // это то же самое, что и просто alert
    Далее. Заменяем это:
    Code:
    // ajaxTest("GET", e.srcElement.valueOf(), function(msg){ alert(msg) });
    на это:
    Code:
    if(e.srcElement.href) ajax("GET", e.srcElement.href, alert);
    Условие необходимо, поскольку объект, по которому щёлкнули, может быть любым из блока menu и самим menu в том числе. Вторым параметром функции, в принципе, можно передать и саму ссылку ( [ HTMLAnchorElement ] ).

    А теперь немного уличной магии. В коде функции ajax:
    Code:
    function ajax(method, url, userFunc) {
    
    window.xmlHttp.onreadystatechange=function() {
    	if(window.xmlHttp.readyState==4)
    		userFunc(window.xmlHttp.responseText);
    }
    
    window.xmlHttp.open(method,url,true);
    window.xmlHttp.send(null);
    }
    нужно поменять местами определение [ object XMLHttpRequest ].onreadystatechange и вызов метода open()

    P.S. Все рекомендации основаны на следующем правиле: переписывать код полностью нельзя.
     
  15. asser

    asser Elder - Старейшина

    Joined:
    25 Jan 2008
    Messages:
    31
    Likes Received:
    5
    Reputations:
    0
    А может туда какую-нить маленькую админку добавить стоит?!Руками конечно не впадлу, но тем не менее))
     
  16. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    ур-ра-а!!
    вот где оказываеца была зарыта эта побитая дождями сцобака!
    теперь везде работает стабильно.

    astrologer
    жму руку! спасибо

    а вот это не понял. поясни? :)

    asser
    какую админку? чтобы изменять меню? для этого нужны скрипты на сервере.
    а это уже совершенно другая история..
     
  17. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    Так. осталось выяснить, чем неугоден следующий код?
    PHP:
    // new XHR
      
    try           {window.xmlHttp=new XMLHttpRequest();}
      catch (
    e){ try{window.xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");}
      catch (
    e){ try{window.xmlHttp=new ActiveXObject("MSXML2.XMLHTTP");}
      catch (
    e){ try{window.xmlHttp=new ActiveXObject("MSXML2.XMLHTTP.3.0");}
      catch (
    e){ try{window.xmlHttp=new ActiveXObject("MSXML2.XMLHTTP.4.0");}
      catch (
    e){ try{window.xmlHttp=new ActiveXObject("MSXML2.XMLHTTP.5.0");}
      catch (
    e){return false;}}}}}}
    его можно как-то улучшить?