‘Чистый’ JavaScript: «Продолжение»

от автора

Иногда человечество поражает своей тупостью и нежеланием видеть ситуацию так, как она действительно есть… ( Неизвестные )

Возможно, данный эпиграф имеет ко мне большее отношение, чем я думаю, но хочется надеяться на лучшее…

Мой первый пост получился, мягко говоря, не очень, но у любого человека должна быть возможность все исправить и сейчас я попробую этим воспользоваться.

Расскажу небольшую историю, которая случилась со мной на работе. Дело было давно, как-то приасанили меня к новому web-проекту, проектированием которого я не имел ни малейшего отношения. Тимлид первым делом залил в svn php и js framework’и.
В качестве JS был выбран Mootools 1.2.2 или 1.2.4, а в дополнение к нему Jx UI Library в виде JxLib. Все шло хорошо, проект подходил к своему завершению, версии браузеров росли и тд. И вот, в один прекрасный момент, придя на работу я увидел баг, в кором говорилось а том что в IE9 (а он только-только вышел) админка не работает вообще. Первым делам начал искать проблему, как оказалось Mootools 1.2.x — не поддерживает IE9, а вот в версиях over 1.3.x — все работает и летает. Ну, долго не думая, качаем последнюю версию сего чуда и ставим. Радоватся пришлось не долго — начали вылазить баги в JxLib. Оказывается, что проект ‘заглох’, и последняя доступная версия совместима только с Mootools 1.2.x. Много времени прошло с того момента, но тот говнокод, с помощью которого пришлось залатать этот баг, надломал мою веру в Mootools и ему подобные вещи. Теперь, я думаю, стало ясно, откуда такое отношение к JS либам.

А теперь хочется ответить (пояснить почему так, а не иначе) на некоторые комментарии.

1)
Сonsole.log — вот этого я не ожидал, я предлогал многое но только не это. Я в курсе того что он (console.log) поддерживает форматирование и передачу нескольких параметров, но я не могу вспомнить, когда последний раз я этим пользовался. Мне вполне хватает одной переменной, а усложнять _d() ради того чтобы использовать всю мощь сonsole.log раз в месяц, — нецелесообразно (проще написать заветные 11 символов `сonsole.log`).

2)

Функция addEvent продолжит выполняться после обработки ошибки с помощью функции _d.

— я в курсе этого, это сделано специально, ибо проверку на существование DOM объекта, а предпочитаю делать в основном скрипте, но вы меня меня убедили — добавлю return false.

3)

Загрязнение глобального пространства переменных — очень плохой тон.

— тут вы правы, но кроме readyList = []; я ничего не могу найти глобального 🙂

Ну что ж, я думаю пора заканчивать эти холивары и начать рассмотрение новой партии JS кода.

    // Учитывая какие гуру сидят на хабре - первые 3 функции (тем более что их названия сами за себя говорят) я оставлю без комментариев     /**      * Function insert DOM element before some element      *      * @version 2012-11-06      * @param   Object  new_element      * @param   Object  targetElement      * @return  void      */     function insertBefore(new_element, targetElement)     {         targetElement.parentNode.insertBefore(new_element, targetElement);     }       /**      * Function insert DOM element after some element      *      * @version 2012-11-06      * @param   Object  new_element      * @param   Object  targetElement      * @return  void      */     function insertAfter(new_element, targetElement)     {         var parent = targetElement.parentNode;          //if the parents lastchild is the targetElement...         if(parent.lastchild == targetElement)             parent.appendChild(new_element);         else             parent.insertBefore(new_element, targetElement.nextSibling);     }       /**      * Function make clone of income object      *      * @version 2012-11-07      * @param   Object  obj      * @return  Object      */     function clone(obj)     {         if(obj == null || typeof(obj) != 'object')             return obj;          var temp = {};         for(var key in obj)             temp[key] = clone(obj[key]);          return temp;     }       // Функция вернет следующий DOM объект в узле, если такой существует     /**      * Function return next element in dom object      *      * @version 2013-01-08      * @param   Object  obj      * @return  Object      */     function getNext(obj)     {         obj = obj.nextSibling;          if(!obj)             return false;          while(obj.nodeType != 1){             obj = obj.nextSibling;              if(!obj)                 return false;         }          return obj;     }       // Функция вернет предыдущий DOM объект в узле, если такой существует     /**      * Function return previous element in dom object      *      * @version 2013-02-13      * @param   Object  obj      * @return  Object      */     function getPrevious(obj)     {         obj = obj.previousSibling;          if(!obj)             return false;          while(obj.nodeType != 1){             obj = obj.previousSibling;              if(!obj)                 return false;         }          return obj;     }        // Следующие 2 функции - это установка и чтение Cookies. C ними, я думаю, проблем не будет     /**      * Function new Cookies      *      * @version 2013-03-26      * @param   string name      * @param   string value      * @param   string expires      * @param   string path      * @return  void      */     function setCookies(name, value, expires, path)     {         if(!name || !value)             return 0;          if(!expires){             expires =  new Date();             expires.setTime(expires.getTime() + (1000 * 86400 * 365)); //save 1 year         }          if(!path)             path = '/';          // set Cookies         document.cookie = name+'='+escape(value)+'; expires='+expires.toGMTString()+'; path='+path;     }       /**      * Function return Cookies value by name      *      * @version 2013-03-26      * @param   string name      * @return  void      */     function getCookies(name)     {         var results = document.cookie.match ( '(^|;) ?' + name + '=([^;]*)(;|$)' );          if ( results )             return ( unescape ( results[2] ) );         else             return null;     }         // А вот здесь придется задержатся     // Вначале создаем функцию Ajax(params), а потом прикручиваем к ней prototype     /**      * Ajax object      *      * Send request by post/get to some url      *      * @version 2013-02-13      * @param   Object  params      * @return  Object      */     window.Ajax = function(params)     {         // параметры по умолчанию         this.options = {             // default url             url: '',              // default method             method: 'get',              // Is synchronous request?             async: true,              // in seconds              timeout: 10000,              // callback function, in default - empty function             onComplete: function(){}         };          // set config params         this.setConfig(params);          // создаем и подготавливаем кроссбраузерный XMLHttpRequest для дальнейшей работы         // initialize         this.init(params);     };      /**      * Pablic methods      */     window.Ajax.prototype = {          /**          * some internal params          */         xml_http_request: null,         timeout: null,         // json|xml|text         response:'json',          // устанавливаем параметры ajax запроса, если таковы были переданы         /**          * configure functionality          */         setConfig: function(opt)         {             // set url             if(opt.url != undefined)                 this.options.url = opt.url;              // set method             if(opt.method != undefined)                 this.options.method = opt.method;              // set asynchronus param             if(opt.async != undefined)                 this.options.async = opt.async;              // set timeout             if(opt.timeout != undefined)                 this.options.timeout = opt.timeout;              // set callback functions             if((opt.onComplete != undefined) && (typeof(opt.onComplete) == 'function'))                 this.options.onComplete = opt.onComplete;         },          /**          * Initialize XMLHTTPRequest          */         init: function()         {             // кроссбраузерное создание XMLHttpRequest             // Cross-browser compatibility for browsers             if (typeof XMLHttpRequest != 'undefined') {                 this.xml_http_request = new XMLHttpRequest();             }             else{                 try {                     this.xml_http_request = new ActiveXObject("Msxml2.XMLHTTP");                 }                 catch (e) {                     try {                         this.xml_http_request = new ActiveXObject("Microsoft.XMLHTTP");                     } catch (E) {                         alert('Your brouser don\'t support Ajax technology. Please download real browser :)');                     }                 }             }              var self_ = this;              // устанавливаем метод (post/get), url, синхронный/несинхронный запрос             // open XMLHttpRequest             this.xml_http_request.open(self_.options.method, self_.options.url, self_.options.async);               /** Вешаем callback в случае успешного              *              *   Список состояний readyState такой:               *   0 - Unitialized              *   1 - Loading              *   2 - Loaded              *   3 - Interactive              *   4 - Complete              *   Состояния 0-2 вообще не используются.              *              * self_.xml_http_request.status - код ответа сервера (200, 404 и тд)              */             // set callback function for XMLHttpRequest             this.xml_http_request.onreadystatechange = function(){                 if((self_.xml_http_request.readyState == 4) && (self_.xml_http_request.status > 0)){                       // отмена принудительного разрыва Ajax запроса (ниже будут пояснения)                     // delete timeout                     clearTimeout(self_.timeout);                      // в завивимости от того, что вы ожидаете формируем ответ сервера                     // JSON.parse - встроеный парсер JSON  (старые браузеры - bye-bye)                     if(self_.response == 'json')                         var response = JSON.parse(self_.xml_http_request.responseText);                     else{                         if(self_.response == 'xml')                             var response = self_.xml_http_request.responseXML;                         else                             var response = self_.xml_http_request.responseText;                     }                     // вызываем обработчик результатов                     self_.options.onComplete(response);                 }             }         },           // Данный метод нужен в очень специфических задачах, когда необходимо играться с заголовками для сервера         /**          * Set some headers if need          */         setRequestHeader: function(name, value)         {             this.xml_http_request.setRequestHeader(name, value);         },           // Отсылаем Ajax на сервер         /**          * Send request          */         send: function(params)         {             this.xml_http_request.send(params);              var self_ = this;              // про это я говорил ранее, если вас запрос повис или на серваке проблемы - обрываем его принудительно             // по умолчанию - 10 секунд ждем, хотя можно и больше             // set timeout need for abort request             this.timeout = setTimeout( function(){ self_.xml_http_request.abort(); }, this.options.timeout);         },           // Данная фишка для того, что бы вы могли в любое время прервать запрос, например при живом поиске (как у хабра или гугла :) )         /**          * Abort request          */         abort: function()         {             this.xml_http_request.abort();         }     }        Пример использования Ajax():      new Ajax({         url: '/index.php',         timeout: 20000,         method: 'post',         onComplete: function(data){ alert(data);}     }).send('qwerty=123');   

PS. Как и обещал, исходники. Статья написана для того, что бы люди не забывали истинный JavaScript и переходила на светлую сторону силы (печеньки тут тоже имеются 🙂 ).

ссылка на оригинал статьи http://habrahabr.ru/post/176273/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *