2009-04-18

ztools.org

Проект ztools.org наконец дожил до состояния бета версии. Посетители сайта теперь могут скачивать оттуда выбранные компоненты в виде zip архива.

 

Коментариев: 2

 
  2009-03-16

Знак $ в именах переменных JavaScript

вот интересно MSDN пишет:

  • The first character must be an ASCII letter (either uppercase or lowercase), or an underscore (_) character. Note that a number cannot be used as the first character.

  • Subsequent characters must be letters, numbers, or underscores.

  • The variable name must not be a reserved word.

Чем в таком случае является переменная $ активно используемая в Prototype или в JQuery - буквой, цифрой или знаком подчекивания? Здравый смысл подсказывает что это скорее буква...

Бывают ли еще такие "странные" буквы которые можно бы было использовать в именах переменных. Например, @ или # использовать не получается.

 

Коментариев: 6

 
  2009-01-27

Browser Detection

Обнаружил что фрагмент кода из mootools выдает какой то странный результат для версии движка, может я не знаю каких нюансов, но все же хочется чтобы версия хоть как то коррелировала с версией браузера, кроме того писать каждый раз Browser.Engine.presto довольно длинно, хотелось бы чтобы было просто Browser.presto.

Mootools в отличие от jQuery и prototype определяет тип движка браузера по определенным особенностям объектной модели а не по navigator.userAgent, это неплохо, вот только версию движка таким образом можно определить очень приблизительно, поэтому версию будет логично определять по navigator.userAgent а сам движок по функционалу объектной модели.

Немного похозяйничав в коде получилось вот что:

var Browser = {	
	platform: (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase(),
	version: (navigator.userAgent.toLowerCase().match(/.+(?:rv|it|ra|ie|me)[\/: ]([\d.]+)/) || [-1,-1])[1]
};

if (window.opera) Browser.presto = true;
else if (window.ActiveXObject) Browser.trident = true;
else if (!navigator.taintEnabled) Browser.webkit = true;
else if (document.getBoxObjectFor != null) Browser.gecko = true;

Ваш браузер:

Версия  
Платформа  
trident (IE)  
presto (Opera)  
webkit (Safary, Chrome)  
gecko (Firefox, Mozilla)  
 

Оставить комментарий

 
  2008-12-30

Скрипт для генерации снега

Сегодня один из заказчиков попросил поставить на сайт снежинки - да да старые добрые снежинки которые вот уже которые год падают на сайтах в новогоднюю ночь.

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

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

 

Читать далее...

 

Оставить комментарий

 
  2008-12-19

Ограничение области видимости в JavaScript

Иногда в JavaScript нужно создать пару методов которые должны быть видны только изнутри определенного куска кода. Для этого достаточно внести эти методы внутрь анонимной функции и сразу ее выполнить:

(function(){ //наша анонимная функция
function func1(){ //первая функция видимость которой нужно ограничить
   alert('!');
}

function func2(){ //вторая функция видимость которой нужно ограничить    
   func1();
}
func2();
//внутри блока func1 и func2 "видят" друг друга и могут быть вызваны!
})(); //выполнить

//при этом вне блока func1 и func2 оказываются невидны!

Этот принцип может быть также использован для создания приватных методов и свойств при программировании объектов.

 

Оставить комментарий

 
  2008-12-19

Корректный способ итерации сквозь объекты

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

Допустим, у нас есть объект созданный вот таким образом:

var obj = {property1:"свойство 1",property2:"свойство 2"};

вот самый распространенный НЕПРАВИЛЬНЫЙ способ показать все свойства объекта:

for(key in obj){
        alert(key);
}

Вроде все работает правильно и на экране действительно последовательно покажутся все свойства объекта. Почему такой способ является неправильным?

Добавим перед циклом вот такую строчку:

Object.prototype['test1'] = "test1 value";

При запуске скрипта еще раз оказывается, что наш объект волшебным образом приобретает еще одно свойство - test1, хотя мы его не создавали! Это значит что любая сторонняя библиотека которая таким способом расширяет функциональность стандартных классов JavaScript, например prototype.js способна непредсказуем образом изменить логику работы ваших программ. В данном случае хорошим тоном является сравнение текущего свойства и свойства прототипа при каждой итерации, если они равны, значит ничего не делаем:

for(key in obj){
   if (obj.constructor.prototype[key]!==obj[key]){
      alert(obj[key]);
   }
}

Обратите внимание, что здесь использовано строгое сравнение !==. Все просто, все логично, вот только набирать это каждый раз довольно утомительно, поэтому создадим вот такую функцию:

    function forEach(obj,fn){
        for(key in obj){
            if (obj.constructor.prototype[key]!==obj[key]){
                if (fn(key)===false) break;
            }
        }
    }

В этом случае итерация запишется совсем просто:

forEach(obj,function(key){
    alert(obj['key']);
});

Обратите внимание, что в функции forEach есть возможность остановить итерацию досрочно, что бывает полезно например при поиске элемента, для этого достаточно возвратить false:

forEach(obj,function(key){
    alert(obj['key']);
    if (key=='property1') return false;
});

 

 

Оставить комментарий

 
  2008-12-11

Native in Chrome

Обнаружил что в Google Chrome в JavaScript нельзя создать переменную с именем native - оказывается это ключевое слово зарезервированное на будущее. Интресно что Safari который работает на том же самом движке все работает.

 

Оставить комментарий

 
  2008-12-04

Эмбриопрограммирование

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

shortEvents:function(names){
     x.forEach(names,function(key){
       this[names[key]] = new Function("fn","remove","this.on('"+[names[key]]+"',fn,remove)");
     },this)
},

Кто догадается что это?

 

Коментариев: 4

 
  2008-11-20

Нестандартное поведение стандартного оператора ||

Иногда при кросс браузерном программировании бывает нужно выбрать из двух или более переменных которые зависят от типа браузера. Например типичный пример - отслеживание событий мыши - в IE параметры события берутся из глобального объекта event а в Firefox и многих других браузерах event передается как формальный параметр в обработчик события. Поэтому необходимо выбирать тот или иной способ получения этого объекта в зависимости от того какой браузер.

Самое первое, что приходит на ум это использовать тернарный оператор "<condition>?<if true>:<if false>"

a.onclick = function(e){
  var ev = e?e:event;
  //далее работаем с ev
}

Сегодня мне предложили еще более короткую запись:

a.onclick = function(e){
  var ev = e||event;
  //далее как обычно
}

Все отлично, все логично, но почему это работает? В MSDN четко сказано что || оператор логический и возвращает он true или false в зависимости от входных параметров. Если параметры на входе не логические то приводятся к логическим, т.е. не должно так работать а работает.

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

    var v1; //undefined
    var v2 = {};
    var result = v1 || v2;    
    alert(result===v2); //true

Интересно, такое поведение где нибудь документировано или это хак?

UPD: Оказыватся у Мозиллы все подробно на этот счет расписано:

https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Logical_Operators

 

Коментариев: 7

 
  2008-11-11

Базовый класс для наследования в JavaScript

Под впечатлением класса разработанного Дином Эдвардсом создал свой собственный класс, который позволяет значительно упростить структуру программ на JavaScript где необходимо неследование.

Основные особенности следующие:
- маленький и простой - неминифицированный размер: 622 байта.
- конструктор описывается явно как функция с именем 'constructor'
- наследование статических и обычных членов класса
- при определениии объекта не используется MyClass.prototype;
- не используются глобальные функции для создания цепочек прототипов;
- не изменяется Object.prototype.

 Вот пример использования:

var Animal = BaseClass.extend({
  constructor:function(){
    alert("Anumal is created!");
  },
  say:function(){
    alert("hm...");
  }

});

ver Cow = Animal.extend({
  constructor:function(){
    alert("Cow is created!");
  },
  say:function(){
    alert("mooo");
  }  

});
var cow1 = new Cow();
cow1.say();

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

Upd. Позже я пересмотрел мысль насчет super и включил её в реализацию метода. В ztools.org можно найти последнюю версию функции.

 

Коментариев: 1