понедельник, 5 ноября 2012 г.

Запуск приложений Ubuntu с правами администратора

Если нужно запустить приложение из под терминала, используем команду sudo:
$ sudo mc

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

Чтобы не держать для каждого приложения параллельно открытую консоль, есть простое решение.

Команда gksu. Это "графический" аналог sudo. Разница только в том, что пароль суперпользователя вас попросят ввести не в консоли, а в диалоговом окне. Можно использовать в настройках команд запуска ярлыков (я думаю, вы уже пробовали писать там sudo и ничего не получилось). Пример команды:
$ gksu gedit

"Графический" пример, научим ярлык приложение Sublime Text запускать приложение с правами администратора:


понедельник, 29 октября 2012 г.

Как узнать версию ejabberd

ejabberd - XMPP сервер, написанный на Erlang. Узнать версию установленную в системе можно так:
1. Если остались файлы дистрибутива, то версию можно узнать по имени пакета ejabberd-x.x.x
2. Найти в системе файл ejabberd.app и найти там строку вида: {vsn, "x.x.x"}
3. Если у вас нет доступа к системе, но нужно открыть в XML-консоль (например в QIP, Miranda) и послать серверу команду:

  

Сервер он вам ответит приблизительно так:

  
    ejabberd
    2.1.10
  unix/linux 3.2.0
  

четверг, 25 октября 2012 г.

XML Viewer. Удобный просмотр XML

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

1. Если вы уже используете какую-то из JetBrains IDE, то нажмите Ctrl+Alt+L (или через меню: Code->Reformat Code)

2 . Еще есть простая бесплатная программа Free XML Editor:

Пример просмотра документа:

Для форматирования документа, нужно нажать F8.

Предварительно нужно открыть пункт меню Tools->Preferense, и там выбрать форматирование табуляцией:




Очень просто и удобно.

среда, 24 октября 2012 г.

VirtualBox. Настройка общих папок для Ubuntu

Основная ОС: Windows 7
VirtualBox ОС: Ubuntu 12.04
Задача: настроить общие папки

1. Создаем папку "d:/share" под Windows 7.

2. Открываем настройки VirtualBox, находим в меню пункт "Общие папки" и добавляем там нужную:

3. Заходим на виртуальную машину, и в папке вашего пользователя, создаем новую папку, ставим нужный уровень доступа:
username@your_server:~# mkdir shared
username@your_server:~# chmod 0777 shared

4. Монтируем папку:
username@your_server:~# sudo mount -t vboxsf share shared

!!! Есть неприятный баг: когда имена папок в обоих системах совпадают - команда mount вернет ошибку, именно потому, папки специально названы share и shared


понедельник, 3 сентября 2012 г.

Javascript. Реализация Singleton и статического класса

Реализовать статический класс в js очень просто, это будет простой объект:
var obj = {
  field: 'value',
  fnTest: function(){
    return 'res: '+ this.field;
  }
};

// Использование:
console.log( obj.field ); // 'value'
console.log( obj.fnTest() ); // 'res: value'
Если нам нужна предварительная инициализация, то добавим некий метод init, который может устанавливать значение полей объекта:
var obj = {
  field: 'value',
  options: {},
  init: function(o){
    this.options = $.extend(true, {}, o);
  },
  fnTest: function(){
     return this.field;
  }
};

// Использование:
obj.init({o:4,test:2});
console.log( obj.options ); //{o:4,test:2}
Этого функционала, в большинстве случаев, должно хватить, но бывает нужен и синглетон (Singleton): например важно иметь приватные данный и методы (статический класс полностью публичен) Один из демонстрационных вариантов реализации синглетона :
var cSingleton = (function(){
  // Class instance:
  var _instance = null;

  // Private:
  var test = 1;
  var options = {};
 
  var fnPrivate = function(){
    // some code
  }
 
  // Constructor:
  function Init(o){
    options = $.extend(true, options, o || {});
  }
  
  // Public:
  Init.prototype = {
    pub: 0,
    fnTest: function(){
       return test;
    },
    getOptions: function(){
      return options;
    }
  }

  return function(args){
    if(!_instance){
       _instance = new Init(args);
    }
    return _instance;
  }
}());

ob = new cSingleton({x:1});

console.log('1:', ob.fnTest());
console.log('opts:', ob.getOptions());

ob2 = new cSingleton({x:2});

console.log('2:', ob2.fnTest());
console.log('opts:', ob.getOptions());

// Результат:
1: 1
opts: Object { x=1}
2: 1
opts: Object { x=1}
Так мы гарантируем, что класс вернет только одно значение. Возможно это и "синтетическая" задача, но возможно кому-то и пригодиться

среда, 13 июня 2012 г.

jQuery. Reverse each. Обратный перебор

Встречаются задачи, когда было бы удобно осуществлять перебор коллекции jQuery в обратном порядке. Ниже привожу функцию которая дает такую возможность:
jQuery.fn.reverseEach = (function () {
 var list = jQuery([1]);
 return function (c) {
  var el, i=this.length;
  try {
   while (i-->0 && (el=list[0]=this[i]) && c.call(list,i,el)!==false);
  }
  catch(e) {
   delete list[0];
   throw e;
  }
  delete list[0];
  return this;
 };
}());

$("li.classname").reverseEach(function(){
  // this сразу содержит объект jQuery
  console.log( 'id:', this.attr('id') );
  //return false; - Если в каком-то случае вернем false - обход прервется в этом месте
});
Если нужно поведение аналогичное .each(), когда к элементу обращаемся через $(this), нужно заменить 13 строчку на:
  return this.get(0); // Вместо: return this; 

вторник, 8 мая 2012 г.

JSON валидатор

Хочу поделиться ссылкой на онлайн валидатор JSON: http://jsonlint.com/
Будет полезным, особенно для проверки ответов сервера в ajax запросах (если ответ в формате JSON)

понедельник, 12 марта 2012 г.

Вставка текущего курса валют USD/UAH в ячейку таблицы google docs

Google Docs Spreadsheets очень удобный онлайн инструмент для ведения бухгалтерии. Допустим, что такая бухгалтерия ведеться в долларах США, но в конечном итоге надо получить все суммы в гривнах, учитывая текущий курс валют.

Как выход - в ячейку вбить текущий курс и отталкиватся от него. Минус такого подхода состоит в том, что постоянно придется корректировать этот самый текущий курс (как минимум раз в день) .

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

На самом деле, тут все решабельно. В качестве такого онлайн сервиса, будет использовать ся Yahoo Finance. Страница, которая предоставляет нужный тип информации (USD в UAH) будет такая: http://finance.yahoo.com/q?s=USDUAH=X.

Остается только выбрать нужное значение со страницы и использовать для себя:

=VALUE(SUBSTITUTE((SUBSTITUTE(INDEX(ImportHTML("http://finance.yahoo.com/q?s=USDUAH=X";"table";1); 1;2);"*";""));".";","))


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

Теперь немного детальнее пройдемся  по формуле:

VALUE - конвертирует текст в чисельное значение

SUBSTITUTE - функция, кторая заменяет одно значение в строке на другое. В нашем примере, мы сначала заменяем * на пустое значение (так как резуьтат выгребается в виде *7.92*), после чего, заменим точку на запятую - так как разделитель дробной части у меня запятая.

INDEX - получаем элемент массива (ячейку таблицы со значением курса валют)

ImportHTML - по заданому URL выгребаем контент, ищем в нем 1 таблицу.

jQuery. Быстрый итератор quickEach

Если вам нужно часто работать с итераторами each в jQuery, и вам приходиться часто внутри него пользоваться $(this), то есть смысл немного оптимизировать код.

Пример: необходимо перебрать список li и что-то сделать с каждым элементом списка
var list = $("ul li");
list.each(function() {
 var el = $(this); // получаем объект jQuery из объекта DOM
 el.....  // Какое-то действие с объектом
});

Следует помнить, что всегда нужно использовать групповые функции над списками, перебирать по одному не оптимально. Но представим себе, что задача стоит так, что без перебора списка поэлементно ее нельзя решить. Тогда узким местом такого алгоритма будет операция получения jQuery объекта на основе контекста this. В методе $.each(), this не является объектом, jQuery - он указывает на текущий элемент DOM. Потому, его надо привести к объекту jQuery, а это есть ресурсоемкая операция.

Можно использовать оптимизированный итератор $.quickEach() описанный ниже, который сразу возвращает в this объект jQuery и его не нужно получать в цикле для каждого элемента DOM которые мы итерируем.

/**
 *  jQuery quick Each
 *
 *  Example:
 *  a.quickEach(function() {
 *      this; // jQuery object
 *  });
 */
jQuery.fn.quickEach = (function() {
    var jq = jQuery([1]);
    return function(c) {
        var i = -1, el, len = this.length;
        try {
            while (++i < len && (el = jq[0] = this[i]) && c.call(jq, i, el) !== false);
        } catch (e) {
            delete jq[0];
            throw e;
        }
        delete jq[0];
        return this;
    };
 }());
Пример использования:
// Стандартный итератор
list.each(function() {
 var el = $(this);
});

// Оптимизированный итератор:
list.quickEach(function() {
 var el = this; // jQuery object
});
Оригинальная статья находиться по адресу http://jsperf.com/jquery-each-vs-quickeach, где также можно ознакомиться с результатами замеров производительности обоих методов.

среда, 29 февраля 2012 г.

Какой комбинацией клавиш перейти в командную строку браузера

Переход в командную строку браузера осуществляется комбинацией Ctrl+L, Тестировал в последних версиях FireFox, Chrome, IE, Opera, Safari.

P.S. Реально позволяет более комфортнее работать.

вторник, 14 февраля 2012 г.

JavaScript. Поиск строки методом like (аналог like из MySQL)

Недавно, мне понадобилось осуществлять поиск по массиву объектов(со строковыми полями). В JavaScript, сложный поиск осуществляется с помощью регулярных выражений, для того чтобы искать в контексте объекта String, есть метод(прототип) match().

Но так как задача похожа на поиск по БД, то мне захотелось использовать синтаксис поиска MySQL функции like() - она очень удобна, когда не нужно явно применять поиск по сложному регулярному выражению. Например: поиск строк начинающихся, заканчивающихся какой-то подстрокой или включают подстроку (что совпадало с моей задачей).

Плюс ко всему - нужно уметь динамически генерировать это условие. Конечно, в JavaScript легко создать регулярное выражение из строки с помощью конструктора new RegExp(pattern, attrs), но это не так красиво как использование like. Потому я расширил прототип String этим методом. Внутри он таки использует регулярные выражения, но от программиста это скрыто, и пользоваться этим удобно и интуитивно всем кто знает SQL.

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

String.prototype.like = function(s) {
  if(undefined==s || typeof(s)!='string') return false;

  function replacer(str, p1, p2) {
    if(p1=='\\') return p2;
    if(p2=='%') return p1+'.+';
    return p1+'\\w';
  }
  
  var pattern = "^"+s.replace(/(.|^)([%_])/gm, replacer)+'$'; 
  var re = new RegExp(pattern, 'mg');

  if(this.match(re)) return true;
  return false;
};

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

var s = "Test string";

console.log( s.like("%ing")  ); // True
console.log( s.like("%in")   ); // False
console.log( s.like("%in_")  ); // True
console.log( s.like("Test%") ); // True
console.log( s.like("%str%") ); // True
console.log( s.like("%spr%") ); // False
console.log( s.like("%s_r%") ); // True


Для того чтобы использовать символы "%", "_" в строке поиска, их нужно экранировать двумя бэк-слешами "\\%".

среда, 8 февраля 2012 г.

JavaScript. Проверить является или нет один хеш подмножеством другого

Задача: Проверить два хеша на предмет того, является или нет, один из них подмножеством другого. Мы проверяем полное соответствие как ключей, так и значений. Порядок параметров значения иметь не должен.

Решение:
var isHashSubset = function(a, b){
  var f = true;
  for(var id in b){
    if(b.hasOwnProperty(id)){
      if(!((undefined!=a[id])&&(undefined!=b[id])&&(b[id]==a[id]))){
        f = false;
      }
    }
  }
  if(!f){
    f = true;   
    for(var id in a){
      if(a.hasOwnProperty(id)){
        if(!((undefined!=a[id])&&(undefined!=b[id])&&(b[id]==a[id]))){
          f = false;
        } 
      }    
    }
  }
  return f;
}

var x = {'key1':'val1','key2':'val2', 'key3':'val3'};
var y = {'key1':'val1','key2':'val2'};

console.log('Result:', isHashSubset(x,y) ); // TRUE
console.log('Result:', isHashSubset(y,x) ); // TRUE

var x = {'key1':'val1','key2':'val2', 'key3':'val3'};
var y = {'key1':'val1','key4':'val4'};

console.log('Result:', isHashSubset(x,y) ); // FALSE
console.log('Result:', isHashSubset(y,x) ); // FALSE


Значения null не будут учитываться, для того чтобы учитывать их также, нужно вместо условия (обоих условиях):
(!((undefined!=a[id])&&(undefined!=b[id])&&(b[id]==a[id])))

использовать:

(!((id in a)&&(id in b)&&(b[id]==a[id])))

Усовершенствованный вариант:

var isHashSubset = function(a, b, c){
  var f = true, 
      c = c || 0; // количество рекурсивных вызовов

  for(var id in b){
    if( b.hasOwnProperty(id) && !( undefined!=a[id] && undefined!=b[id] && b[id]==a[id] ) ){
      f = false;  
    }
  }
  return (!f && c == 0) ? isHashSubset(b, a, 1) : f;
}

вторник, 7 февраля 2012 г.

MySQL. Группировка по интервалам

Постановка задачи: есть таблица table(id:int, time:timestamp, val:double) в которую периодически заносятся показания некого прибора (например каждые 5 секунд).
Задача: вывести средние значения показаний прибора за определенные интервалы времени, например средние значение за каждые 60 минут

SELECT `id`, DATE_FORMAT(`time`, '%Y-%m-%d %H:%i') as `dt`, avg(val) as `value`
FROM `table`
GROUP BY `id`, time_to_sec(`time`)- time_to_sec(`time`)%(60*60)
ORDER BY `dt` DESC

Что же происходит в запросе:
мы, фактически, работаем с целочисельной арифметикой (что есть быстро). Переводим таймстамп в int, а дальше - каждое поле делим нацело на длину интервала. Отсюда вытекает, что всем записям заданного интервала будет задаваться в соответствие одно и то же целое число, по которому и проводим группировку.

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

Можно использовать группировку по интервалу с помощью функции date_sub(), но в данном случае проще и читабельнее именно такой подход (мое субъективное мнение)