Wednesday, August 8, 2012

Кросс браузерный outerHTML

Недавно понадобилось получить outerHTML. На stackoverflow.com нашел такую функцию:


function outerHTML(node){
    // if IE, Chrome take the internal method otherwise build one
  return node.outerHTML || (
      function(n){
          var div = document.createElement('div'), h;
          div.appendChild( n.cloneNode(true) );
          h = div.innerHTML;
          div = null;
          return h;
      })(node);
  }

Thursday, July 26, 2012

Как подружить Google App Engine c MySQL (Windows)

Недавно обновил Google App Engine до новой версии и у меня перестала работать база данных. При запуске любого приложения в консоли висит сообщение:
WARNING  2012-07-26 08:36:41,059 rdbms_mysqldb.py:74] The rdbms API is not available because the MySQLdb library could not be loaded.
Первым делом я решил поставить модуль MySQL-python через easy_install, но модуль не захотел ставиться. Через несколько минут поисков бинарников этого модуля я наткнулся на эти две ссылочки:


После установки модуля все снова заработало.

Friday, July 13, 2012

Запуск Node.JS в качестве демона.

 
Недавно произошла такая неприятная ситуация: выгрузил свой проект на хостинг, а как запустить Node.JS в качестве демона ума не приложу. Есть у меня знакомый админ, он порекомендовал написать скриптик запуска и положить его в /etc/init.d/, у меня конечно же ничего не получилось и я продолжил свои поиски. После нескольких часов вялого поиска я наткнулся на одну очень нужную нам (программистам, не админам) штуку - forever. 
Forever это простой инструмент, который позволяет запускать Node.Js  в качестве домена.
Использовать его крайне просто.


Первым делом устанавливаем пакет с помощью npm
$ [sudo] npm install forever -g


Потом заходим в директорию нашего проекта:
$ cd /path/to/your/project


И запускаем наш сервер:
$ [sudo] forever start server.js

На самом деле там куча всяких параметров и команд, но у меня просто не было времени разбираться. У кого есть время тот сам разберется со всеми премудростями данного инструмента. Я постараюсь выделить несколько часов для этого дела и описать все более подробно.

Для тех кто не видел ссылку в первом абзаце выделяю ее жирным текстом: Forever

Tuesday, June 12, 2012

Наследование в JavaScript с возможностью вызова super методов.

    Недавно мне понадобилось реализовать наследование в JavaScript с возможностью вызова супер конструктора ( конструктор родительского класса, кто не в курсе ). Под рукой у меня была старая добрая крокфордовская функция, которая всегда мне помогала:
function extend(Child, Parent){
   var F = function(){}
   F.prototype = Parent.prototype;
   Child.prototype = new F();
   Child.prototype.constructor = Child;
}
Немного почесав репу я решил добавить в нее немного функционала. Идея достаточно проста -- в каждой функции в JS есть переменная arguments, которая помимо аргументов вызова функции хранит в себе свойство callee, а то в свою очередь свойство caller, которое указывает на функцию, которая вызвала текущую функцию.... Короче говоря вот что у меня получилось:
function extend(Child, Parent){
   var F = function(){}
   F.prototype = Parent.prototype;
   Child.prototype = new F();
   Child.prototype.constructor = Child;


   Child.prototype._super = function(){
      if( arguments.callee.caller === Child){
         Parent.apply(this, arguments);
         return;
      }
      if( !this.__proto__){this.__proto__ = this.constructor.prototype;}
      for(var o in this.__proto__){
         if(this.__proto__[o] === arguments.callee.caller){
            Parent.prototype[o].apply(this, arguments);
         }
      }
   }
}
Теперь постараюсь объяснить свой ход мысли.
Добавляем в прототип дочернего обьекта функцию _super:
   Child.prototype._super = function(){
Первым делом эта функция проверяет не в конструкторе ли она была вызвана:
   if( arguments.callee.caller === Child){
И если она была вызвана в конструкторе, то мы соответственно вызываем конструктор родительского класса.
   Parent.apply(this, arguments);
В ИЕ не существует переменной __proto__, по этому мы ее добавляем сами
   if( !this.__proto__){this.__proto__ = this.constructor.prototype;}
Если функция была вызвана не из конструктора, то мы пробегаемся по всем полям в прототипе нашей текущей функции, чтоб выяснить ее имя, после чего вызываем эту самую функцию, но из родительского класса
   for(var o in this.__proto__){
      if(this.__proto__[o] === arguments.callee.caller){
         Parent.prototype[o].apply(this, arguments);
      }
   }

UPD: Если я правильно понял эт заметку caller - MDN - Mozilla Developer Network то свойство caller не должно существовать... но тем не менее у меня все заработало.